В настоящее время я работаю над приложением, которое воспроизводит звук. Я реализовал воспроизведение для стандартного WAV-файла с Java Sound API, никаких проблем там нет, все работает нормально. Теперь я хочу добавить поддержку MP3, но у меня странная проблема: воспроизведение искажается. Я пытаюсь понять, что я делаю неправильно, я был бы признателен за любые выводы в правильном направлении.
Я использую Mp3SPI (http://www.javazoom.net/mp3spi/documents.html) для воспроизведения файлов Mp3.
Я уже пытался взглянуть на вывод и записал wav-файл с выводом, полученным из mp3, затем я сравнил формы сигнала оригинала и записанного файла. Оказывается, в записанном файле много сэмплов, которые равны 0 или очень близки к нему. Более длинные тоны прерываются, и форма сигнала все время возвращается к 0, а затем возвращается к тому месту, где форма сигнала находится в оригинале.
Я открываю файл так:
private AudioInputStream mp3;
private AudioInputStream rawMp3;
private void openMP3(File file) {
// open the Audio INput Stream
try {
rawMp3 = AudioSystem.getAudioInputStream(file);
AudioFormat baseFormat = rawMp3.getFormat();
AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
baseFormat.getSampleRate(),
16,
baseFormat.getChannels(),
baseFormat.getChannels() * 2,
baseFormat.getSampleRate(),
false);
mp3 = AudioSystem.getAudioInputStream(decodedFormat, rawMp3);
} catch (UnsupportedAudioFileException | IOException ex) {
Logger.getLogger(SoundFile.class.getName()).log(Level.SEVERE, null, ex);
}
}
Часть, где я читаю Mp3-файл:
byte[] data = new byte[length];
// read the data into the buffer
int nBytesRead = 0;
while (nBytesRead != - 1 && nBytesRead < length) {
nBytesRead = mp3.read(data, 0, data.length - nBytesRead);
}
Также я преобразую байтовый массив в удвоения, возможно, я здесь что-то не так делаю (я довольно новичок в использовании побитовых операторов, поэтому, возможно, есть проблема
double[][] frameBuffer = new double[2][1024]; // 2 channel stereo buffer
int nFramesRead = 0;
int byteIndex = 0;
// convert the data into double and write it to frameBuffer
for (int i = 0; i < length; ++i) {
for (int c = 0; c < 2; ++c) {
byte a = data[byteIndex++];
byte b = data[byteIndex++];
int val = a | b << 8; // a is the least significant byte. | functions as a + here. b << 8 moves 8 zeroes to the end of b.
frameBuffer[c][i] = (double) val / (double) Short.MAX_VALUE;
nFramesRead++;
}
}
Затем двойной массив используется для воспроизведения звука. При воспроизведении wav-файла я делаю то же самое с буфером, поэтому я почти уверен, что это должно быть что-то во время процесса чтения, а не я посылаю ошибочные байты на выход.
Я ожидаю, что это будет работать из коробки с Mp3SPI, но каким-то образом что-то ломает звук по пути.
Я также готов попробовать другие библиотеки для воспроизведения MP3, если у вас есть какие-либо рекомендации. Достаточно просто декодера для необработанных MP3-данных.