混合16比特线性PCM数据流,并避免削波/溢出(Mixing 16 bit linear PCM s

2019-07-31 03:33发布

我试图混合2 16位线性PCM音频流在一起,我似乎无法克服的噪音问题。 我认为他们从溢流混合样品在一起的时候到来。

我有以下功能...

short int mix_sample(short int sample1, short int sample2)
{
    return #mixing_algorithm#;
}

...这是我曾尝试为#mixing_algorithm#

sample1/2 + sample2/2
2*(sample1 + sample2) - 2*(sample1*sample2) - 65535
(sample1 + sample2) - sample1*sample2
(sample1 + sample2) - sample1*sample2 - 65535
(sample1 + sample2) - ((sample1*sample2) >> 0x10) // same as divide by 65535

他们中的一些已经产生比别人更好的结果,但即使是最好的结果,包含了相当多的噪音。

任何想法如何解决呢?

Answer 1:

这里有一个描述性的实现:

short int mix_sample(short int sample1, short int sample2) {
    const int32_t result(static_cast<int32_t>(sample1) + static_cast<int32_t>(sample2));
    typedef std::numeric_limits<short int> Range;
    if (Range::max() < result)
        return Range::max();
    else if (Range::min() > result)
        return Range::min();
    else
        return result;
}

混合,它只是添加和夹!

为了避免限幅缺陷,你将要使用的饱和或限幅。 理想情况下,你将有一个小int32_t与前瞻少量缓冲。 这将导致延迟。

不是限制随处较为常见,是在你的信号留下几个比特的价值的‘净空’。



Answer 2:

我已经找到了最好的解决办法是由维克多·托特给出 。 他提供了8位无符号PCM解决方案,并改变了16位有符号PCM将产生这样的:

int a = 111; // first sample (-32768..32767)
int b = 222; // second sample
int m; // mixed result will go here

// Make both samples unsigned (0..65535)
a += 32768;
b += 32768;

// Pick the equation
if ((a < 32768) || (b < 32768)) {
    // Viktor's first equation when both sources are "quiet"
    // (i.e. less than middle of the dynamic range)
    m = a * b / 32768;
} else {
    // Viktor's second equation when one or both sources are loud
    m = 2 * (a + b) - (a * b) / 32768 - 65536;
}

// Output is unsigned (0..65536) so convert back to signed (-32768..32767)
if (m == 65536) m = 65535;
m -= 32768;

使用这个算法意味着几乎不存在需要夹子输出作为它只有一个值短的是在范围内。 不同于直平均,一个源的音量即使当其它源是无声不降低。



Answer 3:

这里是我做了我最近合成的项目。

int* unfiltered = (int *)malloc(lengthOfLongPcmInShorts*4);
int i;
for(i = 0; i < lengthOfShortPcmInShorts; i++){
    unfiltered[i] = shortPcm[i] + longPcm[i];
}
for(; i < lengthOfLongPcmInShorts; i++){
     unfiltered[i] = longPcm[i];
}

int max = 0;
for(int i = 0; i < lengthOfLongPcmInShorts; i++){
   int val = unfiltered[i];
   if(abs(val) > max)
      max = val;
}

short int *newPcm = (short int *)malloc(lengthOfLongPcmInShorts*2);
for(int i = 0; i < lengthOfLongPcmInShorts; i++){
   newPcm[i] = (unfilted[i]/max) * MAX_SHRT;
}

我添加了所有的PCM数据转换成整数数组,所以我得到的所有数据过滤。

这样做,我看了整数数组中的绝对最大值后。

最后,我把整数数组,放入一个短整型阵列通过取每个元素由最大值除以然后通过max短整型值乘以。

这样,你得到“净空”的最低量来满足需要的数据。

你也许可以做到整数数组上的一些统计数据和集成一些剪裁,但是我需要什么净空的最低金额是对我不够好。



Answer 4:

我认为它们应该是功能映射[MIN_SHORT, MAX_SHORT] -> [MIN_SHORT, MAX_SHORT]和它们显然不能(除了第一个),所以溢出发生。

如果开卷的主张是行不通的,你也可以尝试:

((long int)(sample1) + sample2) / 2


Answer 5:

既然你在时域中的频率信息是在连续的采样之间的差值 ,当除以二你损坏该信息。 这就是为什么添加和剪裁效果更好。 裁剪当然会增加这可能是过滤掉非常高频率的噪音。



文章来源: Mixing 16 bit linear PCM streams and avoiding clipping/overflow