shithub: cstory

Download patch

ref: 470c5d86d5ec428c8c372e9050c707d7cba369e6
parent: e67c1e3640260d7797909e8b724b4b5eceb9739e
author: Clownacy <Clownacy@users.noreply.github.com>
date: Wed Aug 28 03:55:42 EDT 2019

ASM-accurate Sound.cpp and Organya.cpp (except for one function)

--- a/msvc2003/CSE2.vcproj
+++ b/msvc2003/CSE2.vcproj
@@ -34,7 +34,7 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib"
+				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
 				OutputFile="$(OutDir)\$(ProjectName).exe"
 				LinkIncremental="2"
 				AdditionalLibraryDirectories=""
@@ -85,7 +85,7 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib"
+				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
 				OutputFile="$(OutDir)\$(ProjectName).exe"
 				LinkIncremental="1"
 				IgnoreAllDefaultLibraries="FALSE"
@@ -135,7 +135,7 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib"
+				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
 				OutputFile="$(OutDir)\$(ProjectName).exe"
 				LinkIncremental="1"
 				IgnoreAllDefaultLibraries="FALSE"
@@ -186,7 +186,7 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib"
+				AdditionalDependencies="SDL2/lib/SDL2.lib SDL2/lib/SDL2main.lib freetype/lib/freetype.lib Version.lib DSound.lib WinMM.lib"
 				OutputFile="$(OutDir)\$(ProjectName).exe"
 				LinkIncremental="2"
 				AdditionalLibraryDirectories=""
--- a/msvc2003/devilution/comparer-config.toml
+++ b/msvc2003/devilution/comparer-config.toml
@@ -964,6 +964,10 @@
 addr = 0x41A7C0
 
 [[func]]
+name = "MakeSoundObject8"
+addr = 0x41A8F0
+
+[[func]]
 name = "ChangeOrganFrequency"
 addr = 0x41ABA0
 size = 0xC9
@@ -983,7 +987,7 @@
 addr = 0x41ADC0
 
 [[func]]
-name = "ReleaseOrganya"
+name = "ReleaseOrganyaObject"
 addr = 0x41B2A0
 
 [[func]]
@@ -1011,6 +1015,95 @@
 addr = 0x41B510
 
 [[func]]
+name = "OrgData::OrgData"
+addr = 0x41B600
+
+[[func]]
+name = "OrgData::InitOrgData"
+addr = 0x41B650
+
+[[func]]
+name = "OrgData::SetMusicInfo"
+addr = 0x41B730
+
+[[func]]
+name = "OrgData::NoteAlloc"
+addr = 0x41B890
+
+[[func]]
+name = "OrgData::ReleaseNote"
+addr = 0x41BA70
+
+[[func]]
+name = "OrgData::InitMusicData"
+addr = 0x41BAD0
+
+[[func]]
+name = "OrgData::GetMusicInfo"
+addr = 0x41C0B0
+
+[[func]]
+name = "InitMMTimer"
+addr = 0x41C180
+
+[[func]]
+name = "StartTimer"
+addr = 0x41C1E0
+size = 0x4A
+
+[[func]]
+name = "TimerProc"
+addr = 0x41C230
+
+[[func]]
+name = "QuitMMTimer"
+addr = 0x41C250
+
+[[func]]
+name = "OrgData::PlayData"
+addr = 0x41C2B0
+
+[[func]]
+name = "OrgData::SetPlayPointer"
+addr = 0x41C630
+
+[[func]]
+name = "StartOrganya"
+addr = 0x41C6C0
+
+[[func]]
+name = "LoadOrganya"
+addr = 0x41C6F0
+
+[[func]]
+name = "SetOrganyaPosition"
+addr = 0x41C730
+
+[[func]]
+name = "GetOrganyaPosition"
+addr = 0x41C770
+
+[[func]]
+name = "PlayOrganyaMusic"
+addr = 0x41C790
+
+[[func]]
+name = "ChangeOrganyaVolume"
+addr = 0x41C7C0
+
+[[func]]
+name = "StopOrganyaMusic"
+addr = 0x41C7F0
+
+[[func]]
+name = "SetOrganyaFadeout"
+addr = 0x41C880
+
+[[func]]
+name = "EndOrganya"
+addr = 0x41C890
+
+[[func]]
 name = "MakeWaveTables"
 addr = 0x41C8F0
 
@@ -1107,6 +1200,22 @@
 addr = 0x41FE70
 
 [[func]]
+name = "InitDirectSound"
+addr = 0x4200C0
+
+[[func]]
+name = "EndDirectSound"
+addr = 0x4201A0
+
+[[func]]
+name = "InitSoundObject"
+addr = 0x420240
+
+[[func]]
+name = "LoadSoundObject"
+addr = 0x420390
+
+[[func]]
 name = "PlaySoundObject"
 addr = 0x420640
 
@@ -1124,6 +1233,10 @@
 name = "ChangeSoundPan"
 addr = 0x4207A0
 size = 0x36
+
+[[func]]
+name = "MakePixToneObject"
+addr = 0x4207E0
 
 [[func]]
 name = "TransferStage"
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -5,6 +5,7 @@
 #include <string.h>
 
 #include "SDL.h"
+#include "SDL_syswm.h"
 
 #include "WindowsWrapper.h"
 
@@ -347,11 +348,16 @@
 			CortBox(&clip_rect, 0x000000);
 			PutBitmap3(&clip_rect, (WINDOW_WIDTH - 64) / 2, (WINDOW_HEIGHT - 8) / 2, &loading_rect, SURFACE_ID_LOADING);
 
+			SDL_SysWMinfo wmInfo;
+			SDL_VERSION(&wmInfo.version);
+			SDL_GetWindowWMInfo(gWindow, &wmInfo);
+			ghWnd = wmInfo.info.win.window;
+
 			// Draw to screen
 			if (Flip_SystemTask(ghWnd))
 			{
 				// Initialize sound
-				InitDirectSound();
+				InitDirectSound(ghWnd);
 
 				// Initialize joystick
 				if (config.bJoystick && InitDirectInput())
--- a/src/Organya.cpp
+++ b/src/Organya.cpp
@@ -10,6 +10,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <dsound.h>
+
 #include "SDL.h"
 
 #include "WindowsWrapper.h"
@@ -24,74 +26,112 @@
 #define MAXMELODY 8
 #define MAXDRAM 8
 
-SOUNDBUFFER *lpORGANBUFFER[8][8][2] = {NULL};
-SOUNDBUFFER **lpDRAMBUFFER = &lpSECONDARYBUFFER[0x96];
+#define ALLOCNOTE 4096
 
-MUSICINFO info;
+#define DEFVOLUME	200//255はVOLDUMMY。MAXは254
+#define DEFPAN		6
 
-int gTrackVol[MAXTRACK];
-int gOrgVolume = 100;
-BOOL bFadeout = FALSE;
+//曲情報をセットする時のフラグ
+#define SETALL		0xffffffff//全てをセット
+#define SETWAIT		0x00000001
+#define SETGRID		0x00000002
+#define SETALLOC	0x00000004
+#define SETREPEAT	0x00000008
+#define SETFREQ		0x00000010
+#define SETWAVE		0x00000020
+#define SETPIPI		0x00000040
 
-BOOL OrganyaNoteAlloc(unsigned short alloc)
+typedef struct ORGANYATRACK
 {
-	for (int j = 0; j < MAXTRACK; j++)
-	{
-		info.tdata[j].wave_no = 0;
-		info.tdata[j].note_list = NULL;
-		info.tdata[j].note_p = new NOTELIST[alloc];
+	unsigned short freq;	// +α周波数(1000がDefault) (+ α frequency (1000 is Default))
+	unsigned char wave_no;	// 波形No (Waveform No)
+	unsigned char pipi;	// ☆
+	unsigned short note_num;	// 音符の数 (Number of notes)
+} ORGANYATRACK;
 
-		if (info.tdata[j].note_p == NULL)
-		{
-			for (int i = 0; i < MAXTRACK; i++)
-			{
-				if (info.tdata[i].note_p != NULL)
-				{
-					delete[] info.tdata[i].note_p;
-					info.tdata[j].note_p = NULL;	// Uses j instead of i
-				}
-			}
+typedef struct ORGANYADATA
+{
+	unsigned short wait;
+	unsigned char line;
+	unsigned char dot;
+	long repeat_x;	// リピート (repeat)
+	long end_x;	// 曲の終わり(リピートに戻る)	(End of song (return to repeat))
+	ORGANYATRACK tdata[MAXTRACK];
+} ORGANYADATA;
 
-			return FALSE;
-		}
+// Below are Organya song data structures
+typedef struct NOTELIST
+{
+	NOTELIST *from;	// Previous address
+	NOTELIST *to;	// Next address
 
-		for (int i = 0; i < alloc; i++)
-		{
-			(info.tdata[j].note_p + i)->from = NULL;
-			(info.tdata[j].note_p + i)->to = NULL;
-			(info.tdata[j].note_p + i)->length = 0;
-			(info.tdata[j].note_p + i)->pan = PANDUMMY;
-			(info.tdata[j].note_p + i)->volume = VOLDUMMY;
-			(info.tdata[j].note_p + i)->y = KEYDUMMY;
-		}
-	}
+	long x;	// Position
+	unsigned char length;	// Sound length
+	unsigned char y;	// Sound height
+	unsigned char volume;	// Volume
+	unsigned char pan;
+} NOTELIST;
 
-	for (int j = 0; j < MAXMELODY; j++)
-		MakeOrganyaWave(j, info.tdata[j].wave_no, info.tdata[j].pipi);
-	// for(int j = 0; j < MAXDRAM; j++)
-	// 	InitDramObject(j);
+// Track data * 8
+typedef struct TRACKDATA
+{
+	unsigned short freq;	// Frequency (1000 is default)
+	unsigned char wave_no;	// Waveform No.
+	signed char pipi;
 
-	// this->track = 0;
+	NOTELIST *note_p;
+	NOTELIST *note_list;
+} TRACKDATA;
 
-	return FALSE;
-}
+// Unique information held in songs
+typedef struct MUSICINFO
+{
+	unsigned short wait;
+	unsigned char line;	// Number of lines in one measure
+	unsigned char dot;	// Number of dots per line
+	unsigned short alloc_note;	// Number of allocated notes
+	long repeat_x;	// Repeat
+	long end_x;	// End of song (Return to repeat)
+	TRACKDATA tdata[16];
+} MUSICINFO;
 
-void OrganyaReleaseNote()
+// メインクラス。このアプリケーションの中心。(クラスってやつを初めて使う) (Main class. The heart of this application. (Class is used for the first time))
+typedef struct OrgData
 {
-	for (int i = 0; i < MAXTRACK; i++)
-	{
-		if (info.tdata[i].note_p != NULL)
-		{
-#ifdef FIX_BUGS
-			delete[] info.tdata[i].note_p;
-#else
-			delete info.tdata[i].note_p;	// Should be delete[]
-#endif
-			info.tdata[i].note_p = NULL;
-		}
-	}
-}
+	OrgData();	// コンストラクタ (Constructor)
+//	~OrgData();	// デストラクタ (Destructor)
+	MUSICINFO info;
+	char track;
+	char mute[MAXTRACK];
+	unsigned char def_pan;
+	unsigned char def_volume;
+	void InitOrgData(void);
+	void GetMusicInfo(MUSICINFO *mi);	// 曲情報を取得 (Get song information)
+	// 曲情報を設定。flagは設定アイテムを指定 (Set song information. flag specifies the setting item)
+	BOOL SetMusicInfo(MUSICINFO *mi,unsigned long flag);
+	BOOL NoteAlloc(unsigned short note_num);	// 指定の数だけNoteDataの領域を確保 (Allocate the specified number of NoteData areas.)
+	void ReleaseNote(void);	// NoteDataを開放 (Release NoteData)
+	// 以下は再生 (The following is playback)
+	void PlayData(void);
+	void SetPlayPointer(long x);	// 再生ポインターを指定の位置に設定 (Set playback pointer to specified position)
+	// 以下はファイル関係 (The following are related to files)
+	BOOL OrgData::InitMusicData(const char *path);
+} ORGDATA;
 
+ORGDATA org_data;
+
+LPDIRECTSOUNDBUFFER lpORGANBUFFER[8][8][2] = {NULL};
+
+int gTrackVol[MAXTRACK];
+int gOrgVolume = 100;
+BOOL bFadeout = FALSE;
+BOOL g_mute[MAXTRACK];	// Used by the debug Mute menu
+
+
+/////////////////////////////////////////////
+//■オルガーニャ■■■■■■■■■■■■/////// (Organya)
+/////////////////////
+
 // Wave playing and loading
 typedef struct
 {
@@ -100,7 +140,7 @@
 	short oct_size;
 } OCTWAVE;
 
-OCTWAVE oct_wave[8] =
+static const OCTWAVE oct_wave[8] =
 {
 	{ 256,  1,  4 }, // 0 Oct
 	{ 256,  2,  8 }, // 1 Oct
@@ -112,44 +152,89 @@
 	{   8,128, 32 }, // 7 Oct
 };
 
+static WAVEFORMATEX format_tbl2 = {WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8, 0};	// 22050HzのFormat
+
+// In the original source code, format_tbl2 was a raw array of bytes, as seen below
+// BYTE format_tbl2[] = {0x01,0x00,0x01,0x00,0x22,0x56,0x00,0x00,0x22,0x56,0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x00};	// 22050HzのFormat
+
 BOOL MakeSoundObject8(signed char *wavep, signed char track, signed char pipi)
 {
-	for (int j = 0; j < 8; j++)
+	DWORD i,j,k;
+	unsigned long wav_tp;	// WAVテーブルをさすポインタ (Pointer to WAV table)
+	DWORD wave_size;	// 256;
+	DWORD data_size;
+	BYTE *wp;
+	BYTE *wp_sub;
+	int work;
+	// セカンダリバッファの生成 (Create secondary buffer)
+	DSBUFFERDESC dsbd;
+
+	if (lpDS == NULL)
+		return FALSE;
+
+	for (j = 0; j < 8; j++)
 	{
-		for (int k = 0; k < 2; k++)
+		for (k = 0; k < 2; k++)
 		{
-			size_t wave_size = oct_wave[j].wave_size;
-			size_t data_size = pipi ? wave_size * oct_wave[j].oct_size : wave_size;
+			wave_size = oct_wave[j].wave_size;
 
-			// Create sound buffer
-			lpORGANBUFFER[track][j][k] = new SOUNDBUFFER(data_size);
+			if (pipi)
+				data_size = wave_size * oct_wave[j].oct_size;
+			else
+				data_size = wave_size;
 
+			ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
+
+			dsbd.dwSize = sizeof(DSBUFFERDESC);
+			dsbd.dwBufferBytes = data_size;
+			dsbd.lpwfxFormat = &format_tbl2;
+			dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
+
+			if(lpDS->CreateSoundBuffer(&dsbd, &lpORGANBUFFER[track][j][k], NULL) != DS_OK)	// j = se_no
+				return FALSE;
+
 			// Get wave data
-			unsigned char *wp = new unsigned char[data_size];
-			unsigned char *wp_sub = wp;
-			size_t wav_tp = 0;
+			wp = (BYTE*)malloc(data_size);
+			wp_sub = wp;
+			wav_tp = 0;
 
-			for (size_t i = 0; i < data_size; i++)
+			for (i = 0; i < data_size; i++)
 			{
-				unsigned char work = *(wavep + wav_tp);
+				work = *(wavep + wav_tp);
 				work += 0x80;
 
-				*wp_sub = work;
+				*wp_sub = (BYTE)work;
 
 				wav_tp += 0x100 / wave_size;
-				if (wav_tp >= 0x100)
+				if (wav_tp > 0xFF)
 					wav_tp -= 0x100;
 
 				wp_sub++;
 			}
 
-			// Copy wave data to sound buffer
-			unsigned char *buf;
-			lpORGANBUFFER[track][j][k]->Lock(&buf, NULL);
-			memcpy(buf, wp, data_size);
-			lpORGANBUFFER[track][j][k]->Unlock();
+			// データの転送 (Data transfer)
+			LPVOID lpbuf1, lpbuf2;
+			DWORD dwbuf1, dwbuf2=0;
+			HRESULT hr;
+
+			hr = lpORGANBUFFER[track][j][k]->Lock(0, data_size, &lpbuf1, &dwbuf1, &lpbuf2, &dwbuf2, 0); 
+
+			if (hr != DS_OK)
+			{
+#ifdef FIX_BUGS
+				free(wp);	// The updated Organya source code includes this fix
+#endif
+				return FALSE;
+			}
+
+			CopyMemory(lpbuf1, (BYTE*)wp, dwbuf1);
+
+			if (dwbuf2 != 0)
+				CopyMemory(lpbuf2, (BYTE*)wp+dwbuf1, dwbuf2);
+
+			lpORGANBUFFER[track][j][k]->Unlock(lpbuf1, dwbuf1, lpbuf2, dwbuf2);
 			lpORGANBUFFER[track][j][k]->SetCurrentPosition(0);
-			delete[] wp;
+			free(wp);
 		}
 	}
 
@@ -156,44 +241,52 @@
 	return TRUE;
 }
 
-// Playing melody tracks
-short freq_tbl[12] = {262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494};
+static const short freq_tbl[12] = {262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494};
 
 void ChangeOrganFrequency(unsigned char key, signed char track, long a)
 {
+	if (lpDS == NULL)
+		return;
+
 	for (int j = 0; j < 8; j++)
-	{
 		for (int i = 0; i < 2; i++)
-		{
-			lpORGANBUFFER[track][j][i]->SetFrequency(((oct_wave[j].wave_size * freq_tbl[key]) * oct_wave[j].oct_par) / 8 + (a - 1000));
-		}
-	}
+			lpORGANBUFFER[track][j][i]->SetFrequency(((oct_wave[j].wave_size * freq_tbl[key]) * oct_wave[j].oct_par) / 8 + (a - 1000));	// 1000を+αのデフォルト値とする (1000 is the default value for + α)
 }
 
-short pan_tbl[13] = {0, 43, 86, 129, 172, 215, 256, 297, 340, 383, 426, 469, 512};
-unsigned char old_key[MAXTRACK] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-unsigned char key_on[MAXTRACK] = {0};
-unsigned char key_twin[MAXTRACK] = {0};
+const short pan_tbl[13] = {0, 43, 86, 129, 172, 215, 256, 297, 340, 383, 426, 469, 512};
+unsigned char old_key[MAXTRACK] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};	// 再生中の音 (Sound being played)
+unsigned char key_on[MAXTRACK];	// キースイッチ (Key switch)
+unsigned char key_twin[MAXTRACK];	// 今使っているキー(連続時のノイズ防止の為に二つ用意) (Currently used keys (prepared for continuous noise prevention))
 
-void ChangeOrganPan(unsigned char key, unsigned char pan, signed char track)
+void ChangeOrganPan(unsigned char key, unsigned char pan, signed char track)	// 512がMAXで256がノーマル (512 is MAX and 256 is normal)
 {
+	if (lpDS == NULL)
+		return;
+
 	if (old_key[track] != PANDUMMY)
 		lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->SetPan((pan_tbl[pan] - 0x100) * 10);
 }
 
-void ChangeOrganVolume(int no, long volume, signed char track)
+void ChangeOrganVolume(int no, long volume, signed char track)	// 300がMAXで300がノーマル (300 is MAX and 300 is normal)
 {
+	if (lpDS == NULL)
+		return;
+
 	if (old_key[track] != VOLDUMMY)
 		lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->SetVolume((volume - 0xFF) * 8);
 }
 
+// サウンドの再生 (Play sound)
 void PlayOrganObject(unsigned char key, int mode, signed char track, long freq)
 {
+	if (lpDS == NULL)
+		return;
+
 	if (lpORGANBUFFER[track][key / 12][key_twin[track]] != NULL)
 	{
 		switch (mode)
 		{
-			case 0:
+			case 0:	// 停止 (Stop)
 				if (old_key[track] != 0xFF)
 				{
 					lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Stop();
@@ -201,51 +294,56 @@
 				}
 				break;
 
-			case 1:
+			case 1: // 再生 (Playback)
 				break;
 
-			case 2:
+			case 2:	// 歩かせ停止 (Stop playback)
 				if (old_key[track] != 0xFF)
 				{
-					lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Play(false);
+					lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Play(0, 0, 0);
 					old_key[track] = 0xFF;
 				}
 				break;
 
 			case -1:
-				if (old_key[track] == 0xFF)
+				if (old_key[track] == 0xFF)	// 新規鳴らす (New sound)
 				{
-					ChangeOrganFrequency(key % 12, track, freq);
-					lpORGANBUFFER[track][key / 12][key_twin[track]]->Play(true);
+					ChangeOrganFrequency(key % 12, track, freq);	// 周波数を設定して (Set the frequency)
+					lpORGANBUFFER[track][key / 12][key_twin[track]]->Play(0, 0, DSBPLAY_LOOPING);
 					old_key[track] = key;
 					key_on[track] = 1;
 				}
-				else if (key_on[track] == 1 && old_key[track] == key)
+				else if (key_on[track] == 1 && old_key[track] == key)	// 同じ音 (Same sound)
 				{
-					lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Play(false);
+					// 今なっているのを歩かせ停止 (Stop playback now)
+					lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Play(0, 0, 0);
 					key_twin[track]++;
-					if (key_twin[track] == 2)
+					if (key_twin[track] > 1)
 						key_twin[track] = 0;
-					lpORGANBUFFER[track][key / 12][key_twin[track]]->Play(true);
+					lpORGANBUFFER[track][key / 12][key_twin[track]]->Play(0, 0, DSBPLAY_LOOPING);
 				}
-				else
+				else	// 違う音を鳴らすなら (If you make a different sound)
 				{
-					lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Play(false);
+					lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Play(0, 0, 0);	// 今なっているのを歩かせ停止 (Stop playback now)
 					key_twin[track]++;
-					if (key_twin[track] == 2)
+					if (key_twin[track] > 1)
 						key_twin[track] = 0;
-					ChangeOrganFrequency(key % 12, track, freq);
-					lpORGANBUFFER[track][key / 12][key_twin[track]]->Play(true);
+					ChangeOrganFrequency(key % 12, track, freq);	// 周波数を設定して (Set the frequency)
+					lpORGANBUFFER[track][key / 12][key_twin[track]]->Play(0, 0, DSBPLAY_LOOPING);
 					old_key[track] = key;
 				}
+
 				break;
 		}
 	}
 }
 
-// Release tracks
+// オルガーニャオブジェクトを開放 (Open Organya object)
 void ReleaseOrganyaObject(signed char track)
 {
+	if (lpDS == NULL)
+		return;
+
 	for (int i = 0; i < 8; i++)
 	{
 		if (lpORGANBUFFER[track][i][0] != NULL)
@@ -261,236 +359,311 @@
 	}
 }
 
-// Handling WAVE100
+// 波形データをロード (Load waveform data)
 signed char wave_data[100][0x100];
 
-BOOL InitWaveData100()
+BOOL InitWaveData100(void)
 {
-	HRSRC hrscr = FindResourceA(NULL, "WAVE100", "WAVE");
+	HRSRC hrscr;
+	DWORD *lpdword;	// リソースのアドレス (Resource address)
 
-	if (hrscr == NULL)
+	if (lpDS == NULL)
 		return FALSE;
 
-	const unsigned char *data = (unsigned char*)LockResource(LoadResource(NULL, hrscr));
+	// リソースの検索 (Search for resources)
+	hrscr = FindResourceA(NULL, "WAVE100", "WAVE");
 
-	memcpy(wave_data, data, 100 * 0x100);
+	if (hrscr == NULL)
+		return FALSE;
 
+	// リソースのアドレスを取得 (Get resource address)
+	lpdword = (DWORD*)LockResource(LoadResource(NULL, hrscr));
+	memcpy(wave_data, lpdword, 100 * 0x100);
+
 	return TRUE;
 }
 
-// Create org wave
+// 波形を100個の中から選択して作成 (Select from 100 waveforms to create)
 BOOL MakeOrganyaWave(signed char track, signed char wave_no, signed char pipi)
 {
+	if (lpDS == NULL)
+		return FALSE;
+
 	if (wave_no > 99)
-	{
-		printf("WARNING: track %d has out-of-range wave_no %d\n", track, wave_no);
 		return FALSE;
-	}
 
 	ReleaseOrganyaObject(track);
 	MakeSoundObject8(wave_data[wave_no], track, pipi);
+
 	return TRUE;
 }
 
-// Dram
+/////////////////////////////////////////////
+//■オルガーニャドラムス■■■■■■■■/////// (Organya drums)
+/////////////////////
+
 void ChangeDramFrequency(unsigned char key, signed char track)
 {
-	lpDRAMBUFFER[track]->SetFrequency(key * 800 + 100);
+	if (lpDS == NULL)
+		return;
+
+	lpSECONDARYBUFFER[150 + track]->SetFrequency(key * 800 + 100);
 }
 
 void ChangeDramPan(unsigned char pan, signed char track)
 {
-	lpDRAMBUFFER[track]->SetPan((pan_tbl[pan] - 0x100) * 10);
+	if (lpDS == NULL)
+		return;
+
+	lpSECONDARYBUFFER[150 + track]->SetPan((pan_tbl[pan] - 0x100) * 10);
 }
 
 void ChangeDramVolume(long volume, signed char track)
 {
-	lpDRAMBUFFER[track]->SetVolume((volume - 0xFF) * 8);
+	if (lpDS == NULL)
+		return;
+
+	lpSECONDARYBUFFER[150 + track]->SetVolume((volume - 0xFF) * 8);
 }
 
+// サウンドの再生 (Play sound)
 void PlayDramObject(unsigned char key, int mode, signed char track)
 {
-	switch (mode)
+	if (lpDS == NULL)
+		return;
+
+	if (lpSECONDARYBUFFER[150 + track] != NULL)
 	{
-		case 0:
-			lpDRAMBUFFER[track]->Stop();
-			lpDRAMBUFFER[track]->SetCurrentPosition(0);
-			break;
+		switch (mode)
+		{
+			case 0:	// 停止 (Stop)
+				lpSECONDARYBUFFER[150 + track]->Stop();
+				lpSECONDARYBUFFER[150 + track]->SetCurrentPosition(0);
+				break;
 
-		case 1:
-			lpDRAMBUFFER[track]->Stop();
-			lpDRAMBUFFER[track]->SetCurrentPosition(0);
-			ChangeDramFrequency(key, track);
-			lpDRAMBUFFER[track]->Play(false);
-			break;
+			case 1:	// 再生 (Playback)
+				lpSECONDARYBUFFER[150 + track]->Stop();
+				lpSECONDARYBUFFER[150 + track]->SetCurrentPosition(0);
+				ChangeDramFrequency(key, track);	// 周波数を設定して ()
+				lpSECONDARYBUFFER[150 + track]->Play(0, 0, 0);
+				break;
 
-		case 2:
-			break;
+			case 2:	// 歩かせ停止 (Stop playback)
+				break;
 
-		case -1:
-			break;
+			case -1:
+				break;
+		}
 	}
 }
 
-// Play data
-long play_p;
-NOTELIST *play_np[MAXTRACK];
-long now_leng[MAXMELODY] = {0};
+OrgData::OrgData()
+{
+	int i;
 
-void OrganyaPlayData()
+	for (i = 0; i < MAXTRACK; i++)
+	{
+		info.tdata[i].note_list = NULL;
+		info.tdata[i].note_p = NULL;
+	}
+}
+
+void OrgData::InitOrgData(void)
 {
-	// Handle fading out
-	if (bFadeout && gOrgVolume)
-		gOrgVolume -= 2;
-	if (gOrgVolume < 0)
-		gOrgVolume = 0;
+	track = 0;
+	info.alloc_note = ALLOCNOTE;	// とりあえず10000個確保 (For the time being, secure 10,000 pieces)
+	info.dot = 4;
+	info.line = 4;
+	info.wait = 128;
+	info.repeat_x = info.dot * info.line * 0;
+	info.end_x = info.dot * info.line * 255;
 
-	// Play melody
-	for (int i = 0; i < MAXMELODY; i++)
+	int i;
+	for (i = 0; i < MAXTRACK; i++)
 	{
-		if (play_np[i] != NULL && play_p == play_np[i]->x)
-		{
-			if (play_np[i]->y != KEYDUMMY)
-			{
-				PlayOrganObject(play_np[i]->y, -1, i, info.tdata[i].freq);
-				now_leng[i] = play_np[i]->length;
-			}
+		info.tdata[i].freq = 1000;
+		info.tdata[i].wave_no = 0;
+		info.tdata[i].pipi = 0;
+	}
 
-			if (play_np[i]->pan != PANDUMMY)
-				ChangeOrganPan(play_np[i]->y, play_np[i]->pan, i);
-			if (play_np[i]->volume != VOLDUMMY)
-				gTrackVol[i] = play_np[i]->volume;
+	NoteAlloc(info.alloc_note);
+	SetMusicInfo(&info, SETALL);
 
-			play_np[i] = play_np[i]->to;
-		}
+	def_pan = DEFPAN;
+	def_volume = DEFVOLUME;
+}
 
-		if (now_leng[i] == 0)
-			PlayOrganObject(0, 2, i, info.tdata[i].freq);
+// 曲情報を設定。flagはアイテムを指定 (Set song information. flag specifies an item)
+BOOL OrgData::SetMusicInfo(MUSICINFO *mi, unsigned long flag)
+{
+#ifndef FIX_BUGS	// Leftover debug junk
+	char str[32];
+#endif
+	int i;
 
-		if (now_leng[i] > 0)
-			now_leng[i]--;
+	if (flag & SETGRID)	// グリッドを有効に (Enable grid)
+	{
+		info.dot = mi->dot;
+		info.line = mi->line;
+	}
 
-		if (play_np[i])
-			ChangeOrganVolume(play_np[i]->y, gOrgVolume * gTrackVol[i] / 0x7F, i);
+	if (flag & SETWAIT)
+	{
+		info.wait = mi->wait;
+#ifndef FIX_BUGS
+		itoa(mi->wait, str, 10);
+#endif
 	}
 
-	for (int i = MAXMELODY; i < MAXTRACK; i++)
+	if (flag & SETREPEAT)
 	{
-		if (play_np[i] != NULL && play_p == play_np[i]->x)
+		info.repeat_x = mi->repeat_x;
+		info.end_x = mi->end_x;
+	}
+
+	if (flag & SETFREQ)
+	{
+		for (i = 0; i < MAXMELODY; i++)
 		{
-			if (play_np[i]->y != KEYDUMMY)
-				PlayDramObject(play_np[i]->y, 1, i - MAXMELODY);
+			info.tdata[i].freq = mi->tdata[i].freq;
+			info.tdata[i].pipi = info.tdata[i].pipi;
+		}
+	}
 
-			if (play_np[i]->pan != PANDUMMY)
-				ChangeDramPan(play_np[i]->pan, i - MAXMELODY);
-			if (play_np[i]->volume != VOLDUMMY)
-				gTrackVol[i] = play_np[i]->volume;
+	if (flag & SETWAVE)
+		for (i = 0; i < MAXTRACK; i++)
+			info.tdata[i].wave_no = mi->tdata[i].wave_no;
 
-			play_np[i] = play_np[i]->to;
-		}
+	if (flag & SETPIPI)
+		for (i = 0; i < MAXTRACK; i++)
+			info.tdata[i].pipi = mi->tdata[i].pipi;
 
-		if (play_np[i])
-			ChangeDramVolume(gOrgVolume * gTrackVol[i] / 0x7F, i - MAXMELODY);
-	}
+	return TRUE;
+}
 
-	// Looping
-	play_p++;
-	if (play_p >= info.end_x)
+// 指定の数だけNoteDataの領域を確保(初期化) (Allocate the specified number of NoteData areas (initialization))
+BOOL OrgData::NoteAlloc(unsigned short alloc)
+{
+	int i,j;
+
+	for (j = 0; j < MAXTRACK; j++)
 	{
-		play_p = info.repeat_x;
-		SetPlayPointer(play_p);
+		info.tdata[j].wave_no = 0;
+		info.tdata[j].note_list = NULL;	// コンストラクタにやらせたい (I want the constructor to do it)
+		info.tdata[j].note_p = (NOTELIST*)malloc(sizeof(NOTELIST) * alloc);
+
+		if (info.tdata[j].note_p == NULL)
+		{
+			for (i = 0; i < MAXTRACK; i++)
+			{
+				if (info.tdata[i].note_p != NULL)
+				{
+					free(info.tdata[i].note_p);
+#ifdef FIX_BUGS
+					info.tdata[i].note_p = NULL;
+#else
+					info.tdata[j].note_p = NULL;	// Uses j instead of i
+#endif
+				}
+			}
+
+			return FALSE;
+		}
+
+		for (i = 0; i < alloc; i++)
+		{
+			(info.tdata[j].note_p + i)->from = NULL;
+			(info.tdata[j].note_p + i)->to = NULL;
+			(info.tdata[j].note_p + i)->length = 0;
+			(info.tdata[j].note_p + i)->pan = PANDUMMY;
+			(info.tdata[j].note_p + i)->volume = VOLDUMMY;
+			(info.tdata[j].note_p + i)->y = KEYDUMMY;
+		}
 	}
+
+	for (j = 0; j < MAXMELODY; j++)
+		MakeOrganyaWave(j, info.tdata[j].wave_no, info.tdata[j].pipi);
+
+	track = 0;	// 今はここに書いておく (Write here now)
+
+	return TRUE;
 }
 
-void SetPlayPointer(long x)
+// NoteDataを開放 (Release NoteData)
+void OrgData::ReleaseNote(void)
 {
 	for (int i = 0; i < MAXTRACK; i++)
 	{
-		play_np[i] = info.tdata[i].note_list;
-		while (play_np[i] != NULL && play_np[i]->x < x)
-			play_np[i] = play_np[i]->to;
+		if (info.tdata[i].note_p != NULL)
+		{
+			free(info.tdata[i].note_p);
+			info.tdata[i].note_p = NULL;
+		}
 	}
-
-	play_p = x;
 }
 
-#define READ_LE16(pointer) pointer[0] | (pointer[1] << 8); pointer += 2;
-#define READ_LE32(pointer) pointer[0] | (pointer[1] << 8) | (pointer[2] << 16) | (pointer[3] << 24); pointer += 4;
+static const char pass[7] = "Org-01";
+static const char pass2[7] = "Org-02";	// Pipi
 
-// Load organya file
-void LoadOrganya(const char *name)
+BOOL OrgData::InitMusicData(const char *path)
 {
-	// Unload previous things
-	OrganyaReleaseNote();
-	memset(&info, 0, sizeof(info));
-	OrganyaNoteAlloc(0xFFFF);
+	ORGANYADATA org_data;
+	NOTELIST *np;
+	int i,j;
+	char pass_check[6];
+	char ver = 0;
 
-	// Stop currently playing notes
-	memset(play_np, 0, sizeof(play_np));
-	memset(old_key, 0xFF, sizeof(old_key));
-	memset(key_on, 0, sizeof(key_on));
-	memset(key_twin, 0, sizeof(key_twin));
-	memset(now_leng, 0, sizeof(now_leng));
-
-	// Open file
-	HRSRC hrscr = FindResourceA(NULL, name, "ORG");
-
+	HRSRC hrscr = FindResourceA(0, path, "ORG");
 	if (hrscr == NULL)
-		return;
+		return FALSE;
 
-	const unsigned char *p = (unsigned char*)LockResource(LoadResource(NULL, hrscr));
+	unsigned char *p = (unsigned char*)LockResource(LoadResource(0, hrscr));
 
-	// Version Check
-	unsigned char ver = 0;
-	char pass_check[6];
-
-	memcpy(pass_check, p, 6);
+	memcpy(&pass_check[0], p, 6);
 	p += 6;
 
-	if (!memcmp(pass_check, "Org-01", 6))
+	if(memcmp(pass_check, pass, 6) == 0)
 		ver = 1;
-
-	if (!memcmp(pass_check, "Org-02", 6))
+	if(memcmp(pass_check, pass2, 6) == 0)
 		ver = 2;
 
-	// if (!memcmp(pass_check, "Org-03", 6))
-	// 	ver = 2;
+	if(ver == 0)
+		return FALSE;
 
-	if (!ver)
-	{
-		printf("Failed to open .org, invalid version %s", pass_check);
-		return;
-	}
+	// 曲情報の読み込み (Loading song information)
+	memcpy(&org_data, p, sizeof(ORGANYADATA));
+	p += sizeof(ORGANYADATA);
 
-	// Set song information
-	info.wait = READ_LE16(p);
-	info.line = *p++;
-	info.dot = *p++;
-	info.repeat_x = READ_LE32(p);
-	info.end_x = READ_LE32(p);
+	// 曲の情報を設定 (Set song information)
+	info.wait = org_data.wait;
+	info.line = org_data.line;
+	info.dot = org_data.dot;
+	info.repeat_x = org_data.repeat_x;
+	info.end_x = org_data.end_x;
 
-	for (int i = 0; i < 16; i++)
+	for (i = 0; i < MAXTRACK; i++)
 	{
-		info.tdata[i].freq = READ_LE16(p);
-		info.tdata[i].wave_no = *p++;
-		const signed char pipi = *p++;
-		info.tdata[i].pipi = ver == 1 ? 0 : pipi;
-		info.tdata[i].note_num = READ_LE16(p);
-	}
+		info.tdata[i].freq = org_data.tdata[i].freq;
 
-	// Load notes
-	NOTELIST *np;
+		if (ver == 1)
+			info.tdata[i].pipi = 0;
+		else
+			info.tdata[i].pipi = org_data.tdata[i].pipi;
 
-	for (int j = 0; j < 16; j++)
+		info.tdata[i].wave_no = org_data.tdata[i].wave_no;
+	}
+
+	// 音符のロード (Loading notes)
+	for (j = 0; j < MAXTRACK; j++)
 	{
-		// The first note from is NULL
-		if (info.tdata[j].note_num == 0)
+		// 最初の音符はfromがNULLとなる (The first note has from as NULL)
+		if (org_data.tdata[j].note_num == 0)
 		{
 			info.tdata[j].note_list = NULL;
 			continue;
 		}
 
-		// Make note list
+		// リストを作る (Make a list)
 		np = info.tdata[j].note_p;
 		info.tdata[j].note_list = info.tdata[j].note_p;
 		np->from = NULL;
@@ -497,7 +670,7 @@
 		np->to = (np + 1);
 		np++;
 
-		for (int i = 1; i < info.tdata[j].note_num; i++)
+		for (i = 1; i < org_data.tdata[j].note_num; i++)
 		{
 			np->from = (np - 1);
 			np->to = (np + 1);
@@ -504,171 +677,394 @@
 			np++;
 		}
 
-		// The last note to is NULL
+		// 最後の音符のtoはNULL (The last note to is NULL)
 		np--;
 		np->to = NULL;
 
-		// Set note properties
-		np = info.tdata[j].note_p; // X position
-		for (int i = 0; i < info.tdata[j].note_num; i++)
+		// 内容を代入 (Assign content)
+		np = info.tdata[j].note_p;	// X座標 (X coordinate)
+		for (i = 0; i < org_data.tdata[j].note_num; i++)
 		{
-			np->x = READ_LE32(p);
+			memcpy(&np->x, p, sizeof(long));
+			p += sizeof(long);
 			np++;
 		}
 
-		np = info.tdata[j].note_p; // Y position
-		for (int i = 0; i < info.tdata[j].note_num; i++)
+		np = info.tdata[j].note_p;	// Y座標 (Y coordinate)
+		for (i = 0; i < org_data.tdata[j].note_num; i++)
 		{
-			np->y = *p++;
+			memcpy(&np->y, p, sizeof(unsigned char));
+			p += sizeof(unsigned char);
 			np++;
 		}
 
-		np = info.tdata[j].note_p; // Length
-		for (int i = 0; i < info.tdata[j].note_num; i++)
+		np = info.tdata[j].note_p;	// 長さ (Length)
+		for (i = 0; i < org_data.tdata[j].note_num; i++)
 		{
-			np->length = *p++;
+			memcpy(&np->length, p, sizeof(unsigned char));
+			p += sizeof(unsigned char);
 			np++;
 		}
 
-		np = info.tdata[j].note_p; // Volume
-		for (int i = 0; i < info.tdata[j].note_num; i++)
+		np = info.tdata[j].note_p;	// ボリューム (Volume)
+		for (i = 0; i < org_data.tdata[j].note_num; i++)
 		{
-			np->volume = *p++;
+			memcpy(&np->volume, p, sizeof(unsigned char));
+			p += sizeof(unsigned char);
 			np++;
 		}
 
-		np = info.tdata[j].note_p; // Pan
-		for (int i = 0; i < info.tdata[j].note_num; i++)
+		np = info.tdata[j].note_p;	// パン (Pan)
+		for (i = 0; i < org_data.tdata[j].note_num; i++)
 		{
-			np->pan = *p++;
+			memcpy(&np->pan, p, sizeof(unsigned char));
+			p += sizeof(unsigned char);
 			np++;
 		}
 	}
 
-	// Create waves
-	for (int j = 0; j < 8; j++)
-		MakeOrganyaWave(j, info.tdata[j].wave_no, info.tdata[j].pipi);
+	// データを有効に (Enable data)
+	for (j = 0; j < MAXMELODY; j++)
+		MakeOrganyaWave(j,info.tdata[j].wave_no, info.tdata[j].pipi);
+#ifndef FIX_BUGS
+	// Pixel ripped out some code so he could use PixTone sounds as drums, but he left this dead code
+	for (j = MAXMELODY; j < MAXTRACK; j++)
+	{
+		i = info.tdata[j].wave_no;
+		//InitDramObject(dram_name[i], j - MAXMELODY);
+	}
+#endif
 
-	// Reset position
-	SetPlayPointer(0);
+	SetPlayPointer(0);	// 頭出し (Cue)
 
-	// Set as loaded
-	info.loaded = TRUE;
+	return TRUE;
 }
 
-void SetOrganyaPosition(unsigned int x)
+// 曲情報を取得 (Get song information)
+void OrgData::GetMusicInfo(MUSICINFO *mi)
 {
-	SetPlayPointer(x);
-	gOrgVolume = 100;
-	bFadeout = FALSE;
+	mi->dot = info.dot;
+	mi->line = info.line;
+	mi->alloc_note = info.alloc_note;
+	mi->wait = info.wait;
+	mi->repeat_x = info.repeat_x;
+	mi->end_x = info.end_x;
+
+	for (int i = 0; i < MAXTRACK; i++)
+	{
+		mi->tdata[i].freq = info.tdata[i].freq;
+		mi->tdata[i].wave_no = info.tdata[i].wave_no;
+		mi->tdata[i].pipi = info.tdata[i].pipi;
+	}
 }
 
-unsigned int GetOrganyaPosition()
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+//プロトタイプ宣言 (prototype declaration)
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+
+BOOL InitMMTimer();
+BOOL StartTimer(DWORD dwTimer);
+VOID CALLBACK TimerProc(UINT uTID,UINT uMsg,DWORD dwUser,DWORD dwParam1,DWORD dwParam2);
+BOOL QuitMMTimer();
+
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+//グローバル変数 (Global variable)
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+static UINT ExactTime   = 13;	// 最小精度 (Minimum accuracy)
+static UINT TimerID     = NULL;
+static BOOL nameless_flag;
+
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+// タイマー精度を設定する。 (Set timer accuracy.)
+// この関数はアプリケーション初期化時に一度呼び出す。 (This function is called once when the application is initialized.)
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+BOOL InitMMTimer()
 {
-	return play_p;
+	TIMECAPS tc;
+	MMRESULT ret;
+
+	// タイマーの精度情報を取得する (Get timer accuracy information)
+	ret = timeGetDevCaps(&tc,sizeof(TIMECAPS));
+	if (ret != TIMERR_NOERROR)
+		return FALSE;
+
+	if (ExactTime < tc.wPeriodMin)
+		ExactTime = tc.wPeriodMin;
+
+	// この精度で初期化する (Initialize with this precision)
+	ret = timeBeginPeriod(ExactTime);
+	if (ret != TIMERR_NOERROR)
+		return FALSE;
+
+	return TRUE;
 }
 
-void PlayOrganyaMusic()
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+// タイマーを起動する。 (Start the timer.)
+// dwTimer   設定するタイマー間隔 (dwTimer   Timer interval to be set)
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+BOOL StartTimer(DWORD dwTimer)
 {
-	// Start timer
-	OrganyaStartTimer(info.wait);
+	MMRESULT ret = NULL;
+	ExactTime = dwTimer;
+
+	// タイマーを生成する (Generate timer)
+	TimerID = timeSetEvent
+	(
+		dwTimer,                   // タイマー時間 (Timer time)
+		10,                        // 許容できるタイマー精度 (Acceptable timer accuracy)
+		(LPTIMECALLBACK)TimerProc, // コールバックプロシージャ (Callback procedure)
+		NULL,                      // ユーザーがコールバック関数のdwUserに送る情報値 (Information value sent by user to dwUser in callback function)
+		TIME_PERIODIC              // タイマー時間毎にイベントを発生させる (Generate an event every timer time)
+	);
+
+	if (ret != TIMERR_NOERROR)
+		return FALSE;
+
+	nameless_flag = TRUE;
+
+	return TRUE;
 }
 
-BOOL ChangeOrganyaVolume(signed int volume)
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+// タイマーのコールバック関数 (Timer callback function)
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+VOID CALLBACK TimerProc(UINT uTID,UINT uMsg,DWORD dwUser,DWORD dwParam1,DWORD dwParam2)
 {
-	if (volume >= 0 && volume <= 100)
-	{
-		gOrgVolume = volume;
-		return TRUE;
-	}
-
-	return FALSE;
+	DWORD dwNowTime;
+	dwNowTime = timeGetTime();
+	//===================================================================================
+	// ここにユーザー定義のソースを書く。 (Write user-defined source here.)
+	// 基本的に関数を呼び出すだけで処理は他の関数でするべきだろう。 (Basically just call a function and the process should be another function.)
+	//===================================================================================
+	org_data.PlayData();
 }
 
-void StopOrganyaMusic()
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+// タイマーリソースを開放する。 (Release timer resources.)
+// アプリケーション終了時に一度呼び出す。 (Call once when the application ends.)
+/*■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■*/
+BOOL QuitMMTimer()
 {
-	// Stop timer
-	OrganyaEndTimer();
+	MMRESULT ret;
 
-	// Stop notes
-	for (int i = 0; i < MAXMELODY; i++)
-		PlayOrganObject(0, 2, i, 0);
+	if (!nameless_flag)
+		return FALSE;
 
-	memset(old_key, 255, sizeof(old_key));
-	memset(key_on, 0, sizeof(key_on));
-	memset(key_twin, 0, sizeof(key_twin));
-}
+	if(TimerID != TIMERR_NOERROR)
+	{
+		// タイマーを使用中なら終了させる (Terminate timer if in use)
+		ret = timeKillEvent(TimerID);
+		if (ret != TIMERR_NOERROR)
+			return FALSE;
+	}
 
-void SetOrganyaFadeout()
-{
-	bFadeout = TRUE;
+	// タイマーリソースを開放する (Release timer resources)
+	ret = timeEndPeriod(ExactTime);
+	if (ret != TIMERR_NOERROR)
+		return FALSE;
+
+	nameless_flag = FALSE;
+
+	return TRUE;
 }
 
-// Org timer
-SDL_Thread *OrganyaTimer = NULL;
-BOOL bEndTimer = FALSE;
+// Play data
+long play_p;
+NOTELIST *play_np[MAXTRACK];
+long now_leng[MAXMELODY];
 
-int OrganyaPlayTimer(void *ptr)
+void OrgData::PlayData()
 {
-	SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
+	int i;
 
-	// Set time for next step to play
-	Uint32 NextTick = SDL_GetTicks() + info.wait;
+	// Handle fading out
+	if (bFadeout && gOrgVolume)
+		gOrgVolume -= 2;
+	if (gOrgVolume < 0)
+		gOrgVolume = 0;
 
-	while (bEndTimer == FALSE)
+	// メロディの再生 (Play melody)
+	for (i = 0; i < MAXMELODY; i++)
 	{
-		if (info.loaded)
+		if (play_np[i] != NULL && play_p == play_np[i]->x)
 		{
-			// Play music
-			OrganyaPlayData();
+			if (!g_mute[i] && play_np[i]->y != KEYDUMMY)	// 音が来た。 (The sound has come.)
+			{
+				PlayOrganObject(play_np[i]->y, -1, i, info.tdata[i].freq);
+				now_leng[i] = play_np[i]->length;
+			}
 
-			// Wait until this step is over
-			while (NextTick > SDL_GetTicks())
-				SDL_Delay(1);
+			if (play_np[i]->pan != PANDUMMY)
+				ChangeOrganPan(play_np[i]->y, play_np[i]->pan, i);
+			if (play_np[i]->volume != VOLDUMMY)
+				gTrackVol[i] = play_np[i]->volume;
 
-			// Get time for next step to play
-			while (NextTick <= SDL_GetTicks())
-				NextTick += info.wait;
+			play_np[i] = play_np[i]->to;	// 次の音符を指す (Points to the next note)
 		}
-		else
+
+		if (now_leng[i] == 0)
+			PlayOrganObject(0, 2, i, info.tdata[i].freq);
+
+		if (now_leng[i] > 0)
+			now_leng[i]--;
+
+		if (play_np[i])
+			ChangeOrganVolume(play_np[i]->y, gTrackVol[i] * gOrgVolume / 0x7F, i);
+	}
+
+	// ドラムの再生 (Drum playback)
+	for (i = MAXMELODY; i < MAXTRACK; i++)
+	{
+		if (play_np[i] != NULL && play_p == play_np[i]->x)	// 音が来た。 (The sound has come.)
 		{
-			// Wait until the org is loaded
-			SDL_Delay(1);
+			if (play_np[i]->y != KEYDUMMY && !g_mute[i])	// ならす (Tame)
+				PlayDramObject(play_np[i]->y, 1, i - MAXMELODY);
+
+			if (play_np[i]->pan != PANDUMMY)
+				ChangeDramPan(play_np[i]->pan, i - MAXMELODY);
+			if (play_np[i]->volume != VOLDUMMY)
+				gTrackVol[i] = play_np[i]->volume;
+
+			play_np[i] = play_np[i]->to;	// 次の音符を指す (Points to the next note)
 		}
+
+		if (play_np[i])
+			ChangeDramVolume(gTrackVol[i] * gOrgVolume / 0x7F, i - MAXMELODY);
 	}
 
-	return 0;
+	// Looping
+	play_p++;
+	if (play_p >= info.end_x)
+	{
+		play_p = info.repeat_x;
+		SetPlayPointer(play_p);
+	}
 }
 
-void OrganyaStartTimer(unsigned int wait)
+void OrgData::SetPlayPointer(long x)
 {
-	OrganyaEndTimer();
-	bEndTimer = FALSE;
-	OrganyaTimer = SDL_CreateThread(OrganyaPlayTimer, "OrganyaPlayTimer", (void*)NULL);
+	for (int i = 0; i < MAXTRACK; i++)
+	{
+		play_np[i] = info.tdata[i].note_list;
+		while (play_np[i] != NULL && play_np[i]->x < x)
+			play_np[i] = play_np[i]->to;	// 見るべき音符を設定 (Set note to watch)
+	}
+
+	play_p = x;
 }
 
-void OrganyaEndTimer()
+// Start and end organya
+BOOL StartOrganya(LPDIRECTSOUND _lpDS, const char *path_wave)	// Both arguments are ignored for some reason
 {
-	bEndTimer = TRUE; // Tell thread to end
-	SDL_WaitThread(OrganyaTimer, NULL); // Wait for thread to end
-	OrganyaTimer = NULL;
+	if (lpDS == NULL)
+		return FALSE;
+
+	if (!InitWaveData100())
+		return FALSE;
+
+	org_data.InitOrgData();
+
+	return TRUE;
 }
 
-// Start and end organya
-void StartOrganya()
+// Load organya file
+BOOL LoadOrganya(const char *name)
 {
-	// Initialize org stuff
-	InitWaveData100();
+	if (lpDS == NULL)
+		return FALSE;
+
+	if (!org_data.InitMusicData(name))
+		return FALSE;
+
+	gOrgVolume = 100;
+	bFadeout = 0;
+
+#ifdef FIX_BUGS
+	return TRUE;
+#else
+	return FALSE;	// Err... isn't this meant to be 'TRUE'?
+#endif
 }
 
+void SetOrganyaPosition(unsigned int x)
+{
+	if (lpDS == NULL)
+		return;
+
+	org_data.SetPlayPointer(x);
+	gOrgVolume = 100;
+	bFadeout = FALSE;
+}
+
+unsigned int GetOrganyaPosition(void)
+{
+	if (lpDS == NULL)
+		return 0;
+
+	return play_p;
+}
+
+void PlayOrganyaMusic(void)
+{
+	if (lpDS == NULL)
+		return;
+
+	QuitMMTimer();
+	InitMMTimer();
+	StartTimer(org_data.info.wait);
+}
+
+BOOL ChangeOrganyaVolume(signed int volume)
+{
+	if (lpDS == NULL)
+		return FALSE;
+
+	if (volume < 0 || volume > 100)
+		return FALSE;
+
+	gOrgVolume = volume;
+	return TRUE;
+}
+
+void StopOrganyaMusic()
+{
+	if (lpDS == NULL)
+		return;
+
+	// Stop timer
+	QuitMMTimer();
+
+	// Stop notes
+	for (int i = 0; i < MAXMELODY; i++)
+		PlayOrganObject(0, 2, i, 0);
+
+	memset(old_key, 255, sizeof(old_key));
+	memset(key_on, 0, sizeof(key_on));
+	memset(key_twin, 0, sizeof(key_twin));
+
+	Sleep(100);
+}
+
+void SetOrganyaFadeout()
+{
+	bFadeout = TRUE;
+}
+
 void EndOrganya()
 {
+	if (lpDS == NULL)
+		return;
+
 	// End timer
-	OrganyaEndTimer();
+	QuitMMTimer();
 
 	// Release everything related to org
-	OrganyaReleaseNote();
+	org_data.ReleaseNote();
 
 	for (int i = 0; i < MAXMELODY; i++)
+	{
+		PlayOrganObject(0, 0, i, 0);
 		ReleaseOrganyaObject(i);
+	}
 }
--- a/src/Organya.h
+++ b/src/Organya.h
@@ -1,50 +1,13 @@
 #pragma once
 
+#include <dsound.h>
+
 #include "WindowsWrapper.h"
 
-//Below are Organya song data structures
-struct NOTELIST
-{
-	NOTELIST *from; //Previous address
-	NOTELIST *to; //Next address
-
-	long x; //Position
-	unsigned char length; //Sound length
-	unsigned char y; //Sound height
-	unsigned char volume; //Volume
-	unsigned char pan;
-};
-
-//Track data * 8
-struct TRACKDATA
-{
-	unsigned short freq; //Frequency (1000 is default)
-	unsigned char wave_no; //Waveform No.
-	signed char pipi;
-	unsigned short note_num; //Number of notes
-
-	NOTELIST *note_p;
-	NOTELIST *note_list;
-};
-
-//Unique information held in songs
-struct MUSICINFO
-{
-	unsigned short wait;
-	BOOL loaded;
-	BOOL playing;
-	unsigned char line; //Number of lines in one measure
-	unsigned char dot; //Number of dots per line
-	unsigned short alloc_note; //Number of allocated notes
-	long repeat_x; //Repeat
-	long end_x; //End of song (Return to repeat)
-	TRACKDATA tdata[16];
-};
-
 BOOL MakeOrganyaWave(signed char track, signed char wave_no, signed char pipi);
 void OrganyaPlayData();
 void SetPlayPointer(long x);
-void LoadOrganya(const char *name);
+BOOL LoadOrganya(const char *name);
 void SetOrganyaPosition(unsigned int x);
 unsigned int GetOrganyaPosition();
 void PlayOrganyaMusic();
@@ -51,7 +14,5 @@
 BOOL ChangeOrganyaVolume(signed int volume);
 void StopOrganyaMusic();
 void SetOrganyaFadeout();
-void OrganyaStartTimer(unsigned int wait);
-void OrganyaEndTimer();
-void StartOrganya();
+BOOL StartOrganya(LPDIRECTSOUND lpDS, const char *wave_filename);
 void EndOrganya();
--- a/src/Sound.cpp
+++ b/src/Sound.cpp
@@ -1,6 +1,15 @@
 // Some of the original source code for this file can be found here:
 // https://github.com/shbow/organya/blob/master/source/Sound.cpp
 
+/*
+TODO - Code style
+Pixel's code was *extremely* Windows-centric, to the point of using
+things like ZeroMemory and LPCSTR instead of standard things like
+memset and const char*. For now, the decompilation is accurate despite
+not using these since they're just macros that evaluate to the portable
+equivalents.
+*/
+
 #include "Sound.h"
 
 #include <math.h>
@@ -8,333 +17,361 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "SDL.h"
+#include <dsound.h>
 
 #include "WindowsWrapper.h"
 
+#include "CommonDefines.h"
 #include "Organya.h"
 #include "PixTone.h"
+#include "Tags.h"
 
 #define FREQUENCY 44100
 
-#ifdef RASPBERRY_PI
-#define STREAM_SIZE 0x400	// Larger buffer to prevent stutter
-#else
-#define STREAM_SIZE 0x100	// FREQUENCY/200 rounded to the nearest power of 2 (SDL2 *needs* a power-of-2 buffer size)
-#endif
+LPDIRECTSOUND       lpDS;            // DirectSoundオブジェクト (DirectSound object)
+LPDIRECTSOUNDBUFFER lpPRIMARYBUFFER; // 一時バッファ (Temporary buffer)
+LPDIRECTSOUNDBUFFER lpSECONDARYBUFFER[SE_MAX]; 
 
-#define clamp(x, y, z) (((x) > (z)) ? (z) : ((x) < (y)) ? (y) : (x))
-
-//Audio device
-SDL_AudioDeviceID audioDevice;
-
-//Keep track of all existing sound buffers
-SOUNDBUFFER *soundBuffers;
-
-//Sound buffer code
-SOUNDBUFFER::SOUNDBUFFER(size_t bufSize)
+// DirectSoundの開始 (Starting DirectSound)
+BOOL InitDirectSound(HWND hwnd)
 {
-	//Lock audio buffer
-	SDL_LockAudioDevice(audioDevice);
+	int i;
+	DSBUFFERDESC1 dsbd;
 
-	//Set parameters
-	size = bufSize;
+	// DirectDrawの初期化 (DirectDraw initialization)
+	if (DirectSoundCreate(NULL, &lpDS, NULL) != DS_OK)
+	{
+		lpDS = NULL;
+		StartOrganya(lpDS, "Org\\Wave.dat");
+		return FALSE;
+	}
 
-	playing = false;
-	looping = false;
-	looped = false;
+	lpDS->SetCooperativeLevel(hwnd, DSSCL_EXCLUSIVE);
 
-	frequency = 0.0;
-	volume = 1.0;
-	volume_l = 1.0;
-	volume_r = 1.0;
-	samplePosition = 0.0;
+	// 一次バッファの初期化 (Initializing the primary buffer)
+	ZeroMemory(&dsbd, sizeof(DSBUFFERDESC1));
+	dsbd.dwSize = sizeof(DSBUFFERDESC1);
+	dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME;
+	lpDS->CreateSoundBuffer((DSBUFFERDESC*)&dsbd, &lpPRIMARYBUFFER, NULL);
 
-	//Create waveform buffer
-	data = new unsigned char[bufSize];
-	memset(data, 0x80, bufSize);
+	for (i = 0; i < SE_MAX; i++)
+		lpSECONDARYBUFFER[i] = NULL;
 
-	//Add to buffer list
-	this->next = soundBuffers;
-	soundBuffers = this;
+	StartOrganya(lpDS, "Org\\Wave.dat");
 
-	//Unlock audio buffer
-	SDL_UnlockAudioDevice(audioDevice);
+	return TRUE;
 }
 
-SOUNDBUFFER::~SOUNDBUFFER()
+// DirectSoundの終了 (Exit DirectSound)
+void EndDirectSound(void)
 {
-	//Lock audio buffer
-	SDL_LockAudioDevice(audioDevice);
+	int i;
 
-	//Free buffer
-	if (data)
-		delete[] data;
+	if (lpDS == NULL)
+		return;
 
-	//Remove from buffer list
-	for (SOUNDBUFFER **soundBuffer = &soundBuffers; *soundBuffer != NULL; soundBuffer = &(*soundBuffer)->next)
-	{
-		if (*soundBuffer == this)
-		{
-			*soundBuffer = this->next;
-			break;
-		}
-	}
+	EndOrganya();
 
-	//Unlock audio buffer
-	SDL_UnlockAudioDevice(audioDevice);
-}
+	for (i = 0; i < SE_MAX; i++)
+		if (lpSECONDARYBUFFER[i] != NULL)
+			lpSECONDARYBUFFER[i]->Release();
 
-void SOUNDBUFFER::Release()
-{
-	//TODO: find a better and more stable(?) way to handle this function
-	delete this;
+	if (lpPRIMARYBUFFER != NULL)
+		lpPRIMARYBUFFER->Release();
+
+	if (lpDS != NULL)
+		lpDS->Release();
+
+	lpDS = NULL;
 }
 
-void SOUNDBUFFER::Lock(unsigned char **outBuffer, size_t *outSize)
+// サウンドの設定 (Sound settings)
+BOOL InitSoundObject(LPCSTR resname, int no)
 {
-	SDL_LockAudioDevice(audioDevice);
+	HRSRC hrscr;
+	DSBUFFERDESC1 dsbd;
+	DWORD *lpdword;	// リソースのアドレス (Resource address)
 
-	if (outBuffer != NULL)
-		*outBuffer = data;
+	if (lpDS == NULL)
+		return TRUE;
 
-	if (outSize != NULL)
-		*outSize = size;
-}
+	// リソースの検索 (Search for resources)
+	if ((hrscr = FindResourceA(NULL, resname, "WAVE")) == NULL)
+		return FALSE;
 
-void SOUNDBUFFER::Unlock()
-{
-	SDL_UnlockAudioDevice(audioDevice);
-}
+	// リソースのアドレスを取得 (Get resource address)
+	lpdword = (DWORD*)LockResource(LoadResource(NULL, hrscr));
 
-void SOUNDBUFFER::SetCurrentPosition(unsigned long dwNewPosition)
-{
-	SDL_LockAudioDevice(audioDevice);
-	samplePosition = dwNewPosition;
-	SDL_UnlockAudioDevice(audioDevice);
-}
+	// 二次バッファの生成 (Create secondary buffer)
+	ZeroMemory(&dsbd, sizeof(DSBUFFERDESC1));
+	dsbd.dwSize = sizeof(DSBUFFERDESC1);
+	dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
+	dsbd.dwBufferBytes = *(DWORD*)((BYTE*)lpdword+0x36);	// WAVEデータのサイズ (WAVE data size)
+	dsbd.lpwfxFormat = (LPWAVEFORMATEX)(lpdword+5); 
 
-void SOUNDBUFFER::SetFrequency(unsigned long dwFrequency)
-{
-	SDL_LockAudioDevice(audioDevice);
-	frequency = (double)dwFrequency;
-	SDL_UnlockAudioDevice(audioDevice);
-}
+	if (lpDS->CreateSoundBuffer((DSBUFFERDESC*)&dsbd, &lpSECONDARYBUFFER[no], NULL) != DS_OK)
+		return FALSE;
 
-float MillibelToVolume(long lVolume)
-{
-	//Volume is in hundredths of decibels, from 0 to -10000
-	lVolume = clamp(lVolume, (long)-10000, (long)0);
-	return (float)pow(10.0, lVolume / 2000.0);
-}
+	LPVOID lpbuf1, lpbuf2;
+	DWORD dwbuf1, dwbuf2;
 
-void SOUNDBUFFER::SetVolume(long lVolume)
-{
-	SDL_LockAudioDevice(audioDevice);
-	volume = MillibelToVolume(lVolume);
-	SDL_UnlockAudioDevice(audioDevice);
-}
+	// 二次バッファのロック (Secondary buffer lock)
+	lpSECONDARYBUFFER[no]->Lock(0, *(DWORD*)((BYTE*)lpdword+0x36), &lpbuf1, &dwbuf1, &lpbuf2, &dwbuf2, 0); 
 
-void SOUNDBUFFER::SetPan(long lPan)
-{
-	SDL_LockAudioDevice(audioDevice);
-	volume_l = MillibelToVolume(-lPan);
-	volume_r = MillibelToVolume(lPan);
-	SDL_UnlockAudioDevice(audioDevice);
-}
+	// 音源データの設定 (Sound source data settings)
+	CopyMemory(lpbuf1, (BYTE*)lpdword+0x3A, dwbuf1);
 
-void SOUNDBUFFER::Play(bool bLooping)
-{
-	SDL_LockAudioDevice(audioDevice);
-	playing = true;
-	looping = bLooping;
-	SDL_UnlockAudioDevice(audioDevice);
-}
+	if (dwbuf2 != 0)
+		CopyMemory(lpbuf2, (BYTE*)lpdword+0x3A+dwbuf1, dwbuf2);
 
-void SOUNDBUFFER::Stop()
-{
-	SDL_LockAudioDevice(audioDevice);
-	playing = false;
-	SDL_UnlockAudioDevice(audioDevice);
+	// 二次バッファのロック解除 (Unlock secondary buffer)
+	lpSECONDARYBUFFER[no]->Unlock(lpbuf1, dwbuf1, lpbuf2, dwbuf2); 
+
+	return TRUE;
 }
 
-void SOUNDBUFFER::Mix(float *buffer, size_t frames)
+BOOL LoadSoundObject(LPCSTR file_name, int no)
 {
-	if (!playing) //This sound buffer isn't playing
-		return;
+	char path[PATH_LENGTH];
+	DWORD i;
+	DWORD file_size = 0;
+	char check_box[58];
+	FILE *fp;
+	HANDLE hFile;
 
-	for (size_t i = 0; i < frames; ++i)
-	{
-		const double freqPosition = frequency / FREQUENCY; //This is added to position at the end
+	sprintf(path, "%s\\%s", gModulePath, file_name);
 
-		//Get the in-between sample this is (linear interpolation)
-		const float sample1 = ((looped || ((size_t)samplePosition) >= 1) ? data[(size_t)samplePosition] : 128.0f);
-		const float sample2 = ((looping || (((size_t)samplePosition) + 1) < size) ? data[(((size_t)samplePosition) + 1) % size] : 128.0f);
+	if (lpDS == NULL)
+		return TRUE;
 
-		//Interpolate sample
-		const float subPos = (float)fmod(samplePosition, 1.0);
-		const float sampleA = sample1 + (sample2 - sample1) * subPos;
+	hFile = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+	if (hFile == INVALID_HANDLE_VALUE)
+		return FALSE;
 
-		//Convert sample to float32
-		const float sampleConvert = (sampleA - 128.0f) / 128.0f;
+	file_size = GetFileSize(hFile, NULL);
+	CloseHandle(hFile);
 
-		//Mix
-		*buffer++ += (float)(sampleConvert * volume * volume_l);
-		*buffer++ += (float)(sampleConvert * volume * volume_r);
+	if ((fp = fopen(path, "rb")) == NULL)
+		return FALSE;
 
-		//Increment position
-		samplePosition += freqPosition;
+	for (i = 0; i < 58; i++)
+		fread(&check_box[i], sizeof(char), 1, fp);
 
-		if (samplePosition >= size)
-		{
-			if (looping)
-			{
-				samplePosition = fmod(samplePosition, size);
-				looped = true;
-			}
-			else
-			{
-				samplePosition = 0.0;
-				playing = false;
-				looped = false;
-				break;
-			}
-		}
-	}
-}
+	if (check_box[0] != 'R')
+		return FALSE;
+	if (check_box[1] != 'I')
+		return FALSE;
+	if (check_box[2] != 'F')
+		return FALSE;
+	if (check_box[3] != 'F')
+		return FALSE;
 
-//Sound mixer
-void AudioCallback(void *userdata, Uint8 *stream, int len)
-{
-	(void)userdata;
+	DWORD *wp;
+	wp = (DWORD*)malloc(file_size);	// ファイルのワークスペースを作る (Create a file workspace)
+	fseek(fp, 0, SEEK_SET);
 
-	float *buffer = (float*)stream;
-	const size_t frames = len / (sizeof(float) * 2);
+	for (i = 0; i < file_size; i++)
+		fread((BYTE*)wp+i, sizeof(BYTE), 1, fp);
 
-	//Clear stream
-	for (size_t i = 0; i < frames * 2; ++i)
-		buffer[i] = 0.0f;
+	fclose(fp);
 
-	//Mix sounds to primary buffer
-	for (SOUNDBUFFER *sound = soundBuffers; sound != NULL; sound = sound->next)
-		sound->Mix(buffer, frames);
-}
+	// セカンダリバッファの生成 (Create secondary buffer)
+	DSBUFFERDESC1 dsbd;
+	ZeroMemory(&dsbd, sizeof(DSBUFFERDESC1));
+	dsbd.dwSize = sizeof(DSBUFFERDESC1);
+	dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
+	dsbd.dwBufferBytes = *(DWORD*)((BYTE*)wp+0x36);	// WAVEデータのサイズ (WAVE data size)
+	dsbd.lpwfxFormat = (LPWAVEFORMATEX)(wp+5); 
 
-//Sound things
-SOUNDBUFFER* lpSECONDARYBUFFER[SE_MAX];
+	if (lpDS->CreateSoundBuffer((DSBUFFERDESC*)&dsbd, &lpSECONDARYBUFFER[no], NULL) != DS_OK)
+	{
+#ifdef FIX_BUGS
+		free(wp);	// The updated Organya source code includes this fix
+#endif
+		return FALSE;	
+	}
 
-BOOL InitDirectSound()
-{
-	//Init sound
-	SDL_InitSubSystem(SDL_INIT_AUDIO);
+	LPVOID lpbuf1, lpbuf2;
+	DWORD dwbuf1, dwbuf2;
 
-	//Open audio device
-	SDL_AudioSpec want, have;
+	HRESULT hr;
+	hr = lpSECONDARYBUFFER[no]->Lock(0, *(DWORD*)((BYTE*)wp+0x36), &lpbuf1, &dwbuf1, &lpbuf2, &dwbuf2, 0);
 
-	//Set specifications we want
-	SDL_memset(&want, 0, sizeof(want));
-	want.freq = FREQUENCY;
-	want.format = AUDIO_F32;
-	want.channels = 2;
-	want.samples = STREAM_SIZE;
-	want.callback = AudioCallback;
-
-	audioDevice = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
-
-	if (audioDevice == 0)
+	if (hr != DS_OK)
 	{
-		printf("Failed to open audio device\nSDL Error: %s\n", SDL_GetError());
+#ifdef FIX_BUGS
+		free(wp);	// The updated Organya source code includes this fix
+#endif
 		return FALSE;
 	}
 
-	//Unpause audio device
-	SDL_PauseAudioDevice(audioDevice, 0);
+	CopyMemory(lpbuf1, (BYTE*)wp+0x3A, dwbuf1);	// +3aはデータの頭 (+ 3a is the head of the data)
 
-	for (unsigned int i = 0; i < SE_MAX; ++i)
-		lpSECONDARYBUFFER[i] = NULL;
+	if (dwbuf2 != 0)
+		CopyMemory(lpbuf2, (BYTE*)wp+0x3A+dwbuf1, dwbuf2);
 
-	//Start organya
-	StartOrganya();
+	lpSECONDARYBUFFER[no]->Unlock(lpbuf1, dwbuf1, lpbuf2, dwbuf2); 
+	
+	free(wp);
+
 	return TRUE;
 }
 
-void EndDirectSound()
-{
-	EndOrganya();
-
-	for (unsigned int i = 0; i < SE_MAX; ++i)
-		if (lpSECONDARYBUFFER[i])
-			lpSECONDARYBUFFER[i]->Release();
-
-	SDL_QuitSubSystem(SDL_INIT_AUDIO);
-
-	SDL_CloseAudioDevice(audioDevice);
-
-}
-
-//Sound effects playing
 void PlaySoundObject(int no, int mode)
 {
-	if (lpSECONDARYBUFFER[no])
+	if (lpDS == NULL)
+		return;
+
+	if (lpSECONDARYBUFFER[no] != NULL)
 	{
 		switch (mode)
 		{
-			case 0:
+			case 0:	// 停止 (Stop)
 				lpSECONDARYBUFFER[no]->Stop();
 				break;
 
-			case 1:
+			case 1:	// 再生 (Playback)
 				lpSECONDARYBUFFER[no]->Stop();
 				lpSECONDARYBUFFER[no]->SetCurrentPosition(0);
-				lpSECONDARYBUFFER[no]->Play(false);
+				lpSECONDARYBUFFER[no]->Play(0, 0, 0);
 				break;
 
-			case -1:
-				lpSECONDARYBUFFER[no]->Play(true);
+			case -1:// ループ再生 (Loop playback)
+				lpSECONDARYBUFFER[no]->Play(0, 0, DSBPLAY_LOOPING);
 				break;
 		}
 	}
 }
 
-void ChangeSoundFrequency(int no, unsigned long rate)
+void ChangeSoundFrequency(int no, DWORD rate)	// 100がMIN9999がMAXで2195?がノーマル (100 is MIN, 9999 is MAX, and 2195 is normal)
 {
+	if (lpDS == NULL)
+		return;
+
 	lpSECONDARYBUFFER[no]->SetFrequency((rate * 10) + 100);
 }
 
-void ChangeSoundVolume(int no, long volume)
+void ChangeSoundVolume(int no, long volume)	// 300がMAXで300がノーマル (300 is MAX and 300 is normal)
 {
+	if (lpDS == NULL)
+		return;
+
 	lpSECONDARYBUFFER[no]->SetVolume((volume - 300) * 8);
 }
 
-void ChangeSoundPan(int no, long pan)
+void ChangeSoundPan(int no, long pan)	// 512がMAXで256がノーマル (512 is MAX and 256 is normal)
 {
+	if (lpDS == NULL)
+		return;
+
 	lpSECONDARYBUFFER[no]->SetPan((pan - 256) * 10);
 }
 
 int MakePixToneObject(const PIXTONEPARAMETER *ptp, int ptp_num, int no)
 {
-	int sample_count = 0;
-	for (int i = 0; i < ptp_num; ++i)
+	typedef struct WavHeader
 	{
-		if (ptp[i].size > sample_count)
-			sample_count = ptp[i].size;
+		char riff_header[4];
+		unsigned long wav_size;
+		char wav_header[4];
+		char fmt_header[4];
+		unsigned long fmt_chunk_size;
+		unsigned short audio_format;
+		unsigned short num_channels;
+		unsigned long sample_rate;
+		unsigned long byte_rate;
+		unsigned short sample_alignment;
+		unsigned short bit_depth;
+		char data_header[4];
+		unsigned long data_bytes;
+	} WavHeader;
+
+	int i;
+	int j;
+	DSBUFFERDESC1 dsbd;
+	WavHeader wav_header;
+	const PIXTONEPARAMETER *ptp_pointer;
+	int sample_count;
+	unsigned char *pcm_buffer;
+	unsigned char *mixed_pcm_buffer;
+
+	if (lpDS == NULL)
+		return 0;
+
+	const char *riff = "RIFF";
+	const char *fmt = "fmt ";
+	const char *wave = "WAVE";
+	const char *data = "data";
+
+	wav_header.bit_depth = 8;
+	wav_header.sample_rate = 22050;
+	wav_header.num_channels = 1;
+	wav_header.audio_format = WAVE_FORMAT_PCM;
+	wav_header.fmt_chunk_size = 16;
+	memcpy(wav_header.riff_header, riff, 4);
+	memcpy(wav_header.fmt_header, fmt, 4);
+	memcpy(wav_header.wav_header, wave, 4);
+	memcpy(wav_header.data_header, data, 4);
+	wav_header.sample_alignment = (wav_header.bit_depth / 8) * wav_header.num_channels;
+	wav_header.byte_rate = (wav_header.bit_depth / 8) * wav_header.num_channels * wav_header.sample_rate;
+	wav_header.data_bytes = wav_header.sample_alignment * ptp->size;
+	wav_header.wav_size = wav_header.data_bytes + 36;
+
+	ptp_pointer = ptp;
+	sample_count = 0;
+
+	for (i = 0; i < ptp_num; i++)
+	{
+		if (ptp_pointer->size > sample_count)
+			sample_count = ptp_pointer->size;
+
+		++ptp_pointer;
 	}
 
-	unsigned char *pcm_buffer = (unsigned char*)malloc(sample_count);
-	unsigned char *mixed_pcm_buffer = (unsigned char*)malloc(sample_count);
+	ZeroMemory(&dsbd, sizeof(DSBUFFERDESC1));
+	dsbd.dwSize = sizeof(DSBUFFERDESC1);
+	dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
+	dsbd.dwBufferBytes = sample_count;
+	dsbd.lpwfxFormat = (WAVEFORMATEX*)&wav_header.audio_format;
+
+	if (lpDS->CreateSoundBuffer((DSBUFFERDESC*)&dsbd, &lpSECONDARYBUFFER[no], 0) != DS_OK)
+		return -1;
+
+	pcm_buffer = mixed_pcm_buffer = NULL;
+
+	pcm_buffer = (unsigned char*)malloc(sample_count);
+	mixed_pcm_buffer = (unsigned char*)malloc(sample_count);
+
+	if (pcm_buffer == NULL || mixed_pcm_buffer == NULL)
+	{
+		if (pcm_buffer != NULL)
+			free(pcm_buffer);
+
+		if (mixed_pcm_buffer != NULL)
+			free(mixed_pcm_buffer);
+
+		return -1;
+	}
+
 	memset(pcm_buffer, 0x80, sample_count);
 	memset(mixed_pcm_buffer, 0x80, sample_count);
 
-	for (int i = 0; i < ptp_num; ++i)
+	ptp_pointer = ptp;
+
+	for (i = 0; i < ptp_num; i++)
 	{
-		if (!MakePixelWaveData(&ptp[i], pcm_buffer))
+		if (!MakePixelWaveData(ptp_pointer, pcm_buffer))
 		{
-			free(pcm_buffer);
-			free(mixed_pcm_buffer);
+			if (pcm_buffer)
+				free(pcm_buffer);
+
+			if (mixed_pcm_buffer)
+				free(mixed_pcm_buffer);
+
 			return -1;
 		}
 
-		for (int j = 0; j < ptp[i].size; ++j)
+		for (j = 0; j < ptp_pointer->size; j++)
 		{
 			if (pcm_buffer[j] + mixed_pcm_buffer[j] - 0x100 < -0x7F)
 				mixed_pcm_buffer[j] = 0;
@@ -341,20 +378,33 @@
 			else if (pcm_buffer[j] + mixed_pcm_buffer[j] - 0x100 > 0x7F)
 				mixed_pcm_buffer[j] = 0xFF;
 			else
-				mixed_pcm_buffer[j] += pcm_buffer[j] + -0x80;
+				mixed_pcm_buffer[j] = mixed_pcm_buffer[j] + pcm_buffer[j] - 0x80;
 		}
+
+		++ptp_pointer;
 	}
 
-	lpSECONDARYBUFFER[no] = new SOUNDBUFFER(sample_count);
+	// Maybe this used to be something to prevent audio popping?
+	mixed_pcm_buffer[0] = mixed_pcm_buffer[0];
+	mixed_pcm_buffer[sample_count - 1] = mixed_pcm_buffer[sample_count - 1];
 
-	unsigned char *buf;
-	lpSECONDARYBUFFER[no]->Lock(&buf, NULL);
-	memcpy(buf, mixed_pcm_buffer, sample_count);
-	lpSECONDARYBUFFER[no]->Unlock();
-	lpSECONDARYBUFFER[no]->SetFrequency(22050);
+	LPVOID lpbuf1, lpbuf2;
+	DWORD dwbuf1, dwbuf2;
 
-	free(pcm_buffer);
-	free(mixed_pcm_buffer);
+	lpSECONDARYBUFFER[no]->Lock(0, sample_count, &lpbuf1, &dwbuf1, &lpbuf2, &dwbuf2, 0); 
+
+	CopyMemory(lpbuf1, mixed_pcm_buffer, dwbuf1);
+
+	if (dwbuf2 != 0)
+		CopyMemory(lpbuf2, mixed_pcm_buffer + dwbuf1, dwbuf2);
+
+	lpSECONDARYBUFFER[no]->Unlock(lpbuf1, dwbuf1, lpbuf2, dwbuf2);
+
+	if (pcm_buffer != NULL)
+		free(pcm_buffer);
+
+	if (mixed_pcm_buffer != NULL)
+		free(mixed_pcm_buffer);
 
 	return sample_count;
 }
--- a/src/Sound.h
+++ b/src/Sound.h
@@ -2,52 +2,19 @@
 
 #include <stddef.h>
 
+#include <dsound.h>
+
 #include "WindowsWrapper.h"
 
 #include "PixTone.h"
 
-class SOUNDBUFFER
-{
-	public:
-		SOUNDBUFFER(size_t bufSize);
-		~SOUNDBUFFER();
-
-		void Release();
-
-		void Lock(unsigned char **buffer, size_t *size);
-		void Unlock();
-
-		void SetCurrentPosition(unsigned long dwNewPosition);
-		void SetFrequency(unsigned long dwFrequency);
-		void SetVolume(long lVolume);
-		void SetPan(long lPan);
-		void Play(bool bLooping);
-		void Stop();
-
-		void Mix(float *buffer, size_t frames);
-
-		SOUNDBUFFER *next;
-
-	private:
-		unsigned char *data;
-		size_t size;
-
-		bool playing;
-		bool looping;
-		bool looped;
-
-		double frequency;
-		double volume;
-		double volume_l;
-		double volume_r;
-		double samplePosition;
-};
-
 #define SE_MAX 160	// According to the Organya source code release, this is the real name for this constant
-extern SOUNDBUFFER* lpSECONDARYBUFFER[SE_MAX];
 
-BOOL InitDirectSound();
-void EndDirectSound();
+extern LPDIRECTSOUND       lpDS;
+extern LPDIRECTSOUNDBUFFER lpSECONDARYBUFFER[SE_MAX];
+
+BOOL InitDirectSound(HWND hwnd);
+void EndDirectSound(void);
 void PlaySoundObject(int no, int mode);
 void ChangeSoundFrequency(int no, unsigned long rate);
 void ChangeSoundVolume(int no, long volume);