C++에서 음악 파일 동시 재생하기
개발 환경 : VS2015에서 Debug, x64 모드로 작업.
소제목: MCI 라이브러리 흉보기...
그런데 대체로 MCI 라이브러리가 동작이 된다고 하니, 일단 2번의 mci 내용을 시도해보시길.
1. PlaySound 함수
동시 재생은 안되지만 wav 파일을 재생가능한 코드를 찾아내었다. 파일 하나씩 재생할 목적이라면 이 방법이 가장 간단하다.
//헤더 선언
#include <windows.h>
//라이브러리 추가
#pragma comment(lib, "winmm.lib")
//main문 내부에서든 어디서든 음악을 재생할 때
PlaySound("file.wav", NULL, SND_FILENAME | SND_ASYNC);
음악을 멈추고 멈춘 부분부터 재생하고, 처음부터 재생하는 등의 응용 방법은 생략한다. PlaySound 함수를 검색해보자.
2. mciSendCommand 함수
mp3 파일인 경우 다중재생이 가능하다. 또 wav 파일도 재생할 수 있다. 다음 링크에 들어가면 mp3 파일을 재생하는 코드가 있다. 채택된 답변에 있는 코드를 붙여 넣고, filename 변수에 들어가는 파일 경로만 내가 원하는대로 고쳐주기만 하면 된다. 고 했다.
그런데 알수없는 이유로 재생이 안된다. 디버깅이 거의 불가능하다.
https://stackoverflow.com/questions/38597898/win32-playsound-overlapping-audio
Win32 PlaySound overlapping audio
I have a C++ Win32 app that needs to be able to play an external .wav file every time a certain event is triggered. I currently have code that looks like this: void CALLBACK timerCall(HWND hwnd, U...
stackoverflow.com
그래서 이 글의 소제목은 MCI 라이브러리 흉보기이다.
3. DirectShow SDK 제공 함수 사용
DirectShow SDK를 사용하면 다중 재생이 된다. 생각보다 사용하기도 쉽다고 하였다.
그런데 워낙에 요즘은 C++에서 음성 재생을 하지 않기 때문에 관련 정보가 검색해도 잘 나오지 않고, 10여년 전 정보가 많다. 그 당시 DirectShow SDK는 원래 DirectX SDK 아래 있었는데, DirectX를 빠져 나오면서, dependencies가 생겨 사용하기 어려워졌다는 얘기가 있었다. 그런데 현재는 Windows SDK에 들어갔고, 사용 방법이 Microsoft 사이트에 문서로 꽤나 잘 정리되어 있다!
자세한 내용은 Microsoft article을 참고하면 된다.
https://docs.microsoft.com/en-us/windows/desktop/directshow/directshow
DirectShow - Windows applications
DirectShow In this article --> The Microsoft DirectShow application programming interface (API) is a media-streaming architecture for Microsoft Windows. Using DirectShow, your applications can perform high-quality video and audio playback or capture. The D
docs.microsoft.com
다음은 헤더파일과 라이브러리 세팅을 추가한 Microsoft article에서 제공된 예제 코드이다.
#include <dshow.h>
#pragma comment (lib, "strmiids.lib")
void main(void)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change this string to a file on your system.
hr = pGraph->RenderFile(L"C:\\A4.mp3", NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}