任意波形を出力する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 // 2と3でDWORD。2が下位 wfe[4] = SRATE wfe[5] = 0 // 4と5で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 // 2と3でDWORD。2が下位 wfe[4] = SRATE wfe[5] = 0 // 4と5で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)
ね、簡単でしょ!