- 발표에 꼭 들어가야 할 것들
- 프로그램에서 사운드 재생은 어떻게 하는가?
- 프로그램에서 동영상 재생은 어떻게 하는가?
- 프로그램에서 사운드 재생은 어떻게 하는가?
1. 사운드 연주 ¶
MFC는 멀티미디어를 위한 별도의 클래스를 제공하지 않는다. Win32 API함수 차원에서 멀티미디어를 지원하기 때문에 MFC에서는 별도의 클래스로 만들어 놓지 않은 것이다.
우선 사운드를 연주하는 API함수를 보자.
우선 사운드를 연주하는 API함수를 보자.
~cpp BOOL PlaySound(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound);
pszSound : 연주할 사운드 파일의 이름. 파일의 경로를 넣을 더 수도 있다.
hmod : 리소스에 있는 Wave파일을 연주할 경우 리소스를 가진 실행파일의 핸들인데, 그 외의 경우는 NULL로 준다.
fdwSound : 사운드의 연주방식과 연주할 사운드의 종류를 정의하는 플래그이다. 이것에 따라 첫 번째, 두 번째 인수의 해석 방식이 달라진다. 여러 플래그 중 몇 가지만 알아보자.
- SND_FILENAME : 첫 번째 인수인 pszSound는 사운드 파일의 이름이다.
- SND_ASYNC : 비동기화된 연수를 한다. 연주시작 후 바로 리턴하므로 다른 작업을 바로 시작할 수 있다.
- SND_LOOP : 지정한 사운드를 반복적으로 계속 연주한다. 이 플래그는 반드시 SND_ASYNC와 함께 사용되어야 한다.
- SND_SYNC : 동기화된 연주를 한다. 사운드 파일의 연주가 완전히 끝나기 전에는 리턴하지 않는다.
- SND_ASYNC : 비동기화된 연수를 한다. 연주시작 후 바로 리턴하므로 다른 작업을 바로 시작할 수 있다.
- SND_LOOP : 지정한 사운드를 반복적으로 계속 연주한다. 이 플래그는 반드시 SND_ASYNC와 함께 사용되어야 한다.
- SND_SYNC : 동기화된 연주를 한다. 사운드 파일의 연주가 완전히 끝나기 전에는 리턴하지 않는다.
예제) AppWizard를 사용하여 Sound라는 이름으로 SDI 프로젝트를 만든다.
뷰에 WM_LBUTTONDOWN메시지의 핸들러를 만들고 OnLButtonDown 핸들러에 다음과 같이 코드를 작성한다.
뷰에 WM_LBUTTONDOWN메시지의 핸들러를 만들고 OnLButtonDown 핸들러에 다음과 같이 코드를 작성한다.
~cpp #include "mmsystem.h" void CSoundView::..... { PlaySound("Battle.wav", NULL, SND_SYNC); CView:.... }
PlaySound 함수를 사용하려면 mmsystem.h 파일을 먼저 include 해주어야 하고,
Project/ Settings/Link 탭에서 winmm.lib를 링크해 주어야 한다.
그 후 컴파일하고 실행한 후 작업영역을 왼쪽 마우스 버튼으로 누르면 소리가 날 것이다. 시스템에 사운드카드가 장착되어 있어야 하며 같은 디렉토리에 Battle.wav라는 파일이 있어야 할 것이다.Project/ Settings/Link 탭에서 winmm.lib를 링크해 주어야 한다.
1-2) 비동기 연주
앞서 만든 예제를 보면 PlaySound 함수는 사운드 파일 연주가 완전히 종료되기 전에는 리턴하지 않으므로 연주중인 동안은 어떤 일도 할 수 없다. 이런 방법을 동기화 방식이라고 한다.
반대로 PlaySound함수가 연주를 시작해 놓고 곧바로 리턴하는 비동기 연주 방식이 있다.
이번에는 SND_LOOP 플래그를 사용하여 작성해 보고, WM_RBUTTONDOWN 메시지의 핸들러도 같이 만들어보자.
반대로 PlaySound함수가 연주를 시작해 놓고 곧바로 리턴하는 비동기 연주 방식이 있다.
이번에는 SND_LOOP 플래그를 사용하여 작성해 보고, WM_RBUTTONDOWN 메시지의 핸들러도 같이 만들어보자.
~cpp void CSoundView::OnLB......... { PlaySound("Battle.wav", NULL, SND_ASYNC | SND_LOOP); CView:.... } void CSoundView::OnRB...... { PlaySound(NULL, NULL, 0); CView:.... }
SND_LOOP 플래그를 지정하면 반복적인 효과음이나 배경음악을 연주하는 등의 설정을 할 수 있을 것이다. 연주를 중지시키려면 PlaySound 함수의 첫 번째 인수를 NULL로 하여 다시 호출해 주면 된다. 따라서, 오른쪽 마우스 버튼을 누르면 연주가 중지될 것이다. 주의할 것은 SND_LOOP 플래그는 반드시 SND_ASYNC와 함께 사용해야 한다. 만약 동기화 연주방식으로 반복연주를 하면 무한 루프로 빠져버릴 위험이 있다.
1-3) 리소스의 Wave 연주사운드 파일을 연주하는 것은 사용하기는 간단하지만 연주할 때마다 디스크에서 사운드 파일을 읽어와야 하므로 반응 속도가 느리다. 따라서 이 경우에는 사운드 파일을 리소스에 포함시켜 놓고 리소스에서 읽어서 연주하는 방법으로 하는 것이 좋을 것이다.
앞에서 만든 예제를 수정해서 Battle.wav 파일을 실행파일에 합쳐보자.
리소스 뷰의 팝업메뉴에서 Import 메뉴항목을 선택하고 리소스에 포함시키고자 하는 Wave 파일을 선택한다. 그러면 IDR_WAVE1이라는 ID로 리소스에 삽입될 것이다.
리소스에 포함된 사운드를 연주하려면 PlaySound의 세 번째 인수에 SND_RESOURCE 플래그를 주고 첫 번째 인수에 리소스의 ID를 준다. 두 번째 인수에는 리소스를 가진 실행파일의 인스턴스 핸들을 주어야 하는데 MFC에서는 AfxGetInstanceHandle() 전역함수로 인스턴스 핸들을 구할 수 있다. 다음과 같이 코드를 작성해 보자.
앞에서 만든 예제를 수정해서 Battle.wav 파일을 실행파일에 합쳐보자.
리소스 뷰의 팝업메뉴에서 Import 메뉴항목을 선택하고 리소스에 포함시키고자 하는 Wave 파일을 선택한다. 그러면 IDR_WAVE1이라는 ID로 리소스에 삽입될 것이다.
리소스에 포함된 사운드를 연주하려면 PlaySound의 세 번째 인수에 SND_RESOURCE 플래그를 주고 첫 번째 인수에 리소스의 ID를 준다. 두 번째 인수에는 리소스를 가진 실행파일의 인스턴스 핸들을 주어야 하는데 MFC에서는 AfxGetInstanceHandle() 전역함수로 인스턴스 핸들을 구할 수 있다. 다음과 같이 코드를 작성해 보자.
~cpp void CSoundView::OnLButtonDown(UINT nFlags, CPoint point) { PlaySound(MAKEINTRESOURCE(IDR_WAVE1), AfxGetInstanceHandle(), SND_RESOURCE | SND_ASYNC); CView:OnLButtonDown(nFlags, point); }
이렇게 하면 실행파일 속에 wav파일이 포함되어 Battle.wav파일이 없어도 연주할수 있게 된다.
1-4) MCI (Media Control Interface)PlaySound함수는 메모리 크기의 제한을 받아서 1-2분 정도의 사운드 밖에 낼 수 없다는 점, Wave형태만 지원한다는 점, 연주과정에 사용자가 개입할 수 없다는 단점이 있다.
MCI는 멀티미디어 요소에 대한 지원을 장치독립적으로 제공하는 일종의 라이브러리이다. 이것은 PlaySound 함수가 하지 못하는 여러 가지 일을 할 수 있지만, 사용 방법은 훨씬 더 복잡하다.
MCI는 멀티미디어 요소에 대한 지원을 장치독립적으로 제공하는 일종의 라이브러리이다. 이것은 PlaySound 함수가 하지 못하는 여러 가지 일을 할 수 있지만, 사용 방법은 훨씬 더 복잡하다.
SoundMwm.zip |
2. 동영상 재생 ¶
2-1) PlayAVI
MCI를 사용하면 동영상도 아주 쉽게 재생할 수 있다. AppWizard로 PlayAVI라는 SDI 프로젝트를 만들고 WM_LBUTTONDOWN 메시지의 핸들러와 WM_DESTROY 메시지의 핸들러를 다음과 같이 작성한다.
MCI를 사용하면 동영상도 아주 쉽게 재생할 수 있다. AppWizard로 PlayAVI라는 SDI 프로젝트를 만들고 WM_LBUTTONDOWN 메시지의 핸들러와 WM_DESTROY 메시지의 핸들러를 다음과 같이 작성한다.
~cpp HWND hWndAVI=0; void CPlayAVIView::OnLButtonDown... { if(hWndAVI) { MCIWndClose(hWndAVI); MCIWndDestroy(hWndAVI); hWndAVI=0; } hWndAVI=MCIWndCreate(this->m_hWnd, AfxGetInstanceHandle(), 0, "cf3.avi"); if(hWndAVI) { MCIWndPlay(hWndAVI); } CView::OnLButtonDown(nFlags, point); } void CPlayAVIView::OnDestroy() { CView::OnDestroy(); MCIWndDestroy(hWndAVI); }
동영상 연주는 Video fot window 라이브러리를 사용하므로 뷰에서 vfw.h를 인클루드 해 주어야 한다.
~cpp #include "PlayAVIDoc.h" #include "PlayAVIView.h" #include <vfw.h>
또한 프로젝트에서 이 라이브러리를 사용할 수 있도록 Project/Settings/Link 탭에 vfw32.lib를 추가한다. 그리고 동영상 파일을 프로젝트 디렉토리에 넣어두면 된다.
MCIWnd 윈도우는 마우스 왼쪽 버튼을 눌르면 만들어진다. 그 전에 hWndAVI가 유효하면 먼저 MCIWnd를 닫는 작업부터 해주고 있다. MCIWnd를 만드는 함수는 MCIWndCreate 함수이다.~cpp HWND MCIWndCreate(HWND hwndParent, HINSTANCE hinstance, DWORD dwStyle, LPSTR szFile);