ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [WinAPI] FMOD로 3D 음향 구현하기
    프로그래밍 공부/Win API 2023. 2. 15. 09:49
    728x90

    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
Designed by Tistory.