/*---------------------------------------------------------------------------* Project: NintendoWare File: snd_HardwareManager.cpp Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. The content herein is highly confidential and should be handled accordingly. $Revision: 32385 $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include #include #include #include NW_SND_ADAPTIVE_SOURCE( HardwareManager ) namespace nw { namespace snd { namespace internal { namespace driver { const BiquadFilterLpf HardwareManager::BIQUAD_FILTER_LPF; const BiquadFilterHpf HardwareManager::BIQUAD_FILTER_HPF; const BiquadFilterBpf512 HardwareManager::BIQUAD_FILTER_BPF_512; const BiquadFilterBpf1024 HardwareManager::BIQUAD_FILTER_BPF_1024; const BiquadFilterBpf2048 HardwareManager::BIQUAD_FILTER_BPF_2048; void HardwareManager::SetOutputMode( OutputMode mode ) { if ( m_OutputMode == mode ) return; m_OutputMode = mode; #ifdef NW_PLATFORM_CTR switch ( mode ) { case OUTPUT_MODE_MONO: nn::snd::SetSoundOutputMode( nn::snd::OUTPUT_MODE_MONO ); break; case OUTPUT_MODE_STEREO: nn::snd::SetSoundOutputMode( nn::snd::OUTPUT_MODE_STEREO ); break; case OUTPUT_MODE_SURROUND: nn::snd::SetSoundOutputMode( nn::snd::OUTPUT_MODE_3DSURROUND ); break; default: NW_ASSERT( false ); break; } #endif // コマンドを投げる { DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance(); DriverCommandAllVoicesSync* command = cmdmgr.AllocCommand(); command->id = DRIVER_COMMAND_ALLVOICES_SYNC; command->syncFlag = Voice::UPDATE_MIX; cmdmgr.PushCommand(command); } // エフェクトの出力モード変更処理 for ( int bus = 0; bus < AUX_BUS_NUM; bus++ ) { FxList& list = GetEffectList( static_cast( bus ) ); for ( FxList::Iterator itr = list.GetBeginIter(); itr != list.GetEndIter(); ++itr ) { itr->OnChangeOutputMode(); } } } f32 HardwareManager::GetOutputVolume() const { f32 volume = m_MasterVolume.GetValue(); volume *= m_VolumeForReset.GetValue(); return volume; } void HardwareManager::SetMasterVolume( float volume, int fadeTimes ) { if ( volume < 0.0f ) volume = 0.0f; m_MasterVolume.SetTarget( volume, ( fadeTimes + HardwareManager::SOUND_FRAME_INTERVAL_MSEC - 1 ) / SOUND_FRAME_INTERVAL_MSEC ); if ( fadeTimes == 0 ) { // コマンドを投げる DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance(); DriverCommandAllVoicesSync* command = cmdmgr.AllocCommand(); command->id = DRIVER_COMMAND_ALLVOICES_SYNC; command->syncFlag = Voice::UPDATE_VE; cmdmgr.PushCommand(command); } } /* ======================================================================== SRC タイプ ======================================================================== */ /*---------------------------------------------------------------------------* Name: SetSrcType Description: SRC タイプを変更する Arguments: type: SRC タイプ Returns: なし *---------------------------------------------------------------------------*/ void HardwareManager::SetSrcType( SrcType type ) { if ( m_SrcType == type ) return; m_SrcType = type; // コマンドを投げる { DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance(); DriverCommandAllVoicesSync* command = cmdmgr.AllocCommand(); command->id = DRIVER_COMMAND_ALLVOICES_SYNC; command->syncFlag = Voice::UPDATE_SRC; cmdmgr.PushCommand(command); } } /* ======================================================================== エフェクト ======================================================================== */ bool HardwareManager::AppendEffect( AuxBus bus, FxBase* pFx ) { NW_NULL_ASSERT( pFx ); if ( ! m_AuxFadeVolume[ bus ].IsFinished() ) { FinalizeEffect( bus ); } m_AuxFadeVolume[ bus ].SetTarget( 1.0f, 0 ); #ifdef NW_PLATFORM_CTRWIN switch ( bus ) { case AUX_BUS_A: AX_SetAuxAReturnVolume( AUX_RETURN_VOLUME_MAX ); break; case AUX_BUS_B: AX_SetAuxBReturnVolume( AUX_RETURN_VOLUME_MAX ); break; } #else nn::snd::SetAuxReturnVolume( static_cast(bus), AUX_RETURN_VOLUME_MAX ); #endif if ( GetEffectList( bus ).IsEmpty() ) { #ifdef NW_PLATFORM_CTRWIN switch ( bus ) { case AUX_BUS_A: AX_RegisterAuxACallback( AuxCallbackFunc, reinterpret_cast( bus ) ); break; case AUX_BUS_B: AX_RegisterAuxBCallback( AuxCallbackFunc, reinterpret_cast( bus ) ); break; } #else nn::snd::RegisterAuxCallback( static_cast( bus ), AuxCallbackFunc, static_cast( bus ) ); #endif } GetEffectList( bus ).PushBack( pFx ); return true; } #ifdef NW_PLATFORM_CTR bool HardwareManager::AppendEffect( AuxBus bus, nn::snd::FxDelay* delay ) { NW_NULL_ASSERT( delay ); if ( ! m_AuxFadeVolume[ bus ].IsFinished() ) { FinalizeEffect( bus ); } m_AuxFadeVolume[ bus ].SetTarget( 1.0f, 0 ); nn::snd::SetAuxReturnVolume( static_cast(bus), AUX_RETURN_VOLUME_MAX ); bool result = nn::snd::SetEffect( static_cast(bus), delay ); return result; } bool HardwareManager::AppendEffect( AuxBus bus, nn::snd::FxReverb* reverb ) { NW_NULL_ASSERT( reverb ); if ( ! m_AuxFadeVolume[ bus ].IsFinished() ) { FinalizeEffect( bus ); } m_AuxFadeVolume[ bus ].SetTarget( 1.0f, 0 ); nn::snd::SetAuxReturnVolume( static_cast(bus), AUX_RETURN_VOLUME_MAX ); bool result = nn::snd::SetEffect( static_cast(bus), reverb ); return result; } #endif void HardwareManager::ClearEffect( AuxBus bus , int fadeTimes ) { if ( fadeTimes == 0 ) { FinalizeEffect( bus ); if ( m_AuxFadeVolume[ bus ].IsFinished() ) { m_AuxFadeVolume[ bus ].SetTarget( 0.0f, 0 ); } } else { m_AuxFadeVolume[ bus ].SetTarget( 0.0f, ( fadeTimes + SOUND_FRAME_INTERVAL_MSEC - 1 ) / SOUND_FRAME_INTERVAL_MSEC ); } } void HardwareManager::FinalizeEffect( AuxBus bus ) { #ifdef NW_PLATFORM_CTR nn::snd::ClearEffect( static_cast( bus ) ); #endif FxList& list = GetEffectList( bus ); if ( list.IsEmpty() ) { return; } #ifdef NW_PLATFORM_CTRWIN switch ( bus ) { case AUX_BUS_A: AX_RegisterAuxACallback( NULL, NULL ); break; case AUX_BUS_B: AX_RegisterAuxBCallback( NULL, NULL ); break; #ifdef NW_PLATFORM_RVL case AUX_C: AX_RegisterAuxCCallback( NULL, NULL ); break; #endif } m_EffectProcessTick[ bus ] = 0; #else nn::snd::ClearAuxCallback( static_cast( bus ) ); m_EffectProcessTick[ bus ] = nn::os::Tick( 0 ); #endif for ( FxList::Iterator itr = list.GetBeginIter(); itr != list.GetEndIter(); ++itr ) { itr->Finalize(); } list.Clear(); } #ifdef NW_PLATFORM_CTRWIN void HardwareManager::AuxCallbackFunc( void *data, void *context ) { AuxBus bus = static_cast( reinterpret_cast( context ) ); NW_MINMAXLT_ASSERT( bus, AUX_BUS_A, AUX_BUS_A + AUX_BUS_NUM ); OSTick tick = OS_GetTick(); // バッファ設定 void* buffer[4]; int numChannels; OutputMode outputMode = GetInstance().GetOutputMode(); { AXFX_BUFFERUPDATE* axfxbuf = static_cast( data ); numChannels = 3; buffer[0] = axfxbuf->left; buffer[1] = axfxbuf->right; buffer[2] = axfxbuf->surround; } // エフェクト処理 for ( FxList::Iterator itr = GetInstance().GetEffectList( bus ).GetBeginIter(); itr != GetInstance().GetEffectList( bus ).GetEndIter(); (void)++itr ) { #if 0 itr->UpdateBuffer( numChannels, buffer, FX_BUFFER_SIZE, FX_SAMPLE_FORMAT, static_cast( FX_SAMPLE_RATE ), outputMode ); #endif } // 処理時間計測 GetInstance().m_EffectProcessTick[ bus ] = static_cast( OS_DiffTick( OS_GetTick(), tick ) ); } #else void HardwareManager::AuxCallbackFunc( nn::snd::AuxBusData *data, s32 sampleLength, uptr userData ) { AuxBus bus = static_cast( userData ); NW_MINMAXLT_ASSERT( bus, AUX_BUS_A, AUX_BUS_A + AUX_BUS_NUM ); const size_t FX_BUFFER_SIZE = sizeof(s32) * sampleLength; nn::os::Tick tick = nn::os::Tick::GetSystemCurrent(); // バッファ設定 int numChannels; OutputMode outputMode = GetInstance().GetOutputMode(); switch ( outputMode ) { case OUTPUT_MODE_SURROUND: numChannels = 4; break; case OUTPUT_MODE_MONO: case OUTPUT_MODE_STEREO: default: numChannels = 2; break; }; // エフェクト処理 for ( FxList::Iterator itr = GetInstance().GetEffectList( bus ).GetBeginIter(); itr != GetInstance().GetEffectList( bus ).GetEndIter(); ++itr ) { itr->UpdateBuffer( numChannels, data, sampleLength, FX_SAMPLE_FORMAT, static_cast( FX_SAMPLE_RATE ), outputMode ); } GetInstance().m_EffectProcessTick[ bus ] = nn::os::Tick::GetSystemCurrent() - tick; } #endif void HardwareManager::SetBiquadFilterCallback( int type, const BiquadFilterCallback* cb ) { NW_MINMAX_ASSERT( type, BIQUAD_FILTER_TYPE_NONE, BIQUAD_FILTER_TYPE_USER_MAX ); if ( type == BIQUAD_FILTER_TYPE_NONE /* 0 */ ) { // 0 番は Biquad フィルタ OFF なので、なにもしない return; } m_BiquadFilterCallbackTable[ type ] = cb; } } // namespace nw::snd::internal:driver } // namespace nw::snd::internal } // namespace nw::snd } // namespace nw