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