Click sound at the beginning when using LAME
Asked Answered
S

4

9

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?

Swath answered 10/9, 2012 at 6:25 Comment(0)
H
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.

Halley answered 27/1, 2013 at 20:47 Comment(1)
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.Swath
G
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.

Gunther answered 6/10, 2012 at 3:59 Comment(1)
That's brilliant. I should always use result oriented solution. I think I'll use this hack until I solve the problem. Thanks man!Swath
F
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.

Follicle answered 15/6, 2015 at 10:22 Comment(0)
V
0

So I found out I had set the -r flag and the documentation stated following:

Input options:

-r

Assume the input file is raw pcm. Sampling rate and mono/stereo/jstereo must be specified on the command line. For each stereo sample, LAME expects the input data to be ordered left channel first, then right channel. By default, LAME expects them to be signed integers with a bitwidth of 16. Without -r, LAME will perform several fseek()'s on the input file looking for WAV and AIFF headers.

So don't use -r flag if you have any header information in the audio files.

Vizierate answered 7/5 at 12:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.