/*---------------------------------------------------------------------------* Project: NintendoWare File: snd_WaveSound.cpp Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. 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. The content herein is highly confidential and should be handled accordingly. $Revision: 31311 $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include #include #include #include namespace nw { namespace snd { namespace internal { NW_UT_RUNTIME_TYPEINFO_DEFINITION(WaveSound,BasicSound); /* ======================================================================== member function ======================================================================== */ /*---------------------------------------------------------------------------* Name: WaveSound Description: コンストラクタ Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ WaveSound::WaveSound( WaveSoundInstanceManager& manager ) : m_pManager( manager ), m_InitializeFlag(false) { } void WaveSound::Initialize() { BasicSound::Initialize(); m_pTempSpecialHandle = NULL; m_LoadingFlag = false; m_PreparedFlag = false; m_InitializeFlag = true; } /*---------------------------------------------------------------------------* Name: Shutdown Description: サウンドの終了 Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void WaveSound::Finalize() { if ( ! m_InitializeFlag ) { return; } m_InitializeFlag = false; // プレイヤーヒープにロード中の場合にロードを停止する if ( m_LoadingFlag ) { TaskManager::GetInstance().CancelTask( &m_DataLoadTask ); m_DataLoadTask.Wait(); } BasicSound::Finalize(); m_DataManager.Finalize(); m_pManager.Free( this ); } /*---------------------------------------------------------------------------* Name: Prepare Description: サウンド開始 Arguments: seqDataBase - シーケンスデータベースアドレス seqDataOffset - シーケンスデータのオフセット bank - バンクデータ Returns: None. *---------------------------------------------------------------------------*/ void WaveSound::Prepare( const void* wsdFile, const StartInfo& startInfo ) { NW_NULL_ASSERT( wsdFile ); NW_NULL_ASSERT( startInfo.callback ); DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance(); DriverCommandWaveSoundSetup* command = cmdmgr.AllocCommand(); command->id = DRIVER_COMMAND_WAVESND_SETUP; command->player = &m_WaveSoundPlayerInstance; command->wsdFile = wsdFile; command->waveSoundOffset = startInfo.index; command->startOffsetType = startInfo.startOffsetType; command->offset = startInfo.startOffset; command->callback = startInfo.callback; command->callbackData = startInfo.callbackData; cmdmgr.PushCommand(command); m_PreparedFlag = true; } bool WaveSound::RegisterDataLoadTask( const LoadInfo& loadInfo, const StartInfo& startInfo ) { PlayerHeap* heap = GetPlayerHeap(); if ( heap == NULL ) { return false; } m_DataManager.Initialize( loadInfo.arc ); m_DataLoadTask.m_pDataManager = &m_DataManager; m_DataLoadTask.m_pAllocator = heap; m_DataLoadTask.m_Callback = NotifyAsyncLoadFinishedFunc; m_DataLoadTask.m_CallbackData = this; m_DataLoadTask.m_pSoundDataManager = loadInfo.mgr; m_DataLoadTask.m_pSoundArchive = loadInfo.arc; m_DataLoadTask.m_LoadInfoWsd = *(loadInfo.wsd); m_DataLoadTask.m_Index = startInfo.index; m_StartInfo = startInfo; TaskManager::GetInstance().AppendTask( &m_DataLoadTask, TaskManager::PRIORITY_MIDDLE ); return true; } /*---------------------------------------------------------------------------* Name: SetChannelPriority Description: 発音プライオリティを変更 Arguments: priority - 発音プライオリティ Returns: None. *---------------------------------------------------------------------------*/ void WaveSound::SetChannelPriority( int priority ) { NW_MINMAX_ASSERT( priority, 0, 127 ); DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance(); DriverCommandWaveSoundChannelPrio* command = cmdmgr.AllocCommand(); command->id = DRIVER_COMMAND_WAVESND_CHANNELPRIO; command->player = &m_WaveSoundPlayerInstance; command->priority = priority; cmdmgr.PushCommand(command); } /*---------------------------------------------------------------------------* Name: SetReleasePriorityFix Description: リリース時のプライオリティを変化しないようにする Arguments: fix - Returns: なし *---------------------------------------------------------------------------*/ void WaveSound::SetReleasePriorityFix( bool fix ) { DriverCommandManager& cmdmgr = DriverCommandManager::GetInstance(); DriverCommandWaveSoundPrioFix* command = cmdmgr.AllocCommand(); command->id = DRIVER_COMMAND_WAVESND_PRIOFIX; command->player = &m_WaveSoundPlayerInstance; command->priorityFix = fix; cmdmgr.PushCommand(command); } /*---------------------------------------------------------------------------* Name: OnUpdatePlayerPriority Description: プレイヤープライオリティを変更 Arguments: Returns: None. *---------------------------------------------------------------------------*/ void WaveSound::OnUpdatePlayerPriority() { int priority = CalcCurrentPlayerPriority(); m_pManager.UpdatePriority( this, priority ); } bool WaveSound::IsAttachedTempSpecialHandle() { return m_pTempSpecialHandle != NULL; } void WaveSound::DetachTempSpecialHandle() { // TODO: m_pTempSpecialHandle->DetachSound(); } bool WaveSound::ReadWaveSoundDataInfo( WaveSoundDataInfo* info ) const { if ( ! IsPlayerAvailable() ) return false; return m_WaveSoundPlayerInstance.ReadWaveSoundDataInfo( info ); } long WaveSound::GetPlaySamplePosition() const { if ( ! IsPlayerAvailable() ) return 0; return m_WaveSoundPlayerInstance.GetPlaySamplePosition(); } void WaveSound::NotifyAsyncLoadFinishedFunc( bool result, const LoadItemInfo* wsd, void* userData ) { NW_NULL_ASSERT( userData ); WaveSound* sound = static_cast( userData ); sound->m_LoadingFlag = false; if ( ! result ) { sound->Stop( 0 ); return; } // プリペア sound->Prepare( wsd->address, sound->m_StartInfo ); // プレイヤーヒープを SeqPlayer にセット sound->m_WaveSoundPlayerInstance.SetPlayerHeapDataManager( &sound->m_DataManager ); } WaveSound::DataLoadTask::DataLoadTask() : m_pDataManager( NULL ), m_pAllocator( NULL ), m_Callback( NULL ), m_CallbackData( NULL ) { } void WaveSound::DataLoadTask::Execute() { m_pAllocator->Clear(); // あらかじめクリアしておく if ( ( m_LoadInfoWsd.address == NULL ) && ( m_LoadInfoWsd.itemId != SoundArchive::INVALID_ID ) ) { SoundArchive::ItemId soundId = m_LoadInfoWsd.itemId; if ( ! m_pDataManager->LoadData( soundId, m_pAllocator, SoundArchiveLoader::LOAD_WSD ) ) { NW_WARNING( false, "failed to load WSD(%08x) to PlayerHeap", soundId ); if ( m_Callback ) { m_Callback( false, NULL, m_CallbackData ); return; } } m_LoadInfoWsd.address = m_pDataManager->detail_GetFileAddressByItemId( soundId ); } // SoundDataManager 側で波形アーカイブがロード済みか? bool result = Util::IsLoadedWaveArchive( m_LoadInfoWsd.address, m_Index, *m_pSoundArchive, *m_pSoundDataManager ); if ( ! result ) { // 未ロードなら、ここでロードする if ( ! m_pDataManager->detail_LoadWaveArchiveByWaveSoundFile( m_LoadInfoWsd.address, m_Index, m_pAllocator ) ) { NW_WARNING( false, "failed to load WSD(%08x)'s WARC to PlayerHeap", m_LoadInfoWsd.itemId ); if ( m_Callback ) { m_Callback( false, NULL, m_CallbackData ); return; } } } // ロード完了 if ( m_Callback ) { m_Callback( true, &m_LoadInfoWsd, m_CallbackData ); } } } // namespace nw::snd::internal } // namespace nw::snd } // namespace nw