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