I spent quite a time to make the header and sub-header of wav file properly. Searched a lot on internet but didn’t find much help. So, after writing the code successfully, I have posted it on my web site and to help any one who is interested in this.
I have tried to explain the code in the most easiest of the fashion along with comments, but if you feel any problem, do ask, I might be able to lend you some hand. One thing should be mentioned, that I have the “Recording.wav” file already created before running this code, you can create it using fstream. The reason for already creating the file is that I was actually interested in creating the header and sub-header of wav file, because even if you record data in wav file, it will not work properly, as long as its header and sub-header are not created successfully. Also, performed sound recording using mimo. You can use fstream for it also. If you want further help in understanding the basic structure of wav file, do check the links given at the end of the post.
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <Mmsystem.h>
#include <Mmreg.h.>
#include <fstream.h>
#define BUFFER_LEN 102400
void main()
{
WAVEINCAPS lpwaveincaps;
MMRESULT sounddeviceinfo;
UINT count = waveInGetNumDevs();
printf("%d\n",count);
sounddeviceinfo = waveInGetDevCaps(0, &lpwaveincaps, sizeof(WAVEINCAPS));
if (sounddeviceinfo != MMSYSERR_NOERROR)
{
printf("Error in getting info about Sound Device\n");
return;
}
printf("%d",sounddeviceinfo);
WAVEFORMATEX formatinfo;
formatinfo.cbSize = 0;
formatinfo.wFormatTag = WAVE_FORMAT_PCM;
formatinfo.nChannels = 1; // 1 for mono 2 and 2 for stereo
formatinfo.wBitsPerSample = 16; // can be 8 or 16
formatinfo.nSamplesPerSec = 8000; // u can set nSamplesPerSec as 16000, 24000.
//44100, 48000 depending on the quality you want
formatinfo.nBlockAlign = formatinfo.nChannels * (formatinfo.wBitsPerSample / 8);
formatinfo.nAvgBytesPerSec = formatinfo.nSamplesPerSec * formatinfo.nBlockAlign;
MMRESULT soundfileopen;
HWAVEIN hwi;
char buffer1[BUFFER_LEN]; //waveform buffer
soundfileopen = waveInOpen( &hwi, WAVE_MAPPER, &formatinfo, 0, 0, 0);
if (soundfileopen != MMSYSERR_NOERROR)
{
if (soundfileopen == MMSYSERR_ALLOCATED)
{
printf("Error in opening audio device, 1\n");
return;
}
if (soundfileopen == MMSYSERR_BADDEVICEID)
{
printf("Error in opening audio device, 2\n");
return;
}
if (soundfileopen == MMSYSERR_NODRIVER)
{
printf("Error in opening audio device, 3 \n");
return;
}
if (soundfileopen == MMSYSERR_NOMEM)
{
printf("Error in opening audio device, 4\n");
return;
}
if (soundfileopen == WAVERR_BADFORMAT)
{
printf("Error in opening audio device, 5 \n");
return;
}
}
// Preaparing WHDR
WAVEHDR buffer;
ZeroMemory(&buffer, sizeof(buffer)); //filling the block with zeros
buffer.dwBufferLength=BUFFER_LEN;
buffer.lpData=(LPSTR)&buffer1;
// Preaparing header
MMRESULT waveinheader;
waveinheader = waveInPrepareHeader( hwi, &buffer, sizeof(WAVEHDR));
if (waveinheader == MMSYSERR_NOERROR)
{
waveInAddBuffer( hwi, &buffer, sizeof(buffer));
printf("Recording Data…\n");
// start recording
waveInStart( hwi);
//keep recording for 100milliseconds unless flag is set
while ( (buffer.dwFlags & WHDR_DONE) != WHDR_DONE)
{
Sleep(100);
//printf("dwFlags %d\n", buffer.dwFlags);
}
waveInStop( hwi);
printf("Recording Completed, number of bytes recorded are %d\n", buffer.dwBytesRecorded );
/*
Basic steps you need to follow while writing wave file using mmio
1) mmioOpen
2) mmioCreateChunk – ‘RIFF’ & ‘WAVE’
3) mmioCreateChunk – ‘fmt ‘
4) mmioWrite – WAVEFORMATEX
5) mmioAscend – out of ‘fmt ‘ – writes fmt length
6) mmioCreateChunk ‘data’
7) mmioWrite – audio data
8) mmioAscend – out of ‘data’ – writes data length
9) mmioAscend -out of ‘RIFF’ – write ‘RIFF’ length
10) mmioClose
*/
// creating a file using mmio, C:\\Recording.wav already exists
HMMIO file;
file = mmioOpen("C:\\Recording.wav", NULL, MMIO_CREATE | MMIO_READWRITE );
if (file == NULL)
{
printf("Error in creating file using MIMO-OPEN\n");
}
MMCKINFO mmckinfo;
MMCKINFO mmckinfoSubchunk;
MMCKINFO mmckinfoData;
memset(&mmckinfo, 0, sizeof(mmckinfo));
memset(&mmckinfoSubchunk, 0, sizeof(mmckinfoSubchunk));
memset(&mmckinfoData, 0, sizeof(mmckinfoData));
//step 1 create riff chunk
mmckinfo.fccType = mmioFOURCC(‘W’, ‘A’, ‘V’, ‘E’);
if(mmioCreateChunk( file, &mmckinfo, MMIO_CREATERIFF) != MMSYSERR_NOERROR)
{
printf("Error in creating chunk wave\n");
}
//step 2 create fmt chunk
//creating fmt chunk also includes writing formatex to this chunk
mmckinfoSubchunk.ckid = mmioFOURCC(‘f’, ‘m’, ‘t’, ‘ ‘);
mmckinfoSubchunk.cksize = sizeof(WAVEFORMATEX) ;
if(mmioCreateChunk( file, &mmckinfoSubchunk, 0) != MMSYSERR_NOERROR)
{
printf("Error in creating chunk sub\n");
}
if(mmioWrite( file, (char*)&formatinfo, sizeof(formatinfo)) == -1 )
{
printf("Error in writing chunk sub\n");
}
if(mmioAscend( file, &mmckinfoSubchunk, 0) != MMSYSERR_NOERROR )
{
printf("Error in ascending out of chunk sub\n");
}
//step 3 creating data chunk
//creating this chunk includes writing actual voice data
mmckinfoData.ckid=mmioFOURCC(‘d’,‘a’,‘t’,‘a’);
mmckinfoData.cksize = formatinfo.nAvgBytesPerSec;
if(mmioCreateChunk( file, &mmckinfoData, 0) != MMSYSERR_NOERROR)
{
printf("Error in creating chunk data\n");
}
if (mmioWrite( file, (char*)&buffer.lpData, BUFFER_LEN) == -1 )
{
printf("Error in writing chunk data\n");
}
MMRESULT check = mmioAscend( file, &mmckinfoData, 0);
if(check != MMSYSERR_NOERROR)
{
printf("Error in ascending out of chunk data\n");
}
if(mmioAscend( file, &mmckinfo, 0) != MMSYSERR_NOERROR )
{
printf("Error in ascending out of chunk wave\n");
}
waveInUnprepareHeader(hwi, &buffer, sizeof(buffer));
mmioClose( MMIO_READ, MMIO_FHOPEN);
waveInClose(hwi);
}
else
{
if (waveinheader == MMSYSERR_INVALHANDLE)
{
printf("Specified device handle is invalid.\n");
return;
}
if (waveinheader == MMSYSERR_NODRIVER)
{
printf("No device driver is present.\n");
return;
}
if (waveinheader == MMSYSERR_NOMEM)
{
printf("Unable to allocate or lock memory.\n");
return;
}
}
}
/*
to read any wav file, use this link
http://loosethinker.com/software_development/?page=knowledge_base&id=2
Refernces
http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
http://www.topherlee.com/software/pcm-tut-wavformat.html
http://www.tech-archive.net/
http://msdn.microsoft.com/en-us/library/ms712601%28VS.85%29.aspx
http://www.programmersheaven.com
*/