ステレオ


チャンネルごとに異なる音声

これまでは、常にひとつのチャンネルに対して音声の入出力を行いました
つまり、「1 サンプル=振幅ビット数」という関係のモノラル音声です
スピーカーがいくつあっても、全てのスピーカーから同じ音声が出力されます

ところが、通常 PC の音声はステレオをサポートしています
ステレオは、2 つの音声出力先を持っているということになります
これを利用すれば、左右のスピーカーに、同時に異なる音声を出力することができます

それこそ、低レベル API を使いこなすことができれば
異なるモノラル音声ファイルを左右のスピーカーに分け、同時に再生するなんてこともできます

瞬間に出力するデバイスが 2 つになるということは、単純に記憶容量も倍になります
つまり、1 サンプルに使う記憶領域が倍になると考えれば良いのです
例えば、8 ビット振幅の場合は 1 サンプルに 16 ビット必要ということになります
この場合 下位 8 ビットに左、上位 8 ビットに右の音声が入ります
16 ビット振幅ならば、下位 16 ビットに左、上位 16 ビットに右の音声が入るということです

この性質を上手く利用することで、プログラムで機械的に生成した音声でも
左から右に流れるような音や、左右交互に音を鳴らすという事ができます
ゲームなど、臨場感や演出が問われるプログラムでは、こういったことも重要です
#include <windows.h>
#define TITLE 	TEXT("Kitty on your lap")
#define SRATE 	11025

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	static HWAVEOUT hWave;
	static BYTE *bWave;
	DWORD dwCount , dwWaveL = 0 , dwWaveR = 0;
	WAVEFORMATEX wfe;
	WAVEHDR whdr;

	switch (msg) {
	case WM_DESTROY:
		waveOutReset(hWave);
		waveOutUnprepareHeader(hWave , &whdr , sizeof(WAVEHDR));
		free(bWave);
		waveOutClose(hWave);
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		bWave = malloc(SRATE * 2);

		for (dwCount = 0 ; dwCount < SRATE * 2 ; dwCount++) {
			if (dwWaveL > 256) dwWaveL = 0;
			*(bWave + dwCount++) = dwWaveL;
			dwWaveL += 10;

			if (dwWaveR > 256) dwWaveR = 0;
			*(bWave + dwCount) = dwWaveR;
			dwWaveR += 20;
		}	
		wfe.wFormatTag = WAVE_FORMAT_PCM;
		wfe.nChannels = 2;
		wfe.nSamplesPerSec = SRATE;
		wfe.nAvgBytesPerSec = SRATE;
		wfe.wBitsPerSample = 8;
		wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8;

		waveOutOpen(&hWave ,
			WAVE_MAPPER , &wfe , 0 , 0 , CALLBACK_NULL);

		whdr.lpData = bWave;
		whdr.dwBufferLength = SRATE * 2;
		whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
		whdr.dwLoops = 5;
		waveOutPrepareHeader(hWave , &whdr , sizeof(WAVEHDR));
		waveOutWrite(hWave , &whdr , sizeof(WAVEHDR));
		return 0;
	}
	return DefWindowProc(hWnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow) {
	HWND hWnd;
	MSG msg;
	WNDCLASS winc;

	winc.style 		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra		= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= TEXT("KITTY");
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return 1;

	hWnd = CreateWindow(
		TEXT("KITTY") , TITLE ,
		WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
		CW_USEDEFAULT , CW_USEDEFAULT ,
		CW_USEDEFAULT , CW_USEDEFAULT ,
		NULL , NULL , hInstance , NULL
	);

	if (hWnd == NULL) return 1;

	while (GetMessage(&msg , NULL , 0 , 0 )) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}
このプログラムを実行すると、左のスピーカに低いノコギリ波を
右のスピーカに左の音をオクターブ上げた高い音を 5 秒間だけ出力します
双方とも 440 Hz よりもやや低い音になっています
スピーカの左右のバランスを調節して、片方だけ鳴らすようにすればよく聞こえます



前のページへ戻る次のページへ