【问题标题】:How to convert a .WAV audio data sample into an double type?如何将 .WAV 音频数据样本转换为双精度类型?
【发布时间】:2010-10-31 18:24:03
【问题描述】:

我正在开发一个处理音频数据的应用程序。 我正在使用 java(我添加了 MP3SPI、Jlayer 和 Tritonus)。我将音频数据从 .wav 文件提取到字节数组。我正在使用的音频数据样本是 16 位立体声。

根据我读到的一个样本的格式是:

AABBCCDD

其中 AABB 表示左通道和 CCDD 右通道(每个通道 2 个字节)。 我需要将此示例转换为双值类型。我已经阅读了有关数据格式的信息。 Java 使用大端,.wav 文件使用小端。我有点困惑。你能帮我完成转换过程吗? 谢谢大家

【问题讨论】:

    标签: java audio signal-processing wav sampling


    【解决方案1】:

    Little Endian 表示数据的格式为 BBAA 和 DDCC。您只需交换它即可。

    从帧的开头:

    int left = (bytes[i+1] << 8) + bytes[i];
    int right = (bytes[i+3] << 8) + bytes[i+2];
    

    其中 i 是您的样本索引。

    【讨论】:

    • 我个人会在轮班周围加上括号 - 我似乎记得优先级可能有点奇怪......
    • 这缺少对低位的适当屏蔽。
    【解决方案2】:

    警告:整数和字节是有符号的。也许你需要在打包时屏蔽低字节:

    for (int i =0; i < length; i += 4) {
        double left = (double)((bytes [i] & 0xff) | (bytes[i + 1] << 8));
        double right = (double)((bytes [i + 2] & 0xff) | (bytes[i + 3] << 8));
    
        ... your code here ...
    
    }
    

    【讨论】:

    • 好点,但是您需要在所有 byte[] 访问中执行此操作(除非它们被左移 24 位或更多位)。它们被提升为整数,因此 0x80 变为 0xffffff80
    • 这正是我想要的,保留高字节的符号。实际上,我没有测试它(而且我不知道它是否有效,尤其是浮点值),但是一个有符号的 16 位值在提升到 32 位或更多位时应该不会丢失它的符号。跨度>
    • 您好,感谢您的回答。 @埃里克森;我真的不明白你的评论。 @GB;通过这样做,我得到了左通道中每个样本的值,而右通道中的每个样本的值。所以,最后我将为每个样本有 2 个值,不是吗?是否可以为每个样本只获取一个值?
    • @dedalo:这取决于你想用这些样本做什么。如果您想要一个 32 位值,则需要屏蔽和移位所有 4 字节值。或者你想对它们进行平均吗?
    • @GB:我要做的是计算不同音频文件的梅尔系数(MFCC)。这些系数用于语音识别。为了计算系数,第一步是从音频文件中获取样本,应用汉明窗并计算 FFT。
    【解决方案3】:

    我个人会寻找一个为您进行字节序交换的库。每种音频文件格式都对您的字节顺序进行了假设,并且对于所有位深度/数据类型的波形文件支持来说,正确地做到这一点是很棘手的:

    • 8bit - uint8
    • 16bit - int16
    • 24 位 - int32
    • 32bit - int32 作为浮点数
    • 32 位 - 浮动
    • 64 位 - 双

    如果您想支持最常见的波形文件类型,则需要对所有这些数据类型进行字节序转换。

    我会查看ByteSwapper,它会为您提供上面列出的大多数类型的字节交换。

    Java 的 File IO 类中没有字节序字段,这太糟糕了。能够简单地打开一个 edianness 大小的文件是解决这个问题的一个更容易的解决方案。

    【讨论】:

      【解决方案4】:

      当你使用ByteBuffer(java.nio.ByteBuffer)时可以使用方法顺序;

      [顺序]

      public final ByteBuffer order(ByteOrder bo)

      Modifies this buffer's byte order.
      
      Parameters:
          bo - The new byte order, either BIG_ENDIAN or LITTLE_ENDIAN
      Returns:
          This buffer
      

      在这之后你可以得到上面提到的值;

      getChar() 得到短() 获取整数() 获取浮动() getDouble()

      Java 是多么伟大的语言 ;-)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多