WP7 - 오디오 출력하기


1. MediaElement

재생할 음원을 프로젝트에 추가후에 속성에서 아래와 같이 변경합니다.
"출력 디렉터리로 복사"는 "항상 복사"로 하셔도 됩니다.
참고로 말씀드리자면..
"항상복사"로 하시면 솔루션 탐색기에 있는 Content(내용)이 빌드할때마다 bin 밑으로 항상 새로 복사됩니다.
"변경된 내용만 복사"를 하시면, 솔루션 탐색기에서 변경이 될때만 bin 밑으로 새로 복사됩니다.

사용자 삽입 이미지

MediaElement me = new MediaElement();
me.Source = new Uri("asdf.mp3", UriKind.RelativeOrAbsolute);
me.Play();
me.Volume = 1; // 볼륨은 0~1
me.Stop();

 

2. XNA의 SoundEffect

Windows Phone 7에서
Winform 개발시 사용했던 사운드 플레이어와 똑같이 사용해 보고 싶어서 하나 만들어봤습니다.

윈폼에서 사용하던 놈 : System.Media.SoundPlayer
윈폰에서 사용할 놈 : Microsoft.Xna.Framework.Audio.SoundEffect

우씨~~~!!! 윈폼(winform), 윈폰(windows phone) 헷갈리네요..

암튼.. 나중에 어떻게 될지 몰라서..
System.Media.SoundPlayer 와의 호환성을 위해 interface 하나 만들었습니다.
간단히 테스트는 해봤지만.. 버그가 있을 수도 있답니다. ^^;
참고로.. 테스트해보니 mp3는 안되더군요.. wav 파일을 사용하세요.

Interface

using System;
using System.IO;

namespace Kimstar.WP7.Library.Audio
{
    public delegate void StringListEvent(IAudioPlayer sender);

    /// <summary>
    /// 음원을 재생하기 위합니다.<br/>
    /// 음원은 Stream 또는 wav파일을 사용합니다.
    /// </summary>
    public interface IAudioPlayer
    {
        // 속성 ----------------------------------
        string SoundLocation { get; set; }
        Stream Stream { get; set; }
        bool IsLoadCompleted { get; }

        // 이벤트 ----------------------------------
        event EventHandler SoundLocationChanged;
        event EventHandler StreamChanged;

        // 메소드 ----------------------------------
        void Load();
        void Play();
        void PlayLooping();
        void Stop();
    }

}

Player

using System;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

namespace Kimstar.WP7.Library.Audio
{
    public class XAudioPlayer : IAudioPlayer
    {
        SoundEffect m_soundEffect;
        string m_soundLocation;
        Stream m_stream;
        bool m_isLoaded = false;
        SoundEffectInstance m_soundInstanceLoop;
        SoundEffectInstance m_soundInstanceOnce;



        // 생성자 -------------------------------
        /// <summary>
        /// XAudioPlayer 클래스의 새 인스턴스를 초기화합니다.
        /// </summary>
        public XAudioPlayer()
        {
            ResetPlayer();
        }

        private void ResetPlayer()
        {
            if (m_soundEffect != null) m_soundEffect.Dispose();
            m_soundEffect = null;

            if (m_soundInstanceLoop != null) m_soundInstanceLoop.Dispose();
            m_soundInstanceLoop = null;

            if (m_soundInstanceOnce != null) m_soundInstanceOnce.Dispose();
            m_soundInstanceOnce = null;

            m_isLoaded = false;
        }

        /// <summary>
        /// XAudioPlayer 클래스의 새 인스턴스를 초기화합니다.
        /// </summary>
        /// <param name="stream">.wav 파일에 대한 System.IO.Stream입니다.</param>
        public XAudioPlayer(Stream stream)
        {
            ResetPlayer();
            m_soundLocation = string.Empty;
            m_stream = stream;
            OnStreamChanged();
        }

        /// <summary>
        /// XAudioPlayer 클래스의 새 인스턴스를 초기화하고 지정된 .wav 파일을 연결합니다.
        /// </summary>
        /// <param name="soundLocation">로드할 .wav 파일의 위치입니다.</param>
        /// <exception cref="System.UriFormatException">soundLocation으로 지정된 URL 값을 확인할 수 없는 경우</exception>
        public XAudioPlayer(string soundLocation)
        {
            ResetPlayer();
            m_soundLocation = soundLocation;
            m_stream = null;
            OnSoundLocationChanged();
        }

        // 속성 -----------------
        /// <summary>
        /// Play() 또는 PlayLoop() 실행시 기존에 재생하던 음원을 끝까지 재생후 연결하여 재생을 원하면 true를 설정합니다.
        /// </summary>
        public bool IsImmediatelyPlay { get; set; }


        /// <summary>
        /// 로드할 .wav 파일의 파일 경로 또는 URL을 가져오거나 설정합니다.
        /// </summary>
        /// <returns>로드할 .wav 파일이 있는 파일 경로 또는 URL이거나, 파일 경로가 없는 경우 System.String.Empty입니다.기본값은 System.String.Empty입니다.</returns>
        public string SoundLocation
        {
            get { return m_soundLocation; }
            set 
            {
                ResetPlayer();
                m_soundLocation = value;
                m_stream = null;
                OnSoundLocationChanged();
            }
        }

        /// <summary>
        /// 로드할 .wav 파일이 포함된 System.IO.Stream을 가져오거나 설정합니다.
        /// </summary>
        /// <returns>로드할 .wav 파일이 포함된 System.IO.Stream이거나, 사용할 수 있는 스트림이 없는 경우 null입니다.기본값은 null입니다.</returns>
        public System.IO.Stream Stream
        {
            get { return m_stream; }
            set 
            {
                ResetPlayer();
                m_soundLocation = string.Empty;
                m_stream = value;
                OnStreamChanged();
            }
        }


        /// <summary>
        /// .wav 파일 로드가 성공적으로 완료되었는지 여부를 나타내는 값을 가져옵니다.
        /// </summary>
        /// <returns>.wav 파일이 로드되었으면 true이고, .wav 파일이 아직 로드되지 않았으면 false입니다.</returns>
        public bool IsLoadCompleted
        {
            get 
            {
                if (string.IsNullOrEmpty(m_soundLocation) && m_stream == null)
                    return false;
                else
                    return m_isLoaded;
            }
        }


        // 이벤트 핸들러 -------------------------------
        /// <summary>
        /// 이 XAudioPlayer의 새 오디오 소스 경로가 설정되었을 때 발생합니다.
        /// </summary>
        public event EventHandler SoundLocationChanged;

        /// <summary>
        /// 이 XAudioPlayer의 새 System.IO.Stream 오디오 소스가 설정되었을 때 발생합니다.
        /// </summary>
        public event EventHandler StreamChanged;


        private void OnSoundLocationChanged()
        {
            EventHandler temp = SoundLocationChanged;

            if (temp != null)
            {
                temp(this, new EventArgs());
            }
        }

        private void OnStreamChanged()
        {
            EventHandler temp = StreamChanged;

            if (temp != null)
            {
                temp(this, new EventArgs());
            }
        }



        // 메소드 -------------------------------
        /// <summary>
        /// 음원을 로드합니다.
        /// </summary>
        /// <exception cref="System.IO.FileNotFoundException">XAudioPlayer.SoundLocation으로 지정된 파일을 찾을 수 없는 경우</exception>
        public void Load()
        {
            StopSound();

            if (!string.IsNullOrEmpty(m_soundLocation))
            {
                m_soundEffect = SoundEffect.FromStream(TitleContainer.OpenStream(m_soundLocation));
                //m_soundEffect = SoundEffect.FromStream(new FileStream(m_soundLocation, FileMode.Open, FileAccess.Read));               
                m_isLoaded = true;
            }
            else if (m_stream != null)
            {
                m_soundEffect = SoundEffect.FromStream(m_stream);
                m_isLoaded = true;
            }
            else
            {
                ResetPlayer();
                m_isLoaded = false;
            }
        }

        /// <summary>
        /// 새 스레드를 사용하여 .wav 파일을 재생하며, .wav 파일이 아직 로드되지 않았으면 먼저 .wav 파일을 로드합니다.
        /// </summary>
        /// <exception cref="System.IO.FileNotFoundException">XAudioPlayer.SoundLocation으로 지정된 파일을 찾을 수 없는 경우</exception>
        /// <exception cref="System.InvalidOperationException">.wav 헤더가 손상된 경우, 즉 XAudioPlayer.SoundLocation으로 지정된 파일이 PCM .wav 파일이 아닌 경우</exception>
        public void Play()
        {
            if (m_isLoaded == false || m_soundEffect == null)
                Load();

            if (m_isLoaded == true && m_soundEffect != null)
                PlayOnce(m_soundEffect);
        }

        /// <summary>
        /// 새 스레드를 사용하여 .wav 파일을 재생 및 반복하며, .wav 파일이 아직 로드되지 않았으면 먼저 .wav 파일을 로드합니다.
        /// </summary>
        /// <exception cref="System.IO.FileNotFoundException">XAudioPlayer.SoundLocation으로 지정된 파일을 찾을 수 없는 경우</exception>
        /// <exception cref="System.InvalidOperationException">.wav 헤더가 손상된 경우, 즉 XAudioPlayer.SoundLocation으로 지정된 파일이 PCM .wav 파일이 아닌 경우</exception>
        public void PlayLooping()
        {
            if (m_isLoaded == false || m_soundEffect == null)
                Load();

            if (m_isLoaded == true && m_soundEffect != null)
                PlayLoop(m_soundEffect);
        }


        /// <summary>
        /// 소리가 재생 중인 경우 재생을 중지합니다.
        /// </summary>
        public void Stop()
        {
            StopSound();
        }



        /// <summary>
        /// 음원을 한번만 재생합니다.
        /// </summary>
        protected void PlayOnce(SoundEffect soundEffect)
        {
            if (IsImmediatelyPlay == true)
            {
                StopSound();
            }
            else
            {
                if (m_soundInstanceLoop != null)
                    m_soundInstanceLoop.Stop();
            }

            if (m_soundInstanceOnce == null)
            {
                m_soundInstanceOnce = soundEffect.CreateInstance();
                m_soundInstanceOnce.IsLooped = false;
            }
            m_soundInstanceOnce.Play();
        }

        /// <summary>
        /// 음원을 반복하여 재생합니다.
        /// </summary>
        protected void PlayLoop(SoundEffect soundEffect)
        {
            if (IsImmediatelyPlay == true)
            {
                StopSound();
            }
            else
            {
                if (m_soundInstanceOnce != null)
                    m_soundInstanceOnce.Stop();
            }

            if (m_soundInstanceLoop == null)
            {
                m_soundInstanceLoop = soundEffect.CreateInstance();
                m_soundInstanceLoop.IsLooped = true;
            }
            m_soundInstanceLoop.Play();
        }

        /// <summary>
        /// 음원 재생을 중지합니다.
        /// </summary>
        protected void StopSound()
        {
            if(m_soundInstanceLoop != null)
                m_soundInstanceLoop.Stop();
            if (m_soundInstanceOnce != null)
                m_soundInstanceOnce.Stop();
        }
    }
}

 

사용시

화면에 버튼 4개 추가, 로드 / 한번재생 / 반복재생 / 중지

using System.Windows;
using Kimstar.WP7.Library.Audio;
using Microsoft.Phone.Controls;

namespace KimstarWP7LibraryTest
{
    public partial class pageXAudio : PhoneApplicationPage
    {
        IAudioPlayer m_audioPlayer;

        public pageXAudio()
        {
            InitializeComponent();

            btnPlayLoop.IsEnabled = false;
            btnPlayOnce.IsEnabled = false;
            btnStop.IsEnabled = false;

        }


        private void btnLoad_Click(object sender, RoutedEventArgs e)
        {
            if (m_audioPlayer == null)
            {
                m_audioPlayer = new XAudioPlayer();
                m_audioPlayer.SoundLocation = "allegro.wav";
            }

            if (m_audioPlayer.IsLoadCompleted == false)
            {
                m_audioPlayer.Load();
            }

            btnPlayLoop.IsEnabled = m_audioPlayer.IsLoadCompleted;
            btnPlayOnce.IsEnabled = m_audioPlayer.IsLoadCompleted;
            btnStop.IsEnabled = m_audioPlayer.IsLoadCompleted;
        }

        private void btnPlayOnce_Click(object sender, RoutedEventArgs e)
        {
            m_audioPlayer.Play();
        }

        private void btnPlayLoop_Click(object sender, RoutedEventArgs e)
        {
            m_audioPlayer.PlayLooping();
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            m_audioPlayer.Stop();
        }
    }
}

 

3. 그밖에

MSDN을 찾아보니..
Background Audio, Background Audio Streamer 라는 놈도 있군요.
요건 나중에 테스트 해봐야겠습니다.

 

광고

댓글 남기기