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