• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #include "pvwavfileparser.h"
19 #include "oscl_dll.h"
20 OSCL_DLL_ENTRY_POINT_DEFAULT()
21 
22 const short MuLawDecompressTable[256] =
23 {
24     -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
25     -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
26     -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
27     -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
28     -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
29     -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
30     -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
31     -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
32     -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
33     -1372, -1308, -1244, -1180, -1116, -1052,  -988,  -924,
34     -876,  -844,  -812,  -780,  -748,  -716,  -684,  -652,
35     -620,  -588,  -556,  -524,  -492,  -460,  -428,  -396,
36     -372,  -356,  -340,  -324,  -308,  -292,  -276,  -260,
37     -244,  -228,  -212,  -196,  -180,  -164,  -148,  -132,
38     -120,  -112,  -104,   -96,   -88,   -80,   -72,   -64,
39     -56,   -48,   -40,   -32,   -24,   -16,    -8,     0,
40     32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
41     23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
42     15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
43     11900, 11388, 10876, 10364,  9852,  9340,  8828,  8316,
44     7932,  7676,  7420,  7164,  6908,  6652,  6396,  6140,
45     5884,  5628,  5372,  5116,  4860,  4604,  4348,  4092,
46     3900,  3772,  3644,  3516,  3388,  3260,  3132,  3004,
47     2876,  2748,  2620,  2492,  2364,  2236,  2108,  1980,
48     1884,  1820,  1756,  1692,  1628,  1564,  1500,  1436,
49     1372,  1308,  1244,  1180,  1116,  1052,   988,   924,
50     876,   844,   812,   780,   748,   716,   684,   652,
51     620,   588,   556,   524,   492,   460,   428,   396,
52     372,   356,   340,   324,   308,   292,   276,   260,
53     244,   228,   212,   196,   180,   164,   148,   132,
54     120,   112,   104,    96,    88,    80,    72,    64,
55     56,    48,    40,    32,    24,    16,     8,     0
56 };
57 
58 const short ALawDecompressTable[256] =
59 {
60     -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
61     -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
62     -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
63     -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
64     -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
65     -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
66     -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
67     -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
68     -344,  -328,  -376,  -360,  -280,  -264,  -312,  -296,
69     -472,  -456,  -504,  -488,  -408,  -392,  -440,  -424,
70     -88,   -72,   -120,  -104,  -24,   -8,    -56,   -40,
71     -216,  -200,  -248,  -232,  -152,  -136,  -184,  -168,
72     -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
73     -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
74     -688,  -656,  -752,  -720,  -560,  -528,  -624,  -592,
75     -944,  -912,  -1008, -976,  -816,  -784,  -880,  -848,
76     5504,  5248,  6016,  5760,  4480,  4224,  4992,  4736,
77     7552,  7296,  8064,  7808,  6528,  6272,  7040,  6784,
78     2752,  2624,  3008,  2880,  2240,  2112,  2496,  2368,
79     3776,  3648,  4032,  3904,  3264,  3136,  3520,  3392,
80     22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
81     30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
82     11008, 10496, 12032, 11520, 8960,  8448,  9984,  9472,
83     15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
84     344,   328,   376,   360,   280,   264,   312,   296,
85     472,   456,   504,   488,   408,   392,   440,   424,
86     88,    72,   120,   104,    24,     8,    56,    40,
87     216,   200,   248,   232,   152,   136,   184,   168,
88     1376,  1312,  1504,  1440,  1120,  1056,  1248,  1184,
89     1888,  1824,  2016,  1952,  1632,  1568,  1760,  1696,
90     688,   656,   752,   720,   560,   528,   624,   592,
91     944,   912,  1008,   976,   816,   784,   880,   848
92 };
93 
94 
95 
~PV_Wav_Parser()96 OSCL_EXPORT_REF PV_Wav_Parser::~PV_Wav_Parser()
97 {
98     CleanupWAVFile();
99 }
100 
101 /* ======================================================================== */
102 /*  Function : ReadData()                                               */
103 /*  Author   :                                                          */
104 /*  Date     :                                                          */
105 /*  Purpose  : Read data from file in a buffer                          */
106 /*  In/out   :                                                          */
107 /*  Return   : Result of read operation                                 */
108 /*  Note     :                                                          */
109 /*  Modified :                                                          */
110 /* ======================================================================== */
ReadData(uint8 * buff,uint32 size,uint32 & bytesread)111 PVWavParserReturnCode PV_Wav_Parser::ReadData(uint8* buff, uint32 size, uint32& bytesread)
112 {
113     OSCL_ASSERT(ipWAVFile != NULL);
114 
115     // read data
116     if ((bytesread = ipWAVFile->Read(buff, 1, size)) == 0)
117     {
118         if (ipWAVFile->EndOfFile())
119             return PVWAVPARSER_END_OF_FILE;
120         else
121             return PVWAVPARSER_READ_ERROR;
122     }
123     return PVWAVPARSER_OK;
124 }
125 
126 /* ======================================================================== */
127 /*  Function : CleanupWAVFile()                                             */
128 /*  Author   :                                                              */
129 /*  Date     :                                                              */
130 /*  Purpose  : Close the file and reset any associated variables            */
131 /*  In/out   :                                                              */
132 /*  Return   : Result of read operation                                     */
133 /*  Note     :                                                              */
134 /*  Modified :                                                              */
135 /* ======================================================================== */
CleanupWAVFile(void)136 OSCL_EXPORT_REF void PV_Wav_Parser::CleanupWAVFile(void)
137 {
138     if (ipWAVFile != NULL)
139         ipWAVFile->Close();
140     OSCL_DELETE(ipWAVFile);
141     ipWAVFile = NULL;
142 
143     AudioFormat = 0;
144     NumChannels = 0;
145     SampleRate = 0;
146     ByteRate = 0;
147     BlockAlign = 0;
148     BitsPerSample = 0;
149     BytesPerSample = 0;
150     PCMBytesRead = 0;
151     PCMBytesPresent = 0;
152     iHeaderSize = 0;
153     isLittleEndian = 1; // little endian by default
154     xLawTable = NULL;
155 }
156 
157 
158 /* ======================================================================== */
159 /*  Function : InitWavParser()                                          */
160 /*  Author   :                                                          */
161 /*  Date     :                                                          */
162 /*  Purpose  : Initialize WAVE Parser                                   */
163 /*  In/out   :                                                          */
164 /*  Return   : Result of reading the WAV file                           */
165 /*  Note     :                                                          */
166 /*  Modified :                                                          */
167 /* ======================================================================== */
InitWavParser(OSCL_wString & aClip,Oscl_FileServer * aFileSession)168 OSCL_EXPORT_REF PVWavParserReturnCode PV_Wav_Parser::InitWavParser(OSCL_wString& aClip, Oscl_FileServer* aFileSession)
169 {
170     //buffer
171     uint8 iBuffer[36];
172 
173     // If a WAV file is already open, close it first and delete the file pointer
174     CleanupWAVFile();
175 
176     // Open the file (aClip)
177     ipWAVFile = OSCL_NEW(Oscl_File, (4096));
178     if (ipWAVFile == NULL)
179     {
180         return PVWAVPARSER_READ_ERROR;
181     }
182 
183     if (ipWAVFile->Open(aClip.get_cstr(), (Oscl_File::MODE_READ | Oscl_File::MODE_BINARY), *aFileSession) != 0)
184     {
185         OSCL_DELETE(ipWAVFile);
186         ipWAVFile = NULL;
187         return PVWAVPARSER_READ_ERROR;
188     }
189 
190     // Get file size at the very first time
191     int32 filesize = 0;
192     if (ipWAVFile->Seek(0, Oscl_File::SEEKEND))
193     {
194         CleanupWAVFile();
195         return PVWAVPARSER_MISC_ERROR;
196     }
197 
198     filesize = (TOsclFileOffsetInt32)ipWAVFile->Tell();
199 
200     if (filesize <= 0)
201     {
202         CleanupWAVFile();
203         return PVWAVPARSER_MISC_ERROR;
204     }
205 
206     if (ipWAVFile->Seek(0, Oscl_File::SEEKSET))
207     {
208         CleanupWAVFile();
209         return PVWAVPARSER_MISC_ERROR;
210     }
211     int32 filepos = 0;
212 
213     // read 12 bytes of data for complete WAVE header including RIFF chunk dDescriptor
214 
215     uint32 bytesread = 0;
216     if (ReadData(iBuffer, 12, bytesread) != PVWAVPARSER_OK)
217     {
218         CleanupWAVFile();
219         return PVWAVPARSER_READ_ERROR;
220     }
221     if (bytesread != 12)
222     {
223         CleanupWAVFile();
224         return PVWAVPARSER_READ_ERROR;
225     }
226     // Update file position counter by 36 bytes
227     filepos += 12;
228 
229     // Check for RIFF/RIFX
230     uint8* pBuffer = &iBuffer[0];
231     if (pBuffer[0] == 'R' &&
232             pBuffer[1] == 'I' &&
233             pBuffer[2] == 'F' &&
234             pBuffer[3] == 'F')
235     {
236         isLittleEndian = 1; // Little endian data
237     }
238     else if (pBuffer[0] == 'R' &&
239              pBuffer[1] == 'I' &&
240              pBuffer[2] == 'F' &&
241              pBuffer[3] == 'X')
242     {
243         isLittleEndian = 0; // Big endian data
244     }
245     else
246     {
247         CleanupWAVFile();
248         return PVWAVPARSER_UNSUPPORTED_FORMAT;
249     }
250 
251     // If a .wav file is clipped manually , the ChunkSize would not relate to the file size. However, we
252     // should still attempt to play that clip for the existing length of the file. To enforce the restriction,
253     // we may opt to uncomment the following lines of code.
254 
255     // To read ChunkSize (in RIFF chunk descriptor) from little endian
256     /*
257     uint32 ChunkSize;
258 
259     ChunkSize = (((*(pBuffer + 7)) <<24)|((*(pBuffer + 6)) << 16)|((*(pBuffer + 5)) << 8)|(*(pBuffer + 4)));
260     if((int32)ChunkSize!= (filesize - 8))
261     {
262         CleanupWAVFile();
263         return PVWAVPARSER_MISC_ERROR;
264     }
265     */
266 
267     // Check for WAVE in Format field
268     if (pBuffer[ 8] != 'W' ||
269             pBuffer[ 9] != 'A' ||
270             pBuffer[10] != 'V' ||
271             pBuffer[11] != 'E')
272     {
273         CleanupWAVFile();
274         return PVWAVPARSER_UNSUPPORTED_FORMAT;
275     }
276 
277     uint32 SubChunk_Size = 0;
278 
279     bool fmtSubchunkFound = false;
280     while (!fmtSubchunkFound)
281     {
282         // read 8 bytes from file to check for next subchunk
283         bytesread = 0;
284         if (ReadData(iBuffer, 8, bytesread) != PVWAVPARSER_OK)
285         {
286             CleanupWAVFile();
287             return PVWAVPARSER_READ_ERROR;
288         }
289         if (bytesread != 8)
290         {
291             CleanupWAVFile();
292             return PVWAVPARSER_READ_ERROR;
293         }
294         // Update file position counter by 8 bytes
295         filepos += 8;
296         uint8* pTempBuffer = &iBuffer[0];
297         SubChunk_Size = (((*(pTempBuffer + 7)) << 24) | ((*(pTempBuffer + 6)) << 16) | ((*(pTempBuffer + 5)) << 8) | (*(pTempBuffer + 4)));
298 
299         // typecast filesize as uint32 - to get to this point, it MUST be
300         // greater than 0.
301         if ((filepos + SubChunk_Size) > (uint32)filesize)
302         {
303             CleanupWAVFile();
304             return PVWAVPARSER_MISC_ERROR;
305         }
306         // Check for FMT subchunk
307         if (pTempBuffer[0] != 'f' ||
308                 pTempBuffer[1] != 'm' ||
309                 pTempBuffer[2] != 't' ||
310                 pTempBuffer[3] != ' ')
311         {
312             // "fmt " chunk not found - Unknown subchunk
313             filepos += SubChunk_Size;
314             if (ipWAVFile->Seek(filepos, Oscl_File::SEEKSET))
315             {
316                 CleanupWAVFile();
317                 return PVWAVPARSER_MISC_ERROR;
318             }
319         }
320         else
321             fmtSubchunkFound = true;
322     }
323     if (ReadData(iBuffer, 16, bytesread) != PVWAVPARSER_OK)
324     {
325         CleanupWAVFile();
326         return PVWAVPARSER_READ_ERROR;
327     }
328     if (bytesread != 16)
329     {
330         CleanupWAVFile();
331         return PVWAVPARSER_READ_ERROR;
332     }
333     filepos += 16;
334 
335     pBuffer = &iBuffer[0];
336 
337     AudioFormat = (unsigned short)(((*(pBuffer + 1)) << 8) | (*pBuffer));   // Save AudioFormat (PCM = 1)
338     xLawTable = NULL;
339 
340     NumChannels = (unsigned short)(((*(pBuffer + 3)) << 8) | (*(pBuffer + 2))); // Save Number of Channels
341     SampleRate = (((*(pBuffer + 7)) << 24) | ((*(pBuffer + 6)) << 16) | ((*(pBuffer + 5)) << 8) | (*(pBuffer + 4)));    //  Save Sampling rate
342     ByteRate = (((*(pBuffer + 11)) << 24) | ((*(pBuffer + 10)) << 16) | ((*(pBuffer + 9)) << 8) | (*(pBuffer + 8)));    //  Save ByteRate ( == SampleRate*NumChannels*BitsPerSample/8)
343     BlockAlign = (unsigned short)(((*(pBuffer + 13)) << 8) | (*(pBuffer + 12)));    //  Save BlockAlign ( == NumChannels*BitsPerSample/8)
344     BitsPerSample = (unsigned short)(((*(pBuffer + 15)) << 8) | (*(pBuffer + 14))); //  Save BitsPerSample  (8 bits == 8, 16 bits == 16 etc.)
345     BytesPerSample = (BitsPerSample + 7) / 8;  // compute (ceil(BitsPerSample/8))
346 
347     // Check for SubChunk_Size (It should be 16 for PCM)
348     // skip remaining bytes if any because we don't currently support any compressed audio formats
349     if (SubChunk_Size != 16)
350     {
351         // seek ahead by Subchunk1_Size - 16
352         filepos += SubChunk_Size - 16;
353         if (ipWAVFile->Seek(filepos, Oscl_File::SEEKSET))
354         {
355             CleanupWAVFile();
356             return PVWAVPARSER_MISC_ERROR;
357         }
358     }
359 
360     bool DataSubchunkFound = false;
361 
362     while (!DataSubchunkFound)
363     {
364         // read 8 bytes from file to check for next subchunk
365         bytesread = 0;
366         if (ReadData(iBuffer, 8, bytesread) != PVWAVPARSER_OK)
367         {
368             CleanupWAVFile();
369             return PVWAVPARSER_READ_ERROR;
370         }
371         if (bytesread != 8)
372         {
373             CleanupWAVFile();
374             return PVWAVPARSER_READ_ERROR;
375         }
376         // Update file position counter by 8 bytes
377         filepos += 8;
378 
379         uint8* pTempBuffer = &iBuffer[0];
380 
381         //It means that some unknown subchunk is present
382         // Calculate  SubChunk Size
383         SubChunk_Size = (((*(pTempBuffer + 7)) << 24) | ((*(pTempBuffer + 6)) << 16) | ((*(pTempBuffer + 5)) << 8) | (*(pTempBuffer + 4)));
384 
385         // Check for DATA subchunk ID
386         if (pTempBuffer[0] != 'd' ||
387                 pTempBuffer[1] != 'a' ||
388                 pTempBuffer[2] != 't' ||
389                 pTempBuffer[3] != 'a')
390         {
391             // we need to skip this many bytes
392             filepos += SubChunk_Size;
393 
394             // seek file pointer to current file position
395             if (ipWAVFile->Seek(filepos, Oscl_File::SEEKSET))
396             {
397                 CleanupWAVFile();
398                 return PVWAVPARSER_MISC_ERROR;
399             }
400         }
401         else
402         {
403             // data subchunk found
404 
405             // header size equals current file pos
406             iHeaderSize = filepos;
407 
408             //data subchunk is found
409             DataSubchunkFound = true;
410 
411             // Read data SubChunk Size (is number of bytes in data or PCMBytesPresent)
412             PCMBytesPresent = SubChunk_Size;
413             iEndOfDataSubChunkOffset = filepos + PCMBytesPresent; //This is where the DataSubChunk is supposed to end
414 
415             //(this check is required to avoid memory crash if any of BytesPerSample or NumChannels is '0')
416             if (BytesPerSample && NumChannels)
417             {
418                 NumSamples = ((PCMBytesPresent / (BytesPerSample)) / NumChannels);
419             }
420         }
421     }
422 
423     //return error if any of these value is not given in wav file header
424     //(AudioFormat check is done at node level)
425     if (!NumChannels || !NumSamples || !SampleRate || !BitsPerSample || !BytesPerSample || !ByteRate)
426     {
427         CleanupWAVFile();
428         return PVWAVPARSER_UNSUPPORTED_FORMAT;  //any error fom parse will be handled as PVMFFailure at corresponsding node level
429     }
430 
431     return PVWAVPARSER_OK;
432 }
433 
434 
435 /* ======================================================================== */
436 /*  Function : GetPCMData()                                             */
437 /*  Author   :                                                          */
438 /*  Date     :                                                          */
439 /*  Purpose  : Copy specified number of samples to output buffer        */
440 /*  In/out   :                                                          */
441 /*  Return   : Result of read operation                                 */
442 /*  Note     :                                                          */
443 /*  Modified :                                                          */
444 /* ======================================================================== */
GetPCMData(uint8 * inBuff,uint32 inBufSize,uint32 NumberOfSamples,uint32 & NumSamplesRead)445 OSCL_EXPORT_REF PVWavParserReturnCode PV_Wav_Parser::GetPCMData(uint8* inBuff, uint32 inBufSize, uint32 NumberOfSamples, uint32& NumSamplesRead)
446 {
447     NumSamplesRead = 0;
448     uint32 BytesRead = 0;
449 
450     uint32 myBufSize = NumberOfSamples * BytesPerSample * NumChannels;
451     if ((ipWAVFile->Tell() + myBufSize) > iEndOfDataSubChunkOffset)
452     {//we don't have enough data to fulfill this request
453         int32 pos = (TOsclFileOffsetInt32)ipWAVFile->Tell();
454         if (((uint32)(BytesPerSample*NumChannels) + pos) > iEndOfDataSubChunkOffset)
455         {
456             return PVWAVPARSER_END_OF_FILE;
457         }
458         NumberOfSamples = (iEndOfDataSubChunkOffset - pos) / (BytesPerSample * NumChannels);
459         myBufSize = NumberOfSamples * BytesPerSample * NumChannels;
460     }
461 
462 
463     if (xLawTable)
464     {
465         //PCM16 2 bytes per sample
466         if (myBufSize*2 > inBufSize)
467         {
468             //buffer too small
469             return PVWAVPARSER_MISC_ERROR ;
470         }
471         if ((uint32)inBuff & 0x3)
472         {
473             //buffer not word aligned
474             return PVWAVPARSER_MISC_ERROR ;
475         }
476 
477         PVWavParserReturnCode retcode = ReadData(inBuff, myBufSize, BytesRead);
478         if (retcode == PVWAVPARSER_OK)
479         {
480             uint8 *mySrcBuf = &inBuff[BytesRead-1];
481             short *myDstBuf = &(((short*) inBuff)[BytesRead-1]);
482             for (int i = BytesRead; i > 0; i--)
483                 *myDstBuf-- = xLawTable[*mySrcBuf--];
484 
485             // Calculate the number of samples read based on the bytes read from file
486             NumSamplesRead = (BytesRead / BytesPerSample) / NumChannels;
487         }
488         return retcode;
489     }
490 
491     if (myBufSize > inBufSize)
492     {
493         //buffer too small
494         return PVWAVPARSER_MISC_ERROR ;
495     }
496     PVWavParserReturnCode retcode = ReadData(inBuff, myBufSize, BytesRead);
497     if (retcode == PVWAVPARSER_OK)
498     {
499         // Calculate the number of samples read based on the bytes read from file
500         NumSamplesRead = (BytesRead / BytesPerSample) / NumChannels;
501     }
502     return retcode;
503 }
504 
505 
506 /* ======================================================================== */
507 /*  Function : RetrieveFileInfo()                                       */
508 /*  Author   :                                                          */
509 /*  Date     :                                                          */
510 /*  Purpose  :                                                          */
511 /*  In/out   :                                                          */
512 /*  Return   : true / false                                             */
513 /*  Note     :                                                          */
514 /*  Modified :                                                          */
515 /* ======================================================================== */
RetrieveFileInfo(PVWAVFileInfo & aInfo)516 OSCL_EXPORT_REF bool PV_Wav_Parser::RetrieveFileInfo(PVWAVFileInfo& aInfo)
517 {
518     // If the file pointer is valid, then WAV file has been parsed
519     if (ipWAVFile)
520     {
521         aInfo.AudioFormat = AudioFormat;
522         aInfo.NumChannels = NumChannels;
523         aInfo.SampleRate = SampleRate;
524         aInfo.ByteRate = ByteRate;
525         aInfo.BlockAlign = BlockAlign;
526         aInfo.BitsPerSample = BitsPerSample;
527         aInfo.BytesPerSample = BytesPerSample;
528         aInfo.NumSamples = NumSamples;
529         aInfo.isLittleEndian = isLittleEndian;
530 
531         return true;
532     }
533     else
534     {
535         return false;
536     }
537 }
538 
SetOutputToUncompressedPCM(void)539 OSCL_EXPORT_REF bool PV_Wav_Parser::SetOutputToUncompressedPCM(void)
540 {
541     xLawTable = NULL;
542     if (PVWAV_ITU_G711_ULAW == AudioFormat)
543     {
544         xLawTable = OSCL_CONST_CAST(short*, MuLawDecompressTable);
545         return true;
546     }
547     else if (PVWAV_ITU_G711_ALAW == AudioFormat)
548     {
549         xLawTable = OSCL_CONST_CAST(short*, ALawDecompressTable);
550         return true;
551     }
552     else if (AudioFormat == PVWAV_PCM_AUDIO_FORMAT)
553     {
554         if ((8 == BitsPerSample) || isLittleEndian)
555             return true;
556     }
557     return false;
558 }
559 
560 /* ======================================================================== */
561 /*  Function : SeekPCMSample()                                          */
562 /*  Author   :                                                          */
563 /*  Date     :                                                          */
564 /*  Purpose  :                                                          */
565 /*  In/out   :                                                          */
566 /*  Return   : Result of seek operation                                 */
567 /*  Note     :                                                          */
568 /*  Modified :                                                          */
569 /* ======================================================================== */
SeekPCMSample(uint32 SampleNumber)570 OSCL_EXPORT_REF PVWavParserReturnCode PV_Wav_Parser::SeekPCMSample(uint32 SampleNumber)
571 {
572     if (ipWAVFile == NULL)
573     {
574         return PVWAVPARSER_MISC_ERROR;
575     }
576 
577     if (SampleNumber >= NumSamples)
578     {
579         // seek to the end of the file and return;
580         ipWAVFile->Seek(0, Oscl_File::SEEKEND);
581         return PVWAVPARSER_OK;
582     }
583 
584     // valid header size must be present(it is initialized only if valid data subchunk is present)
585     if (iHeaderSize)
586     {
587         // Seek to file position corresponding to headersize+(sample# * numchannels * bytespersample)
588         if (ipWAVFile->Seek((iHeaderSize + (SampleNumber*NumChannels*(BytesPerSample))), Oscl_File::SEEKSET))
589         {
590             return PVWAVPARSER_MISC_ERROR;
591         }
592     }
593     else
594     {
595         return PVWAVPARSER_MISC_ERROR;
596     }
597 
598     return PVWAVPARSER_OK;
599 }
600 
601 
602 
603 
604 
605 
606 
607 
608 
609