반응형
Android 녹음 기능 RecMic to Mp3
package com.uraroji.garage.android.mp3recvoice;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import com.kniezrec.remoterecorder.MainService;
import com.uraroji.garage.android.lame.SimpleLame;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class RecMicToMp3 {
static {
System.loadLibrary("mp3lame");
}
public static final int MSG_REC_STARTED = 0;
public static final int MSG_REC_STOPPED = 1;
public static final int MSG_ERROR_GET_MIN_BUFFERSIZE = 2;
public static final int MSG_ERROR_CREATE_FILE = 3;
public static final int MSG_ERROR_REC_START = 4;
public static final int MSG_ERROR_AUDIO_RECORD = 5;
public static final int MSG_ERROR_AUDIO_ENCODE = 6;
public static final int MSG_ERROR_WRITE_FILE = 7;
public static final int MSG_ERROR_CLOSE_FILE = 8;
private String mFilePath;
private String mFileName;
private String DIR;
private int mSampleRate;
private boolean mIsRecording = false;
/**
* @see RecMicToMp3#MSG_REC_STARTED
* @see RecMicToMp3#MSG_REC_STOPPED
* @see RecMicToMp3#MSG_ERROR_GET_MIN_BUFFERSIZE
* @see RecMicToMp3#MSG_ERROR_CREATE_FILE
* @see RecMicToMp3#MSG_ERROR_REC_START
* @see RecMicToMp3#MSG_ERROR_AUDIO_RECORD
* @see RecMicToMp3#MSG_ERROR_AUDIO_ENCODE
* @see RecMicToMp3#MSG_ERROR_WRITE_FILE
* @see RecMicToMp3#MSG_ERROR_CLOSE_FILE
*/
private Handler mHandler;
private int mSec = 0;
private int mMaxSec = 0;
public RecMicToMp3(int sampleRate) {
if (sampleRate <= 0) {
throw new InvalidParameterException(
"Invalid sample rate specified.");
}
this.mSampleRate = sampleRate;
DIR = Environment.getExternalStorageDirectory().getAbsolutePath()
+ MainService.DIR_NAME;
File RRdir = new File(DIR);
if (!RRdir.exists()) {
RRdir.mkdir();
}
}
public void setMaxDuration(int sec) {
this.mMaxSec = sec;
}
public String getmFileName() {
return mFileName;
}
public boolean addSec() {
mSec++;
return (mSec > mMaxSec);
}
public int getSec() {
return mSec;
}
public void start() {
this.mFileName = generateFileName();
this.mFilePath = DIR + mFileName;
if (mIsRecording) {
return;
}
mSec = 0;
new Thread() {
@Override
public void run() {
android.os.Process
.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
final int minBufferSize = AudioRecord.getMinBufferSize(
mSampleRate, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (minBufferSize < 0) {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_ERROR_GET_MIN_BUFFERSIZE);
}
return;
}
AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, mSampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 2);
// PCM buffer size (5sec)
short[] buffer = new short[mSampleRate * (16 / 8) * 1 * 5]; // SampleRate[Hz]
// *
// 16bit
// *
// Mono
// *
// 5sec
byte[] mp3buffer = new byte[(int) (7200 + buffer.length * 2 * 1.25)];
FileOutputStream output;
try {
output = new FileOutputStream(new File(mFilePath));
} catch (FileNotFoundException e) {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_ERROR_CREATE_FILE);
}
return;
}
// Lame init
SimpleLame.init(mSampleRate, 1, mSampleRate, 32);
mIsRecording = true;
try {
try {
audioRecord.startRecording();
} catch (IllegalStateException e) {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_ERROR_REC_START);
}
return;
}
try {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_REC_STARTED);
}
int readSize;
while (mIsRecording) {
readSize = audioRecord.read(buffer, 0,
minBufferSize);
if (readSize < 0) {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_ERROR_AUDIO_RECORD);
}
break;
} else {
int encResult = SimpleLame.encode(buffer,
buffer, readSize, mp3buffer);
if (encResult < 0) {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_ERROR_AUDIO_ENCODE);
}
break;
}
if (encResult != 0) {
try {
output.write(mp3buffer, 0, encResult);
} catch (IOException e) {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_ERROR_WRITE_FILE);
}
break;
}
}
}
}
int flushResult = SimpleLame.flush(mp3buffer);
if (flushResult < 0) {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_ERROR_AUDIO_ENCODE);
}
}
if (flushResult != 0) {
try {
output.write(mp3buffer, 0, flushResult);
} catch (IOException e) {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_ERROR_WRITE_FILE);
}
}
}
try {
output.close();
} catch (IOException e) {
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_ERROR_CLOSE_FILE);
}
}
} finally {
audioRecord.stop();
audioRecord.release();
}
} finally {
SimpleLame.close();
mIsRecording = false;
}
if (mHandler != null) {
mHandler.sendEmptyMessage(MSG_REC_STOPPED);
}
}
}.start();
}
public void stop() {
mIsRecording = false;
}
public boolean isRecording() {
return mIsRecording;
}
/**
* @see RecMicToMp3#MSG_REC_STARTED
* @see RecMicToMp3#MSG_REC_STOPPED
* @see RecMicToMp3#MSG_ERROR_GET_MIN_BUFFERSIZE
* @see RecMicToMp3#MSG_ERROR_CREATE_FILE
* @see RecMicToMp3#MSG_ERROR_REC_START
* @see RecMicToMp3#MSG_ERROR_AUDIO_RECORD
* @see RecMicToMp3#MSG_ERROR_AUDIO_ENCODE
* @see RecMicToMp3#MSG_ERROR_WRITE_FILE
* @see RecMicToMp3#MSG_ERROR_CLOSE_FILE
*/
public void setHandle(Handler handler) {
this.mHandler = handler;
}
private String generateFileName() {
Date dNow = new Date();
StringBuilder sb = new StringBuilder();
SimpleDateFormat ft = new SimpleDateFormat("ddMMyy_hh.mm.ss",
Locale.getDefault());
sb.append(ft.format(dNow)).append(".mp3");
return sb.toString();
}
}
참조 :
반응형
'안드로이드' 카테고리의 다른 글
[Android] 인앱 결제(inapp billing) 순서 (0) | 2022.10.20 |
---|---|
[Android] 문자 보내기 (SEND_SMS) (0) | 2022.10.20 |
[Android] 네비게이션(Navigation)에 대해 알아보자 (0) | 2022.09.22 |
Stack vs Heap (0) | 2022.09.20 |
TextView Ellipsize end가 OS낮은 버전에서 많이 줄여질 때 (0) | 2022.09.20 |