오늘의 공부는?!/Android
[Android] 녹음기 만들기 with 코틀린(3) - 녹음 기능 구현하기(MediaRecorder, MediaPlayer 사용)
꼬물쥰
2022. 2. 22. 16:49
MediaRecorder 공식문서
코덱은 인코더와 디코더를 합친 개념
오디오 소스는 용량이 작은 게 아니라 압축할 필요가 있다.
이렇게 압축할 때 사용하는 것이 인코더
포맷은 컨테이너 역할로 압축된 데이터들을 하나의 박스에 차곡차곡 정리해주는 역할
디코더는 이렇게 정리된 데이터들을 꺼내서 재생하는 형태
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(PATH_NAME);
recorder.prepare();
recorder.start(); // Recording is now started
...
recorder.stop();
recorder.reset(); // You can reuse the object by going back to setAudioSource() step
recorder.release(); // Now the object cannot be reused
공식문서에서 소개하는 녹음 하는 코드이다.
outputFormat과 Encoder 사이에는 호환성이 존재하는데
서로 지원하는 코덱과 컨테이너가 있기 때문에 확인할 필요가 있다.
※ 현재 MediaRecorder는 애뮬레이터에서 작동하지 않는다. -> 나는 디바이스에서 실행하였다.
미디어레코더를 선언하고 null을 대입한다. 레코더는 메모리를 차지하기 때문에 앱 성능 저하가 일어날 수 있기 때문에 사용하지 않을 때는 무조건 메모리를 해제하고 null로 초기화하는 것이 좋다.
private var recorder: MediaRecorder? = null
공식문서에서 소개한 코드대로 오디오 소스를 설정한 후 포맷과 오디오인코더를 정해주고 파일 저장 경로를 설정해주면 녹음 준비가 완료된다. 이번에 만든 녹음기 어플은 저장소에 저장하지 않고 캐시에 저장하였다.
private fun startRecording() {
recorder = MediaRecorder()
.apply {
setAudioSource(MediaRecorder.AudioSource.MIC)
setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
setOutputFile(recordingFilePath)
prepare()
}
recorder?.start()
state = State.ON_RECORDING
}
녹음을 정지할 때 실행하는 함수인 stopRecording()을 만들어준다.
private fun stopRecording(){
recorder?.run{
stop()
release()
}
recorder = null
state = State.AFTER_RECORDING
}
MediaPlayer 공식문서
녹음된 파일을 재생할 때에는 MediaPlayer를 사용한다.
위에서와 같이 mediaPlayer를 선언해주고 null로 초기화해준다.
private var player: MediaPlayer? = null
private fun startPlaying(){
player = MediaPlayer()
.apply {
setDataSource(recordingFilePath)
prepare()
}
player?.start()
state = State.ON_PLAYING
}
private fun stopPlaying(){
player?.release()
player = null
state = State.AFTER_RECORDING
}
지금까지 만든 함수들을 bindViews()를 이용하여 바인딩해준다.
private fun bindViews(){
resetButton.setOnClickListener {
stopPlaying()
state = State.BEFORE_RECORDING
}
recordButton.setOnClickListener {
when(state){
State.BEFORE_RECORDING -> {
startRecording()
}
State.ON_RECORDING -> {
stopRecording()
}
State.AFTER_RECORDING -> {
startPlaying()
}
State.ON_PLAYING -> {
stopPlaying()
}
}
}
}