一、前言:
近期因为项目中没有和硬件沟通好,导致在Android的alsa中录制数据时,硬件给过来的数据参数和需要的不一样,没办法,需要进行重采样,故看了下网上的重采样介绍,这里简单记录下。
二、重采样算法:
首先对录制的数据,当两声道及以上时,需要确认一点就是是否交织,这将决定我们的算法如何剥离数据。
这是网上找到的关于交织与非交织数据的图示,简单来说,交织的数据就是对每一个采样点都写上所有声道的数据之后才进行下一个采样点的数据写入,而非交织则是按到声道个数,一次性写入所有的采样数据。
在我本次的项目中,因为是对Android中tinyalsa的数据进行处理,所以确认数据是交织的。
而重采样的目的是将底层录制的48k采样率数据改为16k采样率数据,所以我们只需要在原来数据的基础上每隔三个点保存一下,保存完毕后,就是16k采样率的数据了。
具体代码实现如下:
/* data_buf为从alsa获取的48k原数数据,xmos_data_buf为重采样之后的数据 */
int count = 0;
int readCount = 0;
short* pu16Src = NULL;
short* pu16Dst = NULL;
pu16Src = (short*)(data_buf);
pu16Dst = (short*)(xmos_data_buf);
/* 重采样处理:48k->16k,每隔三个点重采样一次 */
for (count = 0; count < 320; count++)
{
pu16Dst[count] = pu16Src[count * 3];
}
从代码中可以看到,因为数据位宽是16bit的,所以以short指针的方式去读取缓存中的数据,其次,只要计算出需要处理的帧数(帧数 = 采样率/1000 * 位宽 * 时间),那么转换就可以完成了,经过重采样处理之后的数据体积肯定只有原来的三分之一。
三、分离声道数据:
上面经过重采样之后获取的数据是两个声道的总数据,我们还需要对数据进行声道分离,因为是交织方式获取的,所以算法如下:
/* 分离两个channel的数据 */
int u32Channel = 0;
int i = 0;
for (u32Channel = 0; u32Channel < 2; u32Channel++)
{
pu16Src = (short*)(xmos_data_buf);
/* 两个声道的数据分别存在pChannelBuf的两个缓冲区中 */
pu16Dst = (short*)(pChannelBuf[u32Channel]);
for (i = 0; i < 160; i++)
{
pu16Dst[i] = pu16Src[(i * 2) + u32Channel];
}
}
这里就实现了数据的重采样和分离,但是,对于这种操作我还是推荐硬件给过来的数据就是对的,毕竟,每一次录制都需要使用软件操作还是很占用系统资源的。