1/*---------------------------------------------------------------------------*
2  Project:  NintendoWare
3  File:     snd_HardwareManagerDSP.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#define DSP_32BIT_TO_ARM(value)     (u32)(((u32)(value) >> 16) | ((u32)(value) << 16))
17
18namespace nw {
19namespace snd {
20namespace internal {
21namespace driver {
22
23namespace
24{
25class Perf
26{
27private:
28    static const int LOG_BUF_SIZE = 7;
29#ifdef NW_PLATFORM_CTR
30    nn::os::Tick m_Ticks[ LOG_BUF_SIZE ];
31    nn::os::Tick m_TmpTick;
32#endif
33    int m_Counter;
34public:
35    Perf() : m_Counter( 0 ) {}
36
37    void Begin()
38    {
39        m_TmpTick = nn::os::Tick::GetSystemCurrent();
40    }
41    void End()
42    {
43        m_Ticks[m_Counter] = nn::os::Tick::GetSystemCurrent() - m_TmpTick;
44        m_Counter += 1;
45
46        if ( m_Counter == LOG_BUF_SIZE )
47        {
48            char str[300]; str[0] = '\0';
49            for ( int i = 0; i < LOG_BUF_SIZE; i++ )
50            {
51                std::snprintf( str, 300, "%s %5lld,",
52                        str, m_Ticks[i].ToTimeSpan().GetMicroSeconds() );
53            }
54            NN_LOG("%s\n", str );
55            m_Counter = 0;
56        }
57    }
58};
59Perf s_Perf;
60
61}
62
63//
64// 関数
65//
66/*---------------------------------------------------------------------------*
67    Name:           HardwareManager
68
69    Description:    コンストラクタ
70
71    Arguments:      なし
72
73    Returns:        なし
74 *---------------------------------------------------------------------------*/
75HardwareManager::HardwareManager()
76: m_IsInitialized( false ),
77  m_OutputMode( OUTPUT_MODE_STEREO ),
78  m_SrcType( SRC_TYPE_4TAP )
79{
80    m_MasterVolume.InitValue( 1.0f );
81    m_VolumeForReset.InitValue( 1.0f );
82
83    for ( int i=0; i<AUX_BUS_NUM; i++ )
84    {
85        m_AuxFadeVolume[ i ].InitValue( 1.0f );
86        m_AuxUserVolume[ i ].InitValue( 1.0f );
87        m_AuxCallback[ i ] = NULL;
88        m_AuxCallbackContext[ i ] = NULL;
89        m_EffectProcessTick[ i ] = nn::os::Tick( 0 );
90    }
91}
92
93void HardwareManager::Initialize()
94{
95    if ( m_IsInitialized ) return;
96
97    // AUX コールバック設定、既に登録されている AUX コールバックを保存する
98    for ( int busId = nn::snd::AUX_BUS_A; busId < nn::snd::AUX_BUS_NUM; busId++ )
99    {
100#ifndef NW_SND_DEBUG_NOUSE_CTRSDK
101        nn::snd::GetAuxCallback(
102                static_cast<nn::snd::AuxBusId>( busId ),
103                &m_AuxCallback[ busId ],
104                &m_AuxCallbackContext[ busId ] );
105        nn::snd::RegisterAuxCallback( static_cast<nn::snd::AuxBusId>(busId), NULL, NULL );
106#endif
107    }
108
109    // biquadフィルタテーブル初期化
110    for ( int i = 0; i < BIQUAD_FILTER_TYPE_USER_MAX + 1; i++ )
111    {
112        m_BiquadFilterCallbackTable[i] = NULL;
113    }
114    SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_LPF,     &BIQUAD_FILTER_LPF );
115    SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_HPF,     &BIQUAD_FILTER_HPF );
116    SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_BPF512,  &BIQUAD_FILTER_BPF_512 );
117    SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_BPF1024, &BIQUAD_FILTER_BPF_1024 );
118    SetBiquadFilterCallback( BIQUAD_FILTER_TYPE_BPF2048, &BIQUAD_FILTER_BPF_2048 );
119
120    // マスターボリューム設定
121    nn::snd::SetMasterVolume( 1.0f );
122
123    // サウンド出力モード設定
124    nn::snd::OutputMode mode = nn::snd::GetSoundOutputMode();
125    switch ( mode )
126    {
127    case nn::snd::OUTPUT_MODE_MONO:
128        m_OutputMode = OUTPUT_MODE_MONO;
129        break;
130    case nn::snd::OUTPUT_MODE_STEREO:
131        m_OutputMode = OUTPUT_MODE_STEREO;
132        break;
133    case nn::snd::OUTPUT_MODE_3DSURROUND:
134        m_OutputMode = OUTPUT_MODE_SURROUND;
135        break;
136    default:
137        NW_ASSERT( false );
138        break;
139    }
140
141    m_IsInitialized = true;
142}
143
144void HardwareManager::Finalize()
145{
146    if ( !m_IsInitialized ) return;
147
148    // エフェクトクリア
149    for ( int id = AUX_BUS_A; id < AUX_BUS_NUM; id++ )
150    {
151        FinalizeEffect( static_cast<AuxBus>( id ) );
152#ifndef NW_SND_DEBUG_NOUSE_CTRSDK
153        nn::snd::RegisterAuxCallback(
154                static_cast<nn::snd::AuxBusId>( id ),
155                m_AuxCallback[ id ],
156                static_cast<uptr>( m_AuxCallbackContext[ id ] ) );
157#endif
158        m_AuxCallback[ id ] = NULL;
159        m_AuxCallbackContext[ id ] = NULL;
160    }
161
162    m_IsInitialized = false;
163}
164
165void HardwareManager::Update()
166{
167    // ClearEffect のフェード処理。フェードが完了したらエフェクトをクリア
168    for ( int i=0; i<AUX_BUS_NUM; i++ )
169    {
170        bool updateFlag = false;
171        if ( ! m_AuxUserVolume[ i ].IsFinished() )
172        {
173            m_AuxUserVolume[ i ].Update();
174            updateFlag = true;
175        }
176        if ( ! m_AuxFadeVolume[ i ].IsFinished() )
177        {
178            m_AuxFadeVolume[ i ].Update();
179            if ( m_AuxFadeVolume[ i ].IsFinished() )
180            {
181                FinalizeEffect( static_cast<AuxBus>( i ) );
182            }
183            updateFlag = true;
184        }
185
186        if ( updateFlag )
187        {
188            f32 returnVolume = 1.0f;
189            returnVolume *= ut::Clamp( m_AuxUserVolume[ i ].GetValue(), 0.0f, 1.0f );
190            returnVolume *= ut::Clamp( m_AuxFadeVolume[ i ].GetValue(), 0.0f, 1.0f );
191#ifndef NW_SND_DEBUG_NOUSE_CTRSDK
192            nn::snd::SetAuxReturnVolume( static_cast<nn::snd::AuxBusId>(i), returnVolume );
193#endif
194        }
195    }
196
197    // 音量のアップデート
198    if ( ! m_MasterVolume.IsFinished() ) {
199        m_MasterVolume.Update();
200        VoiceManager::GetInstance().UpdateAllVoicesSync( Voice::UPDATE_VE );
201    }
202
203    if ( ! m_VolumeForReset.IsFinished() ) {
204        m_VolumeForReset.Update();
205        VoiceManager::GetInstance().UpdateAllVoicesSync( Voice::UPDATE_VE );
206    }
207
208    // ( SDK 層の ) マスターボリュームの調整
209    {
210        f32 volume = 1.0f;
211        volume *= m_VolumeForReset.GetValue();
212        volume = ut::Clamp( volume, 0.0f, 1.0f );
213#ifndef NW_SND_DEBUG_NOUSE_CTRSDK
214        nn::snd::SetMasterVolume( volume );
215#endif
216    }
217}
218    // RVL は計96ch中、マージン16だった
219
220u32 HardwareManager::GetChannelCount() const
221{
222    return SOUND_VOICE_COUNT;
223}
224
225/* ========================================================================
226        リセット前準備
227   ======================================================================== */
228
229void HardwareManager::PrepareReset()
230{
231    // if ( m_OldAidCallback != NULL ) return;
232
233    m_VolumeForReset.SetTarget( 0.0f, 3 ); // 3オーディオフレームかけてフェードアウト
234    // m_ResetReadyCounter = -1;
235    // m_OldAidCallback = ::AI_RegisterDMACallback( AiDmaCallbackFunc );
236}
237
238bool HardwareManager::IsResetReady() const
239{
240    return true; // m_ResetReadyCounter == 0 ? true : false;
241}
242
243} /* namespace nw::snd::internal::driver */
244} /* namespace nw::snd::internal */
245} /* namespace nw::snd */
246} /* namespace nw */
247