关于两路PCM音频流混音问题

大王叫我来巡山 发布于 2016/09/29 19:00
阅读 2K+
收藏 0

大家好,我有两路PCM音频流数据,我想把他们混音起来。


采样率是:32000, 样本数量是:320, 每个样本的字节数:PCM(16位)含两个字节,频道数量:1


我现在用直接保存单路PCM文件是没问题的,每秒的数据长度则是 320 * 2 * 1

但是两路数据混音的话,目前还没头绪。

加载中
0
中山野鬼
中山野鬼
转频域能量加起来,可能为了防溢出要归一化或者截取,然后在转成pcm.哈。
大王叫我来巡山
大王叫我来巡山
我现在的数据就是PCM裸流,不需要再转PCM
大王叫我来巡山
大王叫我来巡山
转频域能量加起来? 哥,我表示听不懂啊。
0
大王叫我来巡山
大王叫我来巡山
#define CHECK_MAX_VALUE(value) ((value > 32767) ? 32767 : value)
#define CHECK_MIN_VALUE(value) ((value < -32767) ? -32767 : value)

#define PCM_MAX_SIZE (8192*2)


int MixAudio(int iChannelNum, short* sourceData1, short* sourceData2, 
float fBackgroundGain, float fWordsGain, short *outputData) {
    int const MAX = 32767;
    int const MIN = -32767;
    
    double f = 1.0;
    
    if (iChannelNum <= 0) {
        return -1;
    }
    
    if (iChannelNum > 2) {
        return -2;
    }
    
    if (iChannelNum == 2) {
        float fLeftValue1 = 0;
        float fRightValue1 = 0;
        float fLeftValue2 = 0;
        float fRightValue2 = 0;
        float fLeftValue = 0;
        float fRightValue = 0;
        int output = 0;
        int iIndex = 0;
        
        fLeftValue1 = (float)(sourceData1[0]);
        fRightValue1 = (float)(sourceData1[1]);
        fLeftValue2 = (float)(sourceData2[0]);
        fRightValue2 = (float)(sourceData2[1]);
        fLeftValue1 = fLeftValue1*fBackgroundGain;
        fRightValue1 = fRightValue1*fBackgroundGain;
        fLeftValue2 = fLeftValue2*fWordsGain;
        fRightValue2 = fRightValue2*fWordsGain;
        fLeftValue1 = CHECK_MAX_VALUE(fLeftValue1);
        fLeftValue1 = CHECK_MIN_VALUE(fLeftValue1);
        fRightValue1 = CHECK_MAX_VALUE(fRightValue1);
        fRightValue1 = CHECK_MIN_VALUE(fRightValue1);
        fLeftValue2 = CHECK_MAX_VALUE(fLeftValue2);
        fLeftValue2 = CHECK_MIN_VALUE(fLeftValue2);
        fRightValue2 = CHECK_MAX_VALUE(fRightValue2);
        fRightValue2 = CHECK_MIN_VALUE(fRightValue2);
        fLeftValue = fLeftValue1 + fLeftValue2;
        fRightValue = fRightValue1 + fRightValue2;

        for (iIndex = 0; iIndex < 2; iIndex++) {

            if (iIndex == 0) {
                output = (int)(fLeftValue*f);
            }
            else {
                output = (int)(fRightValue*f);
            }
            if (output>MAX)
            {
                f = (double)MAX / (double)(output);
                output = MAX;
            }
            if (output<MIN)
            {
                f = (double)MIN / (double)(output);
                output = MIN;
            }
            if (f<1)
            {
                f += ((double)1 - f) / (double)32;
            }
            outputData[iIndex] = (short)output;
        }
    }
    else {
        float fValue1 = 0;
        float fValue2 = 0;
        float fValue = 0;
        
        fValue1 = (float)(*(short*)(sourceData1));
        fValue2 = (float)(*(short*)(sourceData2));
        fValue1 = fValue1*fBackgroundGain;
        fValue2 = fValue2*fWordsGain;
        fValue = fValue1 + fValue2;
        
        fValue = CHECK_MAX_VALUE(fValue);
        fValue = CHECK_MIN_VALUE(fValue);
        *outputData = (short)fValue;
    }
    return 1;
}



我找到这么一个算法,但是不清楚这两个参数应该传什么进去

float fBackgroundGain, float fWordsGain

大王叫我来巡山
大王叫我来巡山
好的,感谢兄弟,我试试
k
kchr
fBackgroundGain 背景增益,fWordsGain 这个是主声音的增益似乎没有专门的名称。 你可以取 fBackgroundGain = 0.1,fWordsGain = 0.9, 0.2 / 0.8, 0.3 / 0.7,0.5/0.5 这样的组合来尝试一下效果就知道了。
0
k
kchr

PCM 合成和频域有个毛的关系,不要听野鬼不懂装懂误导你。

其实 PCM 这个东西很简单。

i 遍历 PCM 数据。
合成的结果 = a x PCM1[i] + b x PCM2[i]

其中 a + b = 1,a 和 b 分别是音频的权重,具体取值要看你的需求。如果这 2 路音频
是同等重要的,那就 a = 0.5, b = 0.5

在你的范例里,可能 a 是背景音,比如风声,海浪声,b 是比如歌声,那么可能
a = 0.1, b = 0.9,突出歌声,同时稍微加一点风声

再就是这算法太低效了,应该好好用矢量指令和多线程优化。

0
中山野鬼
中山野鬼

引用来自“kchr”的评论

PCM 合成和频域有个毛的关系,不要听野鬼不懂装懂误导你。

其实 PCM 这个东西很简单。

i 遍历 PCM 数据。
合成的结果 = a x PCM1[i] + b x PCM2[i]

其中 a + b = 1,a 和 b 分别是音频的权重,具体取值要看你的需求。如果这 2 路音频
是同等重要的,那就 a = 0.5, b = 0.5

在你的范例里,可能 a 是背景音,比如风声,海浪声,b 是比如歌声,那么可能
a = 0.1, b = 0.9,突出歌声,同时稍微加一点风声

再就是这算法太低效了,应该好好用矢量指令和多线程优化。

哈,我是否不懂装懂不重要。我问个问题,人耳究竟对音频有反应,还是对时域上的某个点能量有反映呢?

或者在扩展的绕一点的讨论这个问题。咱们要从一段声音中提取某个特定声音,无论你说语音识别还是背景去噪吧,是在频域方便还是时域方便? 这个有点绕的问题是指,反过来,当我们两个声音合并时,希望两个声音都能较好的分辨,在能量溢出时,他们是在频域上按某种比例方式调整好呢,还是在时域上按某种比例方式调整好呢? 

00年我基于一个dsp,用汇编折腾ac3,就是杜比环绕立体声那玩意, 后面做模式识别,对语音这块不是研究点,但多少看过点东西。当然可能这10年有新技术,全当我不懂,不过还请回答一下我上面的一些基础问题。哈。

pcm这么简单的混混,出来是效果真心好吗?

0
不在乎y
不在乎y
之前正好做过音视频录制的,当时就直接相加的。。。效果还行
0
大王叫我来巡山
大王叫我来巡山
感谢大家的支持,混音最后用归一法混的效果还不错,现在遇到一个新问题,如何把PCM编码成aac。谢谢大家
返回顶部
顶部