4

我对自己的所作所为有点困惑。据我所知,java,尤其是 DataOutputStream 以 Big endian 写入值。

我正在编写一个小信号发生器,并且必须以小端存储文件。到目前为止没问题,只需交换字节即可。

writeShort()也说“先写高字节”。

因此,例如十进制“2”通常会存储为:

00 02 (big endian)
02 00 (little endian) is what I need.

所以我交换字节:

public static short swap (short value)
{
        int b1 = value & 0xff;
        int b2 = (value >> 8) & 0xff;

        return (short) (b1 << 8 | b2 << 0);
}

并写出简短的:

dos.writeShort(swap(x[t]));

十六进制编辑器以应为的格式向我显示文件:02 00

当我现在尝试打开生成的音频文件时,我什么也听不见。(大胆的原始数据导入和采样率等设置都正确)。

我删除了字节交换,得到一个文件:00 02这是大端。

我再次打开大胆,以相同的配置,我听到了语气。确实我配置了小端!

我将文件复制到 Windows(我正在使用 Mac)并在 Cool Edit 2000 中打开文件,再次选择 16khz、16 位无符号 pcm 和小端(16 位 LSB、MSB)。又听到了语气,什么都选大端。

我的失败在哪里?有些事情让我感到困惑,因为这不应该像我描述的那样工作..

生成音调:

// x(t) = A*cos (2*pi * f * t + phi)
        // 
        if(null != dos) 
        {
            double sampPeriod = 1.0/16000;
            short x[] = new short[16000]; // 16k samples for 1 second
            for(int t=0; t < x.length; t++)
            {
                double time = t * sampPeriod;
                x[t] = (short) (amplitude * Math.sin(2.0*Math.PI*frequenz*time+phase));
            }

            for(int t=0; t < x.length; t++)
            {
                try {
                    dos.writeShort(x[t]);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

于 2013 年 2 月 4 日下午 2:16 编辑:我正在阅读,假设我的理解是失败,我在维基百科上找到了以下图片:

读取权限

在下一篇文章中查看问题的答案。

4

1 回答 1

2

好的,所有有兴趣的人都关注这个问题:

失败与小端或大端无关。我从 LE 和 BE 了解到的一切都是正确的。(但不是最后关于读取访问的假设,这在我寻找任何解释时欺骗了我的想法......)

失败是关于信号的幅度

如果幅度太低 - 音量本身(通过幅度产生)太低。所以什么也听不见。将写入的大端文件解释为小端使文件中的每个短样本都成为一个更大的样本(回到 zch 的评论:当解释为小端时,00 02 是 512)。

这在当时产生了更高的采样值并让我听到了一些东西。

通过将更高的幅度正确的字节交换设置为小端,我可以再次听到一个东西。所以主要的失败与字节序无关。

zch 的评论让我一次又一次地沉思,导致 windows 上的一些 c++ 代码读取值并看到原生 LE 解释与 zch 所说的相同。这将我带到幅度点,现在我发现了问题。希望没有其他人会犯这种愚蠢的失败,或者将来会找到这篇文章并知道:-)

于 2013-04-02T18:18:25.193 回答