📄 wavrec.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <windows.h>
#include <dsound.h>
#include "stdafx.h"
#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
MMRESULT ReadWaveFile(LPCTSTR pszFilename, PWAVEFORMATEX * ppWFX, PDWORD pdwBufferSize, PBYTE * ppBufferBits);
MMRESULT WriteWaveFile(LPCTSTR pszFilename, PWAVEFORMATEX pWFX, DWORD dwBufferSize, PBYTE pBufferBits);
#define MRCHECK(mr,str)\
if ((mr != MMSYSERR_NOERROR)) { RETAILMSG(1, (TEXT(#str) TEXT(" failed. mr=%08x\r\n"), mr)); goto ERROR_DONE;}
MMRESULT
RecordWaveBuffer (PWAVEHDR pwh, DWORD dwDeviceId, PWAVEFORMATEX pwfx, DWORD dwDuration)
{ const DWORD dwTolerance = 1000;
DWORD dwWait;
HANDLE hevDone;
HWAVEIN hwi;
// create an event so we know when capture is completed
hevDone = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hevDone == NULL) {
RETAILMSG (1, (TEXT("Unable to create completion event\r\n")));
return MMSYSERR_NOMEM;
}
// open the wave capture device
MMRESULT mr = waveInOpen(&hwi,dwDeviceId, pwfx, (DWORD) hevDone, NULL, CALLBACK_EVENT);
if (mr != MMSYSERR_NOERROR) {
RETAILMSG(1, (TEXT("waveInOpen failed. mr=%08x\r\n"), mr));
return mr;
}
// set up the WAVEHDR structure that describes the capture buffer
// prepare the buffer for capture
mr = waveInPrepareHeader(hwi, pwh, sizeof(WAVEHDR));
MRCHECK(mr, waveInPrepareHeader);
// submit the buffer for capture
mr = waveInAddBuffer(hwi, pwh, sizeof(WAVEHDR));
MRCHECK(mr, waveInAddBuffer);
// start capturing
RETAILMSG(1, (TEXT("Starting capture...\r\n\n\n")));
mr = waveInStart(hwi);
MRCHECK(mr, waveInStart);
// wait for completion + 1 second tolerance
// dwWait= WaitForSingleObject(hevDone, dwDuration + dwTolerance);
Sleep(6000);
if (dwWait != WAIT_OBJECT_0) {
RETAILMSG(1, (TEXT("Timeout waiting for capture to complete, writing partialy file.\r\n")));
mr = waveInReset(hwi);
if (mr != MMSYSERR_NOERROR) {
RETAILMSG(1, (TEXT("warning: waveInReset failed. mr=%08x\r\n"), mr));
}
}
// now clean up: unprepare the buffer
mr = waveInUnprepareHeader(hwi, pwh, sizeof(WAVEHDR));
MRCHECK(mr, waveInUnprepareHeader);
ERROR_DONE:
// close the capture device & free the event handle
mr = waveInClose(hwi);
if (mr != MMSYSERR_NOERROR) {
RETAILMSG(1, (TEXT("warning: waveInClose failed. mr=%08x\r\n"), mr));
}
CloseHandle(hevDone);
return mr;
}
MMRESULT
RecordWaveFile (PCTSTR pszFilename, DWORD dwDeviceId, PWAVEFORMATEX pwfx, DWORD dwDuration)
{ MMRESULT mr;
PBYTE pBufferBits;
DWORD dwBufferSize;
// compute the size of the capture buffer
// compute total # of samples & multiply by blocksize to get sample-aligned buffer size
dwBufferSize = (dwDuration * pwfx->nSamplesPerSec / 1000) * pwfx->nBlockAlign;
// let user know what's going on
RETAILMSG(1, (TEXT("Recording %5d ms to \"%s\": %c%02d %5dHz (%8d bytes)\r\n")
, dwDuration
, pszFilename
, pwfx->nChannels == 2 ? L'S' : L'M'
, pwfx->wBitsPerSample
, pwfx->nSamplesPerSec
, dwBufferSize
));
// try to allocate the capture buffer
pBufferBits = new BYTE [dwBufferSize];
if (pBufferBits == NULL) {
RETAILMSG (1, (TEXT("Unable to allocate %d bytes for %d ms of audio data\r\n"), dwBufferSize, dwDuration));
return MMSYSERR_NOMEM;
}
WAVEHDR hdr;
memset(&hdr, 0, sizeof(WAVEHDR));
hdr.dwBufferLength = dwBufferSize;
hdr.lpData = (char *) pBufferBits;
mr = RecordWaveBuffer(&hdr, dwDeviceId, pwfx, dwDuration);
MRCHECK(mr, RecordWaveBuffer);
// finally, write the captured buffer to the file
// note that we use hdr.dwBytesRecorded, not dwBuffersize.
RETAILMSG(1, (TEXT("Capture completed. Writing %s\r\n"), pszFilename));
mr = WriteWaveFile(pszFilename, pwfx, hdr.dwBytesRecorded, pBufferBits);
MRCHECK(mr, WriteWaveFile);
ERROR_DONE:
// free up the capture buffer and release the done event
delete [] pBufferBits;
// and we're done
return mr;
}
PTSTR usage_text[] =
{
TEXT("usage:\r\n"),
TEXT(" -f <filename> output filename\r\n"),
TEXT(" -r <rate> sample rate\r\n"),
TEXT(" -b <8|16> sample size in bits\r\n"),
TEXT(" -c <1|2> channels (mono/stereo)\r\n"),
TEXT(" -t <duration> recording time in milliseconds\r\n"),
TEXT(" -d <device> device index\r\n"),
TEXT(" -? help\r\n"),
};
void
Usage(void)
{ int i;
for (i = 0; i < NELEMS(usage_text); i++) {
RETAILMSG(1, (usage_text[i]));
}
}
void StartRecord(char *pFile)
{
//MessageBox(NULL,(LPCTSTR)pFile,TEXT("msg"),MB_OK);
//MessageBox(NULL,TEXT("msg"),TEXT("msg"),MB_OK);
// The run parameters
// Set up defaults to be overridden by command line
PTSTR pszFilename = (PTSTR)pFile;
DWORD dwDuration = 5 * 1000; // record for 5 seconds
DWORD dwChannels = 1; // default to mono
DWORD dwBitsPerSample = 16; // default to 16-bit samples
DWORD dwSampleRate = 11025; // default to 11.025KHz sample rate
DWORD dwDeviceId = 0; // capture from device 0
WAVEFORMATEX wfx;
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.wBitsPerSample = (WORD) dwBitsPerSample;
wfx.nSamplesPerSec = dwSampleRate;
wfx.nChannels = (WORD) dwChannels;
wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
//MessageBox(NULL,pszFilename,TEXT("msg"),MB_OK);
// we're all set: go do the real work
RecordWaveFile(pszFilename,dwDeviceId, &wfx, dwDuration);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -