我对所做的事情有点困惑。
据我所知,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
,这是大端字节。我再次打开audacity,并使用相同的配置,听到了提示音。
绝对我配置了小端!
我将文件复制到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();
}
}
}
13年4月16日下午2:16编辑:
我在阅读时以为我认为是失败,我在Wikipedia上发现了以下图片:
在下一篇文章中查看问题的答案。
最佳答案
好的,大家和关注此问题的每个人:
失败与尾数大或小无关。
我从LE和BE了解到的一切都是正确的。 (但不是关于读取访问权的最后假设,这在我寻找任何解释时让我大吃一惊。)
故障与信号幅度有关。
如果幅度太低-音量本身(通过幅度产生)太低。所以什么也听不见。将写入的big endian文件解释为little endian,会使文件中的每个短样本都变大(回到zch的注释:00 02在解释为little endian时为512)。
当时产生了更高的采样值,使我听到了声音。
通过通常设置较高的幅度并正确地将字节交换设置为Little Endian,我可以再次听到声音。因此,主要的失败与耐力无关。
zch的注释使我一遍又一遍地沉思,导致在Windows上读取了一些c++代码并读取了值,并看到本地LE解释与zch所说的相同。这导致我到达振幅点,现在我发现了问题。希望没有其他人会做这个愚蠢的失败,或者将来会找到这篇文章并知道:-)