/*---------------------------------------------------------------------------* Project: Horizon File: snd.cpp Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 46365 $ *---------------------------------------------------------------------------*/ #include #include #include "snd.h" // Sound thread related const int SOUND_THREAD_PRIORITY = 2; const int SOUND_THREAD_STACK_SIZE = 1024; nn::snd::WaveBuffer m_WaveBuffer; s16* m_SoundBuffer = NULL; nn::snd::Voice* mp_Voice; // Sound data extern "C" { extern u8* SOUND_BEGIN[]; extern u8* SOUND_END[]; } void SoundThreadFunc(SndDemo* pSndDemo) { pSndDemo->SoundThreadFuncImpl(); } void SndDemo::SoundThreadFuncImpl(void) { // Specify stereo output nn::snd::SetSoundOutputMode(nn::snd::OUTPUT_MODE_STEREO); // Prepare WaveBuffer const u32 SOUND_SIZE = reinterpret_cast(SOUND_END) - reinterpret_cast(SOUND_BEGIN); m_SoundBuffer = reinterpret_cast(mp_AppHeap->Allocate(SOUND_SIZE, 32)); memcpy(m_SoundBuffer, SOUND_BEGIN, SOUND_SIZE); nn::snd::FlushDataCache(reinterpret_cast(m_SoundBuffer), SOUND_SIZE); nn::snd::InitializeWaveBuffer(&m_WaveBuffer); m_WaveBuffer.bufferAddress = reinterpret_cast(m_SoundBuffer); m_WaveBuffer.sampleLength = nn::snd::GetSampleLength(SOUND_SIZE, nn::snd::SAMPLE_FORMAT_PCM16, 2); m_WaveBuffer.loopFlag = true; // Prepare volume Mix nn::snd::MixParam mix; mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_LEFT] = 0.707f; // Main volume (L) mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_RIGHT] = 0.707f; // Main volume (R) // Prepare Voice mp_Voice = nn::snd::AllocVoice(128, NULL, NULL); mp_Voice->SetSampleRate(48000); // Set sampling rate mp_Voice->SetSampleFormat(nn::snd::SAMPLE_FORMAT_PCM16); // Specify format mp_Voice->SetChannelCount(2); // Set number of channels mp_Voice->SetPitch(1.0f); // Set pitch mp_Voice->SetVolume(1.0f); // Set volume mp_Voice->SetMixParam(mix); // Set volume Mix mp_Voice->AppendWaveBuffer(&m_WaveBuffer); // Add buffer // Set master volume nn::snd::SetMasterVolume(1.0f); // Start playback mp_Voice->SetState(nn::snd::Voice::STATE_PLAY); while (!m_EndFlag) { nn::snd::WaitForDspSync(); // Wait for data from DSP. nn::snd::SendParameterToDsp(); // Send parameters to the DSP. } // End playback mp_Voice->SetState(nn::snd::Voice::STATE_STOP); FreeVoice(mp_Voice); } void SndDemo::Initialize(demo::RenderSystemDrawing* p_RenderSystem, nn::fnd::ExpHeap* p_AppHeap) { Device::Initialize(p_RenderSystem); mp_AppHeap = p_AppHeap; // Initialize DSP nn::Result result = nn::dsp::Initialize(); NN_UTIL_PANIC_IF_FAILED(result); result = nn::dsp::LoadDefaultComponent(); NN_UTIL_PANIC_IF_FAILED(result); // Initialize SND result = nn::snd::Initialize(); NN_UTIL_PANIC_IF_FAILED(result); } void SndDemo::Finalize() { // Finalize SND nn::Result result = nn::snd::Finalize(); NN_UTIL_PANIC_IF_FAILED(result); // Finalize DSP result = nn::dsp::UnloadComponent(); NN_UTIL_PANIC_IF_FAILED(result); nn::dsp::Finalize(); // Destroy sound buffer if (m_SoundBuffer) { mp_AppHeap->Free(m_SoundBuffer); } Device::Finalize(); } void SndDemo::Start() { // Register DSP interrupt callback function m_EndFlag = false; m_SoundThread.StartUsingAutoStack( SoundThreadFunc, this, SOUND_THREAD_STACK_SIZE, SOUND_THREAD_PRIORITY ); Device::Start(); } void SndDemo::End() { // Destroy the sound thread m_EndFlag = true; m_SoundThread.Join(); m_SoundThread.Finalize(); Device::End(); } void SndDemo::DrawFrame(void) { } /*---------------------------------------------------------------------------* End of file *---------------------------------------------------------------------------*/