Fix "no remove aqua speed" bug when player leaves the water
[ryzomcore.git] / nel / src / sound / driver / xaudio2 / effect_xaudio2.cpp
blobfb7b1a3b93061fcf5cc6a4a82eb4bf5262dfdc03
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2008 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdxaudio2.h"
19 // Project includes
20 #include "sound_driver_xaudio2.h"
21 #include "listener_xaudio2.h"
22 #include "effect_xaudio2.h"
24 #ifdef DEBUG_NEW
25 #define new DEBUG_NEW
26 #endif
28 using namespace std;
29 using namespace NLMISC;
31 namespace NLSOUND {
33 CEffectXAudio2::CEffectXAudio2(CSoundDriverXAudio2 *soundDriver, uint channels) : _SoundDriver(soundDriver), _DryVoice(NULL), _FilterVoice(NULL), _Effect(NULL)
35 HRESULT hr;
37 XAUDIO2_VOICE_DETAILS voice_details;
38 soundDriver->getListener()->getDryVoice()->GetVoiceDetails(&voice_details);
40 if (channels == 0)
41 channels = voice_details.InputChannels;
43 // Mix voice
45 if (FAILED(hr = soundDriver->getXAudio2()->CreateSubmixVoice(&_DryVoice, channels, voice_details.InputSampleRate, 0, 4510, NULL, NULL)))
46 { release(); _SoundDriver = NULL; nlwarning(NLSOUND_XAUDIO2_PREFIX "FAILED CreateSubmixVoice _DryVoice!"); return; }
48 XAUDIO2_VOICE_SENDS voiceSends;
49 XAUDIO2_SEND_DESCRIPTOR sendDescriptor;
50 voiceSends.pSends = &sendDescriptor;
51 voiceSends.SendCount = 1;
52 sendDescriptor.Flags = 0;
53 sendDescriptor.pOutputVoice = soundDriver->getListener()->getDryVoice();
54 _DryVoice->SetOutputVoices(&voiceSends);
56 if (channels == 1)
58 FLOAT32 outputMatrix[32];
59 for (uint32 i = 0; i < voice_details.InputChannels; ++i)
60 outputMatrix[i] = 1.0f;
61 _DryVoice->SetOutputMatrix(sendDescriptor.pOutputVoice, 1, voice_details.InputChannels, outputMatrix);
65 // Filter dummy voice
67 if (FAILED(hr = soundDriver->getXAudio2()->CreateSubmixVoice(&_FilterVoice, channels, voice_details.InputSampleRate, 0, 4500, NULL, NULL)))
68 { release(); _SoundDriver = NULL; nlwarning(NLSOUND_XAUDIO2_PREFIX "FAILED CreateSubmixVoice _FilterVoice!"); return; }
70 XAUDIO2_VOICE_SENDS voiceSends;
71 XAUDIO2_SEND_DESCRIPTOR sendDescriptor;
72 voiceSends.pSends = &sendDescriptor;
73 voiceSends.SendCount = 1;
74 sendDescriptor.Flags = 0;
75 sendDescriptor.pOutputVoice = _DryVoice;
76 _FilterVoice->SetOutputVoices(&voiceSends);
80 CEffectXAudio2::~CEffectXAudio2()
82 release();
83 if (_SoundDriver) { _SoundDriver->removeEffect(this); _SoundDriver = NULL; }
86 void CEffectXAudio2::release()
88 if (_FilterVoice) { _FilterVoice->DestroyVoice(); _FilterVoice = NULL; }
89 if (_DryVoice) { _DryVoice->DestroyVoice(); _DryVoice = NULL; }
92 CReverbEffectXAudio2::CReverbEffectXAudio2(CSoundDriverXAudio2 *soundDriver) : CEffectXAudio2(soundDriver, 1)
94 if (_DryVoice)
96 HRESULT hr;
98 uint flags = 0;
99 #ifdef NL_DEBUG
100 flags |= XAUDIO2FX_DEBUG;
101 #endif
102 if (FAILED(hr = XAudio2CreateReverb(&_Effect, flags)))
103 { release(); nlwarning(NLSOUND_XAUDIO2_PREFIX "XAudio2CreateReverb FAILED"); return; }
105 XAUDIO2_VOICE_DETAILS voice_details;
106 _DryVoice->GetVoiceDetails(&voice_details);
107 XAUDIO2_EFFECT_DESCRIPTOR effect_descriptor;
108 effect_descriptor.InitialState = TRUE;
109 effect_descriptor.OutputChannels = voice_details.InputChannels;
110 effect_descriptor.pEffect = _Effect;
111 XAUDIO2_EFFECT_CHAIN effect_chain;
112 effect_chain.EffectCount = 1;
113 effect_chain.pEffectDescriptors = &effect_descriptor;
114 if (FAILED(hr = _DryVoice->SetEffectChain(&effect_chain)))
115 { release(); nlwarning(NLSOUND_XAUDIO2_PREFIX "SetEffectChain FAILED"); return; }
117 setEnvironment();
121 CReverbEffectXAudio2::~CReverbEffectXAudio2()
126 void CReverbEffectXAudio2::release()
128 CEffectXAudio2::release();
129 if (_Effect) { _Effect->Release(); _Effect = NULL; }
132 /// Set the environment (you have full control now, have fun)
133 void CReverbEffectXAudio2::setEnvironment(const CEnvironment &environment, float roomSize)
135 // unused params
136 _ReverbParams.LowEQCutoff = 4;
137 _ReverbParams.HighEQCutoff = 6;
138 _ReverbParams.RearDelay = XAUDIO2FX_REVERB_DEFAULT_REAR_DELAY;
139 _ReverbParams.PositionLeft = XAUDIO2FX_REVERB_DEFAULT_POSITION;
140 _ReverbParams.PositionRight = XAUDIO2FX_REVERB_DEFAULT_POSITION;
141 _ReverbParams.PositionMatrixLeft = XAUDIO2FX_REVERB_DEFAULT_POSITION_MATRIX;
142 _ReverbParams.PositionMatrixRight = XAUDIO2FX_REVERB_DEFAULT_POSITION_MATRIX;
143 _ReverbParams.RoomFilterFreq = 5000.0f;
144 _ReverbParams.WetDryMix = 100.0f;
146 // directly mapped
147 _ReverbParams.Density = environment.Density;
148 _ReverbParams.RoomFilterMain = environment.RoomFilter;
149 _ReverbParams.RoomFilterHF = environment.RoomFilterHF;
150 _ReverbParams.ReverbGain = environment.LateReverb;
151 _ReverbParams.ReflectionsGain = environment.Reflections;
152 _ReverbParams.RoomSize = roomSize;
154 // conversions, see ReverbConvertI3DL2ToNative in case of errors
155 if (environment.DecayHFRatio >= 1.0f)
157 _ReverbParams.HighEQGain = XAUDIO2FX_REVERB_DEFAULT_HIGH_EQ_GAIN;
158 sint32 index = (sint32)(log10(environment.DecayHFRatio) * -4.0f) + 8;
159 clamp(index, XAUDIO2FX_REVERB_MIN_LOW_EQ_GAIN, XAUDIO2FX_REVERB_MAX_LOW_EQ_GAIN);
160 _ReverbParams.LowEQGain = (BYTE)index;
161 _ReverbParams.DecayTime = environment.DecayTime * environment.DecayHFRatio;
163 else
165 _ReverbParams.LowEQGain = XAUDIO2FX_REVERB_DEFAULT_LOW_EQ_GAIN;
166 sint32 index = (sint32)(log10(environment.DecayHFRatio) * 4.0f) + 8;
167 clamp(index, XAUDIO2FX_REVERB_MIN_HIGH_EQ_GAIN, XAUDIO2FX_REVERB_MAX_HIGH_EQ_GAIN);
168 _ReverbParams.HighEQGain = (BYTE)index;
169 _ReverbParams.DecayTime = environment.DecayTime;
172 sint32 reflections_delay = (sint32)(environment.ReflectionsDelay * 1000.0f);
173 clamp(reflections_delay, XAUDIO2FX_REVERB_MIN_REFLECTIONS_DELAY, XAUDIO2FX_REVERB_MAX_REFLECTIONS_DELAY);
174 _ReverbParams.ReflectionsDelay = (UINT32)reflections_delay;
176 sint32 reverb_delay = (sint32)(environment.LateReverbDelay * 1000.0f);
177 clamp(reverb_delay, XAUDIO2FX_REVERB_MIN_REVERB_DELAY, XAUDIO2FX_REVERB_MAX_REVERB_DELAY);
178 _ReverbParams.ReverbDelay = (BYTE)reverb_delay;
180 _ReverbParams.EarlyDiffusion = (BYTE)(environment.Diffusion * 0.15f);
181 _ReverbParams.LateDiffusion = _ReverbParams.EarlyDiffusion;
183 _DryVoice->SetEffectParameters(0, &_ReverbParams, sizeof(_ReverbParams), 0);
186 } /* namespace NLSOUND */
188 /* end of file */