�����̓���


���̓f�o�C�X����^������

�჌�x�� API ��p���邱�ƂŁA���̓f�o�C�X����A���ڃo�b�t�@�ɉ�������͂ł��܂�
�J���҂��猩��΁A�u�^���v�Ƃ��������A�u���́v�Ƃ������t���K�؂ł��傤

�����̓��͂��A�o�͂Ƃ����͊�{�I�ɓ����ł�
���̓f�o�C�X�́A���蓖�Ă�ꂽ�o�b�t�@�������������L�^��
�o�b�t�@����t�ɂȂ�΁A���b�Z�[�W���g���ăA�v���P�[�V�����Ƀo�b�t�@��Ԃ��܂�

�������̓f�o�C�X�̑�\�́A�}�C�N���͂ł��傤
���̑��ł��A�������̓f�o�C�X�ł���΁A���̏�͉��ł����܂��܂���

�����o�͓��l�ɁA�ŏ��� waveInOpen() �֐����g���܂�
���̊֐��́A�E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����擾���܂�
MMRESULT waveInOpen(
  LPHWAVEIN phwi , UINT uDeviceID ,
  LPWAVEFORMATEX pwfx ,
  DWORD dwCallback , DWORD dwCallbackInstance ,
  DWORD fdwOpen
);
phwi �� HWAVEIN �^�́A�f�o�C�X���ʗp�n���h���ւ̃|�C���^���w�肵�܂�
����́A�E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h���ł�
�Ȍ�A�������͊֐��ɑ΂��ẮA���̃n���h����p���ďo�̓f�o�C�X���w�肵�܂�

uDeviceID �ɂ́A�Ώۂ̓��̓f�o�C�X�̎��ʎq���w�肵�܂�
WAVE_MAPPER ���w�肷��΁A���[�U�[���I�����Ă���D��f�o�C�X���K������܂�
pwfx �ɂ́AWAVEFORMATEX �\���̂ւ̃|�C���^���w�肵�܂�

dwCallback �́A�֘A���b�Z�[�W���󂯎��Ώۂ��w�肵�܂�
dwCallbackInstance �ɂ́A�R�[���o�b�N�֐��ɓn���f�[�^���w��ł��܂�
fdwOpen �́A�f�o�C�X���J�����߂̃t���O���w�肵�܂�
���̈����ɂ́A�ȉ��̒l�̂����ꂩ�A�܂��͑g�ݍ��킹���w��ł��܂�

�萔���
CALLBACK_EVENT dwCallback �̓C�x���g�n���h���ł���
CALLBACK_FUNCTION dwCallback �̓R�[���o�b�N�֐��̃|�C���^�ł���
CALLBACK_NULL �R�[���o�b�N�͎g�p���Ȃ�
CALLBACK_THREAD dwCallback �̓X���b�h�n���h���ł���
CALLBACK_WINDOW dwCallback �̓E�B���h�E�n���h���ł���
WAVE_FORMAT_DIRECT ���̃t���O���w�肳��Ă����
ACM �h���C�o�͉����f�[�^��]�����Ȃ�
WAVE_FORMAT_QUERY ���̃t���O���w�肳��Ă����
�֐��̓f�o�C�X�ɁA�w��t�H�[�}�b�g���T�|�[�g���Ă��邩���߂�
�������A���ۂɃf�o�C�X�̓I�[�v������Ȃ�
WAVE_MAPPED ���̃t���O���w�肳��Ă����
uDeviceID �́A�E�F�[�u�}���p�ɂ���ă}�b�v�����
�E�F�[�u�t�H�[���I�[�f�B�I�f�o�C�X���w�肷��

�֐������������ MMSYSERR_NOERROR ���A�����łȂ���΃G���[�l���Ԃ�܂�
�G���[�����������ꍇ�A���̂����ꂩ�̒l��������܂�

�萔���
MMSYSERR_ALLOCATED ���\�[�X�́A���łɊ��蓖�Ă��Ă���
MMSYSERR_BADDEVICEID �f�o�C�X���ʎq�������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�
WAVERR_BADFORMAT �f�o�C�X�h���C�o�́A�w�肳�ꂽ�t�H�[�}�b�g���T�|�[�g���Ă��Ȃ�

���̊֐��̈����́AwaveOutOpen() �֐��Ƃ܂����������ł�
�P���ɁA�Ώۂ����̓f�o�C�X���o�̓f�o�C�X���̈Ⴂ��������܂���

���ɁA���̓o�b�t�@����������K�v������܂�
����ɂ� waveInPrepareHeader() �֐����g�p���܂�
MMRESULT waveInPrepareHeader(
	HWAVEIN hwi , LPWAVEHDR pwh , UINT cbwh
);
hwi �ɂ̓E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
pwh �́AWAVEHDR �\���̂ւ̃|�C���^�ł�
cbwh �ɂ́AWAVEHDR �\���̂̃T�C�Y���w�肵�܂�

�֐������������ MMSYSERR_NOERROR ���A�����łȂ���΃G���[�l���Ԃ�܂�
���̊֐����Ԃ��G���[�l�́A�ȉ��̂����ꂩ�̒萔�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�

���ɁA�A�v���P�[�V�����͓��̓f�o�C�X�ɑ΂��ď����ς݃o�b�t�@��񋟂��܂�
�o�b�t�@��ݒ肷��ɂ� waveInAddBuffer() �֐���p���܂�
���̊֐��́A�f�o�C�X���Ǘ�����L���[�Ƀo�b�t�@��lj����܂�
MMRESULT waveInAddBuffer(
	HWAVEIN hwi , LPWAVEHDR pwh , UINT cbwh
);
hwi �ɂ̓E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
pwh �́A�����ς݃o�b�t�@��\�� WAVEHDR �\���̂ւ̃|�C���^���w�肵�܂�
cbwh �ɂ́AWAVEHDR �\���̂̃T�C�Y���w�肵�܂�

�֐������������ MMSYSERR_NOERROR ���A�����łȂ���΃G���[�l���Ԃ�܂�
���̊֐����Ԃ��G���[�l�́A�ȉ��̂����ꂩ�̒萔�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�
WAVERR_UNPREPARED �o�b�t�@����������Ă��Ȃ�

���̓f�o�C�X�́A�L���[�Ɏw�肳�ꂽ�o�b�t�@�����蓖�Ă܂�
�����̓��͂́A���̃L���[�̃o�b�t�@�ɑ΂� FIFO ���ōs���܂�
�����̊֐����g���āA�f�o�C�X�ƃo�b�t�@�̏�����������
���Ƃ́AwaveInStart() �֐��Ńo�b�t�@�ւ̕ۑ����J�n���܂�

MMRESULT waveInStart(HWAVEIN hwi);

hwi �ɂ́A �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
�֐������������ MMSYSERR_NOERROR ���A�����łȂ���΃G���[�l���Ԃ�܂�
���̊֐����Ԃ��G���[�l�́A�ȉ��̂����ꂩ�̒萔�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�

waveInStart() �֐����Ăяo�����ƁA�L���[�̃o�b�t�@�ɑ΂��ĉ��������͂���
�o�b�t�@�����t�ɂȂ�΁A���b�Z�[�W�ŃA�v���P�[�V�����ɕԂ���܂�
�����āA���̃o�b�t�@���f�L���[����A���������͂����Ƃ����d�g�݂ɂȂ��Ă��܂�

�o�b�t�@�ւ̓��͂𒆒f����ꍇ�� waveInStop() �֐����g���܂�
������Ăяo���΁A�f�o�C�X�͋�̃o�b�t�@���L���[���c���ē��͂��~���܂�

MMRESULT waveInStop(HWAVEIN hwi);

hwi �ɂ́A �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
�֐������������ MMSYSERR_NOERROR ���A�����łȂ���΃G���[�l���Ԃ�܂�
���̊֐����Ԃ��G���[�l�́A�ȉ��̂����ꂩ�̒萔�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�

�E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X���J���� MM_WIM_OPEN ���A
�‚������ MM_WIM_CLOSE ���b�Z�[�W���R�[���o�b�N��ɑ��M����܂�
WPARAM �ɂ͓��̓f�o�C�X�̃n���h�����ALPARAM �ɂ� 0 ���i�[����Ă��܂�

���͂ɑ΂��ăo�b�t�@����t�ɂȂ邩�A���͂���~������
MM_WIM_DATA ���b�Z�[�W�����M����܂�
WPARAM �ɂ͕ۑ����s�������̓f�o�C�X�̃n���h����
LPARAM �ɂ́A�Ԃ��ꂽ�o�b�t�@��\�� WAVEHDR �\���̂ւ̃|�C���^���i�[����Ă��܂�
���ꂼ��̃��b�Z�[�W�ŁA�߂�l�͒�`����Ă��܂���

MM_WIM_DATA ����������΁A���t�ɂȂ����o�b�t�@���Ƃ̏������s���܂�
�����̃o�b�t�@�ɕ����ē��͂��s�����ɁA�d�v�ȃ��b�Z�[�W�ɂȂ�ł��傤

���͏������I������΁AwaveInUnprepareHeader() �֐���p��
���͗p�ɏ����ς݂̃o�b�t�@������ł���悤�ɁA�������I�������܂�
MMRESULT waveInUnprepareHeader(
	HWAVEIN hwi , LPWAVEHDR pwh , UINT cbwh
);
hwi �ɂ̓E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
pwh �́AWAVEHDR �\���̂ւ̃|�C���^�ł�
cbwh �ɂ́AWAVEHDR �\���̂̃T�C�Y���w�肵�܂�

�֐������������ MMSYSERR_NOERROR ���A�����łȂ���΃G���[�l���Ԃ�܂�
���̊֐����Ԃ��G���[�l�́A�ȉ��̂����ꂩ�̒萔�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�
WAVERR_STILLPLAYING �L���[���Ƀo�b�t�@���܂��c���Ă���

�E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����s�p�ɂȂ��
waveInClose() �֐��Ńf�o�C�X��������Ȃ���΂Ȃ�܂���

MMRESULT waveInClose(HWAVEIN hwi);

hwi �ɂ̓E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
�֐������������ MMSYSERR_NOERROR ���A�����łȂ���΃G���[�l���Ԃ�܂�
���̊֐����Ԃ��G���[�l�́A�ȉ��̂����ꂩ�̒萔�ɂȂ�܂�

�萔���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�
WAVERR_STILLPLAYING �L���[���Ƀo�b�t�@���܂��c���Ă���

�����̊֐����g���΁A���̓f�o�C�X���特����^�����郌�R�[�_�[�����܂�
������A���͂��ꂽ�������ő�� 1/44100 �b�Ƃ����P�ʂŐ���ł���̂ł�����
���̂悤�ȍׂ��������̐���́A�჌�x�� API �̂��΂炵�������b�g�ł�
//resource.h
#define IDB_REC 0x100
#define IDB_PLAY 0x101
//���\�[�X�X�N���v�g
#include "resource.h"

KITTY DIALOG 10 , 10 , 100 , 20
FONT 12 , "MS Serif"
STYLE WS_VISIBLE | WS_POPUPWINDOW
CLASS "KITTY"
CAPTION "Kitty on your lap" {
	PUSHBUTTON "Recourd" , IDB_REC , 5 , 5 , 40 , 10
	PUSHBUTTON "Play" , IDB_PLAY, 50 , 5 , 40 , 10
}
#include <windows.h>
#include "resource.h"
#define TITLE 	TEXT("Kitty on your lap")
#define SRATE 	11025

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	static WAVEFORMATEX wfe;
	static HWAVEOUT hWaveOut;
	static HWAVEIN hWaveIn;
	static BYTE *bWave;
	static WAVEHDR whdr;

	switch (msg) {
	case WM_DESTROY:
		free(bWave);
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		bWave = malloc(SRATE * 5);

		wfe.wFormatTag = WAVE_FORMAT_PCM;
		wfe.nChannels = 1;
		wfe.nSamplesPerSec = SRATE;
		wfe.nAvgBytesPerSec = SRATE;
		wfe.wBitsPerSample = 8;
		wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8;

		whdr.lpData = bWave;
		whdr.dwBufferLength = SRATE * 5;
		whdr.dwLoops = 1;
		return 0;
	case WM_COMMAND:
		switch(LOWORD(wp)) {
		case IDB_REC:
			waveInOpen(&hWaveIn , WAVE_MAPPER , &wfe ,
				(DWORD)hWnd , 0 , CALLBACK_WINDOW);
			waveInPrepareHeader(hWaveIn , &whdr , sizeof(WAVEHDR));
			break;
		case IDB_PLAY:
			waveOutOpen(&hWaveOut , WAVE_MAPPER , &wfe ,
				(DWORD)hWnd , 0 , CALLBACK_WINDOW);
			waveOutPrepareHeader(hWaveOut , &whdr , sizeof(WAVEHDR));
			break;
		}
		return 0;
	case MM_WIM_OPEN:
		EnableWindow(GetDlgItem(hWnd , IDB_PLAY) , FALSE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC) , FALSE);
		waveInAddBuffer(hWaveIn , &whdr , sizeof(WAVEHDR));
		waveInStart(hWaveIn);
		return 0;
	case MM_WIM_DATA:
		waveInStop(hWaveIn);
		waveInClose(hWaveIn);
		EnableWindow(GetDlgItem(hWnd , IDB_PLAY) , TRUE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC) , TRUE);
		return 0;
	case MM_WIM_CLOSE:
		waveInUnprepareHeader(hWaveIn , &whdr , sizeof(WAVEHDR));
		return 0;
	case MM_WOM_OPEN:
		EnableWindow(GetDlgItem(hWnd , IDB_PLAY) , FALSE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC) , FALSE);
		waveOutWrite(hWaveOut , &whdr , sizeof(WAVEHDR));
		return 0;
	case MM_WOM_DONE:
		waveOutClose(hWaveOut);
		EnableWindow(GetDlgItem(hWnd , IDB_PLAY) , TRUE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC) , TRUE);
		return 0;
	case MM_WOM_CLOSE:
		waveOutUnprepareHeader(hWaveOut , &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		= 0;
	winc.cbWndExtra		= DLGWINDOWEXTRA;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)CreateSolidBrush(GetSysColor(COLOR_MENU));
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

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

	hwnd = CreateDialog(hInstance , TEXT("KITTY") , 0 , NULL);

	if (hwnd == NULL) return -1;

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


���̃v���O���������s����ƁA��̂悤�ȃ_�C�A���O�E�B���h�E���o�����܂�
Record �{�^���������Θ^���APlay �{�^���������΍Đ����n�܂�܂�

�o�b�t�@�́A�T���v�����O���[�g �~ 5 �Ƃ����T�C�Y�ɐݒ肵�Ă���܂�
����́A���Ȃ킿���m���������� 5 �b�ԕ��̃o�b�t�@�T�C�Y�Ƃ������Ƃ��Ӗ����Ă��܂�
Record �{�^���������΁A���̓f�o�C�X����5�b�Ԃ����A�o�b�t�@�ɉ����^������܂�
�o�b�t�@����t�ɂȂ�΁A�f�o�C�X�� MM_WIM_DATA �𑗐M���Ă���̂�
������������Ę^�����I�����A�o�b�t�@�̏����������čĐ��Ȃǂɔ����܂�

�������A���̃v���O�����͊ȒP�ɕ\�����邽�߂ɁA��؂̃G���[�������ȗ����Ă��܂�
�Đ��A�^�����ɃA�v���P�[�V�������I���������肵�Ȃ��ʼn�����
�f�o�C�X�A�o�b�t�@�Ȃǂ̉����ߒ��𖳎����ċ����I�ɏI�������邱�ƂɂȂ�܂�

��̃v���O�����̏ꍇ�A�^�����Ԃ���Ɉ��Ō����Ă��܂���
���H�A�v���P�[�V�����̏ꍇ�́A������񂱂̂悤�Ȕ��e���ȃv���O�����ł͂����܂���
���[�U�[���A�R���s���[�^�̗e�ʂ���������A�D���Ȏ��Ԃ����^���ł���ׂ��ł��傤

���I�ɘ^�����Ԃ�ω�������ꍇ�AMM_WIM_DATA ���b�Z�[�W��������
����I�ɓ��̓f�o�C�X���Ԃ����o�b�t�@���A���̃o�b�t�@�ɃR�s�[���邱�ƂŎ������܂�
�R�s�[��̃o�b�t�@�𓮓I�Ɋm�ۂ���΁A���R�Ȏ��Ԃ����^�����邱�Ƃ��ł��܂�
�ۑ��o�b�t�@�Ƀf�[�^���R�s�[���A�Ăѓ��͗p�̃o�b�t�@���f�o�C�X�ɓn���܂�

�������AMM_WIM_DATA ���������鎞�Ԃ́A�o�b�t�@�ɘ^�����s���Ȃ�����
�P��̃o�b�t�@�ł�����s�����������^���ł��܂���
���̂��߁A�L���[��2�ˆȏ�̃o�b�t�@���C���L���[���A���݂ɉ�������͂���
�f�L���[���ꂽ�o�b�t�@���A�ۑ��p�o�b�t�@�ɃR�s�[����Ƃ������������܂�
�R�s�[���I������΁A�Ăуo�b�t�@���C���L���[���邱�ƂŎg���܂킷���Ƃ��ł��܂�

�^���𖾎��I�ɏI��������ɂ� waveInReset() �֐����g���܂�
���̊֐����Ăяo�����ƁAMM_WIM_DATA ���b�Z�[�W�����s����܂�
����ƁA�ÓI�Ȕ���p�ϐ���p����΁A�C�x���g�ɂ���Ę^���𒆒f�ł��܂�

MMRESULT waveInReset(HWAVEIN hwi);

hwi �ɂ́A �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
�֐������������ MMSYSERR_NOERROR ���A�����łȂ���΃G���[�l���Ԃ�܂�
���̊֐����Ԃ��G���[�l�́A�ȉ��̂����ꂩ�̒萔�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�

�������APCM �͔񈳏k�`���̂��߁A�Z�����Ԃő�ʂ̏��ʂ�����܂�
�����Ԃ̘^���ɑΉ�����ɂ́A�}�V���ɕ��ׂ������Ȃ��悤�ɐS����
����I�Ƀ������o�b�t�@���f�B�X�N�ɑޔ�������Ȃǂ̍H�v���K�v�ɂȂ�܂�
//resource.h
#define IDB_REC 0x100
#define IDB_PLAY 0x101
#define IDB_REC_END 0x102
#define IDB_PLY_END 0x103
//���\�[�X�X�N���v�g
#include "resource.h"

KITTY DIALOG 10 , 10 , 100 , 40
FONT 12 , "MS Serif"
STYLE WS_VISIBLE | WS_POPUPWINDOW
CLASS "KITTY"
CAPTION "Kitty on your lap" {
	PUSHBUTTON "Record" , IDB_REC , 5 , 5 , 40 , 10
	PUSHBUTTON "End" , IDB_REC_END , 50 , 5 , 40 , 10 , WS_DISABLED

	PUSHBUTTON "Play" , IDB_PLAY, 5 , 20 , 40 , 10	
	PUSHBUTTON "End" , IDB_PLY_END , 50 , 20 , 40 , 10 , WS_DISABLED
}
#include <windows.h>
#include "resource.h"
#define TITLE 	TEXT("Kitty on your lap")
#define SRATE 	11025

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	static WAVEFORMATEX wfe;
	static HWAVEOUT hWaveOut;
	static HWAVEIN hWaveIn;
	static BYTE *bWave1 , *bWave2 , *bSave , *bTmp;
	static WAVEHDR whdr1 , whdr2;
	static dwLength = 0 , dwCount;
	static BOOL blReset = FALSE;

	switch (msg) {
	case WM_DESTROY:
		if (bSave) free(bSave);
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		wfe.wFormatTag = WAVE_FORMAT_PCM;
		wfe.nChannels = 1;
		wfe.nSamplesPerSec = SRATE;
		wfe.nAvgBytesPerSec = SRATE;
		wfe.wBitsPerSample = 8;
		wfe.nBlockAlign = 1;
		wfe.cbSize = 0;
		return 0;
	case WM_COMMAND:
		switch(LOWORD(wp)) {
		case IDB_REC:
			bWave1 = malloc(SRATE);
			bWave2 = malloc(SRATE);

			whdr1.lpData = bWave1;
			whdr1.dwBufferLength = SRATE;
			whdr1.dwBytesRecorded = 0;
			whdr1.dwFlags = 0;
			whdr1.dwLoops = 1;
			whdr1.lpNext = NULL;
			whdr1.dwUser = 0;
			whdr1.reserved = 0;

			whdr2.lpData = bWave2;
			whdr2.dwBufferLength = SRATE;
			whdr2.dwBytesRecorded = 0;
			whdr2.dwFlags = 0;
			whdr2.dwLoops = 1;
			whdr2.lpNext = NULL;
			whdr2.dwUser = 0;
			whdr2.reserved = 0;

			waveInOpen(&hWaveIn , WAVE_MAPPER , &wfe ,
				(DWORD)hWnd , 0 , CALLBACK_WINDOW);
			waveInPrepareHeader(hWaveIn , &whdr1 , sizeof(WAVEHDR));
			waveInPrepareHeader(hWaveIn , &whdr2 , sizeof(WAVEHDR));
			break;
		case IDB_PLAY:
			whdr1.lpData = bSave;
			whdr1.dwBufferLength = dwLength;
			whdr1.dwBytesRecorded = 0;
			whdr1.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
			whdr1.dwLoops = 1;
			whdr1.lpNext = NULL;
			whdr1.dwUser = 0;
			whdr1.reserved = 0;

			waveOutOpen(&hWaveOut , WAVE_MAPPER , &wfe ,
				(DWORD)hWnd , 0 , CALLBACK_WINDOW);
			waveOutPrepareHeader(
				hWaveOut , &whdr1 , sizeof(WAVEHDR));
			waveOutWrite(hWaveOut , &whdr1 , sizeof(WAVEHDR));
			break;
		case IDB_REC_END:
			blReset = TRUE;
			waveInReset(hWaveIn);
			break;
		case IDB_PLY_END:
			waveOutReset(hWaveOut);
			break;
		}
		return 0;
	case MM_WIM_OPEN:
		dwLength = 0;
		bSave = realloc(bSave , 1);

		EnableWindow(GetDlgItem(hWnd , IDB_PLAY) , FALSE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC) , FALSE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC_END) , TRUE);
		waveInAddBuffer(hWaveIn , &whdr1 , sizeof(WAVEHDR));
		waveInAddBuffer(hWaveIn , &whdr2 , sizeof(WAVEHDR));
		waveInStart(hWaveIn);
		return 0;
	case MM_WIM_DATA:
		bTmp = realloc(bSave ,
			dwLength + ((PWAVEHDR)lp)->dwBytesRecorded);
		if (blReset || !bTmp) {
			waveInClose(hWaveIn);
			blReset = FALSE;
			return 0;
		}

		bSave = bTmp;
		for (dwCount = 0 ; dwCount < ((PWAVEHDR)lp)->dwBytesRecorded ; dwCount++)
			*(bSave + dwLength + dwCount) = *(((PWAVEHDR)lp)->lpData + dwCount);
		dwLength += ((PWAVEHDR)lp)->dwBytesRecorded;
		waveInAddBuffer(hWaveIn , (PWAVEHDR)lp , sizeof(WAVEHDR));
		return 0;
	case MM_WIM_CLOSE:
		waveInUnprepareHeader(hWaveIn , &whdr1 , sizeof(WAVEHDR));
		waveInUnprepareHeader(hWaveIn , &whdr2 , sizeof(WAVEHDR));
		free(bWave1);
		free(bWave2);
		
		EnableWindow(GetDlgItem(hWnd , IDB_PLAY) , TRUE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC) , TRUE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC_END) , FALSE);
		return 0;
	case MM_WOM_OPEN:
		EnableWindow(GetDlgItem(hWnd , IDB_PLAY) , FALSE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC) , FALSE);
		EnableWindow(GetDlgItem(hWnd , IDB_PLY_END) , TRUE);
		return 0;
	case MM_WOM_DONE:
		waveOutClose(hWaveOut);
		return 0;
	case MM_WOM_CLOSE:
		waveOutUnprepareHeader(hWaveOut , &whdr1 , sizeof(WAVEHDR));
		EnableWindow(GetDlgItem(hWnd , IDB_PLAY) , TRUE);
		EnableWindow(GetDlgItem(hWnd , IDB_REC) , TRUE);
		EnableWindow(GetDlgItem(hWnd , IDB_PLY_END) , FALSE);
		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		= 0;
	winc.cbWndExtra		= DLGWINDOWEXTRA;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= CreateSolidBrush(GetSysColor(COLOR_MENU));
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

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

	hwnd = CreateDialog(hInstance , TEXT("KITTY") , 0 , NULL);

	if (hwnd == NULL) return -1;

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


�v���O���������s���ARecord �{�^���������Θ^�����J�n����܂�
�^������ Record �� Play �{�^���������ƂȂ�A���� End ���L���ɂȂ�܂�
End �{�^���������΁A�^�������̎��_�ŏI�����܂�

�^�����������́APlay �{�^�����������ƂōĐ����邱�Ƃ��ł��܂�
Play �{�^���̉��� End �{�^���������΁A�Đ��𒆒f�ł��܂�
�G���[�`�F�b�N�����Ă��Ȃ����߁A�^�����Ă��Ȃ���Ԃ� Play �{�^���������Ȃ��ʼn�����
�{���Ȃ�΁A���o�̓f�o�C�X�̃I�[�v���̃G���[�`���b�N�Ȃǂ��s���ׂ��ł�

MM_WIM_DATA �������Ă���ƁA�L���[�̃J�����g�o�b�t�@�����t�ɂȂ����Ƃ������ƂȂ̂�
���̓f�o�C�X�͑ҋ@���̂����ЂƂ‚̃o�b�t�@�ɐ؂�ւ��Ę^���𑱂��܂�
���̊ԂɁAMM_WIM_DATA ���ŕۑ��p�o�b�t�@���g����
�g�����������ɘ^�������o�b�t�@���R�s�[���A�ĂуL���[�ɓ��͗p�o�b�t�@�����܂�
�������邱�Ƃɂ���āA�ŏ��̃������̈�Œ����Ԃ̘^���ɂ��Ή����邱�Ƃ��ł��܂�


waveInOpen()

MMRESULT waveInOpen(
  LPHWAVEIN phwi , UINT uDeviceID ,
  LPWAVEFORMATEX pwfx ,
  DWORD dwCallback , DWORD dwCallbackInstance ,
  DWORD fdwOpen
);
�E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X���J���܂�

phwi - HWAVEIN �^�́A�f�o�C�X���ʗp�n���h���ւ̃|�C���^���w�肵�܂�
uDeviceID - �Ώۂ̓��̓f�o�C�X�̎��ʎq���w�肵�܂�
pwfx - WAVEFORMATEX �\���̂ւ̃|�C���^���w�肵�܂�
dwCallback - �֘A���b�Z�[�W���󂯎��Ώۂ��w�肵�܂�
dwCallbackInstance - �R�[���o�b�N�֐��ɓn���f�[�^���w��ł��܂�
fdwOpen - �f�o�C�X���J�����߂̃t���O���w�肵�܂�

�߂�l - ��������� MMSYSERR_NOERROR�A�����łȂ���΃G���[�l

fdwOpen �ɂ͈ȉ��̂����ꂩ�̒l�A�܂��͑g�ݍ��킹���w�肵�܂�
WAVE_ �ɑg�݂��킹�邱�Ƃ��ł���̂� 1 �‚� CALLBACK_ �����ł�

�萔���
CALLBACK_EVENT dwCallback �̓C�x���g�n���h���ł���
CALLBACK_FUNCTION dwCallback �̓R�[���o�b�N�֐��̃|�C���^�ł���
CALLBACK_NULL �R�[���o�b�N�͎g�p���Ȃ�
CALLBACK_THREAD dwCallback �̓X���b�h�n���h���ł���
CALLBACK_WINDOW dwCallback �̓E�B���h�E�n���h���ł���
WAVE_ALLOWSYNC ���̃t���O���w�肳��Ă����
���������E�F�[�u�I�[�f�B�I���J�����Ƃ��ł���
�w�肳��Ă��Ȃ���΁A���s����
WAVE_FORMAT_DIRECT ���̃t���O���w�肳��Ă����
ACM �h���C�o�͉����f�[�^��]�����Ȃ�
WAVE_FORMAT_QUERY ���̃t���O���w�肳��Ă����
�֐��̓f�o�C�X�ɁA�w��t�H�[�}�b�g���T�|�[�g���Ă��邩���߂�
�������A���ۂɃf�o�C�X�̓I�[�v������Ȃ�
WAVE_MAPPED ���̃t���O���w�肳��Ă����
uDeviceID �́A�E�F�[�u�}���p�ɂ���ă}�b�v�����
�E�F�[�u�t�H�[���I�[�f�B�I�f�o�C�X���w�肷��

���̊֐����Ԃ��G���[�l�́A�ȉ��̒萔�̂����ꂩ�ɂȂ�܂�

�萔���
MMSYSERR_ALLOCATED ���\�[�X�́A���łɊ��蓖�Ă��Ă���
MMSYSERR_BADDEVICEID �f�o�C�X���ʎq�������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�
WAVERR_BADFORMAT �f�o�C�X�h���C�o�́A�w�肳�ꂽ�t�H�[�}�b�g���T�|�[�g���Ă��Ȃ�
WAVERR_SYNC �����f�o�C�X���w�肳�ꂽ��
WAVE_ALLOWSYNC �t���O���w�肳��Ă��Ȃ�

waveInPrepareHeader()

MMRESULT waveInPrepareHeader(
	HWAVEIN hwi , LPWAVEHDR pwh , UINT cbwh
);
���̓o�b�t�@�u���b�N���������܂�

hwi - �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
pwh - WAVEHDR �\���̂ւ̃|�C���^�ł�
cbwh - WAVEHDR �\���̂̃T�C�Y���w�肵�܂�

�߂�l - ��������� MMSYSERR_NOERROR�A�����łȂ���΃G���[�l

���̊֐����Ԃ��G���[�l�́A�ȉ��̒萔�̂����ꂩ�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�

waveInAddBuffer()

MMRESULT waveInAddBuffer(
	HWAVEIN hwi , LPWAVEHDR pwh , UINT cbwh
);
���̓f�o�C�X�̃o�b�t�@�L���[�ɏ����ς݃o�b�t�@�u���b�N��lj����܂�

hwi - �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
pwh - WAVEHDR �\���̂ւ̃|�C���^�ł�
cbwh - WAVEHDR �\���̂̃T�C�Y���w�肵�܂�

�߂�l - ��������� MMSYSERR_NOERROR�A�����łȂ���΃G���[�l

���̊֐����Ԃ��G���[�l�́A�ȉ��̒萔�̂����ꂩ�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�
WAVERR_UNPREPARED �o�b�t�@����������Ă��Ȃ�

waveInStart()

MMRESULT waveInStart(HWAVEIN hwi);

�f�o�C�X�̃L���[�̃o�b�t�@�ɉ����̓��͂��J�n���܂�

hwi - �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�

�߂�l - ��������� MMSYSERR_NOERROR�A�����łȂ���΃G���[�l

���̊֐����Ԃ��G���[�l�́A�ȉ��̒萔�̂����ꂩ�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�

waveInStop()

MMRESULT waveInStop(HWAVEIN hwi);

�f�o�C�X�̃L���[�̃o�b�t�@�ɉ����̓��͂��J�n���܂�

hwi - �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�

�߂�l - ��������� MMSYSERR_NOERROR�A�����łȂ���΃G���[�l

���̊֐����Ԃ��G���[�l�́A�ȉ��̒萔�̂����ꂩ�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�

waveInUnprepareHeader()

MMRESULT waveInUnprepareHeader(
	HWAVEIN hwi , LPWAVEHDR pwh , UINT cbwh
);
���͗p�ɏ������ꂽ�o�b�t�@�u���b�N�̏������I�����܂�

hwi - �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�
pwh - WAVEHDR �\���̂ւ̃|�C���^���w�肵�܂�
cbwh - WAVEHDR �\���̂̃T�C�Y���w�肵�܂�

�߂�l - ��������� MMSYSERR_NOERROR�A�����łȂ���΃G���[�l

���̊֐����Ԃ��G���[�l�́A�ȉ��̒萔�̂����ꂩ�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�
WAVERR_STILLPLAYING �L���[���Ƀo�b�t�@���܂��c���Ă���

waveInClose()

MMRESULT waveInClose(HWAVEIN hwi);

�E�F�[�u�t�H�[���I�[�f�B�I���̓o�b�t�@��������܂�

hwi - �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�

�߂�l - ��������� MMSYSERR_NOERROR�A�����łȂ���΃G���[�l

���̊֐����Ԃ��G���[�l�́A�ȉ��̒萔�̂����ꂩ�ɂȂ�܂�

�萔���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�
WAVERR_STILLPLAYING �L���[���Ƀo�b�t�@���܂��c���Ă���

waveInReset()

MMRESULT waveInReset(HWAVEIN hwi);

�E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X����̓��͂��~���܂�

hwi - �E�F�[�u�t�H�[���I�[�f�B�I���̓f�o�C�X�̃n���h�����w�肵�܂�

�߂�l - ��������� MMSYSERR_NOERROR�A�����łȂ���΃G���[�l

���̊֐����Ԃ��G���[�l�́A�ȉ��̒萔�̂����ꂩ�ɂȂ�܂�

�萔���
MMSYSERR_HANDLEBUSY �ʂ̃X���b�h���n���h�����g�p���ł���
MMSYSERR_INVALHANDLE �f�o�C�X�n���h���������ł���
MMSYSERR_NODRIVER �f�o�C�X�h���C�o���Ȃ�
MMSYSERR_NOMEM �����������蓖�Ă��Ȃ��A�܂��̓��b�N�ł��Ȃ�




�O�̃y�[�W���߂����̃y�[�W��