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