1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: snd_WaveFileReader.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. 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 $Revision: 23499 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/snd/snd_WaveFileReader.h>
19
20 namespace nw {
21 namespace snd {
22 namespace internal {
23
24 namespace {
25
26 const u32 SIGNATURE_INFO_BLOCK = NW_UT_MAKE_SIGWORD( 'I', 'N', 'F', 'O' );
27 const u32 SIGNATURE_DATA_BLOCK = NW_UT_MAKE_SIGWORD( 'D', 'A', 'T', 'A' );
28
29 const u32 SUPPORTED_FILE_VERSION = 0x02000000; // ライブラリがサポートする最低バージョン
30 const u32 CURRENT_FILE_VERSION = 0x02010000; // ライブラリがサポートする最新バージョン
31
IsValidFileHeader(const void * waveFile)32 bool IsValidFileHeader( const void* waveFile )
33 {
34 const ut::BinaryFileHeader& header =
35 *reinterpret_cast<const ut::BinaryFileHeader*>( waveFile );
36
37 // シグニチャ確認
38 NW_ASSERTMSG( header.signature == WaveFileReader::SIGNATURE_FILE,
39 "invalid file signature." );
40 if ( header.signature != WaveFileReader::SIGNATURE_FILE )
41 {
42 return false;
43 }
44
45 // バージョン確認
46 NW_ASSERTMSG(
47 header.version >= SUPPORTED_FILE_VERSION,
48 "wave file is not supported version.\n"
49 "please reconvert file using new version tools.\n"
50 "(SUPPORTED_FILE_VERSION:0x%08x >= your version:0x%08x)\n",
51 SUPPORTED_FILE_VERSION, header.version
52 );
53 if ( header.version < SUPPORTED_FILE_VERSION )
54 {
55 return false;
56 }
57 NW_ASSERTMSG(
58 header.version <= CURRENT_FILE_VERSION,
59 "wave file is not supported version.\n"
60 "please reconvert file using new version tools.\n"
61 "(CURRENT_FILE_VERSION:0x%08x <= your version:0x%08x)\n",
62 CURRENT_FILE_VERSION, header.version
63 );
64 if ( header.version > CURRENT_FILE_VERSION )
65 {
66 return false;
67 }
68 return true;
69 }
70
71 } // anonymous namespace
72
73
GetSampleFormat(u8 format)74 SampleFormat WaveFileReader::GetSampleFormat( u8 format )
75 {
76 switch ( format )
77 {
78 case WaveFile::PCM8: return SAMPLE_FORMAT_PCM_S8;
79 case WaveFile::PCM16: return SAMPLE_FORMAT_PCM_S16;
80 case WaveFile::DSP_ADPCM: return SAMPLE_FORMAT_DSP_ADPCM;
81 default:
82 NW_ASSERTMSG( false, "Unknown wave data format(%d)", format );
83 return SAMPLE_FORMAT_DSP_ADPCM;
84 }
85 }
86
WaveFileReader(const void * waveFile)87 WaveFileReader::WaveFileReader( const void* waveFile )
88 : m_pInfoBlockBody( NULL )
89 {
90 if ( ! IsValidFileHeader( waveFile ) ) return;
91
92 const WaveFile::FileHeader* header =
93 reinterpret_cast<const WaveFile::FileHeader*>(waveFile);
94
95 const WaveFile::InfoBlock* infoBlock = header->GetInfoBlock();
96 const WaveFile::DataBlock* dataBlock = header->GetDataBlock();
97
98 if ( infoBlock == NULL ) return;
99 if ( dataBlock == NULL ) return;
100
101 NW_ASSERT( infoBlock->header.kind == SIGNATURE_INFO_BLOCK );
102 NW_ASSERT( dataBlock->header.kind == SIGNATURE_DATA_BLOCK );
103
104 m_pInfoBlockBody = &infoBlock->body;
105 m_pDataBlockBody = &dataBlock->byte;
106 }
107
108 // MEMO: 本当に必要?!
109 // WaveFileReader::WaveFileReader( const WaveFile::InfoBlockBody* infoBlockBody )
110 // : m_pInfoBlockBody( infoBlockBody )
111 // {
112 // }
113
ReadWaveInfo(WaveInfo * info,const void * waveDataOffsetOrigin) const114 bool WaveFileReader::ReadWaveInfo(
115 WaveInfo* info,
116 const void* waveDataOffsetOrigin ) const
117 {
118 NW_ASSERT( m_pInfoBlockBody );
119
120 const SampleFormat format = GetSampleFormat( m_pInfoBlockBody->encoding );
121 info->sampleFormat = format;
122 info->channelCount = m_pInfoBlockBody->GetChannelCount();
123 info->sampleRate = m_pInfoBlockBody->sampleRate;
124 info->loopFlag = ( m_pInfoBlockBody->isLoop == 1 );
125 info->loopStartFrame = m_pInfoBlockBody->loopStartFrame;
126 info->loopEndFrame = m_pInfoBlockBody->loopEndFrame;
127
128 for ( s32 i = 0; i < m_pInfoBlockBody->GetChannelCount(); i++ )
129 {
130 if ( i >= WAVE_CHANNEL_MAX ) continue;
131
132 WaveInfo::ChannelParam& channelParam = info->channelParam[ i ];
133
134 const WaveFile::ChannelInfo& channelInfo = m_pInfoBlockBody->GetChannelInfo( i );
135 // if ( channelInfo.offsetToAdpcmInfo != 0 )
136 if ( channelInfo.referToAdpcmInfo.offset != 0 )
137 {
138 const WaveFile::DspAdpcmInfo& adpcmInfo = channelInfo.GetDspAdpcmInfo();
139 channelParam.adpcmParam = adpcmInfo.adpcmParam;
140 channelParam.adpcmLoopParam = adpcmInfo.adpcmLoopParam;
141 }
142
143 channelParam.dataAddress = GetWaveDataAddress( &channelInfo, waveDataOffsetOrigin );
144 }
145
146 return true;
147 }
148
GetWaveDataAddress(const WaveFile::ChannelInfo * info,const void * waveDataOffsetOrigin) const149 const void* WaveFileReader::GetWaveDataAddress(
150 const WaveFile::ChannelInfo* info,
151 const void* waveDataOffsetOrigin ) const
152 {
153 NW_NULL_ASSERT( m_pInfoBlockBody );
154 NW_NULL_ASSERT( info );
155
156 NW_UNUSED_VARIABLE( waveDataOffsetOrigin );
157
158 #if 0
159 const void* waveDataAddress = NULL;
160
161 // dataLocationがデータブロックの先頭を指しているか(WaveFileの場合)
162 // 波形データの先頭を指しているか(BankFile中のWaveInfoの場合)
163 bool offsetIsDataBlock = ( waveDataOffsetOrigin == NULL );
164
165 if ( waveDataOffsetOrigin == NULL ) {
166 waveDataOffsetOrigin = m_pInfoBlockBody;
167 }
168
169 // MEMO: バンクの波形差し替えで WAVE_DATA_LOCATION_ADDRESS を使っていた?模様。
170 // 今回、バンクの波形差し替えは、インストの warcID と waveIndex を
171 // 差し替えられるようにして、対応する。
172 switch( m_pInfoBlockBody->dataLocationType ) {
173 case WaveFile::WAVE_DATA_LOCATION_OFFSET:
174 waveDataAddress = ut::AddOffsetToPtr( waveDataOffsetOrigin, m_pInfoBlockBody->dataLocation );
175 if ( offsetIsDataBlock ) {
176 waveDataAddress = ut::AddOffsetToPtr( waveDataAddress, 8 );
177 }
178 break;
179 case WaveFile::WAVE_DATA_LOCATION_ADDRESS:
180 waveDataAddress = reinterpret_cast<const void*>( m_pInfoBlockBody->dataLocation );
181 break;
182 default:
183 return NULL;
184 }
185
186 waveDataAddress = ut::AddOffsetToPtr( waveDataAddress, waveChannelInfo->channelDataOffset );
187
188 return waveDataAddress;
189 #endif
190
191 return info->GetSamplesAddress( m_pDataBlockBody );
192 }
193
194
195 } // namespace nw::snd::internal
196 } // namespace nw::snd
197 } // namespace nw
198
199