查看这篇文章的小伙伴,就知道你会为怎么测试混音算法痛苦?痛苦的来源无外乎下面这几个原因。
1、测试的PCM文件怎么制作
2、如何读取PCM文件
3、多个PCM文件数据如何混流,以及写文件
4、生成的PCM文件怎么播放
了解了痛苦的根源后,我们来一一解决。
PCM文件比较难找,而且直接下载也不一定符合测试要求,所以最好的做法是自己做。
1、首先找到一个录音软件(Mac推荐使用Audacity),录制一段wav格式的音频,音频参数可以自己定义。这里我生成的是采样率为44.1khz, 双声道,16bit量化格式。
2、使用ffmpeg将wav格式转为PCM文件,命令如下:
ffmpeg -i 1.wav -f s16be -ar 44100 -acodec pcm_s16be output.raw
生成的output.raw就是PCM文件了。
首选我们认识一下,音频文件的存储格式。以s16bit 大端模式为例:
上代码:
int ReadPcm(const char* fileName, int16_t* buff, int* sampleNum)
{
FILE* fp;
fp = fopen(fileName, "rb");
if (fp == NULL)
{
printf("file:%s, open failed\n",fileName);
return 1;
}
unsigned char *sample=(unsigned char *)malloc(4);
int num = 0;
while (!feof(fp))
{
fread(sample, 1, 4, fp);
// read L
buff[num++] = *(short*)sample;
// read R
buff[num++] = *(short*)(sample + 2);
if(num >= MAX_BLOCK_BUF) {
break;
}
}
*sampleNum = num;
printf("file:%s, Sample Cnt:%d\n",fileName, num);
free(sample);
fclose(fp);
return 0;
}
将每个PCM文件都采用如下的结构体来存储,并放入list列表。
struct PCMInfo
{
int16_t buff[MAX_BLOCK_BUF];
int sampleNum;
};
之后就是依据设定mix算法从List列表中取数据处理。此处以简单的相加算法为例。
int mixAudio(PCMList pcmList, int sampleNum, FILE* outFile) {
if (pcmList.size() == 0 || outFile == NULL)
{
return 1;
}
PCMInfo outPcm;
PCMList::const_iterator cit = pcmList.begin();
for (; cit != pcmList.end(); ++cit)
{
int index = std::min(sampleNum, (*cit)->sampleNum);
for (int j = 0; j < index; j++)
{
outPcm.buff[j] += (*cit)->buff[j];
if (outPcm.buff[j] > MAX_AUDIO_SAMPLE_SIZE)
{
outPcm.buff[j] = MAX_AUDIO_SAMPLE_SIZE;
}
if (outPcm.buff[j] < MIN_AUDIO_SAMPLE_SIZE)
{
outPcm.buff[j] = MIN_AUDIO_SAMPLE_SIZE;
}
}
outPcm.sampleNum = index;
}
// write to file
for (int i = 0; i < outPcm.sampleNum; i++)
{
fwrite(&outPcm.buff[i], 1, 2, outFile);
}
return 0;
}
因为我们的采用格式是16bit, 所以这里写文件按照2字节依次写入。
做完以上三步,我们就已经生成了一个PCM文件了。但是一般的播放器是无法播放PCM文件的,所以此时我们需要将PCM文件在转换为wav格式的文件,指令如下:
ffmpeg -f s16be -ar 44100 -ac 2 -acodec pcm_s16be -i output.raw output.wav -y
说了怎么多步骤,如果一步步实现实在麻烦,没等测试开始,你就已经凌乱了。现在这些我都集成在了一个工具里面,只要一条命令,轻松实现。
./mix_test [file1] [file2] [...]
举例:
混二路视频
./mix_test ./src/test1.wav ./src/test2.wav
混四路视频
./mix_test ./src/test1.wav ./src/test2.wav ./src/1.wav ./src/2.wav
那么定制化Mix算法简单吗,简单 只需改一行代码即可,源码里有详细说明。
如何获取此工具和源码呢?
关注下面微信公众号,发送留言 mix 获取网盘提取码。