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