유니 코드

[Android] 녹음기 만들기 with 코틀린(3) - 녹음 기능 구현하기(MediaRecorder, MediaPlayer 사용) 본문

오늘의 공부는?!/Android

[Android] 녹음기 만들기 with 코틀린(3) - 녹음 기능 구현하기(MediaRecorder, MediaPlayer 사용)

꼬물쥰 2022. 2. 22. 16:49
MediaRecorder 공식문서

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()
            }
        }
    }
}

 

 

 

 

Comments