1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: snd_HardwareManager.cpp
4
5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain proprietary
8 information of Nintendo and/or its licensed developers and are protected by
9 national and international copyright laws. They may not be disclosed to third
10 parties or copied or duplicated in any form, in whole or in part, without the
11 prior written consent of Nintendo.
12
13 The content herein is highly confidential and should be handled accordingly.
14
15 $Revision: 32385 $
16 *---------------------------------------------------------------------------*/
17
18 #include "precompiled.h"
19 #include <nw/snd/snd_HardwareManager.h>
20
21 #include <nw/snd/snd_VoiceManager.h>
22 #include <nw/assert.h>
23 #include <cstring>
24
25 #include NW_SND_ADAPTIVE_SOURCE( HardwareManager )
26
27 namespace nw {
28 namespace snd {
29 namespace internal {
30 namespace driver {
31
32 const BiquadFilterLpf HardwareManager::BIQUAD_FILTER_LPF;
33 const BiquadFilterHpf HardwareManager::BIQUAD_FILTER_HPF;
34 const BiquadFilterBpf512 HardwareManager::BIQUAD_FILTER_BPF_512;
35 const BiquadFilterBpf1024 HardwareManager::BIQUAD_FILTER_BPF_1024;
36 const BiquadFilterBpf2048 HardwareManager::BIQUAD_FILTER_BPF_2048;
37
SetOutputMode(OutputMode mode)38 void HardwareManager::SetOutputMode( OutputMode mode )
39 {
40 if ( m_OutputMode == mode ) return;
41
42 m_OutputMode = mode;
43
44 #ifdef NW_PLATFORM_CTR
45 switch ( mode )
46 {
47 case OUTPUT_MODE_MONO:
48 nn::snd::SetSoundOutputMode( nn::snd::OUTPUT_MODE_MONO );
49 break;
50 case OUTPUT_MODE_STEREO:
51 nn::snd::SetSoundOutputMode( nn::snd::OUTPUT_MODE_STEREO );
52 break;
53 case OUTPUT_MODE_SURROUND:
54 nn::snd::SetSoundOutputMode( nn::snd::OUTPUT_MODE_3DSURROUND );
55 break;
56 default:
57 NW_ASSERT( false );
58 break;
59 }
60 #endif
61
62 // コマンドを投げる
63 {
64 DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance();
65 DriverCommandAllVoicesSync* command =
66 cmdmgr.AllocCommand<DriverCommandAllVoicesSync>();
67 command->id = DRIVER_COMMAND_ALLVOICES_SYNC;
68 command->syncFlag = Voice::UPDATE_MIX;
69 cmdmgr.PushCommand(command);
70 }
71
72 // エフェクトの出力モード変更処理
73 for ( int bus = 0; bus < AUX_BUS_NUM; bus++ )
74 {
75 FxList& list = GetEffectList( static_cast<AuxBus>( bus ) );
76 for ( FxList::Iterator itr = list.GetBeginIter();
77 itr != list.GetEndIter();
78 ++itr )
79 {
80 itr->OnChangeOutputMode();
81 }
82 }
83 }
84
GetOutputVolume() const85 f32 HardwareManager::GetOutputVolume() const
86 {
87 f32 volume = m_MasterVolume.GetValue();
88 volume *= m_VolumeForReset.GetValue();
89 return volume;
90 }
91
SetMasterVolume(float volume,int fadeTimes)92 void HardwareManager::SetMasterVolume( float volume, int fadeTimes )
93 {
94 if ( volume < 0.0f ) volume = 0.0f;
95 m_MasterVolume.SetTarget(
96 volume,
97 ( fadeTimes + HardwareManager::SOUND_FRAME_INTERVAL_MSEC - 1 )
98 / SOUND_FRAME_INTERVAL_MSEC
99 );
100
101 if ( fadeTimes == 0 )
102 {
103 // コマンドを投げる
104 DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance();
105 DriverCommandAllVoicesSync* command =
106 cmdmgr.AllocCommand<DriverCommandAllVoicesSync>();
107 command->id = DRIVER_COMMAND_ALLVOICES_SYNC;
108 command->syncFlag = Voice::UPDATE_VE;
109 cmdmgr.PushCommand(command);
110 }
111 }
112
113 /* ========================================================================
114 SRC タイプ
115 ======================================================================== */
116
117 /*---------------------------------------------------------------------------*
118 Name: SetSrcType
119
120 Description: SRC タイプを変更する
121
122 Arguments: type: SRC タイプ
123
124 Returns: なし
125 *---------------------------------------------------------------------------*/
SetSrcType(SrcType type)126 void HardwareManager::SetSrcType( SrcType type )
127 {
128 if ( m_SrcType == type ) return;
129
130 m_SrcType = type;
131
132 // コマンドを投げる
133 {
134 DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance();
135 DriverCommandAllVoicesSync* command =
136 cmdmgr.AllocCommand<DriverCommandAllVoicesSync>();
137 command->id = DRIVER_COMMAND_ALLVOICES_SYNC;
138 command->syncFlag = Voice::UPDATE_SRC;
139 cmdmgr.PushCommand(command);
140 }
141 }
142
143 /* ========================================================================
144 エフェクト
145 ======================================================================== */
146
AppendEffect(AuxBus bus,FxBase * pFx)147 bool HardwareManager::AppendEffect( AuxBus bus, FxBase* pFx )
148 {
149 NW_NULL_ASSERT( pFx );
150
151 if ( ! m_AuxFadeVolume[ bus ].IsFinished() )
152 {
153 FinalizeEffect( bus );
154 }
155
156 m_AuxFadeVolume[ bus ].SetTarget( 1.0f, 0 );
157 #ifdef NW_PLATFORM_CTRWIN
158 switch ( bus )
159 {
160 case AUX_BUS_A:
161 AX_SetAuxAReturnVolume( AUX_RETURN_VOLUME_MAX );
162 break;
163 case AUX_BUS_B:
164 AX_SetAuxBReturnVolume( AUX_RETURN_VOLUME_MAX );
165 break;
166 }
167 #else
168 nn::snd::SetAuxReturnVolume( static_cast<nn::snd::AuxBusId>(bus), AUX_RETURN_VOLUME_MAX );
169 #endif
170
171 if ( GetEffectList( bus ).IsEmpty() )
172 {
173 #ifdef NW_PLATFORM_CTRWIN
174 switch ( bus )
175 {
176 case AUX_BUS_A:
177 AX_RegisterAuxACallback( AuxCallbackFunc, reinterpret_cast<void*>( bus ) );
178 break;
179 case AUX_BUS_B:
180 AX_RegisterAuxBCallback( AuxCallbackFunc, reinterpret_cast<void*>( bus ) );
181 break;
182 }
183 #else
184 nn::snd::RegisterAuxCallback(
185 static_cast<nn::snd::AuxBusId>( bus ),
186 AuxCallbackFunc,
187 static_cast<uptr>( bus ) );
188 #endif
189 }
190
191 GetEffectList( bus ).PushBack( pFx );
192 return true;
193 }
194
195 #ifdef NW_PLATFORM_CTR
AppendEffect(AuxBus bus,nn::snd::FxDelay * delay)196 bool HardwareManager::AppendEffect( AuxBus bus, nn::snd::FxDelay* delay )
197 {
198 NW_NULL_ASSERT( delay );
199 if ( ! m_AuxFadeVolume[ bus ].IsFinished() )
200 {
201 FinalizeEffect( bus );
202 }
203 m_AuxFadeVolume[ bus ].SetTarget( 1.0f, 0 );
204 nn::snd::SetAuxReturnVolume( static_cast<nn::snd::AuxBusId>(bus), AUX_RETURN_VOLUME_MAX );
205 bool result = nn::snd::SetEffect( static_cast<nn::snd::AuxBusId>(bus), delay );
206 return result;
207 }
208
AppendEffect(AuxBus bus,nn::snd::FxReverb * reverb)209 bool HardwareManager::AppendEffect( AuxBus bus, nn::snd::FxReverb* reverb )
210 {
211 NW_NULL_ASSERT( reverb );
212 if ( ! m_AuxFadeVolume[ bus ].IsFinished() )
213 {
214 FinalizeEffect( bus );
215 }
216 m_AuxFadeVolume[ bus ].SetTarget( 1.0f, 0 );
217 nn::snd::SetAuxReturnVolume( static_cast<nn::snd::AuxBusId>(bus), AUX_RETURN_VOLUME_MAX );
218 bool result = nn::snd::SetEffect( static_cast<nn::snd::AuxBusId>(bus), reverb );
219 return result;
220 }
221 #endif
222
ClearEffect(AuxBus bus,int fadeTimes)223 void HardwareManager::ClearEffect( AuxBus bus , int fadeTimes )
224 {
225 if ( fadeTimes == 0 )
226 {
227 FinalizeEffect( bus );
228
229 if ( m_AuxFadeVolume[ bus ].IsFinished() )
230 {
231 m_AuxFadeVolume[ bus ].SetTarget( 0.0f, 0 );
232 }
233 }
234 else
235 {
236 m_AuxFadeVolume[ bus ].SetTarget(
237 0.0f,
238 ( fadeTimes + SOUND_FRAME_INTERVAL_MSEC - 1 ) / SOUND_FRAME_INTERVAL_MSEC
239 );
240 }
241 }
242
FinalizeEffect(AuxBus bus)243 void HardwareManager::FinalizeEffect( AuxBus bus )
244 {
245 #ifdef NW_PLATFORM_CTR
246 nn::snd::ClearEffect( static_cast<nn::snd::AuxBusId>( bus ) );
247 #endif
248
249 FxList& list = GetEffectList( bus );
250 if ( list.IsEmpty() )
251 {
252 return;
253 }
254
255 #ifdef NW_PLATFORM_CTRWIN
256 switch ( bus )
257 {
258 case AUX_BUS_A:
259 AX_RegisterAuxACallback( NULL, NULL );
260 break;
261 case AUX_BUS_B:
262 AX_RegisterAuxBCallback( NULL, NULL );
263 break;
264 #ifdef NW_PLATFORM_RVL
265 case AUX_C:
266 AX_RegisterAuxCCallback( NULL, NULL );
267 break;
268 #endif
269 }
270 m_EffectProcessTick[ bus ] = 0;
271 #else
272 nn::snd::ClearAuxCallback( static_cast<nn::snd::AuxBusId>( bus ) );
273 m_EffectProcessTick[ bus ] = nn::os::Tick( 0 );
274 #endif
275
276 for ( FxList::Iterator itr = list.GetBeginIter();
277 itr != list.GetEndIter();
278 ++itr )
279 {
280 itr->Finalize();
281 }
282 list.Clear();
283 }
284
285 #ifdef NW_PLATFORM_CTRWIN
AuxCallbackFunc(void * data,void * context)286 void HardwareManager::AuxCallbackFunc( void *data, void *context )
287 {
288 AuxBus bus = static_cast<AuxBus>( reinterpret_cast<u32>( context ) );
289 NW_MINMAXLT_ASSERT( bus, AUX_BUS_A, AUX_BUS_A + AUX_BUS_NUM );
290
291 OSTick tick = OS_GetTick();
292
293 // バッファ設定
294 void* buffer[4];
295 int numChannels;
296 OutputMode outputMode = GetInstance().GetOutputMode();
297 {
298 AXFX_BUFFERUPDATE* axfxbuf = static_cast<AXFX_BUFFERUPDATE*>( data );
299 numChannels = 3;
300 buffer[0] = axfxbuf->left;
301 buffer[1] = axfxbuf->right;
302 buffer[2] = axfxbuf->surround;
303 }
304
305 // エフェクト処理
306 for ( FxList::Iterator itr = GetInstance().GetEffectList( bus ).GetBeginIter();
307 itr != GetInstance().GetEffectList( bus ).GetEndIter();
308 (void)++itr
309 )
310 {
311 #if 0
312 itr->UpdateBuffer(
313 numChannels,
314 buffer,
315 FX_BUFFER_SIZE,
316 FX_SAMPLE_FORMAT,
317 static_cast<float>( FX_SAMPLE_RATE ),
318 outputMode
319 );
320 #endif
321 }
322
323 // 処理時間計測
324 GetInstance().m_EffectProcessTick[ bus ] = static_cast<OSTick>( OS_DiffTick( OS_GetTick(), tick ) );
325 }
326 #else
AuxCallbackFunc(nn::snd::AuxBusData * data,s32 sampleLength,uptr userData)327 void HardwareManager::AuxCallbackFunc(
328 nn::snd::AuxBusData *data,
329 s32 sampleLength,
330 uptr userData )
331 {
332 AuxBus bus = static_cast<AuxBus>( userData );
333 NW_MINMAXLT_ASSERT( bus, AUX_BUS_A, AUX_BUS_A + AUX_BUS_NUM );
334 const size_t FX_BUFFER_SIZE = sizeof(s32) * sampleLength;
335
336 nn::os::Tick tick = nn::os::Tick::GetSystemCurrent();
337
338 // バッファ設定
339 int numChannels;
340 OutputMode outputMode = GetInstance().GetOutputMode();
341 switch ( outputMode )
342 {
343 case OUTPUT_MODE_SURROUND:
344 numChannels = 4;
345 break;
346 case OUTPUT_MODE_MONO:
347 case OUTPUT_MODE_STEREO:
348 default:
349 numChannels = 2;
350 break;
351 };
352
353 // エフェクト処理
354 for ( FxList::Iterator itr = GetInstance().GetEffectList( bus ).GetBeginIter();
355 itr != GetInstance().GetEffectList( bus ).GetEndIter();
356 ++itr )
357 {
358 itr->UpdateBuffer(
359 numChannels,
360 data,
361 sampleLength,
362 FX_SAMPLE_FORMAT,
363 static_cast<f32>( FX_SAMPLE_RATE ),
364 outputMode );
365 }
366 GetInstance().m_EffectProcessTick[ bus ] = nn::os::Tick::GetSystemCurrent() - tick;
367 }
368 #endif
369
SetBiquadFilterCallback(int type,const BiquadFilterCallback * cb)370 void HardwareManager::SetBiquadFilterCallback( int type, const BiquadFilterCallback* cb )
371 {
372 NW_MINMAX_ASSERT( type, BIQUAD_FILTER_TYPE_NONE, BIQUAD_FILTER_TYPE_USER_MAX );
373
374 if ( type == BIQUAD_FILTER_TYPE_NONE /* 0 */ )
375 {
376 // 0 番は Biquad フィルタ OFF なので、なにもしない
377 return;
378 }
379
380 m_BiquadFilterCallbackTable[ type ] = cb;
381 }
382
383 } // namespace nw::snd::internal:driver
384 } // namespace nw::snd::internal
385 } // namespace nw::snd
386 } // namespace nw
387