Issue with sharp attacks in the MP3 decoder


#1

Hi Jules,

 

I think there is a small bug the MP3AudioFormat decoder, it seems to change the attacks of sounds, making them less sharp. It's subtle but definitively audible. This does not happen when I use another mp3 to wav decoder (mpg321, ffmpeg, or juce's CoreAudioFormat). I'm attaching an example mp3 , the wav file produced by MP3AudioFormat and the wav file produced by mpg321 .

Here is the code that I'm using for decoding the mp3 to wav with juce:

 

#include "../JuceLibraryCode/JuceHeader.h"


#include <iostream>
#include <iomanip>

using namespace juce;

int main (int argc, char* argv[])
{
  AudioFormatManager mgr;
  //mgr.registerBasicFormats(); // will use CoreAudioFormat for mp3 decoding
  mgr.registerFormat(new WavAudioFormat, false);
  mgr.registerFormat(new MP3AudioFormat, false);

  if (argc < 2) {
    std::cout << "known audio formats: " << mgr.getWildcardForAllFormats() << "\n";
    return -1;
  }

  juce::File inputfile(File::getCurrentWorkingDirectory().getChildFile(argv[1]));
  ScopedPointer<AudioFormatReader> rd(mgr.createReaderFor(inputfile));

  std::cout << "sample rate: " << rd->sampleRate << "\n";
  std::cout << "channels: " << rd->numChannels << "\n";
  std::cout << "bit-depth: " << rd->bitsPerSample << "\n";
  std::cout << "duration: " << rd->lengthInSamples << "\n";
  std::cout << "use floats: " <<  rd->usesFloatingPointData << "\n";
  for (int i=0; i < rd->metadataValues.size(); ++i) {
    std::cout << "  * " << rd->metadataValues.getAllKeys()[i] << ": " << rd->metadataValues.getAllValues()[i] << "\n";
  }

  std::cout << "reading input file..." << std::endl;
  AudioSampleBuffer buff(rd->numChannels, rd->lengthInSamples);
  rd->read(&buff, 0, rd->lengthInSamples, 0, true, true);
  std::cout << "reading done" << std::endl;
  if (argc > 2) {
    juce::File outputfile(File::getCurrentWorkingDirectory().getChildFile(argv[2]));
    FileOutputStream *os = new FileOutputStream(outputfile);
    if (os->failedToOpen()) {
      std::cerr << "cannot write\n";
      return 1;
    }
    ScopedPointer<AudioFormatWriter> wr;
    if (outputfile.hasFileExtension("wav")) {
      std::cerr << "writing wav file.." << std::endl;
      WavAudioFormat fmt;
      wr = fmt.createWriterFor(os, rd->sampleRate, rd->numChannels, rd->bitsPerSample, StringPairArray(), 0);
    } else if (outputfile.hasFileExtension("aiff")) {
      AiffAudioFormat fmt;
      wr = fmt.createWriterFor(os, rd->sampleRate, rd->numChannels, rd->bitsPerSample, StringPairArray(), 0);
    } else if (outputfile.hasFileExtension("flac")) {
      FlacAudioFormat fmt;
      wr = fmt.createWriterFor(os, rd->sampleRate, rd->numChannels, rd->bitsPerSample, StringPairArray(), 0);
    }
    bool ok = wr->writeFromAudioSampleBuffer(buff, 0, rd->lengthInSamples);
    std::cout << "Write done, ok=" << ok << "\n";
  }
  rd = nullptr;

  return 0;
}

 

 

original mp3:

https://www.claudex.be//olcc/attach/20151013111803_original.mp3

file decoded by mpg321 or ffmpeg or CoreAudioFormat:

https://www.claudex.be//olcc/attach/20151013111915_ok.wav

file decoded by MP3AudioFormat:

https://www.claudex.be//olcc/attach/20151013111939_not-ok.wav

image of the difference:

https://www.claudex.be//olcc/attach/20151013112413_mp3-attack.gif

 

(btw attaching files or images is really difficult on the forum)


#2

Wow.. wouldn't even know where to begin debugging that! My code is based on the same algorithm as mpg123, so should behave the same..


#3

got it ! There is a

        const double piOver72 = double_Pi;

that should definitively be replaced by


        const double piOver72 = double_Pi/72.0;

#4

duplicate post..


#5

Wow, amazing catch! Thanks, will fix that right away!