Android tinyalsa pcm编程介绍

12190阅读 0评论2015-08-03 zhoushiqian
分类:Android平台

1,说明

本文主要是对Android平台下,如何利用tinyalsa库接口实现audio paly audio record.

2,基本知识介绍

2.1 Android audio 框架

这个很多人有描述,基本就是audioframework<——>audio hal<——>tinyalsa<——>alsa驱动

audioframework:这个主要是给上层app提供接口和audio policy管理

audio hal:这个主要是厂家实现,提供audio path的控制,audio 逻辑设备到物理设备的映射,audio校准参数的加载等等


2,2 tinyalsa

这个是alsa库在Android上面的迷你实现,封装了内核alsa接口,和alsa驱动打交道,简化用户空间编程

Android 代码目录external/tinyalsa/

github 托管

2.3 pcm_config

/* Configuration for a stream */

struct pcm_config {

unsigned int channels;

unsigned int rate;

unsigned int period_size;

unsigned int period_count;

enum pcm_format format;


/* Values to use for the ALSA start, stop and silence thresholds. Setting

* any one of these values to 0 will cause the default tinyalsa values to be

* used instead. Tinyalsa defaults are as follows.

*

* start_threshold : period_count * period_size

* stop_threshold : period_count * period_size

* silence_threshold : 0

*/

unsigned int start_threshold;

unsigned int stop_threshold;

unsigned int silence_threshold;


/* Minimum number of frames available before pcm_mmap_write() will actually

* write into the kernel buffer. Only used if the stream is opened in mmap mode

* (pcm_open() called with PCM_MMAP flag set). Use 0 for default.

*/

int avail_min;

};


audio frame countperiod_size × period_count

audio famechannle × sample bytes

pcm类似于文件描述符,不过表示audio stream

3,API介绍


struct pcm *pcm_open(unsigned int card, unsigned int device, unsigned int flags, struct pcm_config *config);



int pcm_write(struct pcm *pcm, const void *data, unsigned int count); //返回0表示成功

int pcm_read(struct pcm *pcm, void *data, unsigned int count);//返回0表示成功

int pcm_close(struct pcm *pcm);

4,一个实际的项目

Firefox OS上面需实现开机铃声,在播放开机画面的时候,audio hal层还没有初始化,意味着只能

直接利用pcm接口来进行处理。

部分代码


if(set_mixer()){ //设置audio path

ALOGE("set_mixer error\n");

return -1;

}


file = fopen(filename, "rb"); //打开开机铃声

if (!file) {

fprintf(stderr, "Unable to open file '%s'\n", filename);

return 1;

}



config.channels = channels;

config.rate = rate;

config.period_size = period_size;

config.period_count = period_count;

if (bits == 32)

config.format = PCM_FORMAT_S32_LE;

else if (bits == 16)

config.format = PCM_FORMAT_S16_LE;

config.start_threshold = 0;

config.stop_threshold = 0;

config.silence_threshold = 0;


if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) {

return;

}



pcm = pcm_open(card, device, PCM_OUT, &config);

if (!pcm || !pcm_is_ready(pcm)) {

fprintf(stderr, "Unable to open PCM device %u (%s)\n",

device, pcm_get_error(pcm));

return;

}


size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));

buffer = malloc(size);

if (!buffer) {

fprintf(stderr, "Unable to allocate %d bytes\n", size);

free(buffer);

pcm_close(pcm);

return;

}


pcm_write(pcm, buffer, num_read))

free(buffer);

pcm_close(pcm);


5,一个稍微负责的项目需求

Firefox上面移植Nuance的音频引擎,实现引擎实时获取pcm数据流。

1,根据Nuance提供的api.h文件实现so

2,so库主要处理好pcm的实时处理,避免overun问题



上一篇:Qualcom QMI系列-基本知识介绍
下一篇:如何使用n2n远程连接