【问题标题】:Convert PCM Byte Array To Surround Channels将 PCM 字节数组转换为环绕声通道
【发布时间】:2011-08-01 14:04:21
【问题描述】:

据我了解,我使用的音频字节数组(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;
    }

【问题讨论】:

    标签: java arrays audio byte surround


    【解决方案1】:

    我不是 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)中。您最好将字节数组转换为 shortint 的数组 - 或使用不同的编程语言,例如 C++。

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

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

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

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

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

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

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

    【讨论】:

    • 如果您有 NetBeans 的副本,我有我所指的程序的代码。 sourceforge.net/projects/loopmaker/files/Development/… 在 Editor.java 中,在第 847 行和第 1205 行调用了 Surround 程序,程序本身在 1309 处。这是我正在编写的循环音频程序,它必须能够放置前置扬声器的 wav后置扬声器的方向。由于 4 字节/样本,它可能是(类似信号的)3D 问题,而不是(类似通道的)8 字节/样本问题。
    猜你喜欢
    • 2016-04-11
    • 2015-08-24
    • 2021-11-20
    • 2014-08-08
    • 2019-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多