Example #1
0
/*****************************************************************************************
Primary query function
*****************************************************************************************/
int CAPEInfo::GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1, int nParam2)
{
    int nRetVal = -1;

    switch (Field)
    {
    case APE_INFO_FILE_VERSION:
        nRetVal = m_APEFileInfo.nVersion;
        break;
    case APE_INFO_COMPRESSION_LEVEL:
        nRetVal = m_APEFileInfo.nCompressionLevel;
        break;
    case APE_INFO_FORMAT_FLAGS:
        nRetVal = m_APEFileInfo.nFormatFlags;
        break;
    case APE_INFO_SAMPLE_RATE:
        nRetVal = m_APEFileInfo.nSampleRate;
        break;
    case APE_INFO_BITS_PER_SAMPLE:
        nRetVal = m_APEFileInfo.nBitsPerSample;
        break;
    case APE_INFO_BYTES_PER_SAMPLE:
        nRetVal = m_APEFileInfo.nBytesPerSample;
        break;
    case APE_INFO_CHANNELS:
        nRetVal = m_APEFileInfo.nChannels;
        break;
    case APE_INFO_BLOCK_ALIGN:
        nRetVal = m_APEFileInfo.nBlockAlign;
        break;
    case APE_INFO_BLOCKS_PER_FRAME:
        nRetVal = m_APEFileInfo.nBlocksPerFrame;
        break;
    case APE_INFO_FINAL_FRAME_BLOCKS:
        nRetVal = m_APEFileInfo.nFinalFrameBlocks;
        break;
    case APE_INFO_TOTAL_FRAMES:
        nRetVal = m_APEFileInfo.nTotalFrames;
        break;
    case APE_INFO_WAV_HEADER_BYTES:
        nRetVal = m_APEFileInfo.nWAVHeaderBytes;
        break;
    case APE_INFO_WAV_TERMINATING_BYTES:
        nRetVal = m_APEFileInfo.nWAVTerminatingBytes;
        break;
    case APE_INFO_WAV_DATA_BYTES:
        nRetVal = m_APEFileInfo.nWAVDataBytes;
        break;
    case APE_INFO_WAV_TOTAL_BYTES:
        nRetVal = m_APEFileInfo.nWAVTotalBytes;
        break;
    case APE_INFO_APE_TOTAL_BYTES:
        nRetVal = m_APEFileInfo.nAPETotalBytes;
        break;
    case APE_INFO_TOTAL_BLOCKS:
        nRetVal = m_APEFileInfo.nTotalBlocks;
        break;
    case APE_INFO_LENGTH_MS:
        nRetVal = m_APEFileInfo.nLengthMS;
        break;
    case APE_INFO_AVERAGE_BITRATE:
        nRetVal = m_APEFileInfo.nAverageBitrate;
        break;
    case APE_INFO_FRAME_BITRATE:
    {
        int nFrame = nParam1;
        
        nRetVal = 0;

        int nFrameBytes = GetInfo(APE_INFO_FRAME_BYTES, nFrame);
        int nFrameBlocks = GetInfo(APE_INFO_FRAME_BLOCKS, nFrame);
        if ((nFrameBytes > 0) && (nFrameBlocks > 0) && m_APEFileInfo.nSampleRate > 0)
        {
            int nFrameMS = (nFrameBlocks * 1000) / m_APEFileInfo.nSampleRate;
            if (nFrameMS != 0)
            {
                nRetVal = (nFrameBytes * 8) / nFrameMS;
            }
        }
        break;
    }
    case APE_INFO_DECOMPRESSED_BITRATE:
        nRetVal = m_APEFileInfo.nDecompressedBitrate;
        break;
    case APE_INFO_PEAK_LEVEL:
        nRetVal = -1; // no longer supported
        break;
    case APE_INFO_SEEK_BIT:
    {
        int nFrame = nParam1;
        if (GET_FRAMES_START_ON_BYTES_BOUNDARIES(this)) 
        {
            nRetVal = 0;
        }
        else 
        {
            if (nFrame < 0 || nFrame >= m_APEFileInfo.nTotalFrames)
                nRetVal = 0;
            else
                nRetVal = m_APEFileInfo.spSeekBitTable[nFrame];
        }
        break;
    }
    case APE_INFO_SEEK_BYTE:
    {
        int nFrame = nParam1;
        if (nFrame < 0 || nFrame >= m_APEFileInfo.nTotalFrames)
            nRetVal = 0;
        else
            nRetVal = m_APEFileInfo.spSeekByteTable[nFrame] + m_APEFileInfo.nJunkHeaderBytes;
        break;
    }
    case APE_INFO_WAV_HEADER_DATA:
    {
        char * pBuffer = (char *) nParam1;
        int nMaxBytes = nParam2;
        
        if (m_APEFileInfo.nFormatFlags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER)
        {
            if (sizeof(WAVE_HEADER) > static_cast<uint32>(nMaxBytes))
            {
                nRetVal = -1;
            }
            else
            {
                WAVEFORMATEX wfeFormat; GetInfo(APE_INFO_WAVEFORMATEX, (int) &wfeFormat, 0);
                WAVE_HEADER WAVHeader; FillWaveHeader(&WAVHeader, m_APEFileInfo.nWAVDataBytes, &wfeFormat,
                    m_APEFileInfo.nWAVTerminatingBytes);
                memcpy(pBuffer, &WAVHeader, sizeof(WAVE_HEADER));
                nRetVal = 0;
            }
        }
        else
        {
            if (m_APEFileInfo.nWAVHeaderBytes > nMaxBytes)
            {
                nRetVal = -1;
            }
            else
            {
                memcpy(pBuffer, m_APEFileInfo.spWaveHeaderData, m_APEFileInfo.nWAVHeaderBytes);
                nRetVal = 0;
            }
        }
        break;
    }
    case APE_INFO_WAV_TERMINATING_DATA:
    {
        char * pBuffer = (char *) nParam1;
        int nMaxBytes = nParam2;

        if (m_APEFileInfo.nWAVTerminatingBytes > nMaxBytes)
        {
            nRetVal = -1;
        }
        else
        {
            if (m_APEFileInfo.nWAVTerminatingBytes > 0) 
            {
                // variables
                int nOriginalFileLocation = m_spIO->GetPosition();
                unsigned int nBytesRead = 0;

                // check for a tag
                m_spIO->Seek(-(m_spAPETag->GetTagBytes() + m_APEFileInfo.nWAVTerminatingBytes), FILE_END);
                m_spIO->Read(pBuffer, m_APEFileInfo.nWAVTerminatingBytes, &nBytesRead);

                // restore the file pointer
                m_spIO->Seek(nOriginalFileLocation, FILE_BEGIN);
            }
            nRetVal = 0;
        }
        break;
    }
    case APE_INFO_WAVEFORMATEX:
    {
        WAVEFORMATEX * pWaveFormatEx = (WAVEFORMATEX *) nParam1;
        FillWaveFormatEx(pWaveFormatEx, m_APEFileInfo.nSampleRate, m_APEFileInfo.nBitsPerSample, m_APEFileInfo.nChannels);
        nRetVal = 0;
        break;
    }
    case APE_INFO_IO_SOURCE:
        nRetVal = (int) m_spIO.GetPtr();
        break;
    case APE_INFO_FRAME_BYTES:
    {
        int nFrame = nParam1;
        
        // bound-check the frame index
        if ((nFrame < 0) || (nFrame >= m_APEFileInfo.nTotalFrames)) 
        {
            nRetVal = -1;
        }
        else
        {
            if (nFrame != (m_APEFileInfo.nTotalFrames - 1)) 
                nRetVal = GetInfo(APE_INFO_SEEK_BYTE, nFrame + 1) - GetInfo(APE_INFO_SEEK_BYTE, nFrame);
            else 
                nRetVal = m_spIO->GetSize() - m_spAPETag->GetTagBytes() - m_APEFileInfo.nWAVTerminatingBytes - GetInfo(APE_INFO_SEEK_BYTE, nFrame);
        }
        break;
    }
    case APE_INFO_FRAME_BLOCKS:
    {
        int nFrame = nParam1;

        // bound-check the frame index
        if ((nFrame < 0) || (nFrame >= m_APEFileInfo.nTotalFrames)) 
        {
            nRetVal = -1;
        }
        else
        {
            if (nFrame != (m_APEFileInfo.nTotalFrames - 1)) 
                nRetVal = m_APEFileInfo.nBlocksPerFrame;
            else 
                nRetVal = m_APEFileInfo.nFinalFrameBlocks;
        }
        break;
    }
    case APE_INFO_TAG:
        nRetVal = (int) m_spAPETag.GetPtr();
        break;
    case APE_INTERNAL_INFO:
        nRetVal = (int) &m_APEFileInfo;
        break;
    default:
    	nRetVal=0;
    }

    return nRetVal;
}
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;
}
Example #3
0
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;
}