|
유튜브 동영상 강의 주소 (2) https://youtu.be/TzhU5MNhlWs (3) https://youtu.be/X4lWB2IZJAs
초기에 사용하기 쉽고 C, C++, Win32 API, MFC등에서 자유롭게 사용할 수 있는 사운드 라이브러리 중에서 FMOD Sound System이 있다. 이 라이브러리에 대한 사항은 저자의 책인 ‘마인드맵을 이용한 C언어 프로그래밍’과 C를 이용한 게임프로그래밍’에서 다룬 내용이다. |
|
이 라이브러리의 특징은 무료이고 사용하기 쉬우며, 콘솔형태에서도 다양한 사운드를 출력할 수 있다는 것이다.
FMOD 사운드 시스템은 www.fmod.org 에서 다운받을 수 있으며 Stable 항목의 최신 버전을 받으면 된다.
또한 자신의 운영체제가 64비트를 사용하고 있더라도 32비트를 받아 설치하면 된다.
[그림 13-1] 윈도우 XP, Vista, 윈도우7 32비트 설치 경로
윈도우 64비트의 설치 경로는 Programming Files(x86) 에서 위 [그림 13-1]을 폴더를 찾아보면 된다.
13.1 FMOD 설치 및 설정
1) FMOD 라이브러리 및 헤더 경로 등록
FMOD 사운드 시스템을 사용하기 위해서는 FMOD 라이브러리와 헤더를 프로그래밍 툴에 등록해야 한다.
- Visual Studio 6.0 (Visual C++ 6.0)
[그림 13-2] 헤더 파일과 라이브러리 경로 등록
- Visual Studio 2008
[그림 13-3] 헤더 파일과 라이브러리 경로 등록
- Visual Studio 2010
Visual Studio 2008에서 헤더와 라이브러리 설정은 [도구]->[옵션]->[프로젝트 및 솔루션]->[VC++ 디렉토리]에서
설정했지만 Visual Studio 2010은 프로젝트를 생성한 후에 [그림 13-4]와 같이 프로젝트 속성에서 헤더와
라이브러리를 설정한다.
[그림 13-4] 헤더 파일과 라이브러리 경로 등록
2) 프로젝트에 FMOD 사운드 라이브러리 설정
이제 FMOD 사운드 라이브러리 fmodex_vc.lib 파일을 프로젝트 생성 후에 아래와 같이 설정해 보자.
(참고: fmodex_vc.lib 파일명은 fmod 제작회사의 변동에 따라 바뀔 수 있다) \
- Visual Studio 6.0 (Visual C++ 6.0)
[그림 13-5] FMOD 사운드 라이브러리 설정
- Visual Studio 2008
[그림 13-6] FMOD 사운드 라이브러리 설정
- Visual Studio 2010
[그림 13-7] FMOD 사운드 라이브러리 설정
3) FMOD 사운드 DLL 파일 복사
fmodex.dll 파일은 FMOD 사운드 시스템이 실행될 때 사용되는 파일로써 프로그램의 실행 파일과 함께
있어야 한다.
[표 13-1]은 fmodex.dll 파일이 있는 폴더의 위치이다.
(참고: fmodex.dll 파일 경로는 fmod 제작 회사의 변동에 따라 바뀔 수 있다 )
OS | 경로 |
윈도우XP, Vista 윈도우7 32비트 | C:\Program Files\FMOD SoundSystem\FMOD Programmers API Win32\api |
윈도우7 64비트 | C:\Program Files (x86)\FMOD SoundSystem\FMOD Programmers API Win32\api |
[표 13-1] fmodex.dll 파일 경로
1) 헤더 설정
#include <fmod.h>
2) FMOD 사운드 시스템 생성과 초기화
FMOD_SYSTEM *g_System; // FMOD system 변수 선언 FMOD_System_Create(&g_System); // FMOD system 객체 생성 FMOD_System_Init( g_System, 32, FMOD_INIT_NORMAL, NULL); // FMOD system 초기화 |
FMOD_RESULT FMOD_System_Create( FMOD_SYSTEM ** system ); |
FMOD_RESULT FMOD_System_Init( FMOD_SYSTEM * system, int maxchannels, FMOD_INITFLAGS flags, void * extradriverdata ); |
[표 13-2] FMOD 사운드 시스템 함수의 원형
3) 출력 가능한 사운드 형식
AIFF, ASF, ASX, DLS, FLAC, FSB, IT, M3U, MID, MOD, MP2, MP3, OGG, PLS, RAW, S3M, VAG, WAV, WMA, XM, XMA
4) 사운드 객체 생성과 사운드 로딩
FMOD_SOUND *sound;
FMOD_SOUND는 사운드 파일과 일대일 대응하며 아래의 함수로 사운드 객체와 파일 로딩을 동시에 한다.
FMOD_System_CreateSound( g_System, “파일경로 및 파일명", FMOD_DEFAULT , 0, &sound); |
사운드의 출력 형태는 크게 배경 사운드와 효과 사운드로 나눌 수 있으며 출력 형태에 따라 사운드의 모드를
다르게 설정한다.
FMOD_MODE | 역할 |
FMOD_DEFAULT | FMOD_LOOP_OFF | FMOD_2D | FMOD_HARDWARE의 설정과 같으며 사운드를 1번만 출력한다. |
FMOD_LOOP_NORMAL | 사운드를 반복적으로 출력한다. |
[표 13-3] FMOD 사운드 출력 모드
FMOD_RESULT FMOD_System_CreateSound( FMOD_SYSTEM * system, const char * name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO * exinfo, FMOD_SOUND ** sound ); |
[표 13-4] FMOD 함수의 원형
5) 사운드 출력
사운드 객체(FMOD_SOUND *sound)를 통해 읽혀진 사운드는 채널(channel)을 통해 출력된다.
따라서 하나의 사운드 파일은 여러 개의 채널을 통해 출력할 수 있다.
FMOD_CHANNEL *channel; |
채널을 통해 사운드를 출력 및 정지시킬 수 있다. 그러므로 효과 사운드를 출력하는 경우에는 채널을
지역 변수로 선언할 수 있지만 배경 사운드를 출력하는 경우에는 static 또는 전역 변수로 선언해야 한다.
FMOD_System_PlaySound( g_System, FMOD_CHANNEL_FREE, sound, 0, &channel); |
FMOD_RESULT FMOD_System_PlaySound( FMOD_SYSTEM * system, FMOD_CHANNELINDEX channelid, FMOD_SOUND * sound, FMOD_BOOL paused, FMOD_CHANNEL ** channel); |
[표 13-5] FMOD 함수의 원형
6) 사운드 출력 정지
아래의 함수를 사용하면 채널을 통해 출력 중인 사운드를 언제든지 정지시킬 수 있다.
FMOD_Channel_Stop( channel ); |
FMOD_RESULT FMOD_Channel_Stop( FMOD_CHANNEL * channel); |
[표 13-6] FMOD 함수의 원형
7) 볼륨 조절
볼륨 조절은 아래 함수의 volume 변수로 조절하며 볼륨 범위는 0.0f부터 1.0f까지이다.
FMOD_Channel_SetVolume( FMOD_CHANNEL * channel, float volume ); |
위의 함수에서 주의할 점은 볼륨 대상이 채널이라는 것이다.
FMOD_RESULT FMOD_Channel_SetVolume( FMOD_CHANNEL * channel, float volume ); |
[표 13-7] FMOD 함수의 원형
8) 출력 사운드의 데이터 갱신
FMOD를 이용하여 사운드를 출력하고 있는 상태에서는 계속적으로 아래의 함수를 호출해야 한다.
FMOD_System_Update( g_System ); |
이와 같이 해 주는 이유는, 사운드 파일을 한꺼번에 메모리에 읽어 출력하는 방식을 사용하는 것이 아니라 사운드 파일을 일정한 크기 단위로 매번 읽어 출력하는 스트리밍(streamming) 방식을 사용하기 때문이다.
FMOD_RESULT FMOD_System_Update( FMOD_SYSTEM * system); |
[표 13-8] FMOD 함수의 원형
9) FMOD 해제
FMOD_Sound_Release(sound); // FMOD sound 객체 해제 FMOD_System_Close( g_System ); // FMOD system 객체 clsoe FMOD_System_Release( g_System ); // FMOD system 객체 해제 |
1) 사운드 파일 1개를 읽고 사운드 출력과 정지 및 소리 조절이 될 수 있도록 프로그램을 작성해 보자.
p 키는 사운드 출력, s 키는 사운드 정지, u 키는 볼륨 높임, d 키는 볼륨 줄임 키이다.
#include “StdAfx.h” #include <conio.h> #include <fmod.h>
FMOD_SYSTEM *g_System; // Note: FMOD system 변수선언 FMOD_SOUND *g_Sound;
void Init() { FMOD_System_Create(&g_System); FMOD_System_Init( g_System, 32, FMOD_INIT_NORMAL, NULL); FMOD_System_CreateSound( g_System, "run.wav", FMOD_DEFAULT, 0, &g_Sound); }
void Release() { FMOD_Sound_Release(g_Sound); FMOD_System_Close( g_System ); FMOD_System_Release( g_System ); }
int main(void) { int nKey; FMOD_CHANNEL *channel = NULL; float volume = 0.5f; FMOD_BOOL IsPlaying;
Init();
while( 1 ) { if( _kbhit() ) { nKey = _getch(); if( nKey == 'q' ) // q 키가 눌리면 프로그램 종료 break
switch( nKey ) { case 'p' : FMOD_System_PlaySound( g_System, FMOD_CHANNEL_FREE, g_Sound, 0, &channel); break; case 's' : FMOD_Channel_Stop( channel ); break; case 'u' : volume += 0.1f; if( volume > 1.0f ) volume = 1.0f; FMOD_Channel_SetVolume( channel, volume ); break case 'd' : volume -= 0.1f; if( volume < 0.0f ) volume = 0.0f; FMOD_Channel_SetVolume( channel, volume ); break; } }
FMOD_Channel_IsPlaying( channel, &IsPlaying ); if( IsPlaying == 1 ) FMOD_System_Update( g_System ); } Release(); return 0; } |
2) 배경 사운드 1개와 효과음 1개를 읽고 's' 키 입력에 따라 효과음이 출력되도록 프로그래밍 해보자.
#include <stdio.h> #include <windows.h> #include <conio.h> #include <time.h> #include “StdAfx.h” #include <fmod.h>
FMOD_SYSTEM *g_System; // Note: FMOD system 변수선언 FMOD_SOUND *g_Sound[2]; FMOD_CHANNEL *g_Channel;
void Init() { FMOD_System_Create(&g_System); FMOD_System_Init( g_System, 32, FMOD_INIT_NORMAL, NULL); FMOD_System_CreateSound( g_System, [안내]태그제한으로등록되지않습니다-bgsound.wav", FMOD_LOOP_NORMAL, 0, &g_Sound[0]); FMOD_System_CreateSound( g_System, "safe.wav", FMOD_DEFAULT, 0, &g_Sound[1]); // 배경음 출력 FMOD_System_PlaySound( g_System, FMOD_CHANNEL_FREE, g_Sound[0], 0, &g_Channel); }
void Release() { int i; for( i =0 ; i < 2 ; i++ ) FMOD_Sound_Release(g_Sound[i]); // FMOD sound 객체 해제
FMOD_System_Close( g_System ); // FMOD system 객체 clsoe FMOD_System_Release( g_System ); // FMOD system 객체 해제 }
int main(void) { int nKey; FMOD_CHANNEL *pChannel;
Init();
while( 1 ) { if( _kbhit() ) { nKey = _getch(); if( nKey == 's' ) FMOD_System_PlaySound( g_System, FMOD_CHANNEL_FREE, g_Sound[1], 0, &pChannel); } FMOD_System_Update( g_System ); }
Release(); return 0; } |
1) CFmodSound 클래스 헤더
#pragma once #include <fmod.h> #include <string> using namespace std;
class CFmodSound { private: FMOD_SYSTEM* m_pSystem; FMOD_SOUND** m_ppBGSound; FMOD_SOUND** m_ppEFFSound; FMOD_CHANNEL** m_ppBGChannel; int m_nEFSoundCount; int m_nBGSoundCount; public: void CreateEffectSound( int nCount, string *SoundFileName ); void CreateBGSound( int nCount, string *SoundFileName ); void PlaySoundEffect( int nIndex ); void PlaySoundBG( int nIndex ); void StopSoundBG( int nIndex ); void ReleaseSound(); void Update(); public: CFmodSound(void); ~CFmodSound(void); }; |
2) CFmodSound 클래스 소스
#include "StdAfx.h" #include "FmodSound.h"
CFmodSound::CFmodSound(void) { FMOD_System_Create( &m_pSystem ); FMOD_System_Init( m_pSystem, 32, FMOD_INIT_NORMAL, NULL ); }
CFmodSound::~CFmodSound(void) { FMOD_System_Close( m_pSystem ); FMOD_System_Release( m_pSystem ); }
void CFmodSound::CreateBGSound( int nCount, string *SoundFileName ) { // 효과 사운드 생성 m_nBGSoundCount = nCount; m_ppBGSound = new FMOD_SOUND*[nCount]; m_ppBGChannel = new FMOD_CHANNEL*[nCount];
for( int i = 0 ; i < nCount ; i++ ) FMOD_System_CreateSound( m_pSystem, SoundFileName[i].data(), FMOD_LOOP_NORMAL, 0, &m_ppBGSound[i] ); }
void CFmodSound::CreateEffectSound( int nCount, string *SoundFileName ) { // 백 그라운드 사운드 생성 m_nEFSoundCount = nCount; m_ppEFFSound = new FMOD_SOUND*[nCount];
for( int i = 0 ; i < nCount ; i++ ) FMOD_System_CreateSound( m_pSystem, SoundFileName[i].data(), FMOD_DEFAULT, 0, &m_ppEFFSound[i] ); }
void CFmodSound::PlaySoundEffect( int nIndex ) { if( nIndex < m_nEFSoundCount ) { FMOD_CHANNEL *pChannel; FMOD_System_PlaySound( m_pSystem, FMOD_CHANNEL_FREE, m_ppEFFSound[nIndex], 0, &pChannel ); } }
void CFmodSound::PlaySoundBG( int nIndex ) { if( nIndex < m_nBGSoundCount ) { FMOD_System_PlaySound( m_pSystem, FMOD_CHANNEL_FREE, m_ppBGSound[nIndex], 0, &m_ppBGChannel[nIndex] ); } }
void CFmodSound::StopSoundBG( int nIndex ) { if( nIndex < m_nBGSoundCount ) { FMOD_Channel_Stop( m_ppBGChannel[nIndex] ); } }
void CFmodSound::ReleaseSound() { int i;
delete [] m_ppBGChannel;
for( i = 0 ; i < m_nBGSoundCount ; i++ ) FMOD_Sound_Release( m_ppBGSound[i] ); delete [] m_ppBGSound;
for( i = 0 ; i < m_nEFSoundCount ; i++ ) FMOD_Sound_Release( m_ppEFFSound[i] ); delete [] m_ppEFFSound; }
void CFmodSound::Update() { if( !m_pSystem ) FMOD_System_Update(m_pSystem); } |
#include "stdafx.h" #include <conio.h> #include <string> #include "FmodSound.h" using namespace std;
int _tmain(int argc, _TCHAR* argv[]) { string strBGFileName[] = { "war.mp3", "wave.mp3" }; string strEffectFileName = "play_fire.wav"; int nKey;
CFmodSound FmodSound; FmodSound.CreateBGSound( 2, strBGFileName ); FmodSound.CreateEffectSound( 1, &strEffectFileName );
printf( "사운드 시스템 준비 완료\n" ); printf( "키 1: 배경1 출력 키 2: 효과음 출력 키 3: 배경음 중지 키 q: 종료\n" );
while( 1 ) { nKey = _getch(); if( nKey == '1' ) FmodSound.PlaySoundBG( 1 ); if( nKey == '2' ) FmodSound.PlaySoundEffect(0);
if( nKey == '3' ) FmodSound.StopSoundBG( 1 );
if( nKey == 'q' ) break;
FmodSound.Update(); }
FmodSound.ReleaseSound();
return 0; } |