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