Android4 之后使用的是 tinyasla
源码路径: external/tinyalsa/
拾音demo: tinycap.c
放音demo:tinyplay.c
可在 源码中执行
mmm external/tinyalsa/
编译后的执行文件在目录: out/target/product/msm8953_64/system/bin/
使用 tinycap tinyplay 设置相应的声卡 即可拾音或放音,命令如下:
tinycap /sdcard/xxx.wav -D 0 -d 0 -c 1 -r 48000 -b 16 -p 240 -n 2
tinyplay /sdcard/xxx.wav -D 0 -d 0
使用 alsa API 的 demo 如下:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#LOCAL_CFLAGS := -D_POSIX_SOURCE
LOCAL_C_INCLUDES += $(TOP)/device/hisilicon/bigfish/external/alsa-lib/include
LOCAL_SRC_FILES := alsa_main.c
LOCAL_MODULE := alsa_test
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libasound
include $(BUILD_EXECUTABLE)
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <utils/Log.h>
#include <alsa/asoundlib.h>
#include <stdlib.h>
#include <signal.h>
#undef LOG_TAG
#define LOG_TAG "alsatest"
#define filename(x) strrchr(x,'/')?strrchr(x,'/')+1:x
#if 1
#define logi(fmt,args...) printf("I \%s " fmt, LOG_TAG, ##args); printf("\n")
#define loge(fmt,args...) printf("E \%s " fmt, LOG_TAG, ##args); printf("\n")
#define logd(fmt,args...) printf("D \%s " fmt, LOG_TAG, ##args); printf("\n")
//#define logi(fmt,args...) ALOGI(fmt, ##args)
//#define loge(fmt,args...) ALOGE(fmt, ##args)
//#define logd(fmt,args...) ALOGD(fmt, ##args)
//#define logenter() ALOGI("enter %s, %s", __func__, filename(__FILE__))
//#define logexit() ALOGI("exit %s, %s", __func__, filename(__FILE__))
#else
#define logi(fmt,args...) do{}while(0)
#define loge(fmt,args...) do{}while(0)
#define logd(fmt,args...) do{}while(0)
#define logenter() do{}while(0)
#define logexit() do{}while(0)
#endif
int capturing = 1;
void sigint_handler(int sig __unused)
{
capturing = 0;
}
int main()
{
int rc;
int size;
int dir;
char *buffer;
unsigned int channel;
unsigned int rate;
snd_pcm_uframes_t frames;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
FILE *out_fp;
out_fp = fopen("a.raw", "wb");
// 访问硬件,并判断硬件是否访问成功
rc = snd_pcm_open(&handle, "hw:0,0", SND_PCM_STREAM_CAPTURE, 0);
if(rc < 0)
{
loge("unable to open device: %s", snd_strerror(rc));
return -1;
}
// 分配一个硬件参数结构体
snd_pcm_hw_params_alloca(¶ms);
// 使用默认参数
snd_pcm_hw_params_any(handle, params);
// interleaved mode 设置数据为交叉模式,即LRLRLR...
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
// 设置数据编码格式为PCM、有符号、16bit、小端
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
// 设置通道数
channel = 2;
snd_pcm_hw_params_set_channels(handle, params, channel);
// 设置采样率
rate = 48000;
snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir);
// 周期长度(帧数) 16bit * 2(双声道)
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
// 将配置写入驱动程序中,判断是否已经配置正确
rc = snd_pcm_hw_params(handle, params);
if(rc < 0)
{
loge("unable to set hw parameters: %s", snd_strerror(rc));
return -1;
}
// 得到一个周期的数据大小
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
// 2 bytes sample, 2 channels;16位: 2*frames*channels
size = frames * 2 * channel;
buffer = (char *)malloc(size);
// 得到一个周期的时间长度
snd_pcm_hw_params_get_period_time(params, &rate, &dir);
while(capturing)
{
// 捕获数据
rc = snd_pcm_readi(handle, buffer, frames);
if(rc == -EPIPE)
{
loge("overrun occured");
snd_pcm_prepare(handle);
}
else if(rc < 0)
{
loge("error from read: %s", snd_strerror(rc));
}
else if(rc != (int)frames)
{
loge("short read %d frames", rc);
}
rc = fwrite(buffer, 1, size, out_fp);
if(rc != size)
{
loge("short write %d bytes", rc);
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
fclose(out_fp);
return 0;
}
源码下载链接 https://download.csdn.net/download/qq_38907791/10975134