/*---------------------------------------------------------------------------* Project: NintendoWare File: main.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. 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. $Revision:$ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include "demolib.h" #include "simple.csid" class EffectApp : public nw::snd::demolib::AppBase { protected: virtual void OnInitialize(); virtual void OnFinalize(); virtual void OnDrawUpLCD( nw::font::TextWriter& ); virtual void OnDrawDownLCD( nw::font::TextWriter& ); virtual void OnUpdatePad( nw::demo::Pad& ); virtual void OnUpdate(); private: enum EffectType { EFFECT_TYPE_NONE, #ifdef NW_SND_AVAILABLE_NN_EFFECT EFFECT_TYPE_NN_REVERB, EFFECT_TYPE_NN_DELAY, #endif EFFECT_TYPE_NW_REVERB, EFFECT_TYPE_NW_DELAY, EFFECT_TYPE_NUM, EFFECT_TYPE_MAX = EFFECT_TYPE_NW_DELAY }; void InitializeSoundSystem(); void InitializeEffect(); void FinalizeEffect(); const char* GetEffectTypeString() const; nw::snd::RomSoundArchive m_Archive; nw::snd::SoundArchivePlayer m_ArchivePlayer; nw::snd::SoundDataManager m_DataManager; nw::snd::SoundHeap m_Heap; nw::snd::SoundHandle m_Handle; nw::snd::FxReverb m_NwFxReverb; nw::snd::FxReverb::Param m_NwFxReverbParam; nw::snd::FxDelay m_NwFxDelay; nw::snd::FxDelay::Param m_NwFxDelayParam; #ifdef NW_SND_AVAILABLE_NN_EFFECT nn::snd::FxReverb m_NnFxReverb; nn::snd::FxReverb::Param m_NnFxReverbParam; nn::snd::FxDelay m_NnFxDelay; nn::snd::FxDelay::Param m_NnFxDelayParam; #endif void* m_pMemoryForSoundSystem; void* m_pMemoryForInfoBlock; void* m_pMemoryForSoundDataManager; void* m_pMemoryForSoundArchivePlayer; void* m_pMemoryForSoundHeap; void* m_pMemoryForStreamBuffer; void* m_pMemoryForNwFxReverb; void* m_pMemoryForNwFxDelay; #ifdef NW_SND_AVAILABLE_NN_EFFECT void* m_pMemoryForNnFxReverb; void* m_pMemoryForNnFxDelay; #endif int m_EffectType; // enum EffectType int m_PreEffectType; }; namespace { const s32 SOUND_THREAD_PRIORITY = 4; const s32 LOAD_THREAD_PRIORITY = 3; const s32 SOUND_HEAP_SIZE = 1 * 1024 * 1024; const char SOUND_ARC_PATH[] = NW_SND_DEMO_PATH_PREFIX "simple.bcsar"; const char DEMO_TITLE[] = "Effect"; } void EffectApp::OnInitialize() { InitializeSoundSystem(); // サウンドデータのロード if ( ! m_DataManager.LoadData( SEQ_MARIOKART, &m_Heap ) ) { NW_ASSERTMSG( false, "LoadData(SEQ_MARIOKART) failed." ); } if ( ! m_DataManager.LoadData( SE_YOSHI, &m_Heap ) ) { NW_ASSERTMSG( false, "LoadData(SE_YOSHI) failed." ); } m_PreEffectType = m_EffectType = 0; } void EffectApp::InitializeSoundSystem() { // サウンドシステムの初期化 { nw::snd::SoundSystem::SoundSystemParam param; size_t workMemSize = nw::snd::SoundSystem::GetRequiredMemSize( param ); m_pMemoryForSoundSystem = MemAlloc( workMemSize ); nw::snd::SoundSystem::Initialize( param, reinterpret_cast( m_pMemoryForSoundSystem ), workMemSize ); } // サウンドアーカイブの初期化 if ( ! m_Archive.Open( SOUND_ARC_PATH ) ) { NW_ASSERTMSG( 0, "cannot open bcsar(%s)\n", SOUND_ARC_PATH ); } // INFO ブロックのロード { size_t infoBlockSize = m_Archive.GetHeaderSize(); m_pMemoryForInfoBlock = MemAlloc( infoBlockSize ); if ( ! m_Archive.LoadHeader( m_pMemoryForInfoBlock, infoBlockSize ) ) { NW_ASSERTMSG( 0, "cannot load infoBlock(%s)", SOUND_ARC_PATH ); } } // サウンドデータマネージャーの初期化 { size_t setupSize = m_DataManager.GetRequiredMemSize( &m_Archive ); m_pMemoryForSoundDataManager = MemAlloc( setupSize ); m_DataManager.Initialize( &m_Archive, m_pMemoryForSoundDataManager, setupSize ); } // サウンドアーカイブプレイヤーの初期化 { size_t setupSize = m_ArchivePlayer.GetRequiredMemSize( &m_Archive ); m_pMemoryForSoundArchivePlayer = MemAlloc( setupSize, 32 ); size_t setupStrmBufferSize = m_ArchivePlayer.GetRequiredStreamBufferSize( &m_Archive ); m_pMemoryForStreamBuffer = MemAlloc( setupStrmBufferSize, 32 ); bool result = m_ArchivePlayer.Initialize( &m_Archive, &m_DataManager, m_pMemoryForSoundArchivePlayer, setupSize, m_pMemoryForStreamBuffer, setupStrmBufferSize ); NW_ASSERT( result ); } // サウンドヒープの構築 { m_pMemoryForSoundHeap = MemAlloc( SOUND_HEAP_SIZE ); bool result = m_Heap.Create( m_pMemoryForSoundHeap, SOUND_HEAP_SIZE ); NW_ASSERT( result ); } } void EffectApp::OnFinalize() { nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A ); nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_B ); m_NwFxReverb.ReleaseWorkBuffer(); m_NwFxDelay.ReleaseWorkBuffer(); #ifdef NW_SND_AVAILABLE_NN_EFFECT m_NnFxReverb.ReleaseWorkBuffer(); m_NnFxDelay.ReleaseWorkBuffer(); #endif nw::snd::SoundSystem::Finalize(); MemFree( m_pMemoryForSoundSystem ); MemFree( m_pMemoryForInfoBlock ); MemFree( m_pMemoryForSoundDataManager ); MemFree( m_pMemoryForSoundArchivePlayer ); MemFree( m_pMemoryForSoundHeap ); MemFree( m_pMemoryForStreamBuffer ); MemFree( m_pMemoryForNwFxReverb ); MemFree( m_pMemoryForNwFxDelay ); #ifdef NW_SND_AVAILABLE_NN_EFFECT MemFree( m_pMemoryForNnFxReverb ); MemFree( m_pMemoryForNnFxDelay ); #endif } void EffectApp::OnDrawUpLCD( nw::font::TextWriter& writer ) { writer.Printf(" DEMO nw::snd %s\n\n", DEMO_TITLE); writer.Print (" -- usage --\n\n"); writer.Print (" [A] Play Sequence Sound\n"); writer.Print (" [X] Play Wave Sound\n"); writer.Print (" [Y] Play Stream Sound\n"); writer.Print (" [B] Stop Sound\n"); writer.Print (" [LEFT/RIGHT] Change Effect\n\n"); writer.Printf(" current effect: %s\n\n", GetEffectTypeString() ); } void EffectApp::OnDrawDownLCD( nw::font::TextWriter& writer ) { (void)writer; } void EffectApp::OnUpdatePad( nw::demo::Pad& pad ) { if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_A ) ) { m_Handle.Stop( 0 ); bool result = m_ArchivePlayer.StartSound( &m_Handle, SEQ_MARIOKART ).IsSuccess(); nw::snd::SequenceSoundHandle handle( &m_Handle ); handle.SetFxSend( nw::snd::AUX_BUS_A, 0.3f ); NN_LOG("[SEQ] SEQ_MARIOKART ... (%d)\n", result); } if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_X ) ) { m_Handle.Stop( 0 ); bool result = m_ArchivePlayer.StartSound( &m_Handle, SE_YOSHI ).IsSuccess(); nw::snd::WaveSoundHandle handle( &m_Handle ); handle.SetFxSend( nw::snd::AUX_BUS_A, 0.3f ); NN_LOG("[WSD] SE_YOSHI ... (%d)\n", result); } if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_Y ) ) { m_Handle.Stop( 0 ); bool result = m_ArchivePlayer.StartSound( &m_Handle, STRM_MARIOKART ).IsSuccess(); nw::snd::StreamSoundHandle handle( &m_Handle ); handle.SetFxSend( nw::snd::AUX_BUS_A, 0.3f ); NN_LOG("[STRM] STRM_MARIOKART ... (%d)\n", result ); } if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_B ) ) { m_Handle.Stop( 3 ); } bool isChangeEffect = false; if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_LEFT ) ) { m_PreEffectType = m_EffectType; m_EffectType -= 1; if ( m_EffectType < 0 ) { m_EffectType = EFFECT_TYPE_MAX; } isChangeEffect = true; } if ( pad.IsButtonDown( nw::demo::Pad::BUTTON_RIGHT ) ) { m_PreEffectType = m_EffectType; m_EffectType += 1; if ( m_EffectType > EFFECT_TYPE_MAX ) { m_EffectType = 0; } isChangeEffect = true; } if ( isChangeEffect ) { FinalizeEffect(); InitializeEffect(); } } void EffectApp::FinalizeEffect() { switch ( m_PreEffectType ) { case EFFECT_TYPE_NW_REVERB: nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A, 0 ); m_NwFxReverb.ReleaseWorkBuffer(); break; case EFFECT_TYPE_NW_DELAY: nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A, 0 ); m_NwFxDelay.ReleaseWorkBuffer(); break; #ifdef NW_SND_AVAILABLE_NN_EFFECT case EFFECT_TYPE_NN_REVERB: nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A, 0 ); m_NnFxReverb.ReleaseWorkBuffer(); break; case EFFECT_TYPE_NN_DELAY: nw::snd::SoundSystem::ClearEffect( nw::snd::AUX_BUS_A, 0 ); m_NnFxDelay.ReleaseWorkBuffer(); break; #endif default: break; } } void EffectApp::InitializeEffect() { switch ( m_EffectType ) { case EFFECT_TYPE_NW_REVERB: // nw::snd::FxReverb の設定 { nw::snd::FxReverb::FilterSize filterSize; filterSize.m_Comb0 = 20 * 160; filterSize.m_Comb1 = 30 * 160; filterSize.m_AllPass = 13 * 160; m_NwFxReverbParam.m_EarlyReflectionTime = 200; m_NwFxReverbParam.m_FusedTime = 1000; m_NwFxReverbParam.m_PreDelayTime = 200; m_NwFxReverbParam.m_pFilterSize = &filterSize; m_NwFxReverb.SetParam( m_NwFxReverbParam ); size_t reverbBufferSize = m_NwFxReverb.GetRequiredMemSize(); m_pMemoryForNwFxReverb = MemAlloc( reverbBufferSize, 4 ); m_NwFxReverb.AssignWorkBuffer( reinterpret_cast( m_pMemoryForNwFxReverb ), reverbBufferSize ); bool result = nw::snd::SoundSystem::AppendEffect( nw::snd::AUX_BUS_A, &m_NwFxReverb ); NN_LOG( "NW_REVREB %d\n", result ); } break; case EFFECT_TYPE_NW_DELAY: // nw::snd::FxDelay の設定 { m_NwFxDelayParam.m_DelayTime = 400; m_NwFxDelayParam.m_FeedbackGain = 0.4f; m_NwFxDelayParam.m_Damping = 0.3f; m_NwFxDelayParam.m_IsEnableSurround = false; m_NwFxDelay.SetParam( m_NwFxDelayParam ); size_t delayBufferSize = m_NwFxDelay.GetRequiredMemSize(); m_pMemoryForNwFxDelay = MemAlloc( delayBufferSize, 4 ); m_NwFxDelay.AssignWorkBuffer( reinterpret_cast( m_pMemoryForNwFxDelay ), delayBufferSize ); bool result = nw::snd::SoundSystem::AppendEffect( nw::snd::AUX_BUS_A, &m_NwFxDelay ); NN_LOG( "NW_DELAY %d\n", result ); } break; #ifdef NW_SND_AVAILABLE_NN_EFFECT case EFFECT_TYPE_NN_REVERB: // nn::snd::FxReverb の設定 { nn::snd::FxReverb::FilterSize filterSize; filterSize.m_Comb0 = 20 * 160; filterSize.m_Comb1 = 30 * 160; filterSize.m_AllPass = 13 * 160; m_NnFxReverbParam.m_EarlyReflectionTime = 200; m_NnFxReverbParam.m_FusedTime = 1000; m_NnFxReverbParam.m_PreDelayTime = 200; m_NnFxReverbParam.m_pFilterSize = &filterSize; m_NnFxReverb.SetParam( m_NnFxReverbParam ); size_t reverbBufferSize = m_NnFxReverb.GetRequiredMemSize(); m_pMemoryForNnFxReverb = MemAlloc( reverbBufferSize, 4 ); m_NnFxReverb.AssignWorkBuffer( reinterpret_cast( m_pMemoryForNnFxReverb ), reverbBufferSize ); bool result = nw::snd::SoundSystem::AppendEffect( nw::snd::AUX_BUS_A, &m_NnFxReverb ); NN_LOG( "NN_REVREB %d\n", result ); } break; case EFFECT_TYPE_NN_DELAY: // nn::snd::FxDelay の設定 { m_NnFxDelayParam.m_DelayTime = 400; m_NnFxDelayParam.m_FeedbackGain = 0.4f; m_NnFxDelayParam.m_Damping = 0.3f; m_NnFxDelayParam.m_IsEnableSurround = false; m_NnFxDelay.SetParam( m_NnFxDelayParam ); size_t delayBufferSize = m_NnFxDelay.GetRequiredMemSize(); m_pMemoryForNnFxDelay = MemAlloc( delayBufferSize, 4 ); m_NnFxDelay.AssignWorkBuffer( reinterpret_cast( m_pMemoryForNnFxDelay ), delayBufferSize ); bool result = nw::snd::SoundSystem::AppendEffect( nw::snd::AUX_BUS_A, &m_NnFxDelay ); NN_LOG( "NN_DELAY %d\n", result ); } break; #endif default: { NN_LOG( "NONE\n"); } break; } } void EffectApp::OnUpdate() { m_ArchivePlayer.Update(); } const char* EffectApp::GetEffectTypeString() const { static const char* EFFECT_TYPE_STRING[] = { "NONE", #ifdef NW_SND_AVAILABLE_NN_EFFECT "NN_REVERB", "NN_DELAY", #endif "NW_REVERB", "NW_DELAY" }; if ( m_EffectType > EFFECT_TYPE_MAX ) { return NULL; } return EFFECT_TYPE_STRING[ m_EffectType ]; } void nnMain() { EffectApp app; app.Initialize(); app.Run(); app.Finalize(); }