1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     main.cpp
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.h>
19 
20 #include "demolib.h"
21 #include "simple.csid"
22 
23 class EffectApp : public nw::snd::demolib::AppBase
24 {
25 protected:
26     virtual void OnInitialize();
27     virtual void OnFinalize();
28     virtual void OnDrawUpLCD( nw::font::TextWriter& );
29     virtual void OnDrawDownLCD( nw::font::TextWriter& );
30     virtual void OnUpdatePad( nw::demo::Pad& );
31     virtual void OnUpdate();
32 
33 private:
34     enum EffectType
35     {
36         EFFECT_TYPE_NONE,
37     #ifdef NW_SND_AVAILABLE_NN_EFFECT
38         EFFECT_TYPE_NN_REVERB,
39         EFFECT_TYPE_NN_DELAY,
40     #endif
41         EFFECT_TYPE_NW_REVERB,
42         EFFECT_TYPE_NW_DELAY,
43         EFFECT_TYPE_NUM,
44         EFFECT_TYPE_MAX = EFFECT_TYPE_NW_DELAY
45     };
46 
47     void InitializeSoundSystem();
48     void InitializeEffect();
49     void FinalizeEffect();
50     const char* GetEffectTypeString() const;
51 
52     nw::snd::RomSoundArchive    m_Archive;
53     nw::snd::SoundArchivePlayer m_ArchivePlayer;
54     nw::snd::SoundDataManager   m_DataManager;
55     nw::snd::SoundHeap          m_Heap;
56     nw::snd::SoundHandle        m_Handle;
57 
58     nw::snd::FxReverb           m_NwFxReverb;
59     nw::snd::FxReverb::Param    m_NwFxReverbParam;
60     nw::snd::FxDelay            m_NwFxDelay;
61     nw::snd::FxDelay::Param     m_NwFxDelayParam;
62 
63 #ifdef NW_SND_AVAILABLE_NN_EFFECT
64     nn::snd::FxReverb           m_NnFxReverb;
65     nn::snd::FxReverb::Param    m_NnFxReverbParam;
66     nn::snd::FxDelay            m_NnFxDelay;
67     nn::snd::FxDelay::Param     m_NnFxDelayParam;
68 #endif
69 
70     void* m_pMemoryForSoundSystem;
71     void* m_pMemoryForInfoBlock;
72     void* m_pMemoryForSoundDataManager;
73     void* m_pMemoryForSoundArchivePlayer;
74     void* m_pMemoryForSoundHeap;
75     void* m_pMemoryForStreamBuffer;
76 
77     void* m_pMemoryForNwFxReverb;
78     void* m_pMemoryForNwFxDelay;
79 
80 #ifdef NW_SND_AVAILABLE_NN_EFFECT
81     void* m_pMemoryForNnFxReverb;
82     void* m_pMemoryForNnFxDelay;
83 #endif
84 
85     int m_EffectType;       // enum EffectType
86     int m_PreEffectType;
87 };
88 
89 
90 namespace
91 {
92 
93 const s32 SOUND_THREAD_PRIORITY = 4;
94 const s32 LOAD_THREAD_PRIORITY = 3;
95 const s32 SOUND_HEAP_SIZE = 1 * 1024 * 1024;
96 const char SOUND_ARC_PATH[] = NW_SND_DEMO_PATH_PREFIX "simple.bcsar";
97 const char DEMO_TITLE[] = "Effect";
98 
99 }
100 
OnInitialize()101 void EffectApp::OnInitialize()
102 {
103     InitializeSoundSystem();
104 
105     // �T�E���h�f�[�^�̃��[�h
106     if ( ! m_DataManager.LoadData( SEQ_MARIOKART, &m_Heap ) )
107     {
108         NW_ASSERTMSG( false, "LoadData(SEQ_MARIOKART) failed." );
109     }
110     if ( ! m_DataManager.LoadData( SE_YOSHI, &m_Heap ) )
111     {
112         NW_ASSERTMSG( false, "LoadData(SE_YOSHI) failed." );
113     }
114 
115     m_PreEffectType = m_EffectType = 0;
116 }
117 
InitializeSoundSystem()118 void EffectApp::InitializeSoundSystem()
119 {
120     // �T�E���h�V�X�e���̏�����
121     {
122         nw::snd::SoundSystem::SoundSystemParam param;
123         size_t workMemSize = nw::snd::SoundSystem::GetRequiredMemSize( param );
124         m_pMemoryForSoundSystem = MemAlloc( workMemSize );
125 
126         nw::snd::SoundSystem::Initialize(
127                 param,
128                 reinterpret_cast<uptr>( m_pMemoryForSoundSystem ),
129                 workMemSize );
130     }
131 
132     // �T�E���h�A�[�J�C�u�̏�����
133     if ( ! m_Archive.Open( SOUND_ARC_PATH ) )
134     {
135         NW_ASSERTMSG( 0, "cannot open bcsar(%s)\n", SOUND_ARC_PATH );
136     }
137 
138     // INFO �u���b�N�̃��[�h
139     {
140         size_t infoBlockSize = m_Archive.GetHeaderSize();
141         m_pMemoryForInfoBlock = MemAlloc( infoBlockSize );
142         if ( ! m_Archive.LoadHeader( m_pMemoryForInfoBlock, infoBlockSize ) )
143         {
144             NW_ASSERTMSG( 0, "cannot load infoBlock(%s)", SOUND_ARC_PATH );
145         }
146     }
147 
148     // �T�E���h�f�[�^�}�l�[�W���[�̏�����
149     {
150         size_t setupSize = m_DataManager.GetRequiredMemSize( &m_Archive );
151         m_pMemoryForSoundDataManager = MemAlloc( setupSize );
152         m_DataManager.Initialize( &m_Archive, m_pMemoryForSoundDataManager, setupSize );
153     }
154 
155     // �T�E���h�A�[�J�C�u�v���C���[�̏�����
156     {
157         size_t setupSize = m_ArchivePlayer.GetRequiredMemSize( &m_Archive );
158         m_pMemoryForSoundArchivePlayer = MemAlloc( setupSize, 32 );
159         size_t setupStrmBufferSize =
160             m_ArchivePlayer.GetRequiredStreamBufferSize( &m_Archive );
161         m_pMemoryForStreamBuffer = MemAlloc( setupStrmBufferSize, 32 );
162         bool result = m_ArchivePlayer.Initialize(
163                 &m_Archive,
164                 &m_DataManager,
165                 m_pMemoryForSoundArchivePlayer, setupSize,
166                 m_pMemoryForStreamBuffer, setupStrmBufferSize );
167         NW_ASSERT( result );
168     }
169 
170     // �T�E���h�q�[�v�̍\�z
171     {
172         m_pMemoryForSoundHeap = MemAlloc( SOUND_HEAP_SIZE );
173         bool result = m_Heap.Create( m_pMemoryForSoundHeap, SOUND_HEAP_SIZE );
174         NW_ASSERT( result );
175     }
176 }
177 
OnFinalize()178 void EffectApp::OnFinalize()
179 {
180     nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A );
181     nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_B );
182 
183     m_NwFxReverb.ReleaseWorkBuffer();
184     m_NwFxDelay.ReleaseWorkBuffer();
185 #ifdef NW_SND_AVAILABLE_NN_EFFECT
186     m_NnFxReverb.ReleaseWorkBuffer();
187     m_NnFxDelay.ReleaseWorkBuffer();
188 #endif
189 
190     nw::snd::SoundSystem::Finalize();
191 
192     MemFree( m_pMemoryForSoundSystem );
193     MemFree( m_pMemoryForInfoBlock );
194     MemFree( m_pMemoryForSoundDataManager );
195     MemFree( m_pMemoryForSoundArchivePlayer );
196     MemFree( m_pMemoryForSoundHeap );
197     MemFree( m_pMemoryForStreamBuffer );
198 
199     MemFree( m_pMemoryForNwFxReverb );
200     MemFree( m_pMemoryForNwFxDelay );
201 #ifdef NW_SND_AVAILABLE_NN_EFFECT
202     MemFree( m_pMemoryForNnFxReverb );
203     MemFree( m_pMemoryForNnFxDelay );
204 #endif
205 }
206 
OnDrawUpLCD(nw::font::TextWriter & writer)207 void EffectApp::OnDrawUpLCD( nw::font::TextWriter& writer )
208 {
209     writer.Printf(" DEMO nw::snd %s\n\n", DEMO_TITLE);
210 
211     writer.Print ("    -- usage --\n\n");
212     writer.Print ("    [A] Play Sequence Sound\n");
213     writer.Print ("    [X] Play Wave Sound\n");
214     writer.Print ("    [Y] Play Stream Sound\n");
215     writer.Print ("    [B] Stop Sound\n");
216     writer.Print ("    [LEFT/RIGHT] Change Effect\n\n");
217     writer.Printf("    current effect: %s\n\n", GetEffectTypeString() );
218 }
219 
OnDrawDownLCD(nw::font::TextWriter & writer)220 void EffectApp::OnDrawDownLCD( nw::font::TextWriter& writer )
221 {
222     (void)writer;
223 }
224 
OnUpdatePad(nw::demo::Pad & pad)225 void EffectApp::OnUpdatePad( nw::demo::Pad& pad )
226 {
227     if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_A ) )
228     {
229         m_Handle.Stop( 0 );
230         bool result = m_ArchivePlayer.StartSound( &m_Handle, SEQ_MARIOKART ).IsSuccess();
231         nw::snd::SequenceSoundHandle handle( &m_Handle );
232         handle.SetFxSend( nw::snd::AUX_BUS_A, 0.3f );
233         NN_LOG("[SEQ] SEQ_MARIOKART ... (%d)\n", result);
234     }
235 
236     if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_X ) )
237     {
238         m_Handle.Stop( 0 );
239         bool result = m_ArchivePlayer.StartSound( &m_Handle, SE_YOSHI ).IsSuccess();
240         nw::snd::WaveSoundHandle handle( &m_Handle );
241         handle.SetFxSend( nw::snd::AUX_BUS_A, 0.3f );
242         NN_LOG("[WSD] SE_YOSHI ... (%d)\n", result);
243     }
244 
245     if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_Y ) )
246     {
247         m_Handle.Stop( 0 );
248         bool result = m_ArchivePlayer.StartSound( &m_Handle, STRM_MARIOKART ).IsSuccess();
249         nw::snd::StreamSoundHandle handle( &m_Handle );
250         handle.SetFxSend( nw::snd::AUX_BUS_A, 0.3f );
251         NN_LOG("[STRM] STRM_MARIOKART ... (%d)\n", result );
252     }
253 
254     if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_B ) )
255     {
256         m_Handle.Stop( 3 );
257     }
258 
259     bool isChangeEffect = false;
260     if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_LEFT ) )
261     {
262         m_PreEffectType = m_EffectType;
263         m_EffectType -= 1;
264         if ( m_EffectType < 0 ) { m_EffectType = EFFECT_TYPE_MAX; }
265         isChangeEffect = true;
266     }
267     if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_RIGHT ) )
268     {
269         m_PreEffectType = m_EffectType;
270         m_EffectType += 1;
271         if ( m_EffectType > EFFECT_TYPE_MAX ) { m_EffectType = 0; }
272         isChangeEffect = true;
273     }
274 
275     if ( isChangeEffect )
276     {
277         FinalizeEffect();
278         InitializeEffect();
279     }
280 }
281 
FinalizeEffect()282 void EffectApp::FinalizeEffect()
283 {
284     switch ( m_PreEffectType )
285     {
286         case EFFECT_TYPE_NW_REVERB:
287             nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A, 0 );
288             m_NwFxReverb.ReleaseWorkBuffer();
289             break;
290         case EFFECT_TYPE_NW_DELAY:
291             nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A, 0 );
292             m_NwFxDelay.ReleaseWorkBuffer();
293             break;
294 #ifdef NW_SND_AVAILABLE_NN_EFFECT
295         case EFFECT_TYPE_NN_REVERB:
296             nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A, 0 );
297             m_NnFxReverb.ReleaseWorkBuffer();
298             break;
299         case EFFECT_TYPE_NN_DELAY:
300             nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A, 0 );
301             m_NnFxDelay.ReleaseWorkBuffer();
302             break;
303 #endif
304         default:
305             break;
306     }
307 }
308 
InitializeEffect()309 void EffectApp::InitializeEffect()
310 {
311     switch ( m_EffectType )
312     {
313         case EFFECT_TYPE_NW_REVERB:
314             // nw::snd::FxReverb �̐ݒ�
315             {
316                 nw::snd::FxReverb::FilterSize filterSize;
317                 filterSize.m_Comb0 = 20 * 160;
318                 filterSize.m_Comb1 = 30 * 160;
319                 filterSize.m_AllPass = 13 * 160;
320 
321                 m_NwFxReverbParam.m_EarlyReflectionTime = 200;
322                 m_NwFxReverbParam.m_FusedTime = 1000;
323                 m_NwFxReverbParam.m_PreDelayTime = 200;
324                 m_NwFxReverbParam.m_pFilterSize = &filterSize;
325                 m_NwFxReverb.SetParam( m_NwFxReverbParam );
326                 size_t reverbBufferSize = m_NwFxReverb.GetRequiredMemSize();
327                 m_pMemoryForNwFxReverb = MemAlloc( reverbBufferSize, 4 );
328                 m_NwFxReverb.AssignWorkBuffer(
329                         reinterpret_cast<uptr>( m_pMemoryForNwFxReverb ),
330                         reverbBufferSize );
331 
332                 bool result = nw::snd::SoundSystem::AppendEffect( nw::snd::AUX_BUS_A, &m_NwFxReverb );
333                 NN_LOG( "NW_REVREB %d\n", result );
334             }
335             break;
336 
337         case EFFECT_TYPE_NW_DELAY:
338             // nw::snd::FxDelay �̐ݒ�
339             {
340                 m_NwFxDelayParam.m_DelayTime = 400;
341                 m_NwFxDelayParam.m_FeedbackGain = 0.4f;
342                 m_NwFxDelayParam.m_Damping = 0.3f;
343                 m_NwFxDelayParam.m_IsEnableSurround = false;
344 
345                 m_NwFxDelay.SetParam( m_NwFxDelayParam );
346                 size_t delayBufferSize = m_NwFxDelay.GetRequiredMemSize();
347                 m_pMemoryForNwFxDelay = MemAlloc( delayBufferSize, 4 );
348                 m_NwFxDelay.AssignWorkBuffer(
349                         reinterpret_cast<uptr>( m_pMemoryForNwFxDelay ),
350                         delayBufferSize );
351 
352                 bool result = nw::snd::SoundSystem::AppendEffect( nw::snd::AUX_BUS_A, &m_NwFxDelay );
353                 NN_LOG( "NW_DELAY %d\n", result );
354             }
355             break;
356 
357     #ifdef NW_SND_AVAILABLE_NN_EFFECT
358         case EFFECT_TYPE_NN_REVERB:
359             // nn::snd::FxReverb �̐ݒ�
360             {
361                 nn::snd::FxReverb::FilterSize filterSize;
362                 filterSize.m_Comb0 = 20 * 160;
363                 filterSize.m_Comb1 = 30 * 160;
364                 filterSize.m_AllPass = 13 * 160;
365 
366                 m_NnFxReverbParam.m_EarlyReflectionTime = 200;
367                 m_NnFxReverbParam.m_FusedTime = 1000;
368                 m_NnFxReverbParam.m_PreDelayTime = 200;
369                 m_NnFxReverbParam.m_pFilterSize = &filterSize;
370                 m_NnFxReverb.SetParam( m_NnFxReverbParam );
371                 size_t reverbBufferSize = m_NnFxReverb.GetRequiredMemSize();
372                 m_pMemoryForNnFxReverb = MemAlloc( reverbBufferSize, 4 );
373                 m_NnFxReverb.AssignWorkBuffer(
374                         reinterpret_cast<uptr>( m_pMemoryForNnFxReverb ),
375                         reverbBufferSize );
376 
377                 bool result = nw::snd::SoundSystem::AppendEffect( nw::snd::AUX_BUS_A, &m_NnFxReverb );
378                 NN_LOG( "NN_REVREB %d\n", result );
379             }
380             break;
381 
382         case EFFECT_TYPE_NN_DELAY:
383             // nn::snd::FxDelay �̐ݒ�
384             {
385                 m_NnFxDelayParam.m_DelayTime = 400;
386                 m_NnFxDelayParam.m_FeedbackGain = 0.4f;
387                 m_NnFxDelayParam.m_Damping = 0.3f;
388                 m_NnFxDelayParam.m_IsEnableSurround = false;
389 
390                 m_NnFxDelay.SetParam( m_NnFxDelayParam );
391                 size_t delayBufferSize = m_NnFxDelay.GetRequiredMemSize();
392                 m_pMemoryForNnFxDelay = MemAlloc( delayBufferSize, 4 );
393                 m_NnFxDelay.AssignWorkBuffer(
394                         reinterpret_cast<uptr>( m_pMemoryForNnFxDelay ),
395                         delayBufferSize );
396 
397                 bool result = nw::snd::SoundSystem::AppendEffect( nw::snd::AUX_BUS_A, &m_NnFxDelay );
398                 NN_LOG( "NN_DELAY %d\n", result );
399             }
400             break;
401     #endif
402 
403         default:
404             {
405                 NN_LOG( "NONE\n");
406             }
407             break;
408     }
409 }
410 
OnUpdate()411 void EffectApp::OnUpdate()
412 {
413     m_ArchivePlayer.Update();
414 }
415 
GetEffectTypeString() const416 const char* EffectApp::GetEffectTypeString() const
417 {
418     static const char* EFFECT_TYPE_STRING[] =
419     {
420         "NONE",
421     #ifdef NW_SND_AVAILABLE_NN_EFFECT
422         "NN_REVERB",
423         "NN_DELAY",
424     #endif
425         "NW_REVERB",
426         "NW_DELAY"
427     };
428     if ( m_EffectType > EFFECT_TYPE_MAX )
429     {
430         return NULL;
431     }
432     return EFFECT_TYPE_STRING[ m_EffectType ];
433 }
434 
nnMain()435 void nnMain()
436 {
437     EffectApp app;
438 
439     app.Initialize();
440     app.Run();
441     app.Finalize();
442 }
443