I am a completely noob in topics related to audio handling with programming, but I want to convert PCM audio data to MP3.
My audio is in PCM format, the frequency is 8kHz, the bitwidth is 8 and the kind of byte is unsigned, and channel is mono.
I am using liblamemp3, and I found the way of doing it by the lame.exe frontend, by executing this command line:
$ ./lame -r -s 8 --bitwidth 8 --unsigned -m m ../../../../voice8K16bitmono.pcm output.mp3
The result is an .mp3 that I can hear well. (After some tries).
The problem is that I want to do it on the fly, so I am trying to code some source to do it without invoking the frontend.
My source code is:
#include <stdio.h>
#include <lame/lame.h>
int main(int argc, char *argv[])
{
int read, write;
FILE *pcm = fopen(argv[1], "rb");
FILE *mp3 = fopen("file.mp3", "wb");
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
unsigned short pcm_buffer;
unsigned short pcm_buffer_le;
unsigned char mp3_buffer[MP3_SIZE];
lame_t lame = lame_init();
lame_set_num_samples(lame, 8000);
lame_set_in_samplerate(lame, 8000);
lame_set_out_samplerate(lame, 8000);
lame_set_num_channels(lame, 1);
lame_set_mode(lame, 3);
lame_init_params(lame);
lame_print_config(lame);
//framesize is bits / channels = 8.
do {
read = fread(&pcm_buffer, sizeof(short), 1, pcm);
pcm_buffer = (pcm_buffer>>8) | (pcm_buffer<<8);
if (read == 0) {
write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
fwrite(mp3_buffer, sizeof(char), write, mp3);
break;
}
//pcm_buffer_le[0] = (pcm_buffer[0]>>8) | (pcm_buffer[0]<<8);
write = lame_encode_buffer_interleaved(lame, &pcm_buffer, sizeof(short), mp3_buffer, MP3_SIZE);
fwrite(mp3_buffer, sizeof(char), write, mp3);
} while (1);
lame_close(lame);
fclose(mp3);
fclose(pcm);
return 0;
}
I took it from an example, and tried to apply the settings I need. But the resulting .mp3 sounds like a reactor and it doesn't sound well. So I am missing some/lot of code.
I want to do it, so, can anybody help?
Thanks in advance.
sizeof(short)
bytes, you should read in 1 byte.lame_encode_buffer()
instead of lame_encode_buffer_interleaved()
, and set the buffer_r
parameter to NULL
(reference).Here is a modified working version of your code:
#include <stdio.h>
#include <lame/lame.h>
int main(int argc, char *argv[])
{
int read, write;
FILE *pcm = fopen(argv[1], "rb");
FILE *mp3 = fopen("file.mp3", "wb");
const int MP3_SIZE = 8192;
unsigned char pcm_buffer_c;
short pcm_buffer;
unsigned char mp3_buffer[MP3_SIZE];
lame_t lame = lame_init();
lame_set_num_samples(lame, 8000);
lame_set_in_samplerate(lame, 8000);
lame_set_out_samplerate(lame, 8000);
lame_set_num_channels(lame, 1);
lame_set_mode(lame, 3);
lame_init_params(lame);
lame_print_config(lame);
//framesize is bits / channels = 8.
do {
read = fread(&pcm_buffer_c, sizeof(char), 1, pcm);
pcm_buffer = (short)(pcm_buffer_c - 0x80) << 8;
if (read == 0) {
write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
fwrite(mp3_buffer, sizeof(char), write, mp3);
break;
}
write = lame_encode_buffer(lame, &pcm_buffer, NULL, read, mp3_buffer, MP3_SIZE);
fwrite(mp3_buffer, sizeof(char), write, mp3);
} while (1);
lame_close(lame);
fclose(mp3);
fclose(pcm);
return 0;
}
The above code reads in 1 byte at a time from the input file, which isn't very efficient. Here's how you would read multiple bytes at a time (I also cleaned up some of your code and removed some unnecessary functions). There is no error checking in this code, so make sure you add checks for the return values of all the LAME library functions.
#include <stdio.h>
#include <lame/lame.h>
#define PCM_BUF_SIZE 1024
#define MP3_SIZE 8192
int main(int argc, char *argv[])
{
FILE *pcm = fopen(argv[1], "rb");
FILE *mp3 = fopen("file.mp3", "wb");
int n_bytes_read;
int n_bytes_write;
int i;
short pcm_buffer_s[PCM_BUF_SIZE];
unsigned char pcm_buffer[PCM_BUF_SIZE];
unsigned char mp3_buffer[MP3_SIZE];
lame_t lame = lame_init();
lame_set_in_samplerate(lame, 8000);
lame_set_num_channels(lame, 1);
lame_set_mode(lame, 3);
lame_init_params(lame);
lame_print_config(lame);
do {
n_bytes_read = fread(pcm_buffer, sizeof(char), PCM_BUF_SIZE, pcm);
for (i = 0; i < n_bytes_read; i++) {
pcm_buffer_s[i] = (short)(pcm_buffer[i] - 0x80) << 8;
}
if (n_bytes_read == 0) {
n_bytes_write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
} else {
n_bytes_write = lame_encode_buffer(lame, pcm_buffer_s, NULL,
n_bytes_read, mp3_buffer, MP3_SIZE);
}
fwrite(mp3_buffer, sizeof(char), n_bytes_write, mp3);
} while (n_bytes_read > 0);
lame_close(lame);
fclose(mp3);
fclose(pcm);
return 0;
}