8

I'm using LAME to convert a WAV file (extracted from Audio CD) into MP3. The conversion result is just fine except at the very beginning of the file there is one single "click" sound. The click takes almost 0.5 second prior to the song itself.

char *input_file = argv[1];
char *output_file = argv[2];

FILE *pcm = fopen(input_file, "rb");
FILE *mp3 = fopen(output_file, "wb+");

size_t nread;
int ret, nwrite;

const int PCM_SIZE = 1152;
const int MP3_SIZE = 1152;

short pcm_buffer[PCM_SIZE * 2];
unsigned char mp3_buffer[MP3_SIZE];

lame_t lame = lame_init();

// Can not put these lines at the end of conversion
id3tag_set_title(lame, "Still reminds me");
id3tag_set_artist(lame, "Anggun");

lame_set_VBR(lame, vbr_mt);
lame_set_VBR_quality(lame, 2);

ret = lame_init_params(lame);

do {
    nread = fread(pcm_buffer, sizeof(short), PCM_SIZE * 2, pcm);

    if (nread != 0) {
        // Is this the cause of the single click?
        int nsamples = nread / 2;
        short buffer_l[nsamples];
        short buffer_r[nsamples];

        int j = 0;
        int i = 0;
        for (i = 0; i < nsamples; i++) {
            buffer_l[i] = pcm_buffer[j++];
            buffer_r[i] = pcm_buffer[j++];

        }

        nwrite = lame_encode_buffer(lame, buffer_l, buffer_r, nsamples,
                mp3_buffer, MP3_SIZE);

    } else {
        nwrite = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);

    }

    fwrite(mp3_buffer, nwrite, 1, mp3);
} while (nread != 0);


lame_close(lame);

fclose(mp3);
fclose(pcm);

What's going on? What do I miss here?

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
sancho21
  • 3,511
  • 1
  • 39
  • 45

3 Answers3

9

Not sure if you are still looking for an answer other than Dave L's, but the click noise is coming from LAME accidentally encoding the header in the audio file. Depending on the WAV file you are producing, the header would probably be 44 bytes. I ran into a similar issue when converting PCM files that I recorded, but those headers are 4096 bytes in my case. If it is a true wav file (and thus has the 44 byte header) just use

fseek(pcm,44,0);

Right after you open the file to skip over the header stuff. I also recommend using a Hex editor on one of your WAV files to verify the size of the header.

Once I skipped over that (again, my headers were 4096b), the clicking noise disappeared.

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
ewrobinson
  • 351
  • 4
  • 9
  • It works except that I got nwrite = -1 when calling `nwrite = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);` I failed to flush. Without fseek, the nwrite return >= 0. – sancho21 Feb 25 '13 at 15:21
  • Thank you so much for this answer! Knowing that headers accidentally getting encoded caused that unwanted “click”/“pop” helped me solve this issue! In my case, the advice given here would have forced me into a situation where I had to transcode MP3s, so I discovered a way to affect the same results using FFmpeg to copy the audio but simply skip 1/8th of a second of audio at the beginning of the file. Full details [on my SuperUser post on the topic shown here](https://superuser.com/q/1342337/167207). – Giacomo1968 Jul 22 '18 at 15:02
3

Any luck solving this issue?

I've been having a similar problem and I tried just skipping the first 1024 bytes when writing to the output file (i.e., I’m just discarding those bytes before I start to write the output from LAME to the output file). This eliminated the “click” at the beginning of the recording but it’s a bit of a hack, but seems to work okay.

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
Dave L
  • 171
  • 10
  • That's brilliant. I should always use result oriented solution. I think I'll use this hack until I solve the problem. Thanks man! – sancho21 Oct 08 '12 at 04:01
0

Skipping the header is important to avoid such a click but a fixed size of eg. 44 Bytes is a not working solution.

My typical WAV files having a 80 Byte header.

Anyway, you should parse the WAV file to find the real header size. This makes also sense to grab some additional stuff like bits per sample, number of channels etc which can be used to set the right parameters for lame or to provide some useful default params.

To make things easier, you must not develop all this things from scratch. The frontend included in the Lame sources can be used (look for the file get_audio.c and the function parse_wave_header(lame_global_flags * gfp, FILE * sf)

If you only need the header size, you can of course modify this function to fit your needs.

Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
devarni
  • 1,782
  • 1
  • 17
  • 13