/*---------------------------------------------------------------------------* Project: NintendoWare File: snd_SoundArchiveFileReader.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: 24218 $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include namespace nw { namespace snd { namespace internal { namespace { const u32 SIGNATURE_STRING_BLOCK = NW_UT_MAKE_SIGWORD( 'S', 'T', 'R', 'G' ); const u32 SIGNATURE_INFO_BLOCK = NW_UT_MAKE_SIGWORD( 'I', 'N', 'F', 'O' ); const u32 SIGNATURE_DATA_BLOCK = NW_UT_MAKE_SIGWORD( 'D', 'A', 'T', 'A' ); const u32 SUPPORTED_FILE_VERSION = 0x02000000; const u32 CURRENT_FILE_VERSION = 0x02000000; bool IsValidFileHeader( const void* soundArchiveData ) { const ut::BinaryFileHeader& header = *reinterpret_cast( soundArchiveData ); // シグニチャ確認 NW_ASSERTMSG( header.signature == SoundArchiveFileReader::SIGNATURE_FILE, "invalid file signature." ); if ( header.signature != SoundArchiveFileReader::SIGNATURE_FILE ) { return false; } // バージョン確認 NW_ASSERTMSG( header.version >= SUPPORTED_FILE_VERSION, "sound archive file is not supported version.\n" "please reconvert file using new version tools.\n" "(SUPPORTED_FILE_VERSION:0x%08x >= your version:0x%08x)\n", SUPPORTED_FILE_VERSION, header.version ); if ( header.version < SUPPORTED_FILE_VERSION ) { return false; } NW_ASSERTMSG( header.version <= CURRENT_FILE_VERSION, "sound archive file is not supported version.\n" "please reconvert file using new version tools.\n" "(CURRENT_FILE_VERSION:0x%08x <= your version:0x%08x)\n", CURRENT_FILE_VERSION, header.version ); if ( header.version > CURRENT_FILE_VERSION ) { return false; } return true; } } // anonymous namespace SoundArchiveFileReader::SoundArchiveFileReader() : m_pStringBlockBody( NULL ), m_pInfoBlockBody( NULL ), m_pFileBlockBody( NULL ) { } void SoundArchiveFileReader::Initialize( const void* soundArchiveData ) { NW_NULL_ASSERT( soundArchiveData ); if ( ! IsValidFileHeader( soundArchiveData ) ) return; const SoundArchiveFile::FileHeader& header = *reinterpret_cast( soundArchiveData ); m_Header = header; // 構造体コピー } void SoundArchiveFileReader::Finalize() { m_pStringBlockBody = NULL; m_pInfoBlockBody = NULL; m_pFileBlockBody = NULL; } void SoundArchiveFileReader::SetStringBlock( const void* stringBlock ) { m_pStringBlockBody = &reinterpret_cast( stringBlock )->body; } void SoundArchiveFileReader::SetInfoBlock( const void* infoBlock ) { m_pInfoBlockBody = &reinterpret_cast( infoBlock )->body; } u32 SoundArchiveFileReader::GetStringCount() const { NW_NULL_ASSERT( m_pStringBlockBody ); return m_pStringBlockBody->GetStringCount(); } const char* SoundArchiveFileReader::GetString( SoundArchive::ItemId stringId ) const { NW_NULL_ASSERT( m_pStringBlockBody ); return m_pStringBlockBody->GetString( stringId ); } void SoundArchiveFileReader::DumpTree() const { NW_NULL_ASSERT( m_pStringBlockBody ); m_pStringBlockBody->DumpTree(); } SoundArchive::ItemId SoundArchiveFileReader::GetItemId( const char* pStr ) const { if ( m_pStringBlockBody == NULL ) { return SoundArchive::INVALID_ID; } return m_pStringBlockBody->GetItemId( pStr ); } const char* SoundArchiveFileReader::GetItemLabel( SoundArchive::ItemId id ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); if ( m_pStringBlockBody == NULL ) { return NULL; } SoundArchive::StringId stringId = m_pInfoBlockBody->GetItemStringId( id ); if ( stringId == SoundArchive::INVALID_ID ) { return NULL; } return m_pStringBlockBody->GetString( stringId ); } SoundArchive::FileId SoundArchiveFileReader::GetItemFileId( SoundArchive::ItemId id ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); return m_pInfoBlockBody->GetItemFileId( id ); } u32 SoundArchiveFileReader::GetSoundCount() const { NW_NULL_ASSERT( m_pInfoBlockBody ); return m_pInfoBlockBody->GetSoundCount(); } u32 SoundArchiveFileReader::GetBankCount() const { NW_NULL_ASSERT( m_pInfoBlockBody ); return m_pInfoBlockBody->GetBankCount(); } u32 SoundArchiveFileReader::GetPlayerCount() const { NW_NULL_ASSERT( m_pInfoBlockBody ); return m_pInfoBlockBody->GetPlayerCount(); } u32 SoundArchiveFileReader::GetSoundGroupCount() const { NW_NULL_ASSERT( m_pInfoBlockBody ); return m_pInfoBlockBody->GetSoundGroupCount(); } u32 SoundArchiveFileReader::GetGroupCount() const { NW_NULL_ASSERT( m_pInfoBlockBody ); return m_pInfoBlockBody->GetGroupCount(); } u32 SoundArchiveFileReader::GetWaveArchiveCount() const { NW_NULL_ASSERT( m_pInfoBlockBody ); return m_pInfoBlockBody->GetWaveArchiveCount(); } u32 SoundArchiveFileReader::GetFileCount() const { NW_NULL_ASSERT( m_pInfoBlockBody ); return m_pInfoBlockBody->GetFileCount(); } bool SoundArchiveFileReader::ReadSoundInfo( SoundArchive::ItemId soundId, SoundArchive::SoundInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::SoundInfo* data = m_pInfoBlockBody->GetSoundInfo( soundId ); if ( data == NULL ) return false; info->fileId = data->fileId; info->playerId = data->playerId; info->volume = data->volume; info->panMode = data->GetPanMode(); info->panCurve = data->GetPanCurve(); info->playerPriority = data->GetPlayerPriority(); info->actorPlayerId = data->GetActorPlayerId(); info->isFrontBypass = data->IsFrontBypass(); return true; } bool SoundArchiveFileReader::ReadBankInfo( SoundArchive::ItemId bankId, SoundArchive::BankInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::BankInfo* data = m_pInfoBlockBody->GetBankInfo( bankId ); if ( data == NULL ) return false; info->fileId = data->fileId; return true; } bool SoundArchiveFileReader::ReadPlayerInfo( SoundArchive::ItemId playerId, SoundArchive::PlayerInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::PlayerInfo* data = m_pInfoBlockBody->GetPlayerInfo( playerId ); if ( data == NULL ) return false; info->playableSoundMax = data->playableSoundMax; info->playerHeapSize = data->GetPlayerHeapSize(); return true; } bool SoundArchiveFileReader::ReadSoundGroupInfo( SoundArchive::ItemId soundGroupId, SoundArchive::SoundGroupInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::SoundGroupInfo* data = m_pInfoBlockBody->GetSoundGroupInfo( soundGroupId ); if ( data == NULL ) return false; info->startId = data->startId; info->endId = data->endId; info->fileIdTable = data->GetFileIdTable(); return true; } bool SoundArchiveFileReader::ReadGroupInfo( SoundArchive::ItemId groupId, SoundArchive::GroupInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::GroupInfo* data = m_pInfoBlockBody->GetGroupInfo( groupId ); if ( data == NULL ) return false; info->fileId = data->fileId; return true; } bool SoundArchiveFileReader::ReadWaveArchiveInfo( SoundArchive::ItemId warcId, SoundArchive::WaveArchiveInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::WaveArchiveInfo* data = m_pInfoBlockBody->GetWaveArchiveInfo( warcId ); if ( data == NULL ) return false; info->fileId = data->fileId; info->waveCount = data->GetWaveCount(); info->isLoadIndividual = data->isLoadIndividual; return true; } bool SoundArchiveFileReader::ReadFileInfo( SoundArchive::FileId id, SoundArchive::FileInfo* info, int index ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); NW_UNUSED_VARIABLE( index ); const SoundArchiveFile::FileInfo* data = m_pInfoBlockBody->GetFileInfo( id ); if ( data == NULL ) return false; switch ( data->GetFileLocationType() ) { case SoundArchiveFile::FILE_LOCATION_TYPE_INTERNAL: { const SoundArchiveFile::InternalFileInfo* location = data->GetInternalFileInfo(); info->fileSize = location->GetFileSize(); info->offsetFromFileBlockHead = location->GetOffsetFromFileBlockHead(); } break; case SoundArchiveFile::FILE_LOCATION_TYPE_EXTERNAL: { const SoundArchiveFile::ExternalFileInfo* location = data->GetExternalFileInfo(); info->externalFilePath = location->filePath; } break; case SoundArchiveFile::FILE_LOCATION_TYPE_NONE: return false; } return true; } bool SoundArchiveFileReader::ReadSoundArchivePlayerInfo( SoundArchive::SoundArchivePlayerInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::SoundArchivePlayerInfo* data = m_pInfoBlockBody->GetSoundArchivePlayerInfo(); if ( data == NULL ) return false; info->sequenceSoundMax = data->sequenceSoundMax; info->sequenceTrackMax = data->sequenceTrackMax; info->streamSoundMax = data->streamSoundMax; info->streamTrackMax = data->streamTrackMax; info->streamChannelMax = data->streamChannelMax; info->waveSoundMax = data->waveSoundMax; info->waveTrackMax = data->waveTrackmax; return true; } bool SoundArchiveFileReader::ReadSound3DInfo( SoundArchive::ItemId soundId, SoundArchive::Sound3DInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId ); if ( soundInfo == NULL ) { return false; } const SoundArchiveFile::Sound3DInfo* sound3dInfo = soundInfo->GetSound3DInfo(); if ( sound3dInfo == NULL ) { return false; } info->flags = sound3dInfo->flags; info->decayRatio = sound3dInfo->decayRatio; info->decayCurve = sound3dInfo->decayCurve; info->dopplerFactor = sound3dInfo->dopplerFactor; return true; } bool SoundArchiveFileReader::ReadSequenceSoundInfo( SoundArchive::ItemId soundId, SoundArchive::SequenceSoundInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId ); if ( soundInfo == NULL ) { return false; } if ( soundInfo->GetSoundType() != SoundArchive::SOUND_TYPE_SEQ ) { return false; } const SoundArchiveFile::SequenceSoundInfo& seqSoundInfo = soundInfo->GetSequenceSoundInfo(); info->startOffset = seqSoundInfo.GetStartOffset(); info->allocateTrackFlags = seqSoundInfo.allocateTrackFlags; info->channelPriority = seqSoundInfo.GetChannelPriority(); info->isReleasePriorityFix = seqSoundInfo.IsReleasePriorityFix(); seqSoundInfo.GetBankIds( info->bankIds ); return true; } bool SoundArchiveFileReader::ReadStreamSoundInfo( SoundArchive::ItemId soundId, SoundArchive::StreamSoundInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId ); if ( soundInfo == NULL ) { return false; } if ( soundInfo->GetSoundType() != SoundArchive::SOUND_TYPE_STRM ) { return false; } const SoundArchiveFile::StreamSoundInfo& strmSoundInfo = soundInfo->GetStreamSoundInfo(); info->allocTrackCount = strmSoundInfo.allocTrackCount; info->allocChannelCount = strmSoundInfo.allocChannelCount; return true; } bool SoundArchiveFileReader::ReadWaveSoundInfo( SoundArchive::ItemId soundId, SoundArchive::WaveSoundInfo* info ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); NW_NULL_ASSERT( info ); const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId ); if ( soundInfo == NULL ) { return false; } if ( soundInfo->GetSoundType() != SoundArchive::SOUND_TYPE_WAVE ) { return false; } const SoundArchiveFile::WaveSoundInfo& waveSoundInfo = soundInfo->GetWaveSoundInfo(); info->index = waveSoundInfo.index; info->allocTrackCount = waveSoundInfo.allocTrackCount; info->channelPriority = waveSoundInfo.GetChannelPriority(); info->isReleasePriorityFix = waveSoundInfo.GetIsReleasePriorityFix() > 0 ? true : false; return true; } const internal::Util::Table* SoundArchiveFileReader::GetWaveArchiveIdTable( SoundArchive::ItemId id ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); switch ( Util::GetItemType( id ) ) { case ItemType_Sound: { const SoundArchiveFile::SoundInfo* pInfo = m_pInfoBlockBody->GetSoundInfo( id ); NW_NULL_ASSERT( pInfo ); if ( pInfo->GetSoundType() == SoundArchive::SOUND_TYPE_WAVE ) { // ウェーブサウンド ID → ウェーブサウンドセット ID を引く for ( u32 i = 0; i < m_pInfoBlockBody->GetSoundGroupCount(); i++ ) { const SoundArchiveFile::SoundGroupInfo* pGroupInfo = m_pInfoBlockBody->GetSoundGroupInfo( Util::GetMaskedItemId( i, ItemType_SoundGroup ) ); NW_NULL_ASSERT( pGroupInfo ); if ( id < pGroupInfo->startId || pGroupInfo->endId < id ) { continue; } // 該当するウェーブサウンドセットの波形アーカイブテーブルを返す const SoundArchiveFile::WaveSoundGroupInfo* pWaveSoundGroupInfo = pGroupInfo->GetWaveSoundGroupInfo(); NW_NULL_ASSERT( pWaveSoundGroupInfo ); return pWaveSoundGroupInfo->GetWaveArchiveItemIdTable(); } } return NULL; } case ItemType_SoundGroup: { const SoundArchiveFile::SoundGroupInfo* pInfo = m_pInfoBlockBody->GetSoundGroupInfo( id ); NW_NULL_ASSERT( pInfo ); const SoundArchiveFile::WaveSoundGroupInfo* pWaveSoundGroupInfo = pInfo->GetWaveSoundGroupInfo(); NW_NULL_ASSERT( pWaveSoundGroupInfo ); return pWaveSoundGroupInfo->GetWaveArchiveItemIdTable(); } case ItemType_Bank: { const SoundArchiveFile::BankInfo* pInfo = m_pInfoBlockBody->GetBankInfo( id ); NW_NULL_ASSERT( pInfo ); return pInfo->GetWaveArchiveItemIdTable(); } default: return NULL; } } SoundArchive::SoundType SoundArchiveFileReader::GetSoundType( SoundArchive::ItemId soundId ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId ); NW_NULL_ASSERT( soundInfo ); return soundInfo->GetSoundType(); } u32 SoundArchiveFileReader::GetSoundUserParam( SoundArchive::ItemId soundId ) const { NW_NULL_ASSERT( m_pInfoBlockBody ); const SoundArchiveFile::SoundInfo* soundInfo = m_pInfoBlockBody->GetSoundInfo( soundId ); NW_NULL_ASSERT( soundInfo ); return soundInfo->GetUserParam(); } } // namespace nw::snd::internal } // namespace nw::snd } // namespace nw