[英]How to Save Playing Audio to WAV Format in Java
我正在使用Waywardgeek开发的Sonic Algorithm,以加快和减慢音频文件的速度。 一切正常。 但是我需要的是我需要将播放音频保存到wav
文件。 我尝试使用ByteArrayInputStream
和TargetDataLink
保存。 但是我做不到。 所以有人可以帮助我将播放音频保存到wav
文件吗? 而且,我还是Java Audio的新手。
这是代码,
Main.java
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Main {
private static void runSonic(
AudioInputStream audioStream,
SourceDataLine line,
float speed,
float pitch,
float rate,
float volume,
boolean emulateChordPitch,
int quality,
int sampleRate,
int numChannels) throws IOException {
Sonic sonic = new Sonic(sampleRate, numChannels);
int bufferSize = line.getBufferSize();
byte inBuffer[] = new byte[bufferSize];
byte outBuffer[] = new byte[bufferSize];
int numRead, numWritten;
sonic.setSpeed(speed);
sonic.setPitch(pitch);
sonic.setRate(rate);
sonic.setVolume(volume);
sonic.setChordPitch(emulateChordPitch);
sonic.setQuality(quality);
do {
numRead = audioStream.read(inBuffer, 0, bufferSize);
if (numRead <= 0) {
sonic.flushStream();
} else {
sonic.writeBytesToStream(inBuffer, numRead);
}
do {
numWritten = sonic.readBytesFromStream(outBuffer, bufferSize);
if (numWritten > 0) {
line.write(outBuffer, 0, numWritten);
}
} while (numWritten > 0);
} while (numRead > 0);
}
public static void main(String[] argv) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
float speed = 1.0f;
float pitch = 1.0f;
float rate = 1.5f;
float volume = 1.0f;
boolean emulateChordPitch = false;
int quality = 0;
AudioInputStream stream = AudioSystem.getAudioInputStream(new File("C:\\audio1.wav"));
AudioFormat format = stream.getFormat();
int sampleRate = (int) format.getSampleRate();
int numChannels = format.getChannels();
SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format,
((int) stream.getFrameLength() * format.getFrameSize()));
SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
line.open(stream.getFormat());
line.start();
runSonic(stream, line, speed, pitch, rate, volume, emulateChordPitch, quality,
sampleRate, numChannels);
line.drain();
line.stop();
}
}
我尝试使用以下代码,将其保存到wav
文件,但播放时具有一字音频。 而且对于TargetDataLink
,什么都TargetDataLink
。
byteArrayOutputStream = new ByteArrayInputStream(outBuffer);
audioStreams = new AudioInputStream(byteArrayOutputStream, line.getFormat(), bufferSize);
AudioSystem.write(audioStreams, AudioFileFormat.Type.WAVE, new File("C:\\audio2.wav"));
Sonic.java
由于允许的字符数有限,因此无法在此处发布完整代码。 代码在这里 。
我已经尝试过,现在我想出了一个使用ByteArrayInputStream
和ByteArrayOutputStream
的解决方案。 首先,我使用ByteArrayOutputStream
和SourceDataLine
line.write()
一样写outBuffer
。 然后将其转换为byteArray
并使用AudioInputStream
保存。 java2s
本教程帮助我做到了这一点。 它正在工作,但我不知道这是否是最佳解决方案。 因此,欢迎提出任何建议。 谢谢。
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Main {
private static void runSonic(
AudioInputStream audioStream,
SourceDataLine line,
float speed,
float pitch,
float rate,
float volume,
boolean emulateChordPitch,
int quality,
int sampleRate,
int numChannels) throws IOException {
Sonic sonic = new Sonic(sampleRate, numChannels);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int bufferSize = line.getBufferSize();
byte inBuffer[] = new byte[bufferSize];
byte outBuffer[] = new byte[bufferSize];
int numRead, numWritten;
sonic.setSpeed(speed);
sonic.setPitch(pitch);
sonic.setRate(rate);
sonic.setVolume(volume);
sonic.setChordPitch(emulateChordPitch);
sonic.setQuality(quality);
do {
numRead = audioStream.read(inBuffer, 0, bufferSize);
if (numRead <= 0) {
sonic.flushStream();
} else {
sonic.writeBytesToStream(inBuffer, numRead);
}
do {
numWritten = sonic.readBytesFromStream(outBuffer, bufferSize);
if (numWritten > 0) {
line.write(outBuffer, 0, numWritten);
byteArrayOutputStream.write(outBuffer, 0, numWritten);
}
} while (numWritten > 0);
} while (numRead > 0);
byte audioBytes[] = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(audioBytes);
AudioFormat format = line.getFormat();
AudioInputStream audioInputStream = new AudioInputStream(byteArrayInputStream, format, audioBytes.length / format.getFrameSize());
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, new File("C:\\audio2.wav"));
}
public static void main(String[] argv) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
float speed = 1.0f;
float pitch = 1.0f;
float rate = 1.5f;
float volume = 1.0f;
boolean emulateChordPitch = false;
int quality = 0;
AudioInputStream stream = AudioSystem.getAudioInputStream(new File("C:\\audio1.wav"));
AudioFormat format = stream.getFormat();
int sampleRate = (int) format.getSampleRate();
int numChannels = format.getChannels();
SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format,
((int) stream.getFrameLength() * format.getFrameSize()));
SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
line.open(stream.getFormat());
line.start();
runSonic(stream, line, speed, pitch, rate, volume, emulateChordPitch, quality,
sampleRate, numChannels);
line.drain();
line.stop();
}
}
我很确定在过去的问题中都涵盖了两个问题,即如何更改播放速率以及如何保存波形。 例如Java-调整WAV文件的播放速度。请参见线性插值的答案。 这并不难实现。 如果仅希望将速度提高一倍,则选择的答案很好,但是插值算法允许指定许多其他速度。
至于保存为wav,我建议从Oracle Sound教程开始。 https://docs.oracle.com/javase/tutorial/sound/converters.html
就将其作为流而不是将完整的文件保存在内存中而言,这需要一些管理,但这是一个非常常见的任务,应该放在任何程序员的手腕上。 在输入和处理数据时,将其保存到输出缓冲区阵列,并在输出缓冲区上跟踪进度。 仅在此缓冲区就绪时才写入输出流。
步骤概述:读取字节,转换为PCM,进行音高转换,如果准备好输出完整的缓冲区:将PCM转换回字节,写入字节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.