1b51fbe43SDavid McPaul #include "All.h"
2b51fbe43SDavid McPaul #include "WAVInputSource.h"
3b51fbe43SDavid McPaul #include IO_HEADER_FILE
4b51fbe43SDavid McPaul #include "MACLib.h"
5b51fbe43SDavid McPaul #include "GlobalFunctions.h"
6b51fbe43SDavid McPaul
7b51fbe43SDavid McPaul struct RIFF_HEADER
8b51fbe43SDavid McPaul {
9b51fbe43SDavid McPaul char cRIFF[4]; // the characters 'RIFF' indicating that it's a RIFF file
10b51fbe43SDavid McPaul unsigned long nBytes; // the number of bytes following this header
11b51fbe43SDavid McPaul };
12b51fbe43SDavid McPaul
13b51fbe43SDavid McPaul struct DATA_TYPE_ID_HEADER
14b51fbe43SDavid McPaul {
15b51fbe43SDavid McPaul char cDataTypeID[4]; // should equal 'WAVE' for a WAV file
16b51fbe43SDavid McPaul };
17b51fbe43SDavid McPaul
18b51fbe43SDavid McPaul struct WAV_FORMAT_HEADER
19b51fbe43SDavid McPaul {
20b51fbe43SDavid McPaul unsigned short nFormatTag; // the format of the WAV...should equal 1 for a PCM file
21b51fbe43SDavid McPaul unsigned short nChannels; // the number of channels
22b51fbe43SDavid McPaul unsigned long nSamplesPerSecond; // the number of samples per second
23b51fbe43SDavid McPaul unsigned long nBytesPerSecond; // the bytes per second
24b51fbe43SDavid McPaul unsigned short nBlockAlign; // block alignment
25b51fbe43SDavid McPaul unsigned short nBitsPerSample; // the number of bits per sample
26b51fbe43SDavid McPaul };
27b51fbe43SDavid McPaul
28b51fbe43SDavid McPaul struct RIFF_CHUNK_HEADER
29b51fbe43SDavid McPaul {
30b51fbe43SDavid McPaul char cChunkLabel[4]; // should equal "data" indicating the data chunk
31b51fbe43SDavid McPaul unsigned long nChunkBytes; // the bytes of the chunk
32b51fbe43SDavid McPaul };
33b51fbe43SDavid McPaul
34b51fbe43SDavid McPaul
CreateInputSource(const char * pSourceName,WAVEFORMATEX * pwfeSource,int * pTotalBlocks,int * pHeaderBytes,int * pTerminatingBytes,int * pErrorCode)35*053cc0d4SAugustin Cavalier CInputSource * __stdcall CreateInputSource(const char* pSourceName, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode)
36b51fbe43SDavid McPaul {
37b51fbe43SDavid McPaul // error check the parameters
38b51fbe43SDavid McPaul if ((pSourceName == NULL) || (wcslen(pSourceName) == 0))
39b51fbe43SDavid McPaul {
40b51fbe43SDavid McPaul if (pErrorCode) *pErrorCode = ERROR_BAD_PARAMETER;
41b51fbe43SDavid McPaul return NULL;
42b51fbe43SDavid McPaul }
43b51fbe43SDavid McPaul
44b51fbe43SDavid McPaul // get the extension
45*053cc0d4SAugustin Cavalier const char* pExtension = &pSourceName[wcslen(pSourceName)];
46b51fbe43SDavid McPaul while ((pExtension > pSourceName) && (*pExtension != '.'))
47b51fbe43SDavid McPaul pExtension--;
48b51fbe43SDavid McPaul
49b51fbe43SDavid McPaul // create the proper input source
50b51fbe43SDavid McPaul // SHINTA -->
51b51fbe43SDavid McPaul // if (wcsicmp(pExtension, L".wav") == 0)
52b51fbe43SDavid McPaul // {
53b51fbe43SDavid McPaul if (pErrorCode) *pErrorCode = ERROR_SUCCESS;
54b51fbe43SDavid McPaul return new CWAVInputSource(pSourceName, pwfeSource, pTotalBlocks, pHeaderBytes, pTerminatingBytes, pErrorCode);
55b51fbe43SDavid McPaul // }
56b51fbe43SDavid McPaul // else
57b51fbe43SDavid McPaul // {
58b51fbe43SDavid McPaul // if (pErrorCode) *pErrorCode = ERROR_INVALID_INPUT_FILE;
59b51fbe43SDavid McPaul // return NULL;
60b51fbe43SDavid McPaul // }
61b51fbe43SDavid McPaul // <-- SHINTA
62b51fbe43SDavid McPaul }
63b51fbe43SDavid McPaul
CWAVInputSource(CIO * pIO,WAVEFORMATEX * pwfeSource,int * pTotalBlocks,int * pHeaderBytes,int * pTerminatingBytes,int * pErrorCode)64b51fbe43SDavid McPaul CWAVInputSource::CWAVInputSource(CIO * pIO, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode)
65b51fbe43SDavid McPaul : CInputSource(pIO, pwfeSource, pTotalBlocks, pHeaderBytes, pTerminatingBytes, pErrorCode)
66b51fbe43SDavid McPaul {
67b51fbe43SDavid McPaul m_bIsValid = FALSE;
68b51fbe43SDavid McPaul
69b51fbe43SDavid McPaul if (pIO == NULL || pwfeSource == NULL)
70b51fbe43SDavid McPaul {
71b51fbe43SDavid McPaul if (pErrorCode) *pErrorCode = ERROR_BAD_PARAMETER;
72b51fbe43SDavid McPaul return;
73b51fbe43SDavid McPaul }
74b51fbe43SDavid McPaul
75b51fbe43SDavid McPaul m_spIO.Assign(pIO, FALSE, FALSE);
76b51fbe43SDavid McPaul
77b51fbe43SDavid McPaul int nRetVal = AnalyzeSource();
78b51fbe43SDavid McPaul if (nRetVal == ERROR_SUCCESS)
79b51fbe43SDavid McPaul {
80b51fbe43SDavid McPaul // fill in the parameters
81b51fbe43SDavid McPaul if (pwfeSource) memcpy(pwfeSource, &m_wfeSource, sizeof(WAVEFORMATEX));
82b51fbe43SDavid McPaul if (pTotalBlocks) *pTotalBlocks = m_nDataBytes / m_wfeSource.nBlockAlign;
83b51fbe43SDavid McPaul if (pHeaderBytes) *pHeaderBytes = m_nHeaderBytes;
84b51fbe43SDavid McPaul if (pTerminatingBytes) *pTerminatingBytes = m_nTerminatingBytes;
85b51fbe43SDavid McPaul
86b51fbe43SDavid McPaul m_bIsValid = TRUE;
87b51fbe43SDavid McPaul }
88b51fbe43SDavid McPaul
89b51fbe43SDavid McPaul if (pErrorCode) *pErrorCode = nRetVal;
90b51fbe43SDavid McPaul }
91b51fbe43SDavid McPaul
CWAVInputSource(const char * pSourceName,WAVEFORMATEX * pwfeSource,int * pTotalBlocks,int * pHeaderBytes,int * pTerminatingBytes,int * pErrorCode)92*053cc0d4SAugustin Cavalier CWAVInputSource::CWAVInputSource(const char* pSourceName, WAVEFORMATEX * pwfeSource, int * pTotalBlocks, int * pHeaderBytes, int * pTerminatingBytes, int * pErrorCode)
93b51fbe43SDavid McPaul : CInputSource(pSourceName, pwfeSource, pTotalBlocks, pHeaderBytes, pTerminatingBytes, pErrorCode)
94b51fbe43SDavid McPaul {
95b51fbe43SDavid McPaul m_bIsValid = FALSE;
96b51fbe43SDavid McPaul
97b51fbe43SDavid McPaul if (pSourceName == NULL || pwfeSource == NULL)
98b51fbe43SDavid McPaul {
99b51fbe43SDavid McPaul if (pErrorCode) *pErrorCode = ERROR_BAD_PARAMETER;
100b51fbe43SDavid McPaul return;
101b51fbe43SDavid McPaul }
102b51fbe43SDavid McPaul
103b51fbe43SDavid McPaul m_spIO.Assign(new IO_CLASS_NAME);
104b51fbe43SDavid McPaul if (m_spIO->Open(pSourceName) != ERROR_SUCCESS)
105b51fbe43SDavid McPaul {
106b51fbe43SDavid McPaul m_spIO.Delete();
107b51fbe43SDavid McPaul if (pErrorCode) *pErrorCode = ERROR_INVALID_INPUT_FILE;
108b51fbe43SDavid McPaul return;
109b51fbe43SDavid McPaul }
110b51fbe43SDavid McPaul
111b51fbe43SDavid McPaul int nRetVal = AnalyzeSource();
112b51fbe43SDavid McPaul if (nRetVal == ERROR_SUCCESS)
113b51fbe43SDavid McPaul {
114b51fbe43SDavid McPaul // fill in the parameters
115b51fbe43SDavid McPaul if (pwfeSource) memcpy(pwfeSource, &m_wfeSource, sizeof(WAVEFORMATEX));
116b51fbe43SDavid McPaul if (pTotalBlocks) *pTotalBlocks = m_nDataBytes / m_wfeSource.nBlockAlign;
117b51fbe43SDavid McPaul if (pHeaderBytes) *pHeaderBytes = m_nHeaderBytes;
118b51fbe43SDavid McPaul if (pTerminatingBytes) *pTerminatingBytes = m_nTerminatingBytes;
119b51fbe43SDavid McPaul
120b51fbe43SDavid McPaul m_bIsValid = TRUE;
121b51fbe43SDavid McPaul }
122b51fbe43SDavid McPaul
123b51fbe43SDavid McPaul if (pErrorCode) *pErrorCode = nRetVal;
124b51fbe43SDavid McPaul }
125b51fbe43SDavid McPaul
~CWAVInputSource()126b51fbe43SDavid McPaul CWAVInputSource::~CWAVInputSource()
127b51fbe43SDavid McPaul {
128b51fbe43SDavid McPaul
129b51fbe43SDavid McPaul
130b51fbe43SDavid McPaul }
131b51fbe43SDavid McPaul
AnalyzeSource()132b51fbe43SDavid McPaul int CWAVInputSource::AnalyzeSource()
133b51fbe43SDavid McPaul {
134b51fbe43SDavid McPaul // seek to the beginning (just in case)
135b51fbe43SDavid McPaul m_spIO->Seek(0, FILE_BEGIN);
136b51fbe43SDavid McPaul
137b51fbe43SDavid McPaul // get the file size
138b51fbe43SDavid McPaul m_nFileBytes = m_spIO->GetSize();
139b51fbe43SDavid McPaul
140b51fbe43SDavid McPaul // get the RIFF header
141b51fbe43SDavid McPaul RIFF_HEADER RIFFHeader;
142b51fbe43SDavid McPaul RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFHeader, sizeof(RIFFHeader)))
143b51fbe43SDavid McPaul
144b51fbe43SDavid McPaul // make sure the RIFF header is valid
145b51fbe43SDavid McPaul if (!(RIFFHeader.cRIFF[0] == 'R' && RIFFHeader.cRIFF[1] == 'I' && RIFFHeader.cRIFF[2] == 'F' && RIFFHeader.cRIFF[3] == 'F'))
146b51fbe43SDavid McPaul return ERROR_INVALID_INPUT_FILE;
147b51fbe43SDavid McPaul
148b51fbe43SDavid McPaul // read the data type header
149b51fbe43SDavid McPaul DATA_TYPE_ID_HEADER DataTypeIDHeader;
150b51fbe43SDavid McPaul RETURN_ON_ERROR(ReadSafe(m_spIO, &DataTypeIDHeader, sizeof(DataTypeIDHeader)))
151b51fbe43SDavid McPaul
152b51fbe43SDavid McPaul // make sure it's the right data type
153b51fbe43SDavid McPaul if (!(DataTypeIDHeader.cDataTypeID[0] == 'W' && DataTypeIDHeader.cDataTypeID[1] == 'A' && DataTypeIDHeader.cDataTypeID[2] == 'V' && DataTypeIDHeader.cDataTypeID[3] == 'E'))
154b51fbe43SDavid McPaul return ERROR_INVALID_INPUT_FILE;
155b51fbe43SDavid McPaul
156b51fbe43SDavid McPaul // find the 'fmt ' chunk
157b51fbe43SDavid McPaul RIFF_CHUNK_HEADER RIFFChunkHeader;
158b51fbe43SDavid McPaul RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader)))
159b51fbe43SDavid McPaul
160b51fbe43SDavid McPaul while (!(RIFFChunkHeader.cChunkLabel[0] == 'f' && RIFFChunkHeader.cChunkLabel[1] == 'm' && RIFFChunkHeader.cChunkLabel[2] == 't' && RIFFChunkHeader.cChunkLabel[3] == ' '))
161b51fbe43SDavid McPaul {
162b51fbe43SDavid McPaul // move the file pointer to the end of this chunk
163b51fbe43SDavid McPaul m_spIO->Seek(RIFFChunkHeader.nChunkBytes, FILE_CURRENT);
164b51fbe43SDavid McPaul
165b51fbe43SDavid McPaul // check again for the data chunk
166b51fbe43SDavid McPaul RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader)))
167b51fbe43SDavid McPaul }
168b51fbe43SDavid McPaul
169b51fbe43SDavid McPaul // read the format info
170b51fbe43SDavid McPaul WAV_FORMAT_HEADER WAVFormatHeader;
171b51fbe43SDavid McPaul RETURN_ON_ERROR(ReadSafe(m_spIO, &WAVFormatHeader, sizeof(WAVFormatHeader)))
172b51fbe43SDavid McPaul
173b51fbe43SDavid McPaul // error check the header to see if we support it
174b51fbe43SDavid McPaul if (WAVFormatHeader.nFormatTag != 1)
175b51fbe43SDavid McPaul return ERROR_INVALID_INPUT_FILE;
176b51fbe43SDavid McPaul
177b51fbe43SDavid McPaul // copy the format information to the WAVEFORMATEX passed in
178b51fbe43SDavid McPaul FillWaveFormatEx(&m_wfeSource, WAVFormatHeader.nSamplesPerSecond, WAVFormatHeader.nBitsPerSample, WAVFormatHeader.nChannels);
179b51fbe43SDavid McPaul
180b51fbe43SDavid McPaul // skip over any extra data in the header
181b51fbe43SDavid McPaul int nWAVFormatHeaderExtra = RIFFChunkHeader.nChunkBytes - sizeof(WAVFormatHeader);
182b51fbe43SDavid McPaul if (nWAVFormatHeaderExtra < 0)
183b51fbe43SDavid McPaul return ERROR_INVALID_INPUT_FILE;
184b51fbe43SDavid McPaul else
185b51fbe43SDavid McPaul m_spIO->Seek(nWAVFormatHeaderExtra, FILE_CURRENT);
186b51fbe43SDavid McPaul
187b51fbe43SDavid McPaul // find the data chunk
188b51fbe43SDavid McPaul RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader)))
189b51fbe43SDavid McPaul
190b51fbe43SDavid McPaul while (!(RIFFChunkHeader.cChunkLabel[0] == 'd' && RIFFChunkHeader.cChunkLabel[1] == 'a' && RIFFChunkHeader.cChunkLabel[2] == 't' && RIFFChunkHeader.cChunkLabel[3] == 'a'))
191b51fbe43SDavid McPaul {
192b51fbe43SDavid McPaul // move the file pointer to the end of this chunk
193b51fbe43SDavid McPaul m_spIO->Seek(RIFFChunkHeader.nChunkBytes, FILE_CURRENT);
194b51fbe43SDavid McPaul
195b51fbe43SDavid McPaul // check again for the data chunk
196b51fbe43SDavid McPaul RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader)))
197b51fbe43SDavid McPaul }
198b51fbe43SDavid McPaul
199b51fbe43SDavid McPaul // we're at the data block
200b51fbe43SDavid McPaul m_nHeaderBytes = m_spIO->GetPosition();
201b51fbe43SDavid McPaul m_nDataBytes = RIFFChunkHeader.nChunkBytes;
202b51fbe43SDavid McPaul if (m_nDataBytes < 0)
203b51fbe43SDavid McPaul m_nDataBytes = m_nFileBytes - m_nHeaderBytes;
204b51fbe43SDavid McPaul
205b51fbe43SDavid McPaul // make sure the data bytes is a whole number of blocks
206b51fbe43SDavid McPaul if ((m_nDataBytes % m_wfeSource.nBlockAlign) != 0)
207b51fbe43SDavid McPaul return ERROR_INVALID_INPUT_FILE;
208b51fbe43SDavid McPaul
209b51fbe43SDavid McPaul // calculate the terminating byts
210b51fbe43SDavid McPaul m_nTerminatingBytes = m_nFileBytes - m_nDataBytes - m_nHeaderBytes;
211b51fbe43SDavid McPaul
212b51fbe43SDavid McPaul // we made it this far, everything must be cool
213b51fbe43SDavid McPaul return ERROR_SUCCESS;
214b51fbe43SDavid McPaul }
215b51fbe43SDavid McPaul
GetData(unsigned char * pBuffer,int nBlocks,int * pBlocksRetrieved)216b51fbe43SDavid McPaul int CWAVInputSource::GetData(unsigned char * pBuffer, int nBlocks, int * pBlocksRetrieved)
217b51fbe43SDavid McPaul {
218b51fbe43SDavid McPaul if (!m_bIsValid) return ERROR_UNDEFINED;
219b51fbe43SDavid McPaul
220b51fbe43SDavid McPaul int nBytes = (m_wfeSource.nBlockAlign * nBlocks);
221b51fbe43SDavid McPaul unsigned int nBytesRead = 0;
222b51fbe43SDavid McPaul
223b51fbe43SDavid McPaul if (m_spIO->Read(pBuffer, nBytes, &nBytesRead) != ERROR_SUCCESS)
224b51fbe43SDavid McPaul return ERROR_IO_READ;
225b51fbe43SDavid McPaul
226b51fbe43SDavid McPaul if (pBlocksRetrieved) *pBlocksRetrieved = (nBytesRead / m_wfeSource.nBlockAlign);
227b51fbe43SDavid McPaul
228b51fbe43SDavid McPaul return ERROR_SUCCESS;
229b51fbe43SDavid McPaul }
230b51fbe43SDavid McPaul
GetHeaderData(unsigned char * pBuffer)231b51fbe43SDavid McPaul int CWAVInputSource::GetHeaderData(unsigned char * pBuffer)
232b51fbe43SDavid McPaul {
233b51fbe43SDavid McPaul if (!m_bIsValid) return ERROR_UNDEFINED;
234b51fbe43SDavid McPaul
235b51fbe43SDavid McPaul int nRetVal = ERROR_SUCCESS;
236b51fbe43SDavid McPaul
237b51fbe43SDavid McPaul if (m_nHeaderBytes > 0)
238b51fbe43SDavid McPaul {
239b51fbe43SDavid McPaul int nOriginalFileLocation = m_spIO->GetPosition();
240b51fbe43SDavid McPaul
241b51fbe43SDavid McPaul m_spIO->Seek(0, FILE_BEGIN);
242b51fbe43SDavid McPaul
243b51fbe43SDavid McPaul unsigned int nBytesRead = 0;
244b51fbe43SDavid McPaul int nReadRetVal = m_spIO->Read(pBuffer, m_nHeaderBytes, &nBytesRead);
245b51fbe43SDavid McPaul
246b51fbe43SDavid McPaul if ((nReadRetVal != ERROR_SUCCESS) || (m_nHeaderBytes != int(nBytesRead)))
247b51fbe43SDavid McPaul {
248b51fbe43SDavid McPaul nRetVal = ERROR_UNDEFINED;
249b51fbe43SDavid McPaul }
250b51fbe43SDavid McPaul
251b51fbe43SDavid McPaul m_spIO->Seek(nOriginalFileLocation, FILE_BEGIN);
252b51fbe43SDavid McPaul }
253b51fbe43SDavid McPaul
254b51fbe43SDavid McPaul return nRetVal;
255b51fbe43SDavid McPaul }
256b51fbe43SDavid McPaul
GetTerminatingData(unsigned char * pBuffer)257b51fbe43SDavid McPaul int CWAVInputSource::GetTerminatingData(unsigned char * pBuffer)
258b51fbe43SDavid McPaul {
259b51fbe43SDavid McPaul if (!m_bIsValid) return ERROR_UNDEFINED;
260b51fbe43SDavid McPaul
261b51fbe43SDavid McPaul int nRetVal = ERROR_SUCCESS;
262b51fbe43SDavid McPaul
263b51fbe43SDavid McPaul if (m_nTerminatingBytes > 0)
264b51fbe43SDavid McPaul {
265b51fbe43SDavid McPaul int nOriginalFileLocation = m_spIO->GetPosition();
266b51fbe43SDavid McPaul
267b51fbe43SDavid McPaul m_spIO->Seek(-m_nTerminatingBytes, FILE_END);
268b51fbe43SDavid McPaul
269b51fbe43SDavid McPaul unsigned int nBytesRead = 0;
270b51fbe43SDavid McPaul int nReadRetVal = m_spIO->Read(pBuffer, m_nTerminatingBytes, &nBytesRead);
271b51fbe43SDavid McPaul
272b51fbe43SDavid McPaul if ((nReadRetVal != ERROR_SUCCESS) || (m_nTerminatingBytes != int(nBytesRead)))
273b51fbe43SDavid McPaul {
274b51fbe43SDavid McPaul nRetVal = ERROR_UNDEFINED;
275b51fbe43SDavid McPaul }
276b51fbe43SDavid McPaul
277b51fbe43SDavid McPaul m_spIO->Seek(nOriginalFileLocation, FILE_BEGIN);
278b51fbe43SDavid McPaul }
279b51fbe43SDavid McPaul
280b51fbe43SDavid McPaul return nRetVal;
281b51fbe43SDavid McPaul }
282