ピストンコラージュ

ピストンコラージュは洞窟物語の作者が作った曲を作るソフトです。
ピストンコラージュの曲をループで聴きたいので、
dllを、ポーティングしてループして再生するようにしました。

implib/system pxtone.lib pxtone.dll

とやって、pxtone.libを作成。

// pxtone.d
private import std.c.windows.windows;

extern(C):


alias bool function(int clock, bool bEnd) PXTONEPLAY_CALLBACK;

// pxtone を生成します。
BOOL  pxtone_Ready(
	HWND hWnd,          // ウインドウハンドルを渡してください
	int channel_num,   // のチャンネル数を指定してください。( 1:モノラル / 2:ステレオ )
	int sps,           // 秒間サンプリングレートです。      ( 11025 / 22050 / 44100 )
	int bps,           // 1サンプルを表現するビット数です。( 8 / 16 )
	float buffer_sec,   // 曲を再生するのに使用するバッファサイズを秒で指定します。( 推奨 0.1 )
	bool bDirectSound,  // TRUE: DirectSound を使用します / FALSE: WAVEMAPPER を使用します。
	PXTONEPLAY_CALLBACK pProc // サンプリング舞に呼ばれる関数です。NULL でかまいません。
); // pxtone の準備

BOOL pxtone_ResetSampling(
	HWND hWnd,
	int channel_num,
	int sps,
	int bps,
	float buffer_sec,
	BOOL bDirectSound,
	PXTONEPLAY_CALLBACK pProc
);

// pxtone で生成されたDirectSoundのポインタ(LPDIRECTSOUND)を取得する。
// 取得したDirectSoundはリリースしないように注意してください。
void *pxtone_GetDirectSound();

// ラストエラー文字列取得
char *pxtone_GetLastError();

// pxtone の音質を取得します
void  pxtone_GetQuality( int *p_channel_num, int *p_sps, int *p_bps, int *p_sample_per_buf ); // pxtone

// pxtone を開放します
BOOL  pxtone_Release();

// 曲を読み込みます
BOOL  pxtone_Tune_Load(
	HMODULE hModule,       // リソースから読む場合はモジュールハンドルを指定します。NULL でも問題ないかも。
	char *type_name, // リソースから読む場合はリソースの種類名。外部ファイルを読む場合は NULL。
	char *file_name  // ファイルパスもしくはリソース名。
	);

// 曲を解放します
BOOL  pxtone_Tune_Release();

// 曲を再生します
BOOL  pxtone_Tune_Play(
	int start_sample,     // 開始位置です。主に Stop や Fadeout で取得した値を設定します。0 で最初から。
	int fade_msec         // フェードインする場合はここに時間(ミリ秒)を指定します。
	);

// フェードアウトスイッチを入れて現在再生サンプルを取得します
int  pxtone_Tune_Fadeout( int msec );

// 曲のボリュームを設定します。1.0 が最大で、0.5 が半分です。
void  pxtone_Tune_SetVolume( double v );

// 曲を停止して現在再生サンプルを取得
int  pxtone_Tune_Stop();

// 再生中かどうかを調べます
BOOL  pxtone_Tune_IsPlaying();

// ループ再生の ON/OFF を切り替えます
void  pxtone_Tune_SetLoop( BOOL bLoop );


// 曲の情報を取得します
void  pxtone_Tune_GetInformation( int *p_beat_num, float *p_beat_tempo, int *p_beat_clock, int *p_meas_num );


// 曲の名称を取得します
char* pxtone_Tune_GetName();

// 曲のコメントを取得します
char* pxtone_Tune_GetComment();
import pxtone;
import std.c.windows.windows;
import std.thread;
import std.string;
import std.c.windows.windows;
import std.file;
import std.path;

class PxTone : Thread {
	HWND hwnd;
	this() {
		HINSTANCE hInst = GetModuleHandleA(null);
		WNDCLASS wc;
		wc.lpszClassName = "DWndClass";
		wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
		wc.lpfnWndProc = &WindowProc;
		wc.hInstance = hInst;
		wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
		wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
		wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
		wc.lpszMenuName = null;
		wc.cbClsExtra = wc.cbWndExtra = 0;
		assert(RegisterClassA(&wc));

		hwnd = CreateWindowA("DWndClass", "pxtone", WS_THICKFRAME |
			WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU,
			CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, HWND_DESKTOP,
			cast(HMENU) null, hInst, null);
		assert(hwnd);
		start();
	}
	int run() {
		MSG msg;
		while (GetMessageA(&msg, cast(HWND) null, 0, 0)) {
			TranslateMessage(&msg);
			DispatchMessageA(&msg);
		}
		return 1;
	}
	static extern(Windows)
	int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
	    switch (uMsg) {
	        case WM_PAINT: {
	            static char text = "pxtone";
	            PAINTSTRUCT ps;
	            HDC dc = BeginPaint(hWnd, &ps);
	            TextOutA(dc, 0, 0, text, text.length);
	            EndPaint(hWnd, &ps);
	            break;
	        }
	        case WM_DESTROY:
	            PostQuitMessage(0);
	            break;
	        default:
	            break;
	    }

	    return DefWindowProcA(hWnd, uMsg, wParam, lParam);
	}

}
static int clock;
static bool bEnd;
static extern(C) bool callBack(int _clock, bool _bEnd) {
	clock = _clock;
	bEnd = _bEnd;
	return true;
}


void main() {
	PxTone m = new PxTone();

	if (pxtone_Ready(m.hwnd, 2, 44100, 16, 0.1, true, &callBack)) {
		pxtone_Tune_SetLoop(false);
		printf("ready\n");
		char list=listdir(".");
		while (true) {
			foreach (char file; list) {
				if (getExt(file) != "ptcop") continue;
				printf("%.*s\n", file);
				if(pxtone_Tune_Load(null, null, std.string.toStringz(file))) {
					printf("%s\n", pxtone_Tune_GetName());
					printf("%s\n", pxtone_Tune_GetComment());
					printf("load \n");
					pxtone_Tune_Play(0, 0);
					printf("play\n");
					do {
						Sleep(100);
					} while (!bEnd);
					printf("stop\n");
					pxtone_Tune_Stop();
					pxtone_Tune_Release();
				}
			}
		}
		pxtone_Release();
	}
}

なかんじで。
コンパイルは、

dmd pxtoneplay.d pxtone.lib gdi32.lib

かな。