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