RiffFile RiffFile::Create(const wstring& filePath)
{
	unsigned int dataSize, fileType;
	const auto riffData = Tools::ReadFileToVector(filePath);

#if DEBUG
	unsigned int bufferPosition = 0;
	auto fileFourCC = Tools::BufferReader::ReadUInt(riffData, bufferPosition);
	Assert(fileFourCC = RiffFourCC::RIFF);
#else
	unsigned int bufferPosition = 4;
#endif

	dataSize = Tools::BufferReader::ReadUInt(riffData, bufferPosition);
	fileType = Tools::BufferReader::ReadUInt(riffData, bufferPosition);

	RiffFile riff(fileType);

	while (bufferPosition < dataSize + 8)
	{
		auto chunkFourCC = Tools::BufferReader::ReadUInt(riffData, bufferPosition);
		//Assert(chunkFourCC != RiffFourCC::LIST);	// Lists currently not supported

		auto chunkSize = Tools::BufferReader::ReadUInt(riffData, bufferPosition);
		
		riff.AddChunk(chunkFourCC, chunkSize, &riffData[bufferPosition]); 
		bufferPosition += chunkSize + (chunkSize % 2);
	}

	return riff;
}
bool CSoundCombiner::LoadSentenceFromWavFileUsingIO( char const *wavfile, CSentence& sentence, IFileReadBinary& io )
{
	sentence.Reset();

	InFileRIFF riff( wavfile, io );

	// UNDONE: Don't use printf to handle errors
	if ( riff.RIFFName() != RIFF_WAVE )
	{
		return false;
	}

	// set up the iterator for the whole file (root RIFF is a chunk)
	IterateRIFF walk( riff, riff.RIFFSize() );

	// This chunk must be first as it contains the wave's format
	// break out when we've parsed it
	bool found = false;
	while ( walk.ChunkAvailable() && !found )
	{
		switch( walk.ChunkName() )
		{
		case WAVE_VALVEDATA:
			{
				found = true;
				CSoundCombiner::ParseSentence( sentence, walk );
			}
			break;
		}
		walk.ChunkNext();
	}

	return true;
}
//-----------------------------------------------------------------------------
// Purpose: Create a wave audio source (streaming or in memory)
// Input  : *pName - file name
//			streaming - if true, don't load, stream each instance
// Output : CAudioSource * - a new source
//-----------------------------------------------------------------------------
// UNDONE : Pool these and check for duplicates?
CAudioSource *CreateWave( const char *pName )
{
	char formatBuffer[1024];
	InFileRIFF riff( pName, io );

	// UNDONE: Don't use printf to handle errors
	if ( riff.RIFFName() != RIFF_WAVE )
	{
		printf("Bad RIFF file type %s\n", pName );
		return NULL;
	}

	// set up the iterator for the whole file (root RIFF is a chunk)
	IterateRIFF walk( riff, riff.RIFFSize() );

	int format = 0;
	int formatSize = 0;

	// This chunk must be first as it contains the wave's format
	// break out when we've parsed it
	while ( walk.ChunkAvailable() && format == 0 )
	{
		switch( walk.ChunkName() )
		{
		case WAVE_FMT:
			{
				if ( walk.ChunkSize() <= 1024 )
				{
					walk.ChunkRead( formatBuffer );
					formatSize = walk.ChunkSize();
					format = ((WAVEFORMATEX *)formatBuffer)->wFormatTag;
				}
			}
			break;
		default:
			{
				ChunkError( walk.ChunkName() );
			}
			break;
		}
		walk.ChunkNext();
	}

	// Not really a WAVE file or no format chunk, bail
	if ( !format )
		return NULL;

	CAudioSourceWave *pWave;

	// create the source from this file
	pWave = new CAudioSourceMemWave();

	// init the wave source
	pWave->Setup( formatBuffer, formatSize, walk );

	return pWave;
}
Esempio n. 4
0
//-----------------------------------------------------------------------------
// xZipComputeWAVPreload
//
// Returns the number of bytes from a xbox compliant WAV file that should go into
// the preload section:
//-----------------------------------------------------------------------------
unsigned xZipComputeWAVPreload( char *pFileName )
{
    InFileRIFF riff( pFileName, *g_pSndIO );
    if ( riff.RIFFName() != RIFF_WAVE )
    {
        return 0;
    }

    IterateRIFF walk( riff, riff.RIFFSize() );

    while ( walk.ChunkAvailable() )
    {
        // xbox compliant wavs have a single PADD chunk
        if ( walk.ChunkName() == PADD_ID )
        {
            // want to preload data up through PADD chunk header
            // and not the actual pad bytes
            return walk.ChunkFilePosition() + 2*sizeof( int );
        }
        walk.ChunkNext();
    }

    return 0;
}
//-----------------------------------------------------------------------------
// Returns the duration of a wav file
//-----------------------------------------------------------------------------
float GetWavSoundDuration( const char *pWavFile )
{
	InFileRIFF riff( pWavFile, *g_pFSIOReadBinary );

	// UNDONE: Don't use printf to handle errors
	if ( riff.RIFFName() != RIFF_WAVE )
		return 0.0f;

	int nDataSize = 0;

	// set up the iterator for the whole file (root RIFF is a chunk)
	IterateRIFF walk( riff, riff.RIFFSize() );

	// This chunk must be first as it contains the wave's format
	// break out when we've parsed it
	char pFormatBuffer[ 1024 ];
	int nFormatSize;
	bool bFound = false;
	for ( ; walk.ChunkAvailable( ); walk.ChunkNext() )
	{
		switch ( walk.ChunkName() )
		{
		case WAVE_FMT:
			bFound = true;
			if ( walk.ChunkSize() > sizeof(pFormatBuffer) )
			{
				Warning( "oops, format tag too big!!!" );
				return 0.0f;
			}

			nFormatSize = walk.ChunkSize();
			walk.ChunkRead( pFormatBuffer );
			break;

		case WAVE_DATA:
			nDataSize += walk.ChunkSize();
			break;
		}
	}

	if ( !bFound )
		return 0.0f;

	const WAVEFORMATEX *pHeader = (const WAVEFORMATEX *)pFormatBuffer;

	int format = pHeader->wFormatTag;

	int nBits = pHeader->wBitsPerSample;
	int nRate = pHeader->nSamplesPerSec;
	int nChannels = pHeader->nChannels;
	int nSampleSize = ( nBits * nChannels ) / 8;

	// this can never be zero -- other functions divide by this. 
	// This should never happen, but avoid crashing
	if ( nSampleSize <= 0 )
	{
		nSampleSize = 1;
	}

	int nSampleCount = 0;
	float flTrueSampleSize = nSampleSize;

	if ( format == WAVE_FORMAT_ADPCM )
	{
		nSampleSize = 1;

		ADPCMWAVEFORMAT *pFormat = (ADPCMWAVEFORMAT *)pFormatBuffer;
		int blockSize = ((pFormat->wSamplesPerBlock - 2) * pFormat->wfx.nChannels ) / 2;
		blockSize += 7 * pFormat->wfx.nChannels;

		int blockCount = nSampleCount / blockSize;
		int blockRem = nSampleCount % blockSize;

		// total samples in complete blocks
		nSampleCount = blockCount * pFormat->wSamplesPerBlock;

		// add remaining in a short block
		if ( blockRem )
		{
			nSampleCount += pFormat->wSamplesPerBlock - (((blockSize - blockRem) * 2) / nChannels);
		}

		flTrueSampleSize = 0.5f;

	}
	else
	{
		nSampleCount = nDataSize / nSampleSize;
	}

	float flDuration = (float)nSampleCount / (float)nRate;
	return flDuration;
}