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