또는

== 실로폰 ===

 

- 기능 소개

음판을 누르면 소리가 재생

 

 

- 주된 도구

SoundPool   (음원을 관리하고 재생하는 클래스. 안드로이드 5.0 이전과 이후 버전의 동작이 다르므로

              모든 기기에서 잘 동작하도록 버전 분기를 적용할 것임)

 

 

1. 프로젝트 생성

프로젝트명 : Xylophone

miniSdkVersion : 19

기본 액티비티 : Empty

 

레이아웃 에디터에서 미리보기 모드를 가로모드 작업 환경으로 설정합시다.

(실로폰이 가로 모양이니까요)

[미리보기를 수평모드로...]

 

2. 텍스트 뷰로 음판 만들기

음판을 적당하게 배치한 후 한 번에 제약을 추가해 봅시다. (Autoconnect 모드 off)

 

디폴트 텍스트 뷰 삭제 > 팔레트 창 Common > TextView를 끌어다 건반 모양으로 배치

 

   id : do1

   layout_width : 50 dp

   layout_height : match_constraint

   , 아래 여백 : 16  (, 우 여백은 모든 건반 배치후 한 번에 설정할 것임)

   text :

   textAppearance : AppCompat.Large

   textColor : @android.color/white

   background : holo_red_dark

   gravity : center에 체크 (컨텐츠를 가운데 배치하는 역할)

위와 같은 형태로 7개의 테스트 뷰를 추가로 배치.

id

, 아래 여백

text

background

re

24

@android:color/holo_orange_dark

mi

32

@android:color/holo_orange_light

fa

40

@android:color/holo_green_light

sol

48

@android:color/holo_blue_light

la

56

@android:color/holo_blue_dark

si

64

@android:color/holo_purple

do2

72

@android:color/holo_red_dark

모든 건반 배치가 끝나면 컨트롤 키를 누른 상태에서 모든 건반을 클릭하여 전체 건반 선택 >

   마우스 우측 버튼 > 컨텍스트 메뉴에서 Chains > Create Horizontal Chain   (뷰들이 체인으로 연결됨)

 

체인으로 연결된 뷰 중 아무 뷰나 선택 후 컨텍스트 메뉴 > Cycle chain mode 클릭

  (클릭할 때마다 세 가지 모드가 전환됨)

  (아래와 같이 건판이 균일한 간격이 되는 모드를 선택)

[실로폰 음판 모양으로 배치한 텍스트 뷰들]

이렇게 텍스트 뷰들로 실로폰 음판을 만들었습니다.

 

 

3. 재생할 소리 리소스 준비

wav, mp3 와 같은 사운드 파일은 .raw 리소스 디렉터리를 만들어 그 안에 저장해 놓고 사용합니다.

 

1) .res 디렉토리 생성

  프로젝트 창의 .res 디렉터리에서 마우스 우측 버튼 클릭 > 컨텍스트 메뉴 중 'New > Android Resource Directory'

    Resource type : raw

 

2) http://bit.ly/2K9dQjo 에서 실로폰 음계의 wav 파일 다운로드 > .res에 저장

 

 

※ 안드로이드 기기에서 소리 재생

방법1) MediaPlayer 클래스  (음악 및 비디오 파일 재생. 한 번만 재생하고 플레이어를 끝낼 때 유용)

 

  사용 예)

    val mediaPlayer = MediaPlayer.create(this, R.raw.do1)

    button.setOnClickListener{ mediaPlayer.start() }

    ...

    mediaPlayer.release()    // 사용이 끝난 후 해제해 줘야 함

 

 

방법2) SoundPool 클래스   (실로폰과 같이 연속으로 소리를 때마다 계속 내야 할 때 유용)

 

 사용 예)

    val soundPool = SoundPool.Builder().build()

    val soundId = soundPool.load(this, R.raw.do1, 1)    // load(컨텍스트, 소리파일, 우선순위)

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

         // play(음원id), 왼쪽볼륨 0.0~1.0, 오른쪽 볼륨, 우선순위(0은 최하순위),

         // 반복여부(0:반복안함, -1:반복), 재생속도(배속)

 

 

4. SoundPool 초기화 버전 분기

 

-- MainActivity

class MainActivity : AppCompatActivity() {

 

   ...

 

   private val soundPool = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

      SoundPool.Builder().setMaxStreams(8).build()  // 한꺼번에 재생하는 음원 개수 (8개 동시 재생)  *1

   } else {

      SoundPool(8, AudioManager.STREAM_MUSIC, 0) // 최대 재생 스트림 개수, 음원 종류, 음질 (default: 0)

   }

}

 

 

*1 에서 오류가 표시될 때 Alt+Enter를 눌러 표시되는 제안 중 Sorround with... 를 선택해 주세요.

   (버전에 따른 if 분기를 하는 코드가 생성됨)

 

5. 건반에 동적으로 클릭 이벤트 정의

-- MainActivity (최종 소스 코드)

class MainActivity : AppCompatActivity() {

 

   override fun onCreate(savedInstanceState: Bundle?) {

      super.onCreate(savedInstanceState)

      setContentView(R.layout.activity_main)

 

      sounds.forEach { tune(it)}   // sounds 리스트를 각각 tune()에 전달

   }

 

   private val soundPool = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

      SoundPool.Builder().setMaxStreams(8).build()  // 한꺼번에 재생하는 음원 개수 (8개 동시 재생)  *1

   } else {

      SoundPool(8, AudioManager.STREAM_MUSIC, 0) // 최대 재생 스트림 개수, 음원 종류, 음질 (default: 0)

   }

 

   private val sounds = listOf(  // 리스트 객체

      Pair(R.id.do1, R.raw.do1),

      Pair(R.id.re, R.raw.re),

      Pair(R.id.mi, R.raw.mi),

      Pair(R.id.fa, R.raw.fa),

      Pair(R.id.sol, R.raw.sol),

      Pair(R.id.la, R.raw.la),

      Pair(R.id.si, R.raw.si),

      Pair(R.id.do2, R.raw.do2)

   )

 

   private fun tune(pitch: Pair<Int, Int>) {

      val soundId = soundPool.load(this, pitch.second, 1)  // 음원 id 얻기

      findViewById<TextView>(pitch.first).setOnClickListener {   // 텍스트 뷰의 id에 해당하는 뷰 얻기

         soundPool.play(soundId, 1.0f, 1.0f, 0, 0, 1.0f)

      }

   }

 

   override fun onDestroy() {

      super.onDestroy()

      soundPool.release()

   }

}

}

 

 

실행한 후 각 건반을 터치 해 봅시다.

(건반을 누르면 저장된 음원을 재생하며 소리가 납니다)

[완성한 모양]

 

 

 

 

<<< 이전 글 보기      다음 글 보기 >>>

 

 

+ Recent posts