Я пытаюсь использовать Java Sound (с MP3SPI и VorbisSPI) для чтения аудиоданных из файлов WAV, MP3 и OGG, хранения их в байтовый массив, в чтобы играть его позже оттуда. Для того, чтобы сделать это, я использую такой код:Как буферизовать и воспроизводить звуковые данные из файлов OGG с помощью Java Sound
public Sound loadSound(File file){
AudioInputStream baseStream = AudioSystem.getAudioInputStream(file);
AudioFormat baseFormat = baseStream.getFormat();
AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(),
16,
baseFormat.getChannels(),
baseFormat.getChannels() * 2,
baseFormat.getSampleRate(),
false);
AudioInputStream decodedStream = AudioSystem.getAudioInputStream(decodedFormat, baseStream);
// Buffer audio data from audio stream
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int nBytesRead = 0;
while (nBytesRead != -1) {
nBytesRead = decodedStream.read(buffer, 0, buffer.length);
// Write read bytes to out stream
byteOut.write(buffer);
}
// close streams and cleanup
byte[] samples = byteOut.toByteArray();
return new Sound(samples,decodedFormat);
}
Звук класса в основном (байт [] образцы, формат AudioFormat) пара. Готово, я стараюсь читать и играть в байтовый массив следующим образом:
public void play(Sound sound) {
InputStream source = new ByteArrayInputStream(sound.getSamples());
AudioFormat format = sound.getFormat();
// use a short, 100ms (1/10th sec) buffer for real-time changes to the sound stream
int bufferSize = format.getFrameSize()
* Math.round(format.getSampleRate()/10);
byte[] buffer = new byte[bufferSize];
// create a line to play to
SourceDataLine line;
try {
DataLine.Info info
= new DataLine.Info(SourceDataLine.class, format);
line = (SourceDataLine) AudioSystem.getLine(info);
line.open(format, bufferSize);
} catch (LineUnavailableException ex) {
ex.printStackTrace();
return;
}
// start the line
line.start();
// copy data to the line
try {
int numBytesRead = 0;
while (numBytesRead != -1) {
numBytesRead
= source.read(buffer, 0, buffer.length);
if (numBytesRead != -1) {
line.write(buffer, 0, numBytesRead);
}
}
} catch (IOException ex) {
ex.printStackTrace();
} catch (ArrayIndexOutOfBoundsException ex2) {
}
// wait until all data is played, then close the line
line.drain();
line.close();
}
Это все работает отлично WAV и MP3, но воспроизведение OGG искажается и несколько замедлились, так как если формат был неправ. Мне бы хотелось, чтобы кто-то мог указать, почему это происходит.
Примечание: Я как бы решил проблему, загрузив весь аудиофайл в виде байтового массива с помощью FileInputStream, а затем воспроизведя его с помощью AudioInputStream над ByteArrayInputStream на массиве. Тем не менее, массив байтов содержит кодированные данные вместо декодированного: на практике это не имеет большого значения для меня, но я не знаю, почему предыдущий подход не работал для OGG. Спасибо всем, кто попытается ответить.
Возможно, это не связано, но вы должны использовать 'nBytesRead' в вызове' byteOut.write'. Возможно, что чтение вернет менее 4096 байт, и в этом случае вы будете писать мусор в поток вывода. Это почти гарантировано произойдет в последнем буфере. – jaket
Это похоже на трюк! Спасибо @jaket :) – EPresident
Прохладный, я напишу это как ответ, который вы можете принять. – jaket