1.首先,给参数配置分配相应的空间,并且根据当前的PCM设备具体的情况初始化:
snd_pcm_hw_params_t *hwparams;
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_hw_params_any(handle,hwparams);
2.设置访问模式为交错模式,这意味着采样点是帧连续的,而不是通道连续的。
snd_pcm_hw_params_set_access(handle,hwparams,SND_PCM_ACCESS_RW_INTERLEAVED);
3.设置量化参数:
snd_ pcm_format_t pcm_format = SND_PCM_FORMAT_S16_LE;
snd_pcm_hw_params_set_format(handle,hwparams,pcm_format);
LE:表示小端(低地址存低位)
S16:short短整型,两个字节
S8 U8 S16_LE S16_BE U16_LE U16_BE格式
4.设置音轨数目(本例中设置为双音轨,1位单音轨)
uint16_t channels = 2;
snd_pcm_hw_params_set_channels(handle,hwparams,channels);
5.设置采样频率,设备所支持的采用频率有规定的数值,本例子中以exact_rate为基准,设置一个接近该值的频率。
uint32_t exact_rate = 44100;
snd_pcm_hw_params_set_rate_near(handle,hwparams,&exact_rate,0);
6.设置buffer size为声卡支持的最大值
snd_pcm_uframe_t buffer_size;
snd_pcm_hw_params_get_buffer_size_max(hwparams,&buffer_size);
snd_pcm_hw_params_set_buffer_size_near(handle,hwparams,&buffer_size);
7.根据buffer size设置period size(比如将period size设置为buffer size的四分之一)
snd_pcm_uframes_t period_size = buffer_size / 4;
snd_pcm_hw_params_set_period_size_near(handle,hwparams,&period_size,0);
8.设置PCM参数
snd_pcm_hw_params(handle,hwparams);
对以上的参数设置,有几个地方需要解释一下;
第一,访问模式可以是一下这些
直接IO就是,当初文件直接读写;
内存映射就是先映射一块内存,然后再把数据填到内存里面。
如果是LCD屏的话使用内存映射更好。
SND_PCM_ACCESS_MMAP_INTEREAVED;//内存映射方式下的交错模式
SND_PCM_ACCESS_MMAP_NONINTERLEAVED;//内存映射方式下的非交错模式
SND_PCM_ACCESS_RW_INTERLEAVED;直接IO方式下的交错模式
SND_PCM_ACCESS_RW_NONITERLEAVED;直接IO方式下的非交错模式
第二:量化位数可以设置为:
SND_PCM_FORMAT_S8 有符号8位
SND_PCM_FORMAT_U8 无符号8位
SND_PCM_FORMAT_S16_LE 有符号16位,小端序
SND_PCM_FORMAT_S16_BE 有符号16位,大端序
本例子中采用16位(2字节)量化位数,而且测试系统的字节序是小端序,因此选择SND_PCM_FORMAT_S16_LE,而且在一个可移植的音频录制程序中,应该让程序自动判断采用哪个量级。
第三:采样频率的设置函数名字为snd_pcm_hw_params_set_rate_near(),从名字中可以看出声卡并非可以支持随意设置的采样频率,该函数的功能就是,以exac_rate为基准,设置一个最接近该值的采样频率,再将最终的实际频率写入exac_rate中。
第四:ALSA系统中的buffer实际上是一个环形循环队列,可以被分割成若干个period,每当一个period被填满,则触发一个就绪事件或者一个SIGIO信号。
最后,启动PCM设备并是这些参数生效:snd_pcm_hw_params(handle,hwparams);做完了这些步骤我们就可以从PCM设备中读取音频数据了,由于采用了直接IO方式的帧连续的交错模式,因此应使用如下函数:
snd_pcm_readi(handle,p,frames);
其中,p指向一块自定义的数据缓冲区,frames是一次读取的帧个数,这个数字至少应该是period size,因为音频设备至少读取到period size这个帧后才会使得读就绪。
从音频设备(麦克风)中读取到数据之后,需要保存成一个某种格式的音频文件,比如wav格式,那么就必须在写数据之前先了解wav格式的细节,下图展示了一个典型的wav格式音频文件的详细信息,在创建一个wav格式的音频文件时,必须要按照下图指示的格式来写。
wav格式不仅要包含音频数据还要包含音轨,采样频率等属性。
RIFF文档的内容又可以由多个数据块组成,对于wav格式来说,,他的组成如下图中右边的部分所示,包含两块,一个是fmt,一个是data块。