1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2008 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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.
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"
20 #include "sound_driver_xaudio2.h"
21 #include "listener_xaudio2.h"
22 #include "effect_xaudio2.h"
29 using namespace NLMISC
;
33 CEffectXAudio2::CEffectXAudio2(CSoundDriverXAudio2
*soundDriver
, uint channels
) : _SoundDriver(soundDriver
), _DryVoice(NULL
), _FilterVoice(NULL
), _Effect(NULL
)
37 XAUDIO2_VOICE_DETAILS voice_details
;
38 soundDriver
->getListener()->getDryVoice()->GetVoiceDetails(&voice_details
);
41 channels
= voice_details
.InputChannels
;
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
);
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
);
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()
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)
100 flags
|= XAUDIO2FX_DEBUG
;
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; }
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
)
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
;
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
;
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 */