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