int CWAVInputSource::AnalyzeSource() { unsigned char *p = FULL_HEADER, *priff = NULL; // seek to the beginning (just in case) m_spIO->Seek(0, FILE_BEGIN); // get the file size m_nFileBytes = m_spIO->GetSize(); // get the RIFF header RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_HEADER))) // make sure the RIFF header is valid if (!(p[0] == 'R' && p[1] == 'I' && p[2] == 'F' && p[3] == 'F')) return ERROR_INVALID_INPUT_FILE; p += sizeof(RIFF_HEADER); // read the data type header RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(DATA_TYPE_ID_HEADER))) // make sure it's the right data type if (!(p[0] == 'W' && p[1] == 'A' && p[2] == 'V' && p[3] == 'E')) return ERROR_INVALID_INPUT_FILE; p += sizeof(DATA_TYPE_ID_HEADER); // find the 'fmt ' chunk RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER))) while (!(p[0] == 'f' && p[1] == 'm' && p[2] == 't' && p[3] == ' ')) { p += sizeof(RIFF_CHUNK_HEADER); // move the file pointer to the end of this chunk RETURN_ON_ERROR(ReadSafe(m_spIO, p, LE_LONG(p+4))) p += LE_LONG(p+4); // check again for the data chunk RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER))) } priff = p+4; p += sizeof(RIFF_CHUNK_HEADER); // read the format info RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(WAV_FORMAT_HEADER))) // error check the header to see if we support it if (LE_SHORT(p) != 1) return ERROR_INVALID_INPUT_FILE; // copy the format information to the WAVEFORMATEX passed in FillWaveFormatEx(&m_wfeSource, LE_LONG(p+4), LE_SHORT(p+14), LE_SHORT(p+2)); p += sizeof(WAV_FORMAT_HEADER); // skip over any extra data in the header int nWAVFormatHeaderExtra = LE_LONG(priff) - sizeof(WAV_FORMAT_HEADER); if (nWAVFormatHeaderExtra < 0) return ERROR_INVALID_INPUT_FILE; else { RETURN_ON_ERROR(ReadSafe(m_spIO, p, nWAVFormatHeaderExtra)) p += nWAVFormatHeaderExtra; } // find the data chunk RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER))) while (!(p[0] == 'd' && p[1] == 'a' && p[2] == 't' && p[3] == 'a')) { p += sizeof(RIFF_CHUNK_HEADER); // move the file pointer to the end of this chunk RETURN_ON_ERROR(ReadSafe(m_spIO, p, LE_LONG(p+4))) p += LE_LONG(p+4); // check again for the data chunk RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER))) } // we're at the data block m_nDataBytes = LE_LONG(p+4); if (m_nDataBytes < 0) m_nDataBytes = m_nFileBytes - m_nHeaderBytes; p += sizeof(RIFF_CHUNK_HEADER); m_nHeaderBytes = p - FULL_HEADER; // make sure the data bytes is a whole number of blocks if ((m_nDataBytes % m_wfeSource.nBlockAlign) != 0) return ERROR_INVALID_INPUT_FILE; // calculate the terminating byts m_nTerminatingBytes = 0; // we made it this far, everything must be cool return ERROR_SUCCESS; }
int CWAVInputSource::AnalyzeSource() { // seek to the beginning (just in case) m_spIO->Seek(0, FILE_BEGIN); // get the file size m_nFileBytes = m_spIO->GetSize(); // get the RIFF header RIFF_HEADER RIFFHeader; RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFHeader, sizeof(RIFFHeader))) // make sure the RIFF header is valid if (!(RIFFHeader.cRIFF[0] == 'R' && RIFFHeader.cRIFF[1] == 'I' && RIFFHeader.cRIFF[2] == 'F' && RIFFHeader.cRIFF[3] == 'F')) return ERROR_INVALID_INPUT_FILE; // read the data type header DATA_TYPE_ID_HEADER DataTypeIDHeader; RETURN_ON_ERROR(ReadSafe(m_spIO, &DataTypeIDHeader, sizeof(DataTypeIDHeader))) // make sure it's the right data type if (!(DataTypeIDHeader.cDataTypeID[0] == 'W' && DataTypeIDHeader.cDataTypeID[1] == 'A' && DataTypeIDHeader.cDataTypeID[2] == 'V' && DataTypeIDHeader.cDataTypeID[3] == 'E')) return ERROR_INVALID_INPUT_FILE; // find the 'fmt ' chunk RIFF_CHUNK_HEADER RIFFChunkHeader; RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader))) while (!(RIFFChunkHeader.cChunkLabel[0] == 'f' && RIFFChunkHeader.cChunkLabel[1] == 'm' && RIFFChunkHeader.cChunkLabel[2] == 't' && RIFFChunkHeader.cChunkLabel[3] == ' ')) { // move the file pointer to the end of this chunk m_spIO->Seek(RIFFChunkHeader.nChunkBytes, FILE_CURRENT); // check again for the data chunk RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader))) } // read the format info WAV_FORMAT_HEADER WAVFormatHeader; RETURN_ON_ERROR(ReadSafe(m_spIO, &WAVFormatHeader, sizeof(WAVFormatHeader))) // error check the header to see if we support it if (WAVFormatHeader.nFormatTag != 1) return ERROR_INVALID_INPUT_FILE; // copy the format information to the WAVEFORMATEX passed in FillWaveFormatEx(&m_wfeSource, WAVFormatHeader.nSamplesPerSecond, WAVFormatHeader.nBitsPerSample, WAVFormatHeader.nChannels); // skip over any extra data in the header int nWAVFormatHeaderExtra = RIFFChunkHeader.nChunkBytes - sizeof(WAVFormatHeader); if (nWAVFormatHeaderExtra < 0) return ERROR_INVALID_INPUT_FILE; else m_spIO->Seek(nWAVFormatHeaderExtra, FILE_CURRENT); // find the data chunk RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader))) while (!(RIFFChunkHeader.cChunkLabel[0] == 'd' && RIFFChunkHeader.cChunkLabel[1] == 'a' && RIFFChunkHeader.cChunkLabel[2] == 't' && RIFFChunkHeader.cChunkLabel[3] == 'a')) { // move the file pointer to the end of this chunk m_spIO->Seek(RIFFChunkHeader.nChunkBytes, FILE_CURRENT); // check again for the data chunk RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFChunkHeader, sizeof(RIFFChunkHeader))) } // we're at the data block m_nHeaderBytes = m_spIO->GetPosition(); m_nDataBytes = RIFFChunkHeader.nChunkBytes; if (m_nDataBytes < 0) m_nDataBytes = m_nFileBytes - m_nHeaderBytes; // make sure the data bytes is a whole number of blocks if ((m_nDataBytes % m_wfeSource.nBlockAlign) != 0) return ERROR_INVALID_INPUT_FILE; // calculate the terminating byts m_nTerminatingBytes = m_nFileBytes - m_nDataBytes - m_nHeaderBytes; // we made it this far, everything must be cool return ERROR_SUCCESS; }