Файлы MP3 искажаются в процессе чтения - PullRequest
0 голосов
/ 12 мая 2019

В настоящее время я работаю над приложением, которое воспроизводит звук. Я реализовал воспроизведение для стандартного 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-данных.

1 Ответ

0 голосов
/ 15 мая 2019

Как оказалось, AudioFormat из mp3 (входной) и AudioFormat выходного не совпадали, что, очевидно, приводило к искажению. Таким образом, с подобранным воспроизведением все в порядке!

...