[ Home | Syllabus |Course Notes]
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; }