Java-在X位置启动音频播放
编辑:我使用的是.wav文件 我正在尝试找出如何在某个位置启动音频(例如:10秒进入音频文件,而不是在开始时)。阅读源数据线的文档时,我认为这可以通过使用偏移量来实现:Java-在X位置启动音频播放,java,arrays,wav,javasound,Java,Arrays,Wav,Javasound,编辑:我使用的是.wav文件 我正在尝试找出如何在某个位置启动音频(例如:10秒进入音频文件,而不是在开始时)。阅读源数据线的文档时,我认为这可以通过使用偏移量来实现: line.write(字节[]b,整数偏移量,整数长度) 但每次我尝试0以外的任何值(我相信是默认值),我都会得到java.lang.IndexOutOfBoundsException,它可能还没有读取x字节位置,所以无法写入x字节位置?我不确定,留下来挠头 我想这是一个很常见的请求,但似乎在网上找不到任何与此相关的内容,只有暂
line.write(字节[]b,整数偏移量,整数长度)
但每次我尝试0以外的任何值(我相信是默认值),我都会得到java.lang.IndexOutOfBoundsException,它可能还没有读取x字节位置,所以无法写入x字节位置?我不确定,留下来挠头
我想这是一个很常见的请求,但似乎在网上找不到任何与此相关的内容,只有暂停和恢复音频。我可能没有正确地搜索
如果这很重要,以下是我目前如何制作音频:
AudioInputStream stream = AudioSystem.getAudioInputStream("...file...");
AudioFormat format = stream.getFormat();
SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class, format,((int)stream.getFrameLength()*format.getFrameSize()));
SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
int bufferSize = line.getBufferSize();
byte inBuffer[] = new byte[bufferSize];
byte outBuffer[] = new byte[bufferSize];
int numRead, numWritten;
do {
numRead = audioStream.read(inBuffer, 0, bufferSize);
if(numRead <= 0) {
myAudio.flushStream();
} else {
myAudio.writeBytesToStream(inBuffer, numRead);
}
do {
numWritten = myAudio.readBytesFromStream(outBuffer, bufferSize);
if(numWritten > 0) {
line.write(outBuffer, 0, numWritten);
}
} while(numWritten > 0);
} while(numRead > 0);
AudioInputStream=AudioSystem.getAudioInputStream(“…文件…”);
AudioFormat=stream.getFormat();
SourceDataLine.Info=newdataline.Info(SourceDataLine.class,format,((int)stream.getFrameLength()*format.getFrameSize());
SourceDataLine=(SourceDataLine)AudioSystem.getLine(info);
int bufferSize=line.getBufferSize();
字节inBuffer[]=新字节[bufferSize];
字节溢出器[]=新字节[bufferSize];
int numRead,numwrited;
做{
numRead=audioStream.read(inBuffer,0,bufferSize);
if(numRead 0){
行写入(突发,0,numwrited);
}
}而(numwrited>0);
}而(numRead>0);
您遇到的问题可能是由于您在调整偏移量时没有调整长度。如果数组的长度为10字节,并且开始从偏移量5(而不是0)读取10字节,则读取的字节数超过了其末尾
我建议首先跳过上使用的适当字节数,然后写入该行
AudioInputStream stream = AudioSystem.getAudioInputStream("...file...");
AudioFormat format = stream.getFormat();
// find out how many bytes you have to skip, this depends on bytes per frame (a.k.a. frameSize)
int secondsToSkip = 10;
long bytesToSkip = format.getFrameSize() * ((int)format.getFrameRate()) * secondsToSkip;
// now skip until the correct number of bytes have been skipped
int justSkipped = 0;
while (bytesToSkip > 0 && (justSkipped = stream.skip(bytesToSkip)) > 0) {
bytesToSkip -= justSkipped;
}
// then proceed with writing to your line like you have done before
[...]
请注意,这仅在音频文件未压缩时有效。如果您正在处理类似于.mp3
的内容,首先必须将流转换为(请参见)我创建了一个编译并运行的示例。您可以从任何时间点播放.wav文件。它应该也适用于mp3文件,但我还没有测试过。为此调用mp3ToWav()
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
public class PlayWavAtTimePoint {
public static void main(String[] args) throws Exception {
String fileName = args[0];
int secondsToSkip = (Integer.parseInt(args[1]));
PlayWavAtTimePoint program = new PlayWavAtTimePoint();
AudioInputStream is = program.getAudioInputStream(fileName);
program.skipFromBeginning(is, secondsToSkip);
program.playSound(is);
}
private static void skipFromBeginning(AudioInputStream audioStream, int secondsToSkip) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
AudioFormat format = audioStream.getFormat();
// find out how many bytes you have to skip, this depends on bytes per frame (a.k.a. frameSize)
long bytesToSkip = format.getFrameSize() * ((int)format.getFrameRate()) * secondsToSkip;
// now skip until the correct number of bytes have been skipped
long justSkipped = 0;
while (bytesToSkip > 0 && (justSkipped = audioStream.skip(bytesToSkip)) > 0) {
bytesToSkip -= justSkipped;
}
}
private static final int BUFFER_SIZE = 128000;
/**
* @param filename the name of the file that is going to be played
*/
public void playSound(String filename) throws IOException, UnsupportedAudioFileException, LineUnavailableException {
AudioInputStream audioStream = getAudioInputStream(filename);
playSound(audioStream);
}
private AudioInputStream getAudioInputStream(String filename) throws UnsupportedAudioFileException, IOException {
return AudioSystem.getAudioInputStream(new File(filename));
}
public void playSound(AudioInputStream audioStream) throws LineUnavailableException, IOException {
AudioFormat audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
SourceDataLine audioOutput = (SourceDataLine) AudioSystem.getLine(info);
audioOutput.open(audioFormat);
audioOutput.start();
//This seems to be reading the whole file into a buffer before playing ... not efficient.
//Why not stream it?
int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
nBytesRead = audioStream.read(abData, 0, abData.length);
if (nBytesRead >= 0) {
audioOutput.write(abData, 0, nBytesRead);
}
}
audioOutput.drain();
audioOutput.close();
}
/**
* Invoke this function to convert to a playable file.
*/
public static void mp3ToWav(File mp3Data) throws UnsupportedAudioFileException, IOException {
// open stream
AudioInputStream mp3Stream = AudioSystem.getAudioInputStream(mp3Data);
AudioFormat sourceFormat = mp3Stream.getFormat();
// create audio format object for the desired stream/audio format
// this is *not* the same as the file format (wav)
AudioFormat convertFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
sourceFormat.getSampleRate(), 16,
sourceFormat.getChannels(),
sourceFormat.getChannels() * 2,
sourceFormat.getSampleRate(),
false);
// create stream that delivers the desired format
AudioInputStream converted = AudioSystem.getAudioInputStream(convertFormat, mp3Stream);
// write stream into a file with file format wav
AudioSystem.write(converted, AudioFileFormat.Type.WAVE, new File("/tmp/out.wav"));
}
}
请指定文件格式。这是压缩音频文件(例如.mp3
)还是未压缩格式(例如.wav
)?编辑:我使用的是.wav文件,如果您先阅读整个文件会怎么样?:>我可能需要您解释,但如果您的意思是将整个文件加载到暂存区域,然后播放,我不确定这是否有效。基本上,我正在动态调整音频(速度和音量),因此每次更改时,我都需要使用新值读取音频文件并立即播放。如果我先读取整个文件,我想在等待读取时音频中会有间隙,不是吗?请发布编译的代码。什么是“myAudio”和“audioStream”。在您的示例中,这些都没有实例化。我想用你的代码跳到.wav文件中的某个时间点。