2017년 8월 8일 화요일

SoundPool & MediaPlayer

안드로이드 스튜디오에서 음향효과를 내는 방법은 두가지가 있습니다. SoundPool을 이용하는 방법과 MediaPlayer을 쓰는 방법이 있습니다.
마찬가지로 자마린에서도 이 두 가지 방법을 사용할 수 있습니다. 이때 필요한 wav파일은 Resource폴더에 raw폴더를 만들어 넣는 것이 좋습니다.


다른 포멧의 음향파일(*.mp3 등)을 리소스로 등록할 수도 있을것 같은데, 제 경우에는 버전문제인지 컴파일이 안되더군요. 일단 wav파일을 넣고 실험해 봤습니다.

1. MediaPlayer
MediaPlayer를 이용해서 소리를 내는 간단한 예제입니다.

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Media;

namespace SoundEffect.Droid
{
    [Activity(Label = "SoundEffect.Android", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        MediaPlayer player1;
        MediaPlayer player2;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById<Button>(Resource.Id.myButton);

            // MediaPlayer객체를 만듦
            player1 = MediaPlayer.Create(this, Resource.Raw.cartoon_22);
            player2 = MediaPlayer.Create(this, Resource.Raw.CoinDrop);

            button.Click += delegate
            {
                button.Text = "Click!";

                // MediaPlayer 소리
                player1.Start();
                player2.Start();
                //player1.Stop();
                //player2.Stop();
            };
        }
    }
}

물론 MediaPlayer.Stop(), MediaPlayer.Pause() 등 여러 메소드가 있지만 이에 대해서는 다음 기회에 다루기로 하겠습니다.

2. SoundPool
이번에는 SoundPool 예제입니다.

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Media;

namespace SoundEffect.Droid
{
    [Activity(Label = "SoundEffect.Android", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        SoundPool pool;
        int soundID1;
        int soundID2;
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById<Button>(Resource.Id.myButton);

            // SoundPool 객체 만들고 리소스 로드
            pool = new SoundPool(4, Stream.System, 0);
            soundID1 = pool.Load(this, Resource.Raw.cartoon_22, 1);
            soundID2 = pool.Load(this, Resource.Raw.CoinDrop, 1);
            // int변수 player1, player2로 제어

            button.Click += delegate
            {
                button.Text = "Click!";

                // 음향 출력
                int streamID1 = pool.Play(soundID1, 1, 1, 0, 0, 1);
                int streamID2 = pool.Play(soundID2, 1, 1, 0, 0, 1);
                //pool.Stop(streamID1);
                //pool.Stop(streamID2);
            };
        }
    }
}

SoundPool.Play()함수의 인수가 많은데, 각각의 인수는 다음과 같은 의미입니다.

int play (int soundID,         // Load함수에서 받아온 SoundID
          float leftVolume,    // 왼쪽 스피커 출력(0 ~ 1)
          float rightVolume,   // 오른쪽 스피커 출력(0 ~ 1)
          int priority,        // 우선순위 - 채널이 가득차면 가장 낮은 음향 제거
          int loop,            // 1 : 끝나면 처음부터 다시 실행, 0 : 한번만 실행
          float rate)          // 재생배율(2 : 2배 재생)

MediaPlayer가 wav파일 하나당 객체 하나를 만들어 관리하는데 비해, SoundPool은 많은 wav파일을 모아서 관리합니다. 그러므로 비교적 사용이 간단한 MediaPlayer에 비해 사용이 복잡하죠. Load시 SoundID를 받아 Play시 사용하며, Play시마다 streamID를 받아 소리를 멈추거나 끝내는데 사용해야 합니다.

MediaPlayer는 짧은 음향효과보다는 배경음악같은 긴 소리를 재생하는데 좋습니다. 실제로 짧은 소리를 MediaPlayer로 반복, 중복재생하면 오동작하는 경우가 종종 있습니다.
반면 SoundPool은 짧은 사운드이펙트를 구현하는데 적당하죠.