[.NET] 여러 사운드 파일 한번에 재생하기 - mciSendString
.NET으로 사운드 파일을 재생하려면 보통 'SoundPlayer'를 사용합니다.
근데 이놈은 한 번에 하나의 파일만 재생이 가능합니다.
여러 파일을 재생하려면
'DirectX SDK', 'Windows Media Player SDK', 'NAudio' 같은 외부 라이브러리를 이용하거나
'WinAPI'를 이용해야 합니다.
이 포스팅에서는 'WinAPI'의 'mciSendString'를 이용하여 재생하겠습니다.
1. 'SoundPlayer'를 사용해 보자
'SoundPlayer'를 사용하여 파일을 재생해봅시다.
아래와 같이 개체를 초기화하고
private SoundPlayer _soundPlayer1;
this._soundPlayer1 = new SoundPlayer();
this._soundPlayer1.SoundLocation = @"SoundFiles\IsUse.wav";
아래 코드로 재생을 해봅시다.
this._soundPlayer1.Play();
재생이 끝나기 전에 다시 재생을 시도하면
기존 재생이 끊기고 다시 재생하는것을 확인할 수 있습니다.
2. 'mciSendString'를 이용하자
WinAPI기 때문에 'DllImport'를 통해 "winmm.dll"파일을 불러와야 합니다.
'mciSendString'의 진입점은 아래와 같이 선언하면 됩니다.
/// <summary>
/// https://docs.microsoft.com/ko-kr/previous-versions//dd757161(v=vs.85)
/// </summary>
/// <param name="command"></param>
/// <param name="buffer"></param>
/// <param name="bufferSize"></param>
/// <param name="hwndCallback"></param>
/// <returns></returns>
[DllImport("winmm.dll")]
static extern Int32 mciSendString(
string command
, StringBuilder buffer
, int bufferSize
, IntPtr hwndCallback);
2-1. 파일 열기
'mciSendString'로 파일을 열려면 아래와 같이 명령어를 만들어야 합니다.
//open [파일 경로] type [파일 타입] alias [구분용 고유이름]
open SoundFiles\IsUse.wav type waveaudio alias SoundMci1
이걸 위에서 만든 진입점의 'command' 파라메타에 넣어주면 됩니다.
mciSendString(@"open SoundFiles\IsUse.wav type waveaudio alias SoundMci1"
, null, 0, IntPtr.Zero);
2-2. 파일 재생하기
파일 재생 명령어는 아래와 같습니다.
//play [구분용 고유이름]
play SoundMci1
'play SoundMci1'을 여러 번 전달해도 재생은 한 번만 되는 것을 알 수 있습니다.
이런 현상이 일어나는 이유는 재생되던 위치를 그대로 가지고 있기 때문입니다.
2-3. 재생 위치 초기화
재생 위치를 초기화하면 처음부터 파일이 재생되게 됩니다.
//seek [구분용 고유이름] to start
seek SoundMci1 to start
이 명령어를 사용하면 재생 중이던 개체(구분용 고유이름 기준)는 재생을 정지합니다.
2-4. 파일 재생 정지
재생 중인 개체도 정지시킬 수 있습니다.
//stop [구분용 고유이름]
stop SoundMci1
하지만 다시 재생하면 멈췄던 부분부터 재생됩니다.
'pause'와 차이점을 모르겠습니다.
처음부터 재생하려면 '2-3. 재생 위치 초기화'를 해야 합니다.
3. 테스트 프로그램
github - dang-gun/DotNetSamples/SoundPlayerTest
윈폼으로 간단하게 만들었습니다.
마무리
이 이슈가 오래된 거로 아는데 왜 .NET에서 공식적으로 지원을 하지 않는지 모르겠습니다.
구현 방법이 없는 것도 아닐 텐데 말이죠....
다른 플랫폼들 때문에 그러나?? 아니면 외부 라이브러리로 커버가 가능해서 그런가?