给你一个工具,轻松解决测试混音算法难?

 

给你一个工具,轻松解决测试混音算法难?_第1张图片

一、痛苦根源

查看这篇文章的小伙伴,就知道你会为怎么测试混音算法痛苦?痛苦的来源无外乎下面这几个原因。

1、测试的PCM文件怎么制作

2、如何读取PCM文件

3、多个PCM文件数据如何混流,以及写文件

4、生成的PCM文件怎么播放

了解了痛苦的根源后,我们来一一解决。

二、测试的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文件了。

三、如何读取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文件数据如何混流,以及写文件

将每个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文件的,所以此时我们需要将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 获取网盘提取码。

 

你可能感兴趣的:(WebRTC技术详解)