1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     Sound3dApp.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 "Sound3dApp.h"
19 #include "simple.csid"
20 
21 namespace
22 {
23 
24 const s32 SOUND_THREAD_PRIORITY = 4;
25 const s32 LOAD_THREAD_PRIORITY = 3;
26 const s32 SOUND_HEAP_SIZE = 1 * 1024 * 1024;
27 const char SOUND_ARC_PATH[] = NW_SND_DEMO_PATH_PREFIX "simple.bcsar";
28 const char DEMO_TITLE[] = "Sound3d";
29 
30 const f32 CONTROL_PAD_STEP = 0.2f;
31 
GetFilterTypeString(int type)32 const char* GetFilterTypeString( int type )
33 {
34     const char* FILTER_TYPE_STRING[] =
35     {
36         "NONE",
37         "BIQUAD_LPF",
38         "BIQUAD_HPF",
39         "BIQUAD_BPF_512",
40         "BIQUAD_BPF_1024",
41         "BIQUAD_BPF_2048"
42     };
43     if ( type > nw::snd::BIQUAD_FILTER_TYPE_BPF2048 || type < 0 )
44     {
45         return "INVALID";
46     }
47     return FILTER_TYPE_STRING[ type ];
48 }
49 }
50 
OnInitialize()51 void Sound3dApp::OnInitialize()
52 {
53     InitializeSoundSystem();
54 
55     // サウンドデータのロード
56     if ( ! m_DataManager.LoadData( SE_SQUARE, &m_Heap ) )
57     {
58         NW_ASSERTMSG( false, "LoadData(SE_SQUARE) failed." );
59     }
60 
61     m_FilterType = 0;
62     m_3dManager.SetBiquadFilterType( m_FilterType );
63 }
64 
InitializeSoundSystem()65 void Sound3dApp::InitializeSoundSystem()
66 {
67     // サウンドシステムの初期化
68     {
69         nw::snd::SoundSystem::SoundSystemParam param;
70         size_t workMemSize = nw::snd::SoundSystem::GetRequiredMemSize( param );
71         m_pMemoryForSoundSystem = MemAlloc( workMemSize );
72 
73         nw::snd::SoundSystem::Initialize(
74                 param,
75                 reinterpret_cast<uptr>( m_pMemoryForSoundSystem ),
76                 workMemSize );
77     }
78 
79     // サウンドアーカイブの初期化
80     if ( ! m_Archive.Open( SOUND_ARC_PATH ) )
81     {
82         NW_ASSERTMSG( 0, "cannot open bcsar(%s)\n", SOUND_ARC_PATH );
83     }
84 
85     // INFO ブロックのロード
86     {
87         size_t infoBlockSize = m_Archive.GetHeaderSize();
88         m_pMemoryForInfoBlock = MemAlloc( infoBlockSize );
89         if ( ! m_Archive.LoadHeader( m_pMemoryForInfoBlock, infoBlockSize ) )
90         {
91             NW_ASSERTMSG( 0, "cannot load infoBlock(%s)", SOUND_ARC_PATH );
92         }
93     }
94 
95     // サウンドデータマネージャーの初期化
96     {
97         size_t setupSize = m_DataManager.GetRequiredMemSize( &m_Archive );
98         m_pMemoryForSoundDataManager = MemAlloc( setupSize );
99         m_DataManager.Initialize( &m_Archive, m_pMemoryForSoundDataManager, setupSize );
100     }
101 
102     // サウンドアーカイブプレイヤーの初期化
103     {
104         size_t setupSize = m_ArchivePlayer.GetRequiredMemSize( &m_Archive );
105         m_pMemoryForSoundArchivePlayer = MemAlloc( setupSize, 32 );
106         size_t setupStrmBufferSize =
107             m_ArchivePlayer.GetRequiredStreamBufferSize( &m_Archive );
108         m_pMemoryForStreamBuffer = MemAlloc( setupStrmBufferSize, 32 );
109         bool result = m_ArchivePlayer.Initialize(
110                 &m_Archive,
111                 &m_DataManager,
112                 m_pMemoryForSoundArchivePlayer, setupSize,
113                 m_pMemoryForStreamBuffer, setupStrmBufferSize );
114         NW_ASSERT( result );
115     }
116 
117     // サウンドヒープの構築
118     {
119         m_pMemoryForSoundHeap = MemAlloc( SOUND_HEAP_SIZE );
120         bool result = m_Heap.Create( m_pMemoryForSoundHeap, SOUND_HEAP_SIZE );
121         NW_ASSERT( result );
122     }
123 
124     // 3D サウンドマネージャーの初期化
125     {
126         size_t setupSize = m_3dManager.GetRequiredMemSize( &m_Archive );
127         m_pMemoryFor3dManager = MemAlloc( setupSize );
128         m_3dManager.Initialize( &m_Archive, m_pMemoryFor3dManager, setupSize );
129         m_3dManager.SetMaxPriorityReduction( 32 );
130         m_3dManager.SetSonicVelocity( 340.0f / 60 );
131     }
132 
133     // 3D サウンドリスナーの初期化
134     {
135         m_3dManager.AddListener( &m_3dListener );
136 
137         CalcListenerMatrix( &m_ListenerMtx );
138         m_3dListener.SetMatrix( m_ListenerMtx );
139         m_3dListener.SetMaxVolumeDistance( 5.0f );
140         m_3dListener.SetUnitDistance( 5.0f );
141         m_3dListener.SetInteriorSize( 5.0f );
142     }
143 
144     // 3D サウンドアクターの初期化
145     {
146         m_3dActor.Initialize( m_ArchivePlayer, m_3dManager );
147         m_ActorPos = nw::math::VEC3::Zero();
148         m_3dActor.SetPosition( m_ActorPos );
149     }
150 }
151 
CalcListenerMatrix(nw::math::MTX34 * mtx)152 void Sound3dApp::CalcListenerMatrix( nw::math::MTX34* mtx )
153 {
154     const nw::math::VEC3 pos( 0.0f, 0.0f, -3.0f );   // リスナーの位置
155     const nw::math::VEC3 upVec( 0.0f, 1.0f, 0.0f );  // リスナーのUp方向ベクトル
156     const f32 degree = 0.0f;    // リスナーの向き
157 
158     // リスナーの方向ベクトル
159     const nw::math::VEC3 direction(
160         -nw::math::SinDeg( degree ), 0.0f, -nw::math::CosDeg( degree )
161     );
162     nw::math::VEC3 target = pos + direction;
163 
164     // リスナー行列生成
165     nw::math::MTX34LookAt( mtx, &pos, &upVec, &target );
166 }
167 
OnFinalize()168 void Sound3dApp::OnFinalize()
169 {
170     nw::snd::SoundSystem::Finalize();
171 
172     MemFree( m_pMemoryForSoundSystem );
173     MemFree( m_pMemoryForInfoBlock );
174     MemFree( m_pMemoryForSoundDataManager );
175     MemFree( m_pMemoryForSoundArchivePlayer );
176     MemFree( m_pMemoryForSoundHeap );
177     MemFree( m_pMemoryForStreamBuffer );
178 }
179 
OnDrawUpLCD(nw::font::TextWriter & writer)180 void Sound3dApp::OnDrawUpLCD( nw::font::TextWriter& writer )
181 {
182     writer.Printf(" DEMO nw::snd %s\n\n", DEMO_TITLE);
183 
184     writer.Print ("    -- usage --\n\n");
185     writer.Print ("    [A] Play Sound (Doppler OFF, Filter OFF)\n");
186     writer.Print ("    [X] Play Sound (Doppler ON,  Filter ON)\n");
187     writer.Print ("    [B] Reset Actor Position\n");
188     writer.Print ("    [L/R] Change Filter Type\n");
189     writer.Print ("    [LEFT/RIGHT] Move Actor Position.x\n");
190     writer.Print ("    [UP/DOWN]    Move Actor Position.z\n\n\n");
191 
192     writer.Print ("    -- status ---\n\n");
193     writer.Printf("    Actor x   :% 2.2f\n", m_ActorPos.x);
194     writer.Printf("          z   :% 2.2f\n", m_ActorPos.z);
195     writer.Printf("    FilterType: %s\n", GetFilterTypeString(
196         m_3dManager.GetBiquadFilterType() ) );
197 }
198 
OnDrawDownLCD(nw::font::TextWriter & writer)199 void Sound3dApp::OnDrawDownLCD( nw::font::TextWriter& writer )
200 {
201     (void)writer;
202 }
203 
OnUpdatePad(nw::demo::Pad & pad)204 void Sound3dApp::OnUpdatePad( nw::demo::Pad& pad )
205 {
206     if ( pad.IsButtonPress( nw::demo::Pad::BUTTON_A ) )
207     {
208         // ドップラーファクター 0 のサウンド
209         m_3dActor.HoldSound( &m_Handle, SE_SQUARE );
210     }
211     if ( pad.IsButtonPress( nw::demo::Pad::BUTTON_X ) )
212     {
213         // ドップラーファクター非 0 のサウンド
214         m_3dActor.HoldSound( &m_Handle, SE_3D_DOPPLER );
215     }
216 
217     // 3D サウンドアクター座標をリセット
218     if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_B ) )
219     {
220         m_ActorPos.x = 0.0f;
221         m_ActorPos.z = 0.0f;
222 
223         // 位置が飛ぶ時は、ResetPosition関数を呼び出す必要がある
224         m_3dActor.ResetPosition();
225     }
226 
227     // 3D サウンドアクターの座標変更
228     if ( pad.IsButtonPress( nw::demo::Pad::BUTTON_UP ) )
229     {
230         m_ActorPos.z += -CONTROL_PAD_STEP;
231     }
232     if ( pad.IsButtonPress( nw::demo::Pad::BUTTON_DOWN ) )
233     {
234         m_ActorPos.z += CONTROL_PAD_STEP;
235     }
236     if ( pad.IsButtonPress( nw::demo::Pad::BUTTON_LEFT ) )
237     {
238         m_ActorPos.x += -CONTROL_PAD_STEP;
239     }
240     if ( pad.IsButtonPress( nw::demo::Pad::BUTTON_RIGHT ) )
241     {
242         m_ActorPos.x += CONTROL_PAD_STEP;
243     }
244 #if 0
245     if ( pad.IsButtonPress( nw::demo::Pad::BUTTON_L ) ||
246          pad.IsButtonPress( nw::demo::Pad::BUTTON_R ) )
247     {
248         f32 l, r = 0.0f;
249         if ( pad.IsButtonPress( nw::demo::Pad::BUTTON_L ) )
250         {
251             l = 1.0f;
252         }
253         if ( pad.IsButtonPress( nw::demo::Pad::BUTTON_R ) )
254         {
255             r = 1.0f;
256         }
257 
258         double distance = std::sqrt(
259                 m_ActorPos.x * m_ActorPos.x +
260                 m_ActorPos.z + m_ActorPos.z );
261         double angle = 0.0f;
262         if ( m_ActorPos.x != 0.0f )
263         {
264             angle = std::atan( m_ActorPos.z / m_ActorPos.x );
265             if ( m_ActorPos.x < 0 ) angle += nw::math::F_PI;
266         }
267         else
268         {
269             angle = ( m_ActorPos.z > 0 ) ? nw::math::F_PI / 2.0f :
270                                           -nw::math::F_PI / 2.0f;
271         }
272         angle -= l / 360.0f * 2 * nw::math::F_PI * 2;
273         angle += r / 360.0f * 2 * nw::math::F_PI * 2;
274         m_ActorPos.x = static_cast<f32>( std::cos( angle ) * distance );
275         m_ActorPos.z = static_cast<f32>( std::sin( angle ) * distance );
276     }
277 #endif
278 
279     // フィルタタイプの変更
280     if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_L ) )
281     {
282         m_FilterType -= 1;
283         if ( m_FilterType < 0 )
284         {
285             m_FilterType = nw::snd::BIQUAD_FILTER_TYPE_BPF2048;
286         }
287         m_3dManager.SetBiquadFilterType( m_FilterType );
288     }
289     if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_R ) )
290     {
291         m_FilterType += 1;
292         if ( m_FilterType > nw::snd::BIQUAD_FILTER_TYPE_BPF2048 )
293         {
294             m_FilterType = 0;
295         }
296         m_3dManager.SetBiquadFilterType( m_FilterType );
297     }
298 }
299 
OnUpdate()300 void Sound3dApp::OnUpdate()
301 {
302     m_3dActor.SetPosition( m_ActorPos );
303     m_ArchivePlayer.Update();
304 }
305