-
[WinAPI] FMOD로 3D 음향 구현하기프로그래밍 공부/Win API 2023. 2. 15. 09:49728x90
FMOD로 프레임워크가 이미 구축되어 있기에 해당 프레임워크에 추가하여 사용하기로 했다.
해당 글은 다음 문서를 기반으로 추가했다.
https://documentation.help/FMOD-Ex/3dsound.html
3D Sound - FMOD Ex Documentation
Firelight Technologies FMOD Ex
documentation.help
일단 리스너의 변수를 할당해주고, 필요한 함수를 추가해주었다.
private: System* _system; Sound** _sound; Channel** _channel; arrSounds _mTotalSounds; FMOD_VECTOR listenerPos; FMOD_VECTOR listenerForward; FMOD_VECTOR listenerUp; FMOD_VECTOR listenerVel; public: ... void add3DSound(string keyName, string soundName); void play3D(string keyName, float volume, FMOD_VECTOR pos, FMOD_VECTOR vel); ... FMOD_VECTOR getListenerPos() { return listenerPos; } void setListenerPos(FMOD_VECTOR _listenerPos) { listenerPos = _listenerPos; }
이하는 추가되거나 수정된 부분만 확인한다.
soundManager.cpp
HRESULT SoundManager::init(void) { //사운드 시스템 생성 System_Create(&_system); //시스템 초기화 _system->init(totalSoundChannel, FMOD_INIT_NORMAL, 0); //3D 사운드 설정 _system->set3DSettings(1.0f, 1.0f, 1.0f); //채널수 만큼 메모리 버퍼 및 사운드를 생성하겠다. _sound = new Sound * [totalSoundChannel]; _channel = new Channel * [totalSoundChannel]; //메모리 한번 밀자 memset(_sound, 0, sizeof(Sound*) * (totalSoundChannel)); memset(_channel, 0, sizeof(Channel*) * (totalSoundChannel)); listenerPos = { 0.0f, 0.0f, 0.0f }; listenerForward = { 0.0f, 0.0f, 1.0f }; listenerUp = { 0.0f, 1.0f, 0.0f }; listenerVel = { 0.0f, 0.0f, 0.0f }; return S_OK; }
set3DSettings의 매개변수
- float dopplerscale: 도플러 효과 스케일. 기본값은 1.0이다. 1보다 크면 더 과장된 소리를 낸다.
- float distancefactor: 3D 위치의 단위. 기본값은 1.0이다.
- float rolloffscale: 3D 사운드의 릴롱필터 강도. 기본값은 1.0
더보기도플러 효과란?
거리에서 경찰차가 다가올때는 사이렌 소리의 피치가 증가하여 반대로 경찰차가 지나가면 소리의 피치가 감소하는 현상이 발생한다. 이를 도플러 효과라고 한다.
void SoundManager::update(void) { _system->set3DListenerAttributes(0, &listenerPos, &listenerVel, &listenerForward, &listenerUp); _system->update(); }
set3DListenerAttributes의 매개변수
int listener: 다중 수신기 환경의 수신기 ID입니다.수신기가 하나만 있는 경우 0을 지정합니다.
const FMOD_VECTOR pos: 위치. 거리 단위로 측정된 월드 공간에서 청자의 위치입니다.위치를 업데이트하지 않으려면 0 또는 NULL을 지정할 수 있습니다. 세 개의 실수(float) 값으로 이루어진 3D 좌표입니다.
const FMOD_VECTOR vel: 속도. 초당 거리 단위로 측정된 청취자의 속도입니다.리스너의 속도를 업데이트하지 않으려면 0 또는 NULL을 지정할 수 있습니다. 속도는 세 개의 실수(float) 값으로 이루어진 3D 벡터입니다.
const FMOD_VECTOR forward: 청자의 정방향입니다.이 벡터는 단위 길이여야 하며 위쪽 벡터에 수직이어야 합니다.수신기의 정방향을 업데이트하지 않으려면 0 또는 NULL을 지정할 수 있습니다.
const FMOD_VECTOR up: 청취자의 위쪽 방향입니다.이 벡터는 단위 길이여야 하며 정방향 벡터에 수직이어야 합니다.수신기의 위쪽 방향을 업데이트하지 않으려면 0 또는 NULL을 지정할 수 있습니다.사운드를 추가할 때 FMOD_3D 속성을 이용해야 하기 때문에 함수를 추가 작성했다.
void SoundManager::add3DSound(string keyName, string soundName) { _system->createSound(soundName.c_str(), FMOD_3D, 0, &_sound[_mTotalSounds.size()]); //맵에 사운드를 키값과 함께 넣어준다. _mTotalSounds.insert(make_pair(keyName, &_sound[_mTotalSounds.size()])); }
만약 루프를 한다면
_system->createStream(soundName.c_str(), FMOD_3D | FMOD_LOOP_NORMAL, 0, &_sound[_mTotalSounds.size()]);
와 같이 속성값을 추가해주면 되지만, 3D음향 중 루프되는 게 없으므로 제외하기로 했다.
마지막으로 플레이 함수를 만들었다.
void SoundManager::play3D(string keyName, float volume, FMOD_VECTOR pos, FMOD_VECTOR vel) { arrSoundIter iter = _mTotalSounds.begin(); int count = 0; for (iter; iter != _mTotalSounds.end(); ++iter, count++) { if (keyName == iter->first) { _system->playSound(FMOD_CHANNEL_FREE, *iter->second, false, &_channel[count]); _channel[count]->set3DAttributes(&pos, &vel); _channel[count]->setVolume(volume); break; } } }
set3DAttributes(&pos, &vel); 3D음향이 나올 위치와 속력값을 인자로 갖는다.
예를 들어 플레이어가 x,y,z의 pos 값이 {0,0,0}이고, 음량이 {-1,0,0}일 경우 보다 왼쪽에서 소리가 나게 된다.
728x90'프로그래밍 공부 > Win API' 카테고리의 다른 글
[WinAPI] 동영상 추가하기 (0) 2023.02.17 [WinAPI] STL 우선순위 큐(Priority Queue, PQueue) (0) 2023.02.15 [WinAPI] 프레임워크에 기반한 JSON 세이브로드(저장/파싱) (0) 2023.01.30 [WinAPI] Json 예제 작성 및 시도 (0) 2023.01.20 [WinAPI] 프레임워크 구축(17) - JSON 매니저 만들기 (0) 2023.01.19