1/*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: snd_HardwareManagerAX.cppi 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: $ 16 *---------------------------------------------------------------------------*/ 17 18#include "precompiled.h" 19 20#include <nw/snd/snd_HardwareManager.h> 21 22namespace nw { 23namespace snd { 24namespace internal { 25namespace driver { 26 27namespace 28{ 29NN_ATTRIBUTE_ALIGN(32) u8 s_ZeroBuffer[ HardwareManager::ZERO_BUFFER_SIZE ]; 30const u16 AUX_RETURN_VOLUME_MAX = 0x8000; 31} 32 33// 34// 関数 35// 36/*---------------------------------------------------------------------------* 37 Name: HardwareManager 38 39 Description: コンストラクタ 40 41 Arguments: なし 42 43 Returns: なし 44 *---------------------------------------------------------------------------*/ 45HardwareManager::HardwareManager() 46: m_IsInitialized( false ), 47// m_UpdateVoicePrioFlag( true ), 48 m_pZeroBufferAddress( NULL ), 49 m_OldAidCallback( NULL ), 50 m_ResetReadyCounter( -1 ), 51 m_OutputMode( OUTPUT_MODE_STEREO ), 52 m_SrcType( SRC_TYPE_4TAP ) 53{ 54 m_MasterVolume.InitValue( 1.0f ); 55 m_VolumeForReset.InitValue( 1.0f ); 56 57 for ( int i=0; i<AUX_BUS_NUM; i++ ) 58 { 59 m_AuxFadeVolume[ i ].InitValue( 1.0f ); 60 m_AuxUserVolume[ i ].InitValue( 1.0f ); 61 m_AuxCallback[ i ] = NULL; 62 m_AuxCallbackContext[ i ] = NULL; 63 m_EffectProcessTick[ i ] = 0; 64 } 65} 66 67void* HardwareManager::GetZeroBufferAddress() 68{ 69 NW_ASSERTMSG( m_pZeroBufferAddress, "Zero buffer is not created." ); 70 return m_pZeroBufferAddress; 71} 72 73void HardwareManager::Initialize() 74{ 75 if ( m_IsInitialized ) return; 76 77 // TODO: NW_ASSERTMSG( AI_CheckInit(), "not initialized AI\n" ); 78 79 // ゼロバッファ作成 80 (void)std::memset( s_ZeroBuffer, 0, ZERO_BUFFER_SIZE ); 81 // TODO: DCFlushRange( s_ZeroBuffer, ZERO_BUFFER_SIZE ); 82 m_pZeroBufferAddress = s_ZeroBuffer; 83 84 // AUXコールバック設定 85 // 既に登録されているAUXコールバックを保存する 86 AX_GetAuxACallback( &m_AuxCallback[ AUX_BUS_A ], &m_AuxCallbackContext[ AUX_BUS_A ] ); 87 AX_GetAuxBCallback( &m_AuxCallback[ AUX_BUS_B ], &m_AuxCallbackContext[ AUX_BUS_B ] ); 88 89 // AXコールバック設定(既に登録されているAXコールバックがあれば保存する) 90 m_PreRegisteredCallback = AX_RegisterCallback( &AxCallbackFunc ); 91 92#if 0 // BIQUAD 93 // biquadフィルタテーブル初期化 94 (void)std::memset( sBiquadFilterCallbackTable, 0, sizeof( sBiquadFilterCallbackTable ) ); 95 SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_LPF, &sBiquadFilterLpf ); 96 SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_HPF, &sBiquadFilterHpf ); 97 SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_BPF512, &sBiquadFilterBpf512 ); 98 SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_BPF1024, &sBiquadFilterBpf1024 ); 99 SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_BPF2048, &sBiquadFilterBpf2048 ); 100#endif 101 102 m_IsInitialized = true; 103 m_OutputMode = OUTPUT_MODE_STEREO; 104} 105 106void HardwareManager::Finalize() 107{ 108 if ( !m_IsInitialized ) return; 109 110 // AXコールバックを元に戻す 111 (void)AX_RegisterCallback( m_PreRegisteredCallback ); 112 113 // エフェクトクリア 114 for ( int bus = AUX_BUS_A; bus < AUX_BUS_NUM; bus++ ) 115 { 116 FinalizeEffect( static_cast<AuxBus>( bus ) ); 117 } 118 119 // AXのコールバックを元に戻す 120 AX_RegisterAuxACallback( m_AuxCallback[ AUX_BUS_A ], m_AuxCallbackContext[ AUX_BUS_A ] ); 121 AX_RegisterAuxBCallback( m_AuxCallback[ AUX_BUS_B ], m_AuxCallbackContext[ AUX_BUS_B ] ); 122 for ( int i=0; i<AUX_BUS_NUM; i++ ) 123 { 124 m_AuxCallback[ i ] = NULL; 125 m_AuxCallbackContext[ i ] = NULL; 126 } 127 128 // ゼロバッファへの参照をクリア 129 m_pZeroBufferAddress = NULL; 130 131 m_IsInitialized = false; 132} 133 134void HardwareManager::Update() 135{ 136 // ClearEffect のフェード処理。フェードが完了したらエフェクトをクリア 137 for ( int i=0; i<AUX_BUS_NUM; i++ ) 138 { 139 bool updateFlag = false; 140 if ( ! m_AuxUserVolume[ i ].IsFinished() ) 141 { 142 m_AuxUserVolume[ i ].Update(); 143 updateFlag = true; 144 } 145 if ( ! m_AuxFadeVolume[ i ].IsFinished() ) 146 { 147 m_AuxFadeVolume[ i ].Update(); 148 if ( m_AuxFadeVolume[ i ].IsFinished() ) 149 { 150 FinalizeEffect( static_cast<AuxBus>( i ) ); 151 } 152 updateFlag = true; 153 } 154 155 if ( updateFlag ) 156 { 157 float returnVolumeFloat = 1.0f; 158 returnVolumeFloat *= ut::Clamp( m_AuxUserVolume[ i ].GetValue(), 0.0f, 1.0f ); 159 returnVolumeFloat *= ut::Clamp( m_AuxFadeVolume[ i ].GetValue(), 0.0f, 1.0f ); 160 u16 returnVolume = static_cast<u16>( returnVolumeFloat * AUX_RETURN_VOLUME_MAX ); 161 switch ( i ) 162 { 163 case AUX_BUS_A: 164 AX_SetAuxAReturnVolume( returnVolume ); 165 break; 166 case AUX_BUS_B: 167 AX_SetAuxBReturnVolume( returnVolume ); 168 break; 169 } 170 } 171 } 172 173 // 音量のアップデート 174 if ( ! m_MasterVolume.IsFinished() ) { 175 m_MasterVolume.Update(); 176 VoiceManager::GetInstance().UpdateAllVoicesSync( Voice::UPDATE_VE ); 177 } 178 179 if ( ! m_VolumeForReset.IsFinished() ) { 180 m_VolumeForReset.Update(); 181 VoiceManager::GetInstance().UpdateAllVoicesSync( Voice::UPDATE_VE ); 182 } 183 184 { 185 f32 volume = 1.0f; 186 volume *= m_VolumeForReset.GetValue(); 187 188 volume = ut::Clamp( volume, 0.0f, 1.0f ); 189 190 AX_SetMasterVolume( static_cast<u16>(volume * 0x8000) ); 191 } 192} 193 // RVL は計96ch中、マージン16だった 194 195u32 HardwareManager::GetChannelCount() const 196{ 197 return AX_GetMaxVoices(); 198} 199 200/* ======================================================================== 201 リセット前準備 202 ======================================================================== */ 203 204void HardwareManager::PrepareReset() 205{ 206 if ( m_OldAidCallback != NULL ) return; 207 208 m_VolumeForReset.SetTarget( 0.0f, 3 ); // 3オーディオフレームかけてフェードアウト 209 m_ResetReadyCounter = -1; 210 m_OldAidCallback = ::AI_RegisterDMACallback( AiDmaCallbackFunc ); 211} 212 213void HardwareManager::AiDmaCallbackFunc() 214{ 215 GetInstance().PrepareResetProc(); 216} 217 218void HardwareManager::PrepareResetProc() 219{ 220 static bool finishedFlag = false; 221 m_OldAidCallback(); 222 223 if ( finishedFlag ) 224 { 225 if ( m_ResetReadyCounter < 0 ) 226 { 227 AX_SetMaxDspCycles( 0 ); 228 m_ResetReadyCounter = 6; 229 } 230 } 231 else if ( m_VolumeForReset.GetValue() == 0.0f ) 232 { 233 finishedFlag = true; 234 } 235 236 if ( m_ResetReadyCounter > 0 ) --m_ResetReadyCounter; 237} 238 239bool HardwareManager::IsResetReady() const 240{ 241 return m_ResetReadyCounter == 0 ? true : false; 242} 243 244void HardwareManager::AxCallbackFunc() 245{ 246 // ユーザーコールバックの呼び出し 247 HardwareCallbackFunc(); 248 249 // もともと設定されていたコールバックの呼び出し 250 AXUserCallback callback = GetInstance().m_PreRegisteredCallback; 251 if ( callback != NULL ) 252 { 253 callback(); 254 } 255} 256 257/*---------------------------------------------------------------------------* 258 Name: AxCallbackFunc 259 260 Description: AXコールバックに登録される関数 261 262 Arguments: なし 263 264 Returns: なし 265 *---------------------------------------------------------------------------*/ 266void HardwareManager::HardwareCallbackFunc() 267{ 268 for ( CallbackList::Iterator itr = GetInstance().m_CallbackList.GetBeginIter(); 269 itr != GetInstance().m_CallbackList.GetEndIter(); 270 ) 271 { 272 CallbackList::Iterator curItr = itr++; 273 curItr->callback(); 274 } 275} 276 277/*---------------------------------------------------------------------------* 278 Name: RegisterAxCallback 279 280 Description: AXコールバックの登録をリストに追加する 281 282 Arguments: node: AXコールバックリストのノード 283 callback: AXコールバック関数 284 285 Returns: 286 *---------------------------------------------------------------------------*/ 287void HardwareManager::RegisterCallback( 288 CallbackListNode* node, 289 HardwareCallback callback ) 290{ 291 node->callback = callback; 292 m_CallbackList.PushBack( node ); 293} 294 295/*---------------------------------------------------------------------------* 296 Name: UnregisterAxCallback 297 298 Description: AXコールバックの登録をリストから削除する 299 300 Arguments: node: AXコールバックリストのノード 301 302 Returns: 303 *---------------------------------------------------------------------------*/ 304void HardwareManager::UnregisterCallback( CallbackListNode* node ) 305{ 306 m_CallbackList.Erase( node ); 307} 308 309} /* namespace nw::snd::internal::driver */ 310} /* namespace nw::snd::internal */ 311} /* namespace nw::snd */ 312} /* namespace nw */ 313