1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: snd.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. 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 $Rev: 46365 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/snd.h>
17 #include <string.h>
18 #include "snd.h"
19
20 // Sound thread related
21 const int SOUND_THREAD_PRIORITY = 2;
22 const int SOUND_THREAD_STACK_SIZE = 1024;
23
24 nn::snd::WaveBuffer m_WaveBuffer;
25 s16* m_SoundBuffer = NULL;
26 nn::snd::Voice* mp_Voice;
27
28 // Sound data
29 extern "C" {
30 extern u8* SOUND_BEGIN[];
31 extern u8* SOUND_END[];
32 }
33
SoundThreadFunc(SndDemo * pSndDemo)34 void SoundThreadFunc(SndDemo* pSndDemo)
35 {
36 pSndDemo->SoundThreadFuncImpl();
37 }
38
SoundThreadFuncImpl(void)39 void SndDemo::SoundThreadFuncImpl(void)
40 {
41 // Specify stereo output
42 nn::snd::SetSoundOutputMode(nn::snd::OUTPUT_MODE_STEREO);
43
44 // Prepare WaveBuffer
45 const u32 SOUND_SIZE = reinterpret_cast<u32>(SOUND_END) - reinterpret_cast<u32>(SOUND_BEGIN);
46 m_SoundBuffer = reinterpret_cast<s16*>(mp_AppHeap->Allocate(SOUND_SIZE, 32));
47 memcpy(m_SoundBuffer, SOUND_BEGIN, SOUND_SIZE);
48 nn::snd::FlushDataCache(reinterpret_cast<uptr>(m_SoundBuffer), SOUND_SIZE);
49 nn::snd::InitializeWaveBuffer(&m_WaveBuffer);
50 m_WaveBuffer.bufferAddress = reinterpret_cast<void*>(m_SoundBuffer);
51 m_WaveBuffer.sampleLength = nn::snd::GetSampleLength(SOUND_SIZE, nn::snd::SAMPLE_FORMAT_PCM16, 2);
52 m_WaveBuffer.loopFlag = true;
53
54 // Prepare volume Mix
55 nn::snd::MixParam mix;
56 mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_LEFT] = 0.707f; // Main volume (L)
57 mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_RIGHT] = 0.707f; // Main volume (R)
58
59 // Prepare Voice
60 mp_Voice = nn::snd::AllocVoice(128, NULL, NULL);
61 mp_Voice->SetSampleRate(48000); // Set sampling rate
62 mp_Voice->SetSampleFormat(nn::snd::SAMPLE_FORMAT_PCM16); // Specify format
63 mp_Voice->SetChannelCount(2); // Set number of channels
64 mp_Voice->SetPitch(1.0f); // Set pitch
65 mp_Voice->SetVolume(1.0f); // Set volume
66 mp_Voice->SetMixParam(mix); // Set volume Mix
67
68 mp_Voice->AppendWaveBuffer(&m_WaveBuffer); // Add buffer
69
70 // Set master volume
71 nn::snd::SetMasterVolume(1.0f);
72
73 // Start playback
74 mp_Voice->SetState(nn::snd::Voice::STATE_PLAY);
75
76 while (!m_EndFlag)
77 {
78 nn::snd::WaitForDspSync(); // Wait for data from DSP.
79 nn::snd::SendParameterToDsp(); // Send parameters to the DSP.
80 }
81
82 // End playback
83 mp_Voice->SetState(nn::snd::Voice::STATE_STOP);
84 FreeVoice(mp_Voice);
85 }
86
Initialize(demo::RenderSystemDrawing * p_RenderSystem,nn::fnd::ExpHeap * p_AppHeap)87 void SndDemo::Initialize(demo::RenderSystemDrawing* p_RenderSystem, nn::fnd::ExpHeap* p_AppHeap)
88 {
89 Device::Initialize(p_RenderSystem);
90
91 mp_AppHeap = p_AppHeap;
92
93 // Initialize DSP
94 nn::Result result = nn::dsp::Initialize();
95 NN_UTIL_PANIC_IF_FAILED(result);
96
97 result = nn::dsp::LoadDefaultComponent();
98 NN_UTIL_PANIC_IF_FAILED(result);
99
100 // Initialize SND
101 result = nn::snd::Initialize();
102 NN_UTIL_PANIC_IF_FAILED(result);
103 }
104
Finalize()105 void SndDemo::Finalize()
106 {
107 // Finalize SND
108 nn::Result result = nn::snd::Finalize();
109 NN_UTIL_PANIC_IF_FAILED(result);
110
111 // Finalize DSP
112 result = nn::dsp::UnloadComponent();
113 NN_UTIL_PANIC_IF_FAILED(result);
114 nn::dsp::Finalize();
115
116 // Destroy sound buffer
117 if (m_SoundBuffer)
118 {
119 mp_AppHeap->Free(m_SoundBuffer);
120 }
121
122 Device::Finalize();
123 }
124
Start()125 void SndDemo::Start()
126 {
127 // Register DSP interrupt callback function
128 m_EndFlag = false;
129 m_SoundThread.StartUsingAutoStack(
130 SoundThreadFunc,
131 this,
132 SOUND_THREAD_STACK_SIZE,
133 SOUND_THREAD_PRIORITY
134 );
135
136 Device::Start();
137 }
138
End()139 void SndDemo::End()
140 {
141 // Destroy the sound thread
142 m_EndFlag = true;
143 m_SoundThread.Join();
144 m_SoundThread.Finalize();
145
146 Device::End();
147 }
148
DrawFrame(void)149 void SndDemo::DrawFrame(void)
150 {
151 }
152
153 /*---------------------------------------------------------------------------*
154 End of file
155 *---------------------------------------------------------------------------*/
156