当前位置: 代码迷 >> 综合 >> Android 音频 alsa 拾音例子
  详细解决方案

Android 音频 alsa 拾音例子

热度:25   发布时间:2023-12-29 09:27:21.0

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(&params);// 使用默认参数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

  相关解决方案