VOC File Player
Wave files (.WAV) are very easy to handle with Microsoft compilers. Unfortunately, I had to work with Creative Labs' .VOC audio files which are not directly supported.
Although some documentation say that you simply need to "throw the sound file to the wave mapper which will take care of everything!", it was not that easy. When I was doing so, I was hearing a constant 'pop' in the playback. To solve this problem, I had to extract each data block from the file and get rid of the unwanted data.
VOC files work in blocks. Each of the nine different blocks has its own format. A basic VOC file only uses blocks of type 1, 8 and 9. This is what I had to work with, and this is what my code uses.
The code uses the waveOutxxx() functions. These functions work wonderfully, as long as you provide the correct information to them. The class used to play the VOC file is declared as follow:
class CVocPlayer
{
public:
CVocPlayer();
virtual ~CVocPlayer();
void lay( const CString &rcFileName, CWnd *pCallbackWnd );
inline void Reset() const
{
waveOutReset( hWaveOut );
}
void Clear();
protected:
char *pData;
bool boPlaying;
HWAVEOUT hWaveOut;
WAVEHDR sWaveHdr;
protected:
void Decode( const CString &rcFileName, FILEINFO *psFileInfo );
};
Obviously, the function used to play the file is Play(). Notice that a pointer to a window must be specified as a parameter. This window is the one that will be notified when the audio file is done playing, and this step is required to cleanup by calling the Clear() function. There are many ways to let us know when the file is done playing, and this is the one I prefer. Changing the method shouldn't be too hard.
The Decode() function uses a FILEINFO structure. This structure is used to gather information about the audio file required by the device. The structure is defined as follow:
typedef struct
{
UCHAR ucBitsPerSample;
UCHAR ucChannels;
USHORT usFileFormat;
USHORT usTimeConstant;
long lSamplesPerSeconds;
long lTotalLength;
} FILEINFO;
Now, the source code of the Play() function
void CVocPlayer::Play( const CString &rcFileName, CWnd *pCallbackWnd )
{
Clear();
// Decode the file
FILEINFO sFileInfo;
Decode( rcFileName, &sFileInfo );
// Prepare a WAVEFORMATEX required for opening the device driver
WAVEFORMATEX sWaveFormat;
sWaveFormat.wFormatTag = WAVE_FORMAT_PCM;
sWaveFormat.nChannels = sFileInfo.ucChannels;
sWaveFormat.nSamplesPerSec = sFileInfo.lSamplesPerSeconds;
sWaveFormat.nAvgBytesPerSec = sFileInfo.lSamplesPerSeconds;
sWaveFormat.nBlockAlign = 1;
sWaveFormat.wBitsPerSample = sFileInfo.ucBitsPerSample;
sWaveFormat.cbSize = sizeof(WAVEFORMATEX);
// Try to open the device driver
MMRESULT Result = waveOutOpen( &hWaveOut, WAVE_MAPPER, &sWaveFormat,
(ULONG)pCallbackWnd->m_hWnd, 0,
CALLBACK_WINDOW );
if ( Result != MMSYSERR_NOERROR )
{
hWaveOut = 0;
return;
}
// Prepare the header
sWaveHdr.lpData = pData;
sWaveHdr.dwBufferLength = sFileInfo.lTotalLength;
sWaveHdr.dwFlags = 0;
sWaveHdr.dwLoops = 0;
waveOutPrepareHeader( hWaveOut, &sWaveHdr, sizeof(sWaveHdr) );
// Play the file
boPlaying = true;
waveOutWrite( hWaveOut, &sWaveHdr, sizeof(sWaveHdr) );
}
After decoding the file and storing its information in the FILEINFO structure, we fill the WAVEFORMATEX structure with the appropriate information and give it to the waveOutOpen() function. If the device can handle the wanted format, we prepare the header of the audio output and send our data to the waveOutWrite() function.
To decode the VOC file, we go through each of its blocks and store those we want in a memory buffer (our pData member). At the same time, we fill the FILEINFO structure with the information required by the WAVEFORMATEX structure.
void CVocPlayer::Decode( const CString &rcFileName, FILEINFO *psFileInfo )
{
// Open the file and allocate the memory
FILE *pFile = fopen( rcFileName, "rb" );
long lFileLength = _filelength( _fileno(pFile) );
pData = new char[ lFileLength ];
char *pDataPos = pData;
// Place the file pointer at the beginning of the data
fseek( pFile, 0x1A, SEEK_SET );
BYTE bType;
signed long int lLen;
do
{
// Read the block type
fread( &bType, sizeof(bType), 1, pFile );
lLen = 0;
switch( bType )
{
case 1:
{
fread( &lLen, 3, 1, pFile );
lLen -= 2; // Remove Time Constant and File Format bytes
fread( &psFileInfo->usTimeConstant, 1, 1, pFile );
fread( &psFileInfo->usFileFormat, 1, 1, pFile );
// For the moment, it's a plain 8-bit mono file
psFileInfo->ucBitsPerSample = 8;
psFileInfo->ucChannels = 1;
psFileInfo->lSamplesPerSeconds = 1000000 /
(256-(psFileInfo->usTimeConstant % 256));
// Store this sample in memory
fread( pDataPos, lLen, 1, pFile );
pDataPos += lLen;
break;
}
case 8:
{
fseek( pFile, 3, SEEK_CUR ); // Skip the length
fread( &psFileInfo->usTimeConstant, 2, 1, pFile );
fread( &psFileInfo->usFileFormat, 1, 1, pFile );
fread( &psFileInfo->ucChannels, 1, 1, pFile );
// Block of type 8 is always followed by a block of type 1
fread( &bType, sizeof(bType), 1, pFile );
fread( &lLen, 3, 1, pFile );
lLen -= 2; // Remove Time Constant and File Format bytes
fseek( pFile, 2, SEEK_CUR ); // Skip T.C. and F.F.
psFileInfo->ucBitsPerSample = 8;
psFileInfo->ucChannels++;
psFileInfo->usTimeConstant >>= 8;
psFileInfo->lSamplesPerSeconds = 1000000 /
(256-(psFileInfo->usTimeConstant % 256));
// Store this sample in memory
fread( pDataPos, lLen, 1, pFile );
pDataPos += lLen;
break;
}
case 9:
{
fread( &lLen, 3, 1, pFile );
lLen -= 12;
fread( &psFileInfo->lSamplesPerSeconds, 4, 1, pFile );
fread( &psFileInfo->ucBitsPerSample, 1, 1, pFile );
fread( &psFileInfo->ucChannels, 1, 1, pFile );
fread( &psFileInfo->usFileFormat, 2, 1, pFile );
// Store this sample in memory
fread( pDataPos, lLen, 1, pFile );
pDataPos += lLen;
break;
}
};
} while ( bType != 0 );
psFileInfo->lTotalLength = pDataPos-pData;
fclose( pFile );
}
After the file is played, we need to clean our stuff. The Clear() function takes care of that
void CVocPlayer::Clear()
{
if ( !boPlaying )
return;
waveOutUnprepareHeader( hWaveOut, &sWaveHdr, sizeof(sWaveHdr) );
delete [] pData;
pData = NULL;
waveOutClose( hWaveOut );
boPlaying = false;
}
...and that's it! All you need to do to play the file is call the Play() function!
Downloads
Download source - 25 KBDownload demo project - 98KB

Comments
Goal
Posted by snareenactina on 11/07/2012 04:06amaxils The U.S. economy is about to get the Bob Woodward treatment. I try and avoid the chain stores as much as possible, but itââ¬â¢s become nearly impossible here in the city of Boston. Iââ¬â¢ve always held a dim view of these large, sterile warehouse kinds of stores. I really miss the little neighborhood stores, which are almost all gone now. After viewing product detail pages or search results, look here to find an easy way to navigate back to pages you are interested in. glucagon If you can't remember the last time you had your car serviced, take it in. In extreme situations, you might increase your mileage by up to 10 percent. So what? Well, if you drove 20,000 miles a year, you would save $250 - enough to cover the cost of the service, buy yourself a super-size falafel sandwich and still have a few bucks left over to start tipping your mechanic. (You did know you're supposed to tip your mechanic, right?) suiko The history of empires past and present is the story of this stripping away of that ability and that right, this violent mangling of the relationships that different peoples have created over time with the places that they live in. lviii Already a member? ridbc Unemployment is a phenomenon when a person is available for work but is not able to get it. The level of unemployment is known as unemployment rate which is a major criterion to check a country's growth rate and macroeconomics. Causes of unemployment always have been controversial and have been debated by many financial experts. Unemployment and its causes change with the location as well. harbaugh Academic and policy interest has now moved beyond simply the optimal commercial exploitation of the standard trio of resources to encompass management for other objectives. For example, natural resources more broadly defined have recreational, as well as commercial values. They may also contribute to overall social welfare levels, by their mere existence. rail The gross domestic product (GDP) has been widely adopted to measure the wealth of a country for a long time. However, actually, it can not comprehensively reflect the economic power of a country and if the countries have been ranked from another perspective, they may be another story. orgstephanie Combined
ReplyHelp me decode jp2 file format
Posted by Legacy on 02/11/2003 12:00amOriginally posted by: Signs
Please help me decode .jp2 file format for PDA
ReplyVOC can be space compressed
Posted by Legacy on 11/08/2002 12:00amOriginally posted by: Dan WInsor
A voc file can be compressed by including a block type 3.
ReplyThe block tells how many bytes should follow with silence.
WAVE from
Posted by Legacy on 07/01/2002 12:00amOriginally posted by: Janakiraman
ReplyThanks a lot...
Posted by Legacy on 03/07/2002 12:00amOriginally posted by: Gerson
I was looking for informations about wave files... I found it in your page! Thanks a lot. Congratulations...
Gerson.
ReplyRecord .voc file
Posted by Legacy on 02/18/2002 12:00amOriginally posted by: Bryan Evenson
I'm looking to do a project that can record and playback a .voc file. Any suggestions on how to record a .voc file?
Thanks,
ReplyBryan
.CPP파일이 하나 없군요
Posted by Legacy on 12/11/2001 12:00amOriginally posted by: BONGSOO
없는 파일이 하나 있습니다.
하지만 윗글을 참고 해서 만들면됩니다.
Reply
Anyone looking for VocPlayer.cpp? Here is the way...
Posted by Legacy on 04/04/2001 12:00amOriginally posted by: Senel Canik
To have a VocPlayer.cpp, simply create a new Dialog based MFC project with a name "VocPlayer". Grab the VocPlayer.cpp file just created by MFC and merge with the project supplied by Mr. Pierre Fournier? Good luck.
Senel Canik
ReplyAircraft Engineer
Anyone looking for VocPlayer.cpp? Here is the way...
Posted by Legacy on 04/03/2001 12:00amOriginally posted by: Senel Canik
To have a VocPlayer.cpp, simply create a new Dialog based MFC project with a name "VocPlayer". Grab the VocPlayer.cpp file just created by MFC and merge with the project supplied by Mr. Pierre Fournier? Good luck.
Senel Canik
ReplyAircraft Engineer
help me to process the video image
Posted by Legacy on 04/12/2000 12:00amOriginally posted by: Guest
ReplyLoading, Please Wait ...