mackron / dr_libs

Audio decoding libraries for C/C++, each in a single source file.
Other
1.24k stars 205 forks source link

issue with dr_mp3 and 16khz decoding #187

Closed mrrostam closed 3 years ago

mrrostam commented 3 years ago

First, I'd like to thank you for this great project! I really appreciate your work.

using dr_mp3, I read an mp3 file with the following code:

#define DR_MP3_IMPLEMENTATION

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#include "dr_mp3.h"

#define PCM_LENGTH 128

int main() {
    int16_t pcm[PCM_LENGTH];

    drmp3 *mp3 = (drmp3 *) malloc(sizeof(drmp3));
    if (!mp3) {
        printf("Memory not allocated.\n");
        exit(0);
    }
    FILE *fptr = fopen("./pcm.dat", "w");
    if (fptr == NULL) {
        printf("Error!");
        exit(1);
    }

    if (!drmp3_init_file(mp3, "sample.mp3", NULL)) {
        printf("Error!");
        exit(1);
    }
    printf("sample rate = %d\n", mp3->sampleRate);
    printf("channels = %d\n", mp3->channels);

    for (int32_t i = 0; i < (drmp3_get_pcm_frame_count(mp3) / PCM_LENGTH); i++) {
        int sample = drmp3_read_pcm_frames_s16(mp3, PCM_LENGTH, pcm);
        for (int k = 0; k < sample; k++) {
            fprintf(fptr, "%d\n", pcm[k]);
        }
    }
    drmp3_uninit(mp3);
    fclose(fptr);
    return 0;
}

everything seemed fine till I analyzed the output pcm in audacity and compared it to the original audio signal:

image

as you can see, the decoded one has a lot of noise. I wonder if I am doing it wrong or there are some tuning parameters that deal with this kind of situations.

Thanks again,

lieff commented 3 years ago

Can you compare with lame, mpg123 or ffmpeg decoders? It can be just loss from encoder you are using.

mrrostam commented 3 years ago

The output of ffmpeg and mpg123 look fine. I didn't find the same phenomenon there.

mrrostam commented 3 years ago

with a little more investigation, I noticed it is the case for other frequencies as well (for this one I used minimp3 lib directly)

image

kcgen commented 3 years ago

Can you describe the units on the axis?

Is the color range (blue->red->white) the absolute-value of the difference between the decoded sample vs. original (pre-encoded) sample? Or is it some other measure of "noise"?

Do these results only differ for 16 KHz encoded files - or does this pattern hold at the other common sample-rate steps? (22.05 / 32 / 44.1 / 48)?

lieff commented 3 years ago

If other decoders looks ok - it can be bug in minimp3. Can you attach encoded sample and reference pcm file? So I can look at it.

mrrostam commented 3 years ago

@kcgen it's the spectrogram of the files so the y-axis is frequency and x-axis is time.

Colors just show the intensity of the signal in that frequency at that time. In the picture there are two spectrograms, upper one is the original mp3 and the lower one is the decoded one using minimp3 (or dr_mp3).

At first I thought it is just for 16khz, but then noticed the same effect for 48 and 44.1 as well. Although the distortion seems worse for 16khz.

mrrostam commented 3 years ago

@lieff sure!

Sample audio

lieff commented 3 years ago

It says Access Denied.

mrrostam commented 3 years ago

sry! fixed now

lieff commented 3 years ago

I have very big difference with minimp3 decoder on my side and decoded_pcm.pcm :

$ ./minimp3 original_sample.mp3 decoded_pcm.pcm minimp3_out.pcm
rate=16000 samples=98203 max_diff=15972 PSNR=27.295479
error: PSNR compliance failed

So it can be some compiler difference or some dr_mp3 modification. Can you build https://github.com/lieff/minimp3/blob/master/minimp3_test.c and try same command line? Will be minimp3_out.pcm normal on your side?

mrrostam commented 3 years ago

I got the same result, and yes minimp3_out has no noise! :/

Now I wrote the same code for minimp3, but I am still getting the distorted output!

#define MINIMP3_IMPLEMENTATION

#include "minimp3_ex.h"

#include <stdlib.h>
#include <stdio.h>

int main()
{
    FILE *fptr = fopen("decoded_pcm.txt", "w");
    if (fptr == NULL)
    {
        printf("Error!");
        exit(1);
    }

    mp3dec_t mp3d;
    mp3dec_file_info_t info;
    if (mp3dec_load(&mp3d, "original_sample.mp3", &info, NULL, NULL))
    {
       printf("Error!");
       exit(1);
    }
    printf("%d\n", info.samples);
    printf("%d\n", info.hz);

    for (int i = 0; i < info.samples; i++)
    {
        fprintf(fptr, "%d\n", info.buffer[i]);
    }
    fclose(fptr);
    return 0;
}
lieff commented 3 years ago

How is this text data used later? Looks like bug in there. First sample in decoded_pcm.txt is -32, minimp3_out.pcm contains correct 0xe0ff while decoded_pcm.pcm contains 0xceff which is wrong.

mackron commented 3 years ago

@mrrostam Change "w" to "wb" in your fopen() call. Not sure if that'll actually affect anything, but it's something I've seen as a source of errors before.

mrrostam commented 3 years ago

I got it! The software I am using to convert .txt to .wav expects data in hex and not dec! @lieff @mackron Thank you so much again for your helps and awesome projects