在 Java 中将 double[] 写入 WAV 文件
writing double[] as WAV file in Java
我正在尝试使用此方法将 double[] 数组保存为 .WAV 文件:
public static void saveWav(String filename, double[] samples) {
// assumes 44,100 samples per second
// use 16-bit audio, 2 channels, signed PCM, little Endian
AudioFormat format = new AudioFormat(SAMPLE_RATE * 2, 16, 1, true, false);
byte[] data = new byte[2 * samples.length];
for (int i = 0; i < samples.length; i++) {
int temp = (short) (samples[i] * MAX_16_BIT);
data[2*i + 0] = (byte) temp;
data[2*i + 1] = (byte) (temp >> 8);
}
// now save the file
try {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
AudioInputStream ais = new AudioInputStream(bais, format, samples.length);
if (filename.endsWith(".wav") || filename.endsWith(".WAV")) {
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File(filename));
}
else if (filename.endsWith(".au") || filename.endsWith(".AU")) {
AudioSystem.write(ais, AudioFileFormat.Type.AU, new File(filename));
}
else {
throw new RuntimeException("File format not supported: " + filename);
}
}
catch (IOException e) {
System.out.println(e);
System.exit(1);
}
}
但是当我重新加载我保存的文件时,对于每首歌曲[i],double 值都与原始值不同。我用这个方法读取WAV文件:
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) MAX_16_BIT);
}
return d;
}
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);
data = new byte[ais.available()];
ais.read(data);
}
// try to read from URL
else {
URL url = StdAudio.class.getResource(filename);
ais = AudioSystem.getAudioInputStream(url);
data = new byte[ais.available()];
ais.read(data);
}
}
catch (IOException e) {
System.out.println(e.getMessage());
throw new RuntimeException("Could not read " + filename);
}
catch (UnsupportedAudioFileException e) {
System.out.println(e.getMessage());
throw new RuntimeException(filename + " in unsupported audio format");
}
return data;
}
我需要两个 double[] 数组具有完全相同的值,但事实并非如此。
当我听到歌曲播放时,我无法分辨出区别,但我仍然需要那些原始值。
感谢任何帮助。
男人
double 需要 64 位存储并且具有很高的精度。您不能在往返过程中丢弃 48 位数据并期望得到完全相同的值。这类似于从高分辨率图像开始,将其转换为缩略图,然后期望您可以神奇地恢复原始高分辨率图像。在现实世界中,人耳无法区分两者。更高的分辨率 在计算和信号处理例程中很有用,可以减少计算错误的累积。也就是说,如果您想存储 64 位,则需要使用 .WAV 以外的东西。最接近的是 32 位。
我正在尝试使用此方法将 double[] 数组保存为 .WAV 文件:
public static void saveWav(String filename, double[] samples) {
// assumes 44,100 samples per second
// use 16-bit audio, 2 channels, signed PCM, little Endian
AudioFormat format = new AudioFormat(SAMPLE_RATE * 2, 16, 1, true, false);
byte[] data = new byte[2 * samples.length];
for (int i = 0; i < samples.length; i++) {
int temp = (short) (samples[i] * MAX_16_BIT);
data[2*i + 0] = (byte) temp;
data[2*i + 1] = (byte) (temp >> 8);
}
// now save the file
try {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
AudioInputStream ais = new AudioInputStream(bais, format, samples.length);
if (filename.endsWith(".wav") || filename.endsWith(".WAV")) {
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File(filename));
}
else if (filename.endsWith(".au") || filename.endsWith(".AU")) {
AudioSystem.write(ais, AudioFileFormat.Type.AU, new File(filename));
}
else {
throw new RuntimeException("File format not supported: " + filename);
}
}
catch (IOException e) {
System.out.println(e);
System.exit(1);
}
}
但是当我重新加载我保存的文件时,对于每首歌曲[i],double 值都与原始值不同。我用这个方法读取WAV文件:
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) MAX_16_BIT);
}
return d;
}
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);
data = new byte[ais.available()];
ais.read(data);
}
// try to read from URL
else {
URL url = StdAudio.class.getResource(filename);
ais = AudioSystem.getAudioInputStream(url);
data = new byte[ais.available()];
ais.read(data);
}
}
catch (IOException e) {
System.out.println(e.getMessage());
throw new RuntimeException("Could not read " + filename);
}
catch (UnsupportedAudioFileException e) {
System.out.println(e.getMessage());
throw new RuntimeException(filename + " in unsupported audio format");
}
return data;
}
我需要两个 double[] 数组具有完全相同的值,但事实并非如此。 当我听到歌曲播放时,我无法分辨出区别,但我仍然需要那些原始值。
感谢任何帮助。
男人
double 需要 64 位存储并且具有很高的精度。您不能在往返过程中丢弃 48 位数据并期望得到完全相同的值。这类似于从高分辨率图像开始,将其转换为缩略图,然后期望您可以神奇地恢复原始高分辨率图像。在现实世界中,人耳无法区分两者。更高的分辨率 在计算和信号处理例程中很有用,可以减少计算错误的累积。也就是说,如果您想存储 64 位,则需要使用 .WAV 以外的东西。最接近的是 32 位。