我正在开发一个音频项目,我正在使用this audio library . 它有一个方法可以读取wav文件并返回一个值为-1到1的双精度数组(每秒44100个音频值) . 此库中的所有方法似乎都使用相同的双数组格式来保存音频 .
但是,该方法不起作用 . 这是一个wav file我喂它的样本,这里是程序读取该文件的recording(在听之前调低音量) .
它与原始文件的长度不同,并且会失真 . 这是该方法背后的代码(TL; DR在阅读之前阅读我的评论):
public static double[] read(String filename) {
byte[] data = readByte(filename);
int n = data.length;
double[] d = new double[n/2];
for (int i = 0; i < n/2; i++) {
d[i] = ((short) (((data[2*i+1] & 0xFF) << 8) + (data[2*i] & 0xFF))) / ((double) Short.MAX_VALUE);
}
return d;
}
// return data as a byte array
private static byte[] readByte(String filename) {
byte[] data = null;
AudioInputStream ais = null;
try {
// try to read from file
File file = new File(filename);
if (file.exists()) {
ais = AudioSystem.getAudioInputStream(file);
int bytesToRead = ais.available();
data = new byte[bytesToRead];
int bytesRead = ais.read(data);
if (bytesToRead != bytesRead)
throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes");
}
// try to read from URL
else {
URL url = StdAudio.class.getResource(filename);
ais = AudioSystem.getAudioInputStream(url);
int bytesToRead = ais.available();
data = new byte[bytesToRead];
int bytesRead = ais.read(data);
if (bytesToRead != bytesRead)
throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes");
}
}
catch (IOException e) {
throw new IllegalArgumentException("could not read '" + filename + "'", e);
}
catch (UnsupportedAudioFileException e) {
throw new IllegalArgumentException("unsupported audio format: '" + filename + "'", e);
}
return data;
}
我测试了readByte()方法返回的字节数组的长度(read()方法使用的),它是49016个位置 . 原始剪辑为4秒,采样率为44100,阵列应为44100 * 4左右 . 失真的音频有点超过第二个持续时间,与失真的wav文件的长度相匹配,所以我认为问题出在readByte()方法中 . 我可能是错的(有人让我知道,如果是这样),但由于这一点,我认为问题出在这个代码中 . 这里消除异常处理程序是代码(返回一个字节数组):
byte[] data = null;
AudioInputStream ais = null;
try {
// try to read from file
File file = new File(filename);
if (file.exists()) {
ais = AudioSystem.getAudioInputStream(file);
int bytesToRead = ais.available();
data = new byte[bytesToRead];
int bytesRead = ais.read(data);
if (bytesToRead != bytesRead)
throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes");
}
// try to read from URL
else {
URL url = StdAudio.class.getResource(filename);
ais = AudioSystem.getAudioInputStream(url);
int bytesToRead = ais.available();
data = new byte[bytesToRead];
int bytesRead = ais.read(data);
if (bytesToRead != bytesRead)
throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes");
}
}
...
return data;
为什么这个字节数组的数据失真?
编辑:我尝试将我尝试播放的wav文件转换为大约一半的采样率,它似乎正常播放(仍有点偏离) . Here是由此产生的录音 . 任何想法如何更改代码,以使其读取44100采样率文件? "getAudioInputStream"方法的采样率是否低于44100?这个库说它"Assumes the audio is monaural, with sampling rate of 44,100"所以这看起来像个bug .