混合音频通道

4
我正在实现一个音频通道混合器,并使用 Viktor T. Toth's algorithm。尝试混合两个音频通道流。
在代码中,quantization_是通道位深度的字节表示。我的mix函数接受指向目标和源uint8_t缓冲区的指针,将两个通道混合并写入目标缓冲区。因为我正在使用uint8_t缓冲区中的数据,所以需要进行加法、除法和乘法运算来获取实际的8、16或24位样本,并再次将它们转换为8位。
一般来说,它会给出预期的输出样本值。然而,当我在 Audacity中查看输出时,有些样本的值接近于0,这不应该是这样的。在截图中,底部的两个信号是两个单声道,顶部的信号是混合后的信号。可以看到,特别是在中间,有一些非常低的值。

Mixed Channels

以下是我的 mix 函数;
void audio_mixer::mix(uint8_t* dest, const uint8_t* source)
{
    uint64_t mixed_sample = 0;
    uint64_t dest_sample = 0;
    uint64_t source_sample = 0;
    uint64_t factor = 0;

    for (int i = 0; i < channel_size_; ++i)
    {
        dest_sample = 0;
        source_sample = 0;
        factor = 1;

        for (int j = 0; j < quantization_; ++j)
        {
            dest_sample += factor * static_cast<uint64_t>(*dest++);
            source_sample += factor * static_cast<uint64_t>(*source++);
            factor = factor * 256;
        }

        mixed_sample = (dest_sample + source_sample) - (dest_sample * source_sample / factor);

        dest -= quantization_;

        for (int k = 0; k < quantization_; ++k)
        {
            *dest++ = static_cast<uint8_t>(mixed_sample % 256);
            mixed_sample = mixed_sample / 256;
        }
    }
}
1个回答

3
似乎你没有正确处理有符号的音频样本。你的音频信号应该从水平线开始为零电压。
如果你看正电压的音频样本,它们会正确地遵循你的公式(除了中心的峰值)。负值被压缩了,这让我感觉像它们被视为小的正电压而不是负电压。
换句话说,也许那些无符号整数应该是有符号整数,这样最高位就表示电压极性,你可以拥有范围在+127到-128之间的音频样本。
中心的那些峰值似乎在模255下包裹,这将是你的音频的无符号字节表示的峰值。我不确定这怎么会发生,但它似乎与有符号和无符号信号有关。
也许你应该尝试维克托在他的文档中提供的另一个公式:
Z = 2(A+B)-(AB / 128)-256

感谢您的帮助,看来我没有理解有符号数据和无符号数据之间的区别。如果我将数据视为有符号,我相信我将获得正确的输出。等我完全明白了这一点并纠正了我的错误时,我会回来的。 - xeco
是的,它起作用了!现在,我能够混合具有8、16、24位深度的通道。 - xeco
问题与有符号和无符号的混淆有关。 - xeco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接