Issue with sharp attacks in the MP3 decoder

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)

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..

got it ! There is a

        const double piOver72 = double_Pi;

that should definitively be replaced by


        const double piOver72 = double_Pi/72.0;

duplicate post..

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