본문 바로가기
Kotlin

Kotlin - 소리 재생하기(MediaPlayer ,SoundPool 클래스, 버전분기)

by 봄석 2019. 1. 5.

Kotlin - 소리 재생하기(MediaPlayer ,SoundPool 클래스, 버전분기)



안드로이드에서 소리를 재생하는 방법에는 대표적으로 

MediaPlayer 클래스와 SoundPool 클래스를 사용하는 방법이 있습니다.



MediaPlayer

일반적인 소리 파일 전주에는 MediaPalyer 클래스를 사용합니다. 클래스 이름에서 알 수 있듯이 음악파일과 비디오 파일을 모두 재생할 수 있습니다. MediaPlayer로 raw 디렉터리 파일을 재생하는 코드는 다음과 같이 간단합니다.

//raw 디렉터리의 do1 파일을 재생하는 예
val mediaPlayer = MediaPlayer.create(this,R.raw.do1)
button.setOnClickListener{ mdiaPlayer.start() }
....
// 사용이 끝나면 릴리즈해야함
mediaPlayer.release()



MediaPlayer 클래스는 일반적으로 소리를 한 번만 재생하는 경우 또는 노래나 배경음과 같은 경우에는 유용합니다. 하지만 실로폰과 같이 연타를 해서 연속으로 소리를 재생하는 경우에는 

SoundPool 클래스가 더 유용합니다.



SoundPool

SoundPool은 다음과 같이 사용합니다 . Builder().build() 메소드로 SoundPool 객체를 생성하고

load() 메소드로 소리 파일을 로드하여 그 아이디를 반환합니다.

val soundPool SoundPool.Builder().build()
 
val soundId = soundPool.load(this, R.raw.do1,1)

button.setOnClickListener{ soundPool.play(soundId, 1.0f, 1.0f, 0, 0, 1.0f)}



load() 메소드와 play() 메소드의 원형은 아래와 같습니다.

//음원을 준비하여 id를 반환합니다.

load(context :Context, resId:Int, priority:Int):



- context : 컨텍스트를 지정합니다. 액티비티를 지정합니다.

- resId : 재생할 raw 디렉터리의 소리 파일 리소스를 지정합니다.

- priority : 우선순위를 지정합니다. 숫자가 높으면 우선순위가 높습니다.

//음원을 재생합니다

play(soundId: Int, leftVolume:Float, rightVolume:Float, priority:Int, loop:Int, rate:Float):


- soundId : load( ) 메소드에서 반환된 음원의 id를 지정합니다.

- leftVolume : 왼쪽 볼륨을 0.0~1.0 사이에서 지정합니다.

- rightVolume : 오른쪽 볼륨을 0.0~1.0 사이에서 지정합니다.

- priority : 우선순위를 지정합니다. 0이 가장 낮은 순위입니다.

- loop : 반복을 지정합니다. 0이면 반복하지 않고 -1 이면 반복합니다.

- rate : 재생 속도를 지정합니다. 1.0이면 보통,  0.5이면 0.5 배속, 2.0 이면 2배속입니다.



SoundPool 초기화 버전 분기

SoundPool 객체를 초기화 하는 코드를 작성합니다. 

setMaxStreams() 메소드는 한꺼번에 재생하는 음원 개수를 지정할 수 있습니다. 

여기서는 음원 파일 개수에 맞게 8개를 동시에 재생할 수 있게 했습니다. 

load() 메소드로 음원 8개를 한번에 로드할 수 있습니다.

class MainActivity : AppCompatActivity() {
    private soundPool = SoundPool.Builder().setMaxStreams(8).build()
 
....

}

하지만 위의 코드를 작성하면 에디터 창에 빨간 줄이 표시됩니다.

마우스 커서를 빨간줄 표시 부분에 올려보면 아래같은 메시지가 표시됩니다.

Call requires API level 21 (current min is 19): android.media.SoundPool.Builder#setMaxStreams...



SoundPool클래스의 초기화 방법은 안드로이드 5.0 부터 변경되었습니다.

프로젝트의 minSdkVersion이 19이기 때문에 위 코드는 안드로이드 API 21(5.0) 이상에서만 

지원된다는 메시지입니다.




변경되기 전에는 아래와 같은 코드를 사용했습니다.

private val soundPool =SoundPool(8,AudioManager.STREAM_MUSIC,0)


첫 번째 인자는 최대 재생 스트림 개수이고, 두 번째 인자는 어떤 종류의 음원인지 결정합니다.

마지막 인자는 음직이며 0이 기본값입니다


하지만 초기화 코드를 위와같이 변경하면 에디터 창에는 SoundPool 클래스에 사선이 그어져 있습니다. 마우스를 올려보면 아래와같이 더이상 생성자가 사용되지 않는다는 메시지가 출력됩니다.

constructor SoundPool(Int, Int, Int)' is deprecated. 





안드로이드 개발을 하다보면 API가 버전업 되면서 생성자나 메소드에서 이런 경우를 종종 볼수 있습니다. 이 때는 각 버전에서 추천되는 방식으로 동작하도록 버전을 분기합니다.

위에서 작성했던 코드로 돌아가서 SoundPool 초기화 코드를 작성하고

빨간줄에서 [Alt]+[Enter]를 눌러 제안사항을 표시해 보겠습니다


생성된 코드문에 다음과 같이 구 버전용 SoundPool 객체 초기화 코드를 추가합니다.

자동으로 추가된 if문이 사용되어 롤리팝(5.0)이후와 이전에 다른 코드가 수행되게 되었습니다.

private val soundPool = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        SoundPool.Builder().setMaxStreams(8).build()
    } else {
        SoundPool(8,AudioManager.STREAM_MUSIC,1)
    }


댓글