[Android] AudioRecorder로 Lame을 이용한 MP3 녹음하기

안드로이드에서 MediaRecorder를 이용해 녹음하는 것은 쉽지만, 조금 더 심도있는(?) 녹음을 위해서는 AudioRecorder 클래스를 이용해야한다.

AudioRecorder로 MP3를 녹음하는 방법은 WAV를 녹음하는 방법과 크게 다르지 않다. – 기회가 되면 WAV도 포스팅하기로 하고.

 

 

일단 MP3녹음을 위해 외부 library를 import한다.

일본인이 만든 듯한 SimpleLameLibForAndroid라는 라이브러리가 잘 쓰이는 듯 하며 구글에 많은 예제가 있으나 뭔가 복잡한 듯.

이를 간소화 시킨 버전이 있으며, 이를 이용한 프로젝트인 Mp3VoiceRecorderSample을 불러온다.

https://github.com/yhirano/Mp3VoiceRecorderSampleForAndroid

 

Import하는 방법은 Eclipse에서 좌측 Package Explore에서 마우스 우측 버튼 – Import -> Existing Android code… 를 이용해서 불러온다.

그 뒤 Mp3VoiceRecorderSampleForAndroid 프로젝트 위에서 마우스 우측버튼 – 맨아래 Properties – 메뉴의 Android 항목에서 Target Build 아래쪽에 Library -> Is Library 체크 박스를 선택해놓는다.

이제 이 라이브러리를 이용하려는 프로젝트 위에서 다시 마우스 우측버튼 – Properties – 메뉴의 Android 항목에서 Target Build 아래쪽에 Library 에서 Mp3Voice… 라이브러리를 추가한다.

스크린샷 2014-04-23 오후 12.01.56

 

이제 아래는 소스코드

import com.uraroji.garage.android.lame.SimpleLame;

public class RecordService extends Service implements Runnable {

	static {
		System.loadLibrary("mp3lame");
	}

사용을 원하는 클래스에 패키지 및 Library를 로드한다.

 

파일 생성 -> 함수 내부는 적절히 변경할것

private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";

public static String getTempMP3Filename()
{
        String filepath = Environment.getExternalStorageDirectory().getPath();
        Date dt = new GregorianCalendar().getTime();
        String AUDIO_RECORDER_MP3_FILE = "record_" + String.valueOf(dt.getTime()) + ".mp3";
        Log.d(TAG,"Name : " + AUDIO_RECORDER_MP3_FILE);
        File file = new File(filepath,AUDIO_RECORDER_FOLDER);
        if(!file.exists()){
                file.mkdirs();
        }

        File tempFile = new File(filepath,AUDIO_RECORDER_MP3_FILE);

        if(tempFile.exists())
                tempFile.delete();

        return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_MP3_FILE);
}

 

적절한 위치에 변수 정의

FileOutputStream mp3file = null;
String mp3name;

 

적절한 위치에서 파일 생성

mp3name = getTempMP3Filename();
try 
{
    mp3file = new FileOutputStream(mp3name);
{
    e.printStackTrace();
}

 

적절한 위치에서 AudioRecorder 초기화 및 버퍼 생성

int frequency = 44100; //8000;
int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding); 
audioRecord = new AudioRecord( MediaRecorder.AudioSource.MIC, frequency, 
                    channelConfiguration, audioEncoding, bufferSize); 
audioRecord.startRecording();

byte[] mp3buffer = new byte[(int) (7200 + bufferSize * 2 * 1.25)];
short[] buffer = new short[bufferSize];

SimpleLame.init(frequency, 1, frequency, 32);

여기서 주목할 것은 mp3의 버퍼 사이즈다.

Lame의 메뉴얼을 보면

@param mp3buf result encoded MP3 stream. You must specified
*            “7200 + (1.25 * samples)” length array.

라고 되어있는데, MONO channel임에도 불구하고 Mp3Voice…예제에서는 x2를 한다.

그리고 프로그램 실행시 문제 없이 작동하는 것으로 보아 이렇게 둬도 되는 듯 하다.

init하는 함수의 parameter들은 SimpleLame.java파일에 설명이 나와있으니 적절히 수정할 것

 

이제 적절히 Thread함수에서 녹음을 시행한다.

while (threadState) 
{
    int bufferReadResult = audioRecord.read(buffer, 0,bufferSize);
    byte[] byteBuffer = ShortToByte(buffer,bufferReadResult); //이건 WAV 만들 때 이용할 수 있다 
    int encResult = SimpleLame.encode(buffer,
                                buffer, bufferReadResult, mp3buffer);
    if (encResult != 0) {
       try {
               mp3file.write(mp3buffer, 0, encResult);
        } catch (IOException e) {
               break;
        }
    }
}

//Thread가 끝나면 남아있는 버퍼를 정리한다.
flushResult = SimpleLame.flush(mp3buffer);
if (flushResult != 0) {
    try {
       mp3file.write(mp3buffer, 0, flushResult);
    } catch (IOException e) {
        Log.d(TAG,"MP3 flush error");
     }
}
//close file
try {
   mp3file.close();
} catch (IOException e) {
    e.printStackTrace();
}

 

이것으로 끝

0 Shares:
1 comment
Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.