3

据我了解,我使用的音频字节数组(PCM 立体声 16 位)是每个样本 4 个字节。我注意到,当您反转字节值(即-128 到 128 和 128 到 -128)时,它不会将声音放入环绕声道。听起来一样(前置音频)。我尝试反转每隔一个字节(每 2 个字节)而不是所有字节,并得到类似环绕声的东西,但它非常脏且不稳定。我究竟如何操作常规 PCM 16 位立体声 WAV 文件(以字节数组形式),以便将音频放置在环绕声道中?

我的代码:

public byte[] putInSurround(byte[] audio) {
        for (int i = 0; i < audio.length; i += 4) {
            int i0 = audio[i + 0];
            int i1 = audio[i + 1];
            int i2 = audio[i + 2];
            int i3 = audio[i + 3];
            if (0 > audio[i + 0]) {
                i0 = Math.abs(audio[i + 0]);
            }
            if (0 < audio[i + 0]) {
                i0 = 0 - audio[i + 0];
            }
            if (0 > audio[i + 1]) {
                i1 = Math.abs(audio[i + 1]);
            }
            if (0 < audio[i + 1]) {
                i1 = 0 - audio[i + 1];
            }
            if (0 > audio[i + 2]) {
                i2 = Math.abs(audio[i + 2]);
            }
            if (0 < audio[i + 2]) {
                i2 = 0 - audio[i + 2];
            }
            if (0 > audio[i + 3]) {
                i3 = Math.abs(audio[i + 3]);
            }
            if (0 < audio[i + 3]) {
                i3 = 0 - audio[i + 3];
            }
            audio[i + 0] = (byte) i0;
            //audio[i + 1] = (byte) i1; <-- Commented Out For Every Other Byte.
            //audio[i + 2] = (byte) i2; <-- Commented Out For Every Other Byte.
            audio[i + 3] = (byte) i3;
        }
        return audio;
    }
4

1 回答 1

0

在任何方面,我都不是 DSP 方面的专家,但我有一些观察可能会有所帮助:

  • 您以 4 字节为增量解析数组,这正确对应于单个 16 位立体声样本2 channels * 16 bits = 32 bits = 4 bytes

    现在,我可能不明白您要做什么,但在现代环绕音频中,环绕声道通常是相互独立的。这意味着每个环绕音频样本需要超过 4 个字节。例如,如果您有 5 个通道,则需要 10 个字节/样本,这可能意味着您需要在代码中使用单独的输入和输出数组。

    有诸如Dolby SurroundDolby Pro Logic之类的方法,其中环绕声道被矩阵编码到两个立体声声道中,但是所涉及的 DSP 数学比您的代码中的复杂得多。更不用说对特殊解码器的需求以及此类方法所隐含的质量损失。

  • 反转2 字节样本的每个字节是没有意义的:样本值 1000d 将变为 -744d。像这样的按位运算在 DSP 中很少使用,如果有的话。

  • 通常音频样本存储为带符号的 2 的补码二进制数。这使得按字节处理它们非常复杂,尤其是在没有无符号数和没有指针转换的语言(如 Java)中。您最好将字节数组转换为shortor数组int- 或使用不同的编程语言,例如 C++。

  • 反转 -128 会产生 +128,它不能存储在 Java 使用的有符号字节中。

  • i + 0当“相互反转字节”时,您存储and的倒数i + 3,而不是i + 0and i + 2or i + 1and i + 3

  • 相互反转字节的结果虽然仍然没有任何意义,但具有不同的效果,具体取决于您的音频表示是little-endian 还是 big-endianRIFF WAV 文件使用 little-endian 字节顺序。

    反转字节 0 和 2 会更改样本的 LSB,这只会在音频剪辑的动态范围有限时添加高幅度噪声和彻底失真。

    反转字节 1 和 3 将近似以高幅度反转整个样本,并在动态范围有限的剪辑中添加大量失真。

  • 反转整个样本,而不是单个字节,是180 度相移的近似值。我不确定你可以在哪里使用它,虽然......

如果您需要比这更多的帮助,您需要告诉我们您到底想做什么。您至少应该提及您的预期输出以及您使用的 DSP 算法。

于 2011-04-09T10:10:47.023 回答