[ Home | Syllabus | Course Notes | Assignments | Search]

typedef struct {
LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD dwFlags;
DWORD dwLoops;
struct wavehdr_tag * lpNext;
DWORD reserved;
} WAVEHDR;
Flags supplying information about the buffer. The following values are defined:
WHDR_BEGINLOOP
This buffer is the first buffer in a loop. This flag is used only with output buffers.
WHDR_DONE
Set by the device driver to indicate that it is finished with the buffer and is returning
it to the application.
WHDR_ENDLOOP
This buffer is the last buffer in a loop. This flag is used only with output buffers.
WHDR_INQUEUE
Set by Windows to indicate that the buffer is queued for playback.
WHDR_PREPARED
Set by Windows to indicate that the buffer has been prepared with the waveInPrepareHeader
or waveOutPrepareHeader function.
typedef struct {
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX;
Examples:
Telephone quality, mono, 8 bit PCM
WAVEFORMATEX PCMWaveFmtRecord; PCMWaveFmtRecord.wFormatTag = WAVE_FORMAT_PCM; PCMWaveFmtRecord.nChannels = 1; PCMWaveFmtRecord.nSamplesPerSec = 8000; PCMWaveFmtRecord.wBitsPerSample = 8; PCMWaveFmtRecord.nAvgBytesPerSec = PCMWaveFmtRecord.nSamplesPerSec * PCMWaveFmtRecord.wBitsPerSample / 8; PCMWaveFmtRecord.nBlockAlign = PCMWaveFmtRecord.nChannels * PCMWaveFmtRecord.wBitsPerSample / 8;
First Examine a simple playback program.
bool playBack(char* buffer,int numrcv)
{
//Handle for the WAVE device.
HWAVEOUT hWaveOut;
WAVEFORMATEX PCMWaveFmtRecord;
int errorCode;
PCMWaveFmtRecord.wFormatTag = WAVE_FORMAT_PCM;
PCMWaveFmtRecord.nChannels = 1;
PCMWaveFmtRecord.nSamplesPerSec = 8000;
PCMWaveFmtRecord.nAvgBytesPerSec = 8000;
PCMWaveFmtRecord.nBlockAlign = 1;
PCMWaveFmtRecord.wBitsPerSample = 8;
errorCode = waveOutOpen(NULL, WAVE_MAPPER,
&PCMWaveFmtRecord,
0L, 0L, WAVE_FORMAT_QUERY);
if (errorCode)
{
//MessageBox(" Device Cannot handle this format");
return false;
}
waveOutOpen(&hWaveOut, WAVE_MAPPER,
&PCMWaveFmtRecord,
0L, 0L, 0L);
//Prepare the header.
WaveHeader.lpData = (LPSTR) buffer;
WaveHeader.dwBufferLength = numrcv;
WaveHeader.dwFlags = WaveHeader.reserved = 0;
WaveHeader.dwLoops = 0;
WaveHeader.lpNext = NULL;
waveOutPrepareHeader(hWaveOut, &WaveHeader, sizeof(WaveHeader));
//Write data to WAVE device.
waveOutWrite(hWaveOut, &WaveHeader, sizeof(WaveHeader));
//Loop until playback is finished.
do {}
while (!(WaveHeader.dwFlags & WHDR_DONE)); // inefficient busy wait!
//Unprepare the wave output header.
waveOutUnprepareHeader(hWaveOut, &WaveHeader, sizeof(WaveHeader));
//Close the WAVE device.
waveOutClose(hWaveOut);
return true;
}
HANDLE recordDone; // event of audio input completion HWAVEIN hWaveIn; // onput WAVE audio device handle char inbuf[BUFSIZE]; // WAVE input data buffer area HANDLE audioFileHandle; // handle for audio file WAVEHDR WaveHeader; // . . .
void CMessage::RecordMessage()
// Records Message to file
// for testing name is hardcoded in.
{
DWORD threadid;
HANDLE RecordHandle;
audioFileHandle = CreateFile("TestRecord", GENERIC_WRITE,
0,0, CREATE_ALWAYS, 0, 0);
recordDone = CreateEvent(0, FALSE, FALSE, 0);
ResetEvent(recordDone);
RecordHandle = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) Recorder, NULL, 0,
&threadid);
openWaveDev();
msgApp.m_pMainWnd->SetWindowText("Start Recording");
WaitForSingleObject(RecordHandle, INFINITE);
waveInClose(hWaveIn);
msgApp.m_pMainWnd->SetWindowText("Done Recording");
CloseHandle(audioFileHandle);
return;
}
void openWaveDev()
{
MMRESULT Rc;
WAVEFORMATEX PCMWaveFmtRecord;
PCMWaveFmtRecord.wFormatTag = WAVE_FORMAT_PCM;
PCMWaveFmtRecord.nChannels = 1;
PCMWaveFmtRecord.nSamplesPerSec = 8000;
PCMWaveFmtRecord.wBitsPerSample = 8;
PCMWaveFmtRecord.nAvgBytesPerSec = PCMWaveFmtRecord.nSamplesPerSec
* PCMWaveFmtRecord.wBitsPerSample / 8;
PCMWaveFmtRecord.nBlockAlign = PCMWaveFmtRecord.nChannels *
PCMWaveFmtRecord.wBitsPerSample / 8;
Rc = waveInOpen(&hWaveIn, WAVE_MAPPER, &PCMWaveFmtRecord,
(DWORD) recordCallBack, 0L,
CALLBACK_FUNCTION);
if (Rc)
{ // must not be an audio recording device
return;
}
WaveHeader.dwBufferLength = BUFSIZE;
WaveHeader.lpData = (LPSTR) (inbuf);
WaveHeader.dwFlags = WaveHeader.reserved = 0;
WaveHeader.dwLoops = 0;
WaveHeader.lpNext = 0;
Rc = waveInPrepareHeader(hWaveIn, &WaveHeader,
sizeof(WAVEHDR));
Rc = waveInAddBuffer(hWaveIn, &WaveHeader,
sizeof(WAVEHDR));
ResetEvent(recordDone);
if (Rc = waveInStart(hWaveIn))
{
waveInClose(hWaveIn);
}
}
void CALLBACK recordCallBack(HWAVEIN hWaveIn, UINT uMsg,
DWORD p1, DWORD p2, DWORD p3)
{
if (uMsg != WIM_DATA)
return;
SetEvent(recordDone);
}
UINT Recorder(void *p)
{
int i; // number of BUFSIZ buffers to record before reaching MAXBUF
BOOL success;
DWORD numWrite;
for(i = 0; i < MAXBUF/BUFSIZE; i++) // just record a little bit
{
WaitForSingleObject(recordDone, INFINITE); // wait till device has called back
if (!(WaveHeader.dwFlags & WHDR_DONE)) // just make sure really done
{
continue;
}
if(success = WriteFile(audioFileHandle, WaveHeader.lpData,
WaveHeader.dwBytesRecorded, &numWrite, 0))
{
}
if (waveInUnprepareHeader(hWaveIn, &WaveHeader,
sizeof(WAVEHDR)))
{
}
WaveHeader.dwFlags = 0;
if (waveInPrepareHeader(hWaveIn, &WaveHeader,
sizeof(WAVEHDR)))
{
}
if (waveInAddBuffer(hWaveIn, &WaveHeader,
sizeof(WAVEHDR)))
{
}
}
waveInReset(hWaveIn);
waveInClose(hWaveIn);
return 0;
}
// main.h
#include <afxwin.h>
#include "Message.h"
// Define an application object
class CMsgApp : public CWinApp
{
public:
virtual BOOL InitInstance(); // everybody overrides this one
CMessage msg;
};
#include "main.h"
#include "CMsgDlg.h"
#include "resource.h"
// Create an instance of the application
CMsgApp msgApp;
// Init the application and the main window
BOOL CMsgApp::InitInstance()
{
CMsgDlg dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}