WindowsAPIによる録音と再生

41698 ワード

レコーディング
1、初期化
	memset(&hWaveIn, 0, sizeof(HWAVEIN));
	memset(&waveForm, 0, sizeof(WAVEFORMATEX));

	if (getAudioDevices())   //        
	{
		//      
		setWaveFormat(&waveForm, 2, 44100, 16);

		//        
		for (int i = 0; i < 2; ++i)
		{
			whdr[i].lpData = (CHAR*)malloc(bufLength);
			memset(whdr[i].lpData, 0, bufLength);
			whdr[i].dwBufferLength = bufLength;	//     
			whdr[i].dwBytesRecorded = 0;		//      ,           
			whdr[i].dwUser = 0;				   	//       
			whdr[i].dwFlags = 0;				//   
			whdr[i].dwLoops = 0;				//   
			whdr[i].lpNext = NULL;				//   
			whdr[i].reserved = 0;				//   
		}
	}

bool InputSound::getAudioDevices()
{
	//        
	int count = 0;
	count = waveInGetNumDevs();
	if (count == 0)
	{
		printf("        ,     
"
); return false; } printf(" :%d
"
, count); // WAVEINCAPS waveIncaps; MMRESULT mmResult = waveInGetDevCaps(0, &waveIncaps, sizeof(WAVEINCAPS)); if (mmResult != MMSYSERR_NOERROR) { printf("
"
); return false; } //printf(" :%s
", waveIncaps.szPname);
std::cout << " :" << waveIncaps.szPname << std::endl; return true; }

2、録音のパラメータを設定する
void InputSound::setWaveFormat(LPWAVEFORMATEX waveformat, WORD nCh, DWORD nSampleRate, WORD BitsPerSample)
{
	waveformat->wFormatTag = WAVE_FORMAT_PCM;
	waveformat->nChannels = nCh;	//   
	waveformat->nSamplesPerSec = nSampleRate;	//   
	waveformat->nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample / 8;	//     
	waveformat->nBlockAlign = nCh * BitsPerSample / 8;	//     
	waveformat->wBitsPerSample = BitsPerSample;		//    
	waveformat->cbSize = 0;
}

3、レコーディング開始
void InputSound::startRecording()
{
	try
	{
		MMRESULT mmResult = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveForm, (DWORD)waveInProc, (DWORD)this, CALLBACK_FUNCTION);
		if (mmResult != MMSYSERR_NOERROR)
		{
			printf("      
"
); return; } waveInPrepareHeader(hWaveIn, &whdr[0], sizeof(WAVEHDR)); // waveInPrepareHeader(hWaveIn, &whdr[1], sizeof(WAVEHDR)); // waveInAddBuffer(hWaveIn, &whdr[0], sizeof(WAVEHDR)); // waveInAddBuffer(hWaveIn, &whdr[1], sizeof(WAVEHDR)); // waveInStart(hWaveIn); isStop = FALSE; printf("
"
); } catch (...) { printf("
"
); } return; }

4、コールバック処理は、データをファイルに書き込んだ後、バッファをクリアし、録音装置に再追加する必要があることに注意する.
DWORD CALLBACK InputSound::waveInProc(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
	InputSound* inputSound = (InputSound*)dwInstance;
	char buf[bufLength] = {0};
	switch (uMsg)
	{
	case WIM_OPEN:		//      
		printf("      
"
); break; case WIM_DATA: // memcpy(&buf, ((LPWAVEHDR)dwParam1)->lpData, bufLength); // FILE *pf; fopen_s(&pf, "./RecordSounds.pcm", "ab+"); if (strlen(buf)) { // fwrite(buf, 1, ((LPWAVEHDR)dwParam1)->dwBufferLength, pf); } if (inputSound->isStop != TRUE) { // memset(((LPWAVEHDR)dwParam1)->lpData, 0, bufLength); ((LPWAVEHDR)dwParam1)->dwBytesRecorded = 0; waveInAddBuffer(hwavein, (PWAVEHDR)dwParam1, sizeof(WAVEHDR)); // } fclose(pf); break; case WIM_CLOSE: // printf("
"
); break; default: break; } return 0; }

5、録音を止める
void InputSound::stopRocording()
{
	try
	{
		isStop = TRUE;
		//    
		waveInStop(hWaveIn);
		waveInReset(hWaveIn);

		//     
		waveInUnprepareHeader(hWaveIn, &whdr[0], sizeof(WAVEHDR));
		waveInUnprepareHeader(hWaveIn, &whdr[1], sizeof(WAVEHDR));
		
		printf("    
"
); // waveInClose(hWaveIn); } catch (...) { printf("
"
); } return; }

再生
1、ここで初期化するとき、dwUserという変数を1つのデータが再生されたかどうかのマークにします.getAudioDevices()、setWaveFormat()の2つの関数は、録音中の処理と似ています.
if (getAudioDevices())
	{
		//      
		setWaveFormat(&waveForm, 2, 44100, 16);

		for (int i = 0; i < 2; ++i)
		{
			whdr[i].lpData = (CHAR*)malloc(bufLength);
			memset(whdr[i].lpData, 0, bufLength);
			whdr[i].dwBufferLength = bufLength;	//     
			whdr[i].dwBytesRecorded = 0;		//      ,           
			whdr[i].dwUser = 0;				//       ,0     ,1     
			whdr[i].dwFlags = 0;				//   
			whdr[i].dwLoops = 0;				//   
			whdr[i].lpNext = NULL;				//   
			whdr[i].reserved = 0;				//   
		}
	}

2、放送開始
void OutputSound::startPlaying()
{
	try
	{
		MMRESULT mmResult = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveForm, (DWORD)waveOutProc, (DWORD)this, CALLBACK_FUNCTION);
		if (mmResult != MMSYSERR_NOERROR)
		{
			printf("      
"
); return; } FILE *pf; fopen_s(&pf, "./RecordSounds.pcm", "rb"); while (true) { for (int i = 0; i < 2; ++i) { if (whdr[i].dwUser != 1) // , { char buf[bufLength] = { 0 }; //whdr[i].dwBufferLength = fread(&buf, sizeof(char), bufLength, pf); fread(&buf, bufLength, 1, pf); memcpy(whdr[i].lpData, &buf, bufLength); whdr[i].dwUser = 1; waveOutPrepareHeader(hWaveOut, &whdr[i], sizeof(WAVEHDR));// waveOutWrite(hWaveOut, &whdr[i], sizeof(WAVEHDR)); // } } if (feof(pf)) { printf("
"
); Sleep(1000); waveOutClose(hWaveOut); break; } } fclose(pf); } catch (...) { printf("
"
); } return; }

3、コールバック処理
DWORD CALLBACK OutputSound::waveOutProc(HWAVEOUT hwaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
	LPWAVEHDR phdr = (LPWAVEHDR)dwParam1;
	switch (uMsg)
	{
	case WOM_OPEN:
		printf("      
"
); break; case WOM_DONE: // , phdr->dwUser = 0; break; case WOM_CLOSE: printf("
"
); break; default: break; } return 0; }

プロジェクトのダウンロード先:https://download.csdn.net/download/zeroling96/11939315