跳到主要内容

语音功能开发

音频开发基础概念​

硬件参数​

录制和播放声音的本质是将耳朵听到的声音进行采样、保存和恢复。在采集声音时,采集频率越高、采样精度(每个数据用多少bit来表示)越高,播放时的效果就越逼真。

在图中,如果采集声音时t1至t6的间隔越短,那么恢复的波形就越逼真。记录v1至v6时,使用的比特数越多,得到的数值精度越高,右侧恢复的波形也会更加逼真。

如果能将左耳和右耳听到的声音分别采样并记录下来,在播放时通过两个喇叭或耳机播放出来,就能听到立体声效果。在原始音频数据里,左右声道的数据交叉存放,比如“v1,v2,...”是左声道采样的数据,“v1’v2’,...”是右声道采样的数据,在原始文件中存放如下:

v1v1’v2v2’,...

这就涉及了声音采集和播放的三个关键参数:采样频率、采样精度和声道数。

软件参数​

编写软件时,也涉及采样频率、采样精度和声道数。其中采样精度使用format来表示,有如下这些格式,这些格式不仅表示了采样精度,还表示了数据的保存格式(大字节序、小字节序):

……

SND_PCM_FORMAT_S16_LE

SND_PCM_FORMAT_S16_BE

SND_PCM_FORMAT_S24_LE

SND_PCM_FORMAT_S24_BE

……

还有其他概念,如下。

① 帧(frame):一帧表示一个采样点,对于单声道一帧有一个数据,对于双声道一帧有两个数据。

② period:每次读写声音数据的最小单位是多少,它的单位是帧。如果period设置得很小,那么录制或播放一段声音时需要频繁发起read/write操作,效率很低。如果period设置得很大,如果采集的声音要转发出去,那么对方就会感觉声音很卡顿;如果播放的声音来自网络,程序就要收集很多的数据才能播放,也会感觉到卡顿。

③ buffer_size:音频缓冲区大小,单位也是帧,对录音和播放很关键。假设APP读取数据后进行处理,处理的时间多长了,这可能会导致数据丢失。这时可以把buffer设置得比较大,在恶劣情况下可以缓存更多数据。

在阅读openvela里aplay、arecord的代码时,会看到如下函数,它就是用来设置这5个参数的:

int set_param(snd_pcm_t \*handle, snd_pcm_format_t format,

unsigned int rate, unsigned int channels,

snd_pcm_uframes_t period_size,

snd_pcm_uframes_t buffer_size);

aplay和arecord代码解读​

分析:

vendor/allwinnertech/chips/r528/drivers/rtos-hal/hal/test/sound/aplay.c

vendor/allwinnertech/chips/r528/drivers/rtos-hal/hal/test/sound/arecord.c

添加opus编解码功能​

参考代码:external/opus/opus/src/opus_demo.c

修改:

vendor/allwinnertech/chips/r528/drivers/rtos-hal/hal/test/sound/aplay.c

vendor/allwinnertech/chips/r528/drivers/rtos-hal/hal/test/sound/arecord.c

修改arecord程序,把采集到的声音数据使用opus编码后保存为文件“/tmp/sound001.opus、/tmp/sound002.opus、……”。

修改aplay程序,读取文件“/tmp/sound001.opus、/tmp/sound002.opus、……”,使用opus解码得到PCM数据并播放出来。

以后把写文件、读文件的函数改为其他函数,就可以对接控制中心了。

opus库的使用​

使用opus编码、解码的函数流程如下:

创建编码器只需要指定PCM数据的采样率、声道数,就可以使用“opus_encode”函数把PCM数据压缩为opus码流。

创建解码器时只需要指定PCM数据的采样率、声道数,就可以使用“opus_decode”函数把opus码流解码为PCM数据。

在创建编码器时需要指定源声音的参数,在创建解码器时需要指定目的声音的参数:

示例程序​

先添加配置项:

CONFIG_LIB_OPUS

并且添加这个宏:

修改:

vendor/allwinnertech/chips/r528/drivers/rtos-hal/hal/test/sound/aplay.c

vendor/allwinnertech/chips/r528/drivers/rtos-hal/hal/test/sound/arecord.c

添加“-o”选项,即arecord读取麦克风数据后,使用opus进行编码,存为文件“/tmp/sound001.opus、……”。aplay读取文件“/tmp/sound001.opus、……”,使用opus进行解压再播放。使用命令如下:

# 录音

amixer set 19 255

amixer set 20 255

amixer set 21 255

arecord -D hw:snddmic -r 48000 -f 16 -d 10 -c 2 -o

# 播放

amixer set 6 180

amixer set 7 180

amixer set 15 7

aplay -D hw:audiocodec -r 48000 -f 16 -c 2 -o

arecord源码修改​

arecord.c添加的核心代码如下。

第1步:支持“-o”参数。

第2步:采集、编码、存储。

aplay源码修改​

aplay.c添加的核心代码如下。

第1步:支持“-o”参数。

第2步:读取opus文件、解码、播放。