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_SOURCELOCAL_C_INCLUDES += $(TOP)/device/hisilicon/bigfish/external/alsa-lib/includeLOCAL_SRC_FILES := alsa_main.cLOCAL_MODULE := alsa_testLOCAL_SHARED_LIBRARIES := \libcutils \libutils \libasoundinclude $(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)#endifint 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*channelssize = 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