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