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