任意波形を出力するCプログラムをUWSCスクリプトに変換する

UWSC公式掲示板に任意のサウンド(例えば正弦波を一波)出力できないか?
というのに、以下のURLを提示して、変換すれば良いだけ、と書いたので、変換してみた。
http://wisdom.sakura.ne.jp/system/winapi/media/mm5.html



もとのCプログラム

#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;
	static WAVEHDR whdr;
	DWORD dwCount , dwWave = 0;
	WAVEFORMATEX wfe;

	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);
		for (dwCount = 0 ; dwCount < SRATE ; dwCount++ , dwWave += 10) {
			if (dwWave > 256) dwWave = 0;
			*(bWave + dwCount) = dwWave;
		}	
		wfe.wFormatTag = WAVE_FORMAT_PCM;
		wfe.nChannels = 1;
		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;
		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	= NULL;
	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;
}


まずは、Window関連を削る。
ついでにWM_CREATEとWM_DESTROYを逆にして、間にMSGBOXを入れる。

#define SRATE 	11025

	static HWAVEOUT hWave;
	static BYTE *bWave;
	static WAVEHDR whdr;
	DWORD dwCount , dwWave = 0;
	WAVEFORMATEX wfe;

		bWave = malloc(SRATE);
		for (dwCount = 0 ; dwCount < SRATE ; dwCount++ , dwWave += 10) {
			if (dwWave > 256) dwWave = 0;
			*(bWave + dwCount) = dwWave;
		}	
		wfe.wFormatTag = WAVE_FORMAT_PCM;
		wfe.nChannels = 1;
		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;
		whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
		whdr.dwLoops = 5;
		waveOutPrepareHeader(hWave , &whdr , sizeof(WAVEHDR));
		waveOutWrite(hWave , &whdr , sizeof(WAVEHDR));

MSGBOX("Window表示中")

		waveOutReset(hWave);
		waveOutUnprepareHeader(hWave , &whdr , sizeof(WAVEHDR));
		free(bWave);
		waveOutClose(hWave);


#defineをCONSTにする等、文法の修正と、構造体の扱いを考える。
構造体は配列でよさげ。

CONST SRATE = 11025

DIM hWave
DIM bWave[0]
DIM whdr[7]	// こっちはDWORD8個分
DIM dwCount, dwWave = 0
DIM wfe[8]	// こっちはWORD9個分

RESIZE(bWave, SRATE - 1)
FOR dwCount = 0 TO SRATE - 1
	IF dwWave > 255 THEN dwWave = 0
	bWave[dwCount] = dwWave
	dwWave = dwWave + 10
NEXT
wfe[0] = 1
wfe[1] = 1
wfe[2] = SRATE
wfe[3] = 0	// 23でDWORD。2が下位
wfe[4] = SRATE
wfe[5] = 0	// 45でDWORD。4が下位
wfe[7] = 8
wfe[6] = wfe[1] * wfe[7] / 8

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

whdr[0] = bWave	// 文法誤り
whdr[1] = LENGTH(bWave)
whdr[4] = WHDR_BEGINLOOP OR WHDR_ENDLOOP
whdr[5] = 5
waveOutPrepareHeader(hWave, &whdr, sizeof(WAVEHDR));
waveOutWrite(hWave, &whdr, sizeof(WAVEHDR));

MSGBOX("Window表示中")

waveOutReset(hWave);
waveOutUnprepareHeader(hWave, &whdr, sizeof(WAVEHDR));
free(bWave);
waveOutClose(hWave);


あとは、定数とDEF_DLLとメモリー関連を修正するだけ。

UWSCスクリプト

OPTION EXPLICIT
CONST SRATE = 11025

DEF_DLL waveOutOpen(var DWORD,DWORD,WORD[],DWORD,DWORD,DWORD): long: winmm
DEF_DLL waveOutPrepareHeader(DWORD,var DWORD[],DWORD): long: winmm
DEF_DLL waveOutWrite(DWORD,var DWORD[],DWORD): long: winmm
DEF_DLL waveOutReset(DWORD): long: winmm
DEF_DLL waveOutUnprepareHeader(DWORD,var DWORD[],DWORD): long: winmm
DEF_DLL waveOutClose(DWORD): long: winmm
DEF_DLL VirtualAlloc(DWORD, DWORD, DWORD, DWORD): DWORD: kernel32
DEF_DLL VirtualFree(DWORD, DWORD, DWORD): bool: kernel32
DEF_DLL RtlMoveMemory(DWORD, BYTE[], DWORD): kernel32


DIM hWave
DIM bWave[0], bufWave
DIM whdr[7], whdrSize = LENGTH(whdr) * 4
DIM dwCount, dwWave = 0
DIM wfe[8]

RESIZE(bWave, SRATE - 1)
FOR dwCount = 0 TO SRATE - 1
	IF dwWave > 255 THEN dwWave = 0
	bWave[dwCount] = dwWave
	dwWave = dwWave + 10
NEXT
bufWave = VirtualAlloc(0, LENGTH(bWave), $1000, 4)
RtlMoveMemory(bufWave, bWave, LENGTH(bWave))

wfe[0] = 1
wfe[1] = 1
wfe[2] = SRATE
wfe[3] = 0	// 23でDWORD。2が下位
wfe[4] = SRATE
wfe[5] = 0	// 45でDWORD。4が下位
wfe[7] = 8
wfe[6] = wfe[1] * wfe[7] / 8
waveOutOpen(hWave, -1, wfe, 0, 0, 0)

whdr[0] = bufWave
whdr[1] = LENGTH(bWave)
whdr[4] = 4 OR 8
whdr[5] = 5
waveOutPrepareHeader(hWave, whdr, whdrSize)
waveOutWrite(hWave, whdr, whdrSize)

MSGBOX("Window表示中")

waveOutReset(hWave)
waveOutUnprepareHeader(hWave, whdr, whdrSize)
VirtualFree(bufWave, 0, $8000)
waveOutClose(hWave)

ね、簡単でしょ!