반응형
음성을 녹음해서 파일로 저장해야 할 일이 있어서..
여기저기서 갈무리 했습니다... 많은 개발자 및 스택오버플로우 형님들께 감사를...
public class VoiceRecorder implements Runnable {
Context _context;
private final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO; //안드로이드 녹음시 채널 상수값
private final int WAVE_CHANNEL_MONO = 1; //wav 파일 헤더 생성시 채널 상수값
private final int HEADER_SIZE = 0x2c;
private final int RECORDER_BPP = 16;
private final int RECORDER_SAMPLERATE = 0xac44;
private final int BUFFER_SIZE;
private final String TEMP_FILE_NAME = "temp.bak";
private AudioRecord mAudioRecord;
private boolean mIsRecording;
private String mFileName;
private BufferedInputStream mBIStream;
private BufferedOutputStream mBOStream;
private int mAudioLen = 0;
private OnVoiceRecordFinishedListener voiceRecordFinishedListener;
public VoiceRecorder(Context context, String fileName) {
super();
_context = context;
mFileName = fileName;
BUFFER_SIZE = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
mIsRecording = false;
}
@Override
public void run() {
// 권한 체크
if (ActivityCompat.checkSelfPermission(_context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
return;
}
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, RECORDER_SAMPLERATE, RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING, BUFFER_SIZE);
mAudioRecord.startRecording();
mIsRecording = true;
writeAudioDataToFile();
}
private void writeAudioDataToFile() {
byte[] buffer = new byte[BUFFER_SIZE];
byte[] data = new byte[BUFFER_SIZE];
File waveFile = new File(저장하고 싶은 경로+"/"+mFileName);
File tempFile = new File(저장하고 싶은 경로+"/"+TEMP_FILE_NAME);
try {
mBOStream = new BufferedOutputStream(new FileOutputStream(tempFile));
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (null != mBOStream) {
new Thread(() -> {
int read = 0;
try {
while (mIsRecording) {
read = mAudioRecord.read(data, 0, BUFFER_SIZE);
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
mBOStream.write(data);
}
}
mAudioRecord.stop();
mAudioRecord.release();
mAudioRecord = null;
mBOStream.flush();
mAudioLen = (int)tempFile.length();
mBIStream = new BufferedInputStream(new FileInputStream(tempFile));
mBOStream.close();
mBOStream = new BufferedOutputStream(new FileOutputStream(waveFile));
mBOStream.write(getFileHeader());
while (mBIStream.read(buffer) != -1) {
mBOStream.write(buffer);
}
mBOStream.flush();
mBIStream.close();
mBOStream.close();
voiceRecordFinishedListener.onVoiceRecordFinishedListener(mFileName);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}).start();
}
}
private byte[] getFileHeader() {
byte[] header = new byte[HEADER_SIZE];
int totalDataLen = mAudioLen + 40;
long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * WAVE_CHANNEL_MONO/8;
header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = (byte)1; // format = 1 (PCM방식)
header[21] = 0;
header[22] = WAVE_CHANNEL_MONO;
header[23] = 0;
header[24] = (byte) (RECORDER_SAMPLERATE & 0xff);
header[25] = (byte) ((RECORDER_SAMPLERATE >> 8) & 0xff);
header[26] = (byte) ((RECORDER_SAMPLERATE >> 16) & 0xff);
header[27] = (byte) ((RECORDER_SAMPLERATE >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) RECORDER_BPP * WAVE_CHANNEL_MONO/8; // block align
header[33] = 0;
header[34] = RECORDER_BPP; // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte)(mAudioLen & 0xff);
header[41] = (byte)((mAudioLen >> 8) & 0xff);
header[42] = (byte)((mAudioLen >> 16) & 0xff);
header[43] = (byte)((mAudioLen >> 24) & 0xff);
return header;
}
public void stopRecording() {
if (null != mAudioRecord) {
mIsRecording = false;
}
}
public interface OnVoiceRecordFinishedListener {
void onVoiceRecordFinishedListener(String fileName);
}
// OnItemClickListener 전달 메소드
public void setOnVoiceRecordFinishedListener (OnVoiceRecordFinishedListener listener) {
voiceRecordFinishedListener = listener;
}
}
startRecording을 호출하면 녹음이 시작되고
stopRecording을 호출하면 녹음이 종료됨!
setOnVoiceRecordFinishedListener를 미리 설정해두면 녹음이 끝난 후에 이벤트를 캐치할 수 있음!
반응형