Windowsで録音 再生

メモメモ。 音声を録音して再生するだけのプログラムです

MMSystem.h だけだと 動かないけど、Windows.hで、 うごく。。。不思議
Windowsマルチメディア系のAPIはここに書いてありました msdn WIN32API

参考にしたサイト一覧
WAVEデータの作成と再生
WAVE
WAVEファイルにリアルタイムで加工を施し再生する

リアルタイムに音声を録音し続けたいなら、コールバック関数を利用して、複数のバファを切り替えながら、waveInAddBuffer でおk。
録音と再生のレイテンシを小さくしたいなら、バッファの大きさを小さくすればok?
どちらにせよ、再生中のポインタと録音中のポインタの距離が近いほどレイテンシは抑えられそう。

ポインタが重なったりしたら、えらい雑音が入りそうだな@@

#include <Windows.h>
//#include <MMSystem.h>
//#pragma comment (lib, "winmm.lib")

#include <iostream>
using namespace std;

// waveInOpenが利用するコールバック関数
void CALLBACK waveInProc(
	HWAVEIN hwi,      
	UINT uMsg,        
	DWORD dwInstance, 
	DWORD dwParam1,   
	DWORD dwParam2    
	)
{
	switch(uMsg)
	{
	case WIM_OPEN:
		cout << "waveInOpen" << endl;
		break;
	case WIM_CLOSE:
		cout << "waveInClose" << endl;
		break;
	case WIM_DATA:
		cout << "バッファがいっぱいになりました" << endl;
		break;
	}
}

// waveOutOpenが利用するコールバック関数
void CALLBACK waveOutProc(
	HWAVEOUT hwo,
	UINT uMsg,        
	DWORD dwInstance, 
	DWORD dwParam1,   
	DWORD dwParam2    
	)
{
	switch(uMsg)
	{
	case WOM_OPEN:
		cout << "waveOutOpen" << endl;
		break;
	case WOM_CLOSE:
		cout << "waveOutClose" << endl;
		break;
	case WOM_DONE:
		cout << "バッファをすべて再生しました" << endl;
		break;
	}
}

int main()
{
	/*******************************************************************************
		録音
	********************************************************************************/
	HWAVEIN      hwi = NULL;				// WAVEハンドル
	LPBYTE       lpWaveData = NULL;			// バッファ本体のポインタ[ヒープ領域]
	WAVEFORMATEX wf = {0};					// デバイスオープン時に使う、設定構造体
	WAVEHDR      wh = {0};					// デバイスに与えるバッファの設定構造体

	// デバイスオープン時の設定
	wf.wFormatTag      = WAVE_FORMAT_PCM;	// PCM形式
	wf.nChannels       = 1;					// ステレオかモノラルか
	wf.nSamplesPerSec  = 22050;				// サンプリングレート 22.05KHz
	wf.wBitsPerSample  = 8;					// 量子化レベル
	wf.nBlockAlign     = wf.wBitsPerSample * wf.nChannels / 8;	// バイトあたりのビット数[PCMの仕様]
	wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;	// 1 秒あたりのバイト数
	// モノラル+サンプル22050+量子化8bitなので 一秒間に22050byteのデータが発生する
	// サンプル x nBlockAlign = 一秒間のデータ量なので nBlockAlignは1

	// デバイスオープン
	if(waveInOpen(
		&hwi,				// ハンドル
		WAVE_MAPPER,		// デバイスID。 WAVE_MAPPERデフォルトのデバイスを指定
		&wf,				// オープン時の設定
		(DWORD)waveInProc,	// コールバック関数
		0,					// しらん
		CALLBACK_FUNCTION	// コールバック関数の属性
		) != MMSYSERR_NOERROR)
		cout << "デバイスのオープンに失敗しました" << endl;

	DWORD dwRecordSecond = 10;		// 10秒
	DWORD dwDataSize;

	dwDataSize = wf.nAvgBytesPerSec * dwRecordSecond;	// 一秒間のデータ量 x 秒数
	lpWaveData = (LPBYTE)new BYTE[dwDataSize];

	// バッファ情報セット
	wh.lpData         = (LPSTR)lpWaveData;
	wh.dwBufferLength = dwDataSize;
	wh.dwFlags        = 0;

	// バッファの初期化
	waveInPrepareHeader(hwi, &wh, sizeof(WAVEHDR));

	// バッファの関連付け
	waveInAddBuffer(hwi, &wh, sizeof(WAVEHDR));

	// 録音開始
	waveInStart(hwi);

	rewind(stdin);
	getchar(); // 10秒待機すると、 "バッファがいっぱいになった" が表示されるはず

	// 録音終了
	waveInReset(hwi);
	waveInUnprepareHeader(hwi, &wh, sizeof(WAVEHDR));
	waveInClose(hwi);


	/*******************************************************************************
		再生
	********************************************************************************/
	
	HWAVEOUT hwo;	// ハンドル
	WAVEHDR whdr;		// 

	// デバイスを開く
	if(waveOutOpen(
		&hwo,			// ハンドル
		WAVE_MAPPER,		// デフォルトのデバイスを指定
		&wf,				// waveInOpenのとおなじでおk
		(DWORD)waveOutProc,	// コールバック関数
		0,					// しらん
		CALLBACK_FUNCTION	// コールバック関数の属性
		)
		!= MMSYSERR_NOERROR )
		cout << "Erroe" << endl;


	// 音声ファイルのパラメータを設定
	whdr.lpData =			(LPSTR)lpWaveData;			// 音声データの入ってるポインタ
	whdr.dwBufferLength =	dwDataSize;						// 音声データのサイズ
	whdr.dwFlags =			WHDR_BEGINLOOP | WHDR_ENDLOOP;	// 再生オプション
	whdr.dwLoops =			1;								// ループ回数

	// 初期化
	waveOutPrepareHeader(hwo,&whdr,sizeof(WAVEHDR));

	// 音声データブロックの書き込み
	waveOutWrite(hwo,&whdr,whdr.dwBufferLength);

	rewind(stdin);
	getchar();	// 再生中待機

	waveOutReset(hwo);
	waveOutUnprepareHeader(hwo, &whdr, sizeof(whdr));
	waveOutClose(hwo);
}

投稿者:

「Windowsで録音 再生」への26件のフィードバック

  1. Hey all, simply turned into alert to your site through Engines like google, and located it is really academic. We all?michael planning to look out for belgium’s capital. I am going to appreciate if you carry on this later on. Plenty of other folks will be benefited from your own creating. Many thanks!

  2. hey there and thank you to your info – I have definitely picked up anything new from right here. I did on the other hand experience several technical points the use of this website, since I experienced to reload the site many instances previous to I could get it to load correctly. I were thinking about if your web host is OK?

  3. From all the blogs I’ve be familiar with lately, this undivided seems to be the most evocative – it gave me something to think about.

  4. I’d come to okay with you here. Which is not something I typically do! I enjoy reading a post that will make people think. Also, thanks for allowing me to speak my mind!

  5. I found your blog on google and read a few of your other posts. I just added you to my Google News Reader. Keep up the good work Look forward to reading more from you in the future.

  6. i was starting to imagine i would probably end up being the sole man who cared about this, at the least now i find out im not insane 🙂 i’ll make sure to pay a visit to a few several other threads right after i get some caffeine in me, cheers 🙂

  7. My partner and I really enjoyed reading this blog post, I was just itching to know do you trade featured posts? I am always trying to find someone to make trades with and merely thought I would ask.

コメントを残す

メールアドレスが公開されることはありません。