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