Lame
LAME은 오픈 소스 MP3 인코더이다. LAME이라는 이름은 “LAME Ain't an MP3 Encoder”의 재귀 약자이다. 이름은 이렇게 지었지만, 실제로는 오늘날 가장 널리 쓰이는 MP3 인코더 중의 하나이다. 2004년 기준으로 LAME은 128 kbit/s 이상의 비트레이트에서 가장 품질이 좋은 MP3 파일을 만든다고 알려져 있다. 2004년 초 공개 청취 테스트에서 LAME으로 인코딩한 파일이 원본 오디오와 비교했을 때 음질 열화가 가장 적었다고 한다.
Porting and using LAME MP3 on Android with JNI
Preparing libraries: The LAME library can be downloaded from the following website: http://lame.sourceforge.net/download.php When the download is finished, an initial version (without a functional wrapper) of the shared library being created can be built. In order to do so, it is needed to create a directory called jni in the project's root. Then copy the libmp3lame directory from the downloaded archive to the created one. It is needed to copy all .c and .h files, so all others can be skipped. The main library header file named lame.h is also necessary. It is placed in the include directory in the downloaded archive. Copy it as the rest of files to the libmp3lame directory. Some preparations are to be made yet. Since the standard compilation method with autoconf will not be used, some changes in header files need to be performed. First of all edit util.h and replace line:
with used architecture 32-bit float implementation, which is simply float:
In set_get.h replace
with
LAME MPEG1 or MPEG2 Audio Layer III Select logic
LAME을 사용할 경우 'Output Samplerate'에 따라, MPEG1 또는 MPEG2 선택이 바뀐다.
자세한 내용은 util.c 파일의 SmpFrqIndex()를 참조하면 된다.
/* convert samp freq in Hz to index */
int SmpFrqIndex(int sample_freq, int *const version)
{
// version = 0: MPEG2.
// version = 1: MPEG1.
switch (sample_freq) {
case 44100:
*version = 1;
return 0;
case 48000:
*version = 1;
return 1;
case 32000:
*version = 1;
return 2;
case 22050:
*version = 0;
return 0;
case 24000:
*version = 0;
return 1;
case 16000:
*version = 0;
return 2;
case 11025:
*version = 0;
return 0;
case 12000:
*version = 0;
return 1;
case 8000:
*version = 0;
return 2;
default:
*version = 0;
return -1;
}
}
위와 같은 로직이 포함된 이유는 Wikipedia를 읽어보면 알 수 있다.
MPEG-2에도 Audio Layer-3이 있어 MP3라고 부르지만, MPEG-2 AudioBC (Backward Compatible)이 정식 명칭이다.
MPEG-2 MP3는 압축 방식은 동일하지만, 비트율이 낮은 매체를 위한 낮은 고정 비트율, 다채널 대응이 포함되어 있다.
이 형식은 유럽형 DVD에 채용되어 있다.
또한 ISO 표준 규격이 아닌 MPEG2.5 Audio Layer 3 이라는 것도 있다.
Sample encoding for iOS
/// @brief 기본 설정 PCM/MP3의 Sample Rate.
#define DEFAULT_SAMPLE_RATE 44100.0f
// ...
- (void)readyRecorder
{
// Recorder setting...
NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:DEFAULT_SAMPLE_RATE] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
[recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityMax] forKey:AVEncoderAudioQualityKey];
// ...
}
- (void)runConvertPcmToMp3
{
[NSThread detachNewThreadSelector:@selector(convertPcmToMp3) toTarget:self withObject:nil];
}
- (void)convertPcmToMp3
{
BOOL isConvertSuccess = NO;
FILE * pcm = NULL;
FILE * mp3 = NULL;
lame_t lame = NULL;
@try {
int read = 0, write = 0;
pcm = fopen([recordPcmPath cStringUsingEncoding:1], "rb"); // source
fseek(pcm, 4 * 1024, SEEK_CUR); // skip file header
mp3 = fopen([recordMp3Path cStringUsingEncoding:1], "wb"); // output
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
short int pcm_buffer[PCM_SIZE*2] = {0,};
unsigned char mp3_buffer[MP3_SIZE] = {0,};
lame = lame_init();
lame_set_in_samplerate(lame, DEFAULT_SAMPLE_RATE);
lame_set_VBR(lame, vbr_default);
lame_init_params(lame);
do {
read = fread(pcm_buffer, 2 * sizeof(short int), PCM_SIZE, pcm);
if (read == 0) {
write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
} else {
write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
}
fwrite(mp3_buffer, write, 1, mp3);
} while (read != 0);
// convert success.
isConvertSuccess = YES;
} @catch (NSException * e) {
isConvertSuccess = NO;
NSLog(@"PCM to MP3 Convert failure: %@", [e description]);
} @finally {
if (lame != NULL) {
lame_close(lame);
}
if (mp3 != NULL) {
fclose(mp3);
}
if (pcm != NULL) {
fclose(pcm);
}
[self performSelectorOnMainThread:@selector(convertMp3Finish:)
withObject:[NSNumber numberWithBool:isConvertSuccess]
waitUntilDone:YES];
}
}
- (void)convertMp3Finish:(NSNumber*)convertResult
{
// ...
}
See also
Favorite site
- LAME website.
- Wikipedia (en) LAME에 대한 설명.
- LAME Libraries.
- Github: MP3 voice recorder sample for Android.
- Github: LAME for Android.
References
-
Porting_and_using_LAME_MP3_on_Android_with_JNI.pdf ↩