ASM-accurate Sound.cpp and Organya.cpp (except for one function)
This commit is contained in:
parent
e67c1e3640
commit
470c5d86d5
7 changed files with 1207 additions and 714 deletions
|
@ -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=""
|
||||
|
|
|
@ -963,6 +963,10 @@ addr = 0x41A5D0
|
|||
name = "LoadTimeCounter"
|
||||
addr = 0x41A7C0
|
||||
|
||||
[[func]]
|
||||
name = "MakeSoundObject8"
|
||||
addr = 0x41A8F0
|
||||
|
||||
[[func]]
|
||||
name = "ChangeOrganFrequency"
|
||||
addr = 0x41ABA0
|
||||
|
@ -983,7 +987,7 @@ name = "PlayOrganObject"
|
|||
addr = 0x41ADC0
|
||||
|
||||
[[func]]
|
||||
name = "ReleaseOrganya"
|
||||
name = "ReleaseOrganyaObject"
|
||||
addr = 0x41B2A0
|
||||
|
||||
[[func]]
|
||||
|
@ -1010,6 +1014,95 @@ addr = 0x41B4D0
|
|||
name = "PlayDramObject"
|
||||
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
|
||||
|
@ -1106,6 +1199,22 @@ addr = 0x41FA10
|
|||
name = "ShootBullet"
|
||||
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
|
||||
|
@ -1125,6 +1234,10 @@ name = "ChangeSoundPan"
|
|||
addr = 0x4207A0
|
||||
size = 0x36
|
||||
|
||||
[[func]]
|
||||
name = "MakePixToneObject"
|
||||
addr = 0x4207E0
|
||||
|
||||
[[func]]
|
||||
name = "TransferStage"
|
||||
addr = 0x420BE0
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_syswm.h"
|
||||
|
||||
#include "WindowsWrapper.h"
|
||||
|
||||
|
@ -347,11 +348,16 @@ int main(int argc, char *argv[])
|
|||
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())
|
||||
|
|
1118
src/Organya.cpp
1118
src/Organya.cpp
File diff suppressed because it is too large
Load diff
|
@ -1,57 +1,18 @@
|
|||
#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();
|
||||
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();
|
||||
|
|
578
src/Sound.cpp
578
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,353 +17,394 @@
|
|||
#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;
|
||||
|
||||
playing = false;
|
||||
looping = false;
|
||||
looped = false;
|
||||
|
||||
frequency = 0.0;
|
||||
volume = 1.0;
|
||||
volume_l = 1.0;
|
||||
volume_r = 1.0;
|
||||
samplePosition = 0.0;
|
||||
|
||||
//Create waveform buffer
|
||||
data = new unsigned char[bufSize];
|
||||
memset(data, 0x80, bufSize);
|
||||
|
||||
//Add to buffer list
|
||||
this->next = soundBuffers;
|
||||
soundBuffers = this;
|
||||
|
||||
//Unlock audio buffer
|
||||
SDL_UnlockAudioDevice(audioDevice);
|
||||
}
|
||||
|
||||
SOUNDBUFFER::~SOUNDBUFFER()
|
||||
{
|
||||
//Lock audio buffer
|
||||
SDL_LockAudioDevice(audioDevice);
|
||||
|
||||
//Free buffer
|
||||
if (data)
|
||||
delete[] data;
|
||||
|
||||
//Remove from buffer list
|
||||
for (SOUNDBUFFER **soundBuffer = &soundBuffers; *soundBuffer != NULL; soundBuffer = &(*soundBuffer)->next)
|
||||
// DirectDrawの初期化 (DirectDraw initialization)
|
||||
if (DirectSoundCreate(NULL, &lpDS, NULL) != DS_OK)
|
||||
{
|
||||
if (*soundBuffer == this)
|
||||
{
|
||||
*soundBuffer = this->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Unlock audio buffer
|
||||
SDL_UnlockAudioDevice(audioDevice);
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::Release()
|
||||
{
|
||||
//TODO: find a better and more stable(?) way to handle this function
|
||||
delete this;
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::Lock(unsigned char **outBuffer, size_t *outSize)
|
||||
{
|
||||
SDL_LockAudioDevice(audioDevice);
|
||||
|
||||
if (outBuffer != NULL)
|
||||
*outBuffer = data;
|
||||
|
||||
if (outSize != NULL)
|
||||
*outSize = size;
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::Unlock()
|
||||
{
|
||||
SDL_UnlockAudioDevice(audioDevice);
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::SetCurrentPosition(unsigned long dwNewPosition)
|
||||
{
|
||||
SDL_LockAudioDevice(audioDevice);
|
||||
samplePosition = dwNewPosition;
|
||||
SDL_UnlockAudioDevice(audioDevice);
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::SetFrequency(unsigned long dwFrequency)
|
||||
{
|
||||
SDL_LockAudioDevice(audioDevice);
|
||||
frequency = (double)dwFrequency;
|
||||
SDL_UnlockAudioDevice(audioDevice);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::SetVolume(long lVolume)
|
||||
{
|
||||
SDL_LockAudioDevice(audioDevice);
|
||||
volume = MillibelToVolume(lVolume);
|
||||
SDL_UnlockAudioDevice(audioDevice);
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::SetPan(long lPan)
|
||||
{
|
||||
SDL_LockAudioDevice(audioDevice);
|
||||
volume_l = MillibelToVolume(-lPan);
|
||||
volume_r = MillibelToVolume(lPan);
|
||||
SDL_UnlockAudioDevice(audioDevice);
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::Play(bool bLooping)
|
||||
{
|
||||
SDL_LockAudioDevice(audioDevice);
|
||||
playing = true;
|
||||
looping = bLooping;
|
||||
SDL_UnlockAudioDevice(audioDevice);
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::Stop()
|
||||
{
|
||||
SDL_LockAudioDevice(audioDevice);
|
||||
playing = false;
|
||||
SDL_UnlockAudioDevice(audioDevice);
|
||||
}
|
||||
|
||||
void SOUNDBUFFER::Mix(float *buffer, size_t frames)
|
||||
{
|
||||
if (!playing) //This sound buffer isn't playing
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < frames; ++i)
|
||||
{
|
||||
const double freqPosition = frequency / FREQUENCY; //This is added to position at the end
|
||||
|
||||
//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);
|
||||
|
||||
//Interpolate sample
|
||||
const float subPos = (float)fmod(samplePosition, 1.0);
|
||||
const float sampleA = sample1 + (sample2 - sample1) * subPos;
|
||||
|
||||
//Convert sample to float32
|
||||
const float sampleConvert = (sampleA - 128.0f) / 128.0f;
|
||||
|
||||
//Mix
|
||||
*buffer++ += (float)(sampleConvert * volume * volume_l);
|
||||
*buffer++ += (float)(sampleConvert * volume * volume_r);
|
||||
|
||||
//Increment position
|
||||
samplePosition += freqPosition;
|
||||
|
||||
if (samplePosition >= size)
|
||||
{
|
||||
if (looping)
|
||||
{
|
||||
samplePosition = fmod(samplePosition, size);
|
||||
looped = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
samplePosition = 0.0;
|
||||
playing = false;
|
||||
looped = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Sound mixer
|
||||
void AudioCallback(void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
(void)userdata;
|
||||
|
||||
float *buffer = (float*)stream;
|
||||
const size_t frames = len / (sizeof(float) * 2);
|
||||
|
||||
//Clear stream
|
||||
for (size_t i = 0; i < frames * 2; ++i)
|
||||
buffer[i] = 0.0f;
|
||||
|
||||
//Mix sounds to primary buffer
|
||||
for (SOUNDBUFFER *sound = soundBuffers; sound != NULL; sound = sound->next)
|
||||
sound->Mix(buffer, frames);
|
||||
}
|
||||
|
||||
//Sound things
|
||||
SOUNDBUFFER* lpSECONDARYBUFFER[SE_MAX];
|
||||
|
||||
BOOL InitDirectSound()
|
||||
{
|
||||
//Init sound
|
||||
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||
|
||||
//Open audio device
|
||||
SDL_AudioSpec want, have;
|
||||
|
||||
//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)
|
||||
{
|
||||
printf("Failed to open audio device\nSDL Error: %s\n", SDL_GetError());
|
||||
lpDS = NULL;
|
||||
StartOrganya(lpDS, "Org\\Wave.dat");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//Unpause audio device
|
||||
SDL_PauseAudioDevice(audioDevice, 0);
|
||||
lpDS->SetCooperativeLevel(hwnd, DSSCL_EXCLUSIVE);
|
||||
|
||||
for (unsigned int i = 0; i < SE_MAX; ++i)
|
||||
// 一次バッファの初期化 (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);
|
||||
|
||||
for (i = 0; i < SE_MAX; i++)
|
||||
lpSECONDARYBUFFER[i] = NULL;
|
||||
|
||||
//Start organya
|
||||
StartOrganya();
|
||||
StartOrganya(lpDS, "Org\\Wave.dat");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void EndDirectSound()
|
||||
// DirectSoundの終了 (Exit DirectSound)
|
||||
void EndDirectSound(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (lpDS == NULL)
|
||||
return;
|
||||
|
||||
EndOrganya();
|
||||
|
||||
for (unsigned int i = 0; i < SE_MAX; ++i)
|
||||
if (lpSECONDARYBUFFER[i])
|
||||
for (i = 0; i < SE_MAX; i++)
|
||||
if (lpSECONDARYBUFFER[i] != NULL)
|
||||
lpSECONDARYBUFFER[i]->Release();
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
if (lpPRIMARYBUFFER != NULL)
|
||||
lpPRIMARYBUFFER->Release();
|
||||
|
||||
SDL_CloseAudioDevice(audioDevice);
|
||||
if (lpDS != NULL)
|
||||
lpDS->Release();
|
||||
|
||||
lpDS = NULL;
|
||||
}
|
||||
|
||||
// サウンドの設定 (Sound settings)
|
||||
BOOL InitSoundObject(LPCSTR resname, int no)
|
||||
{
|
||||
HRSRC hrscr;
|
||||
DSBUFFERDESC1 dsbd;
|
||||
DWORD *lpdword; // リソースのアドレス (Resource address)
|
||||
|
||||
if (lpDS == NULL)
|
||||
return TRUE;
|
||||
|
||||
// リソースの検索 (Search for resources)
|
||||
if ((hrscr = FindResourceA(NULL, resname, "WAVE")) == NULL)
|
||||
return FALSE;
|
||||
|
||||
// リソースのアドレスを取得 (Get resource address)
|
||||
lpdword = (DWORD*)LockResource(LoadResource(NULL, hrscr));
|
||||
|
||||
// 二次バッファの生成 (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);
|
||||
|
||||
if (lpDS->CreateSoundBuffer((DSBUFFERDESC*)&dsbd, &lpSECONDARYBUFFER[no], NULL) != DS_OK)
|
||||
return FALSE;
|
||||
|
||||
LPVOID lpbuf1, lpbuf2;
|
||||
DWORD dwbuf1, dwbuf2;
|
||||
|
||||
// 二次バッファのロック (Secondary buffer lock)
|
||||
lpSECONDARYBUFFER[no]->Lock(0, *(DWORD*)((BYTE*)lpdword+0x36), &lpbuf1, &dwbuf1, &lpbuf2, &dwbuf2, 0);
|
||||
|
||||
// 音源データの設定 (Sound source data settings)
|
||||
CopyMemory(lpbuf1, (BYTE*)lpdword+0x3A, dwbuf1);
|
||||
|
||||
if (dwbuf2 != 0)
|
||||
CopyMemory(lpbuf2, (BYTE*)lpdword+0x3A+dwbuf1, dwbuf2);
|
||||
|
||||
// 二次バッファのロック解除 (Unlock secondary buffer)
|
||||
lpSECONDARYBUFFER[no]->Unlock(lpbuf1, dwbuf1, lpbuf2, dwbuf2);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LoadSoundObject(LPCSTR file_name, int no)
|
||||
{
|
||||
char path[PATH_LENGTH];
|
||||
DWORD i;
|
||||
DWORD file_size = 0;
|
||||
char check_box[58];
|
||||
FILE *fp;
|
||||
HANDLE hFile;
|
||||
|
||||
sprintf(path, "%s\\%s", gModulePath, file_name);
|
||||
|
||||
if (lpDS == NULL)
|
||||
return TRUE;
|
||||
|
||||
hFile = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
|
||||
file_size = GetFileSize(hFile, NULL);
|
||||
CloseHandle(hFile);
|
||||
|
||||
if ((fp = fopen(path, "rb")) == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < 58; i++)
|
||||
fread(&check_box[i], sizeof(char), 1, fp);
|
||||
|
||||
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;
|
||||
|
||||
DWORD *wp;
|
||||
wp = (DWORD*)malloc(file_size); // ファイルのワークスペースを作る (Create a file workspace)
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
for (i = 0; i < file_size; i++)
|
||||
fread((BYTE*)wp+i, sizeof(BYTE), 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
// セカンダリバッファの生成 (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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
LPVOID lpbuf1, lpbuf2;
|
||||
DWORD dwbuf1, dwbuf2;
|
||||
|
||||
HRESULT hr;
|
||||
hr = lpSECONDARYBUFFER[no]->Lock(0, *(DWORD*)((BYTE*)wp+0x36), &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+0x3A, dwbuf1); // +3aはデータの頭 (+ 3a is the head of the data)
|
||||
|
||||
if (dwbuf2 != 0)
|
||||
CopyMemory(lpbuf2, (BYTE*)wp+0x3A+dwbuf1, dwbuf2);
|
||||
|
||||
lpSECONDARYBUFFER[no]->Unlock(lpbuf1, dwbuf1, lpbuf2, dwbuf2);
|
||||
|
||||
free(wp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
unsigned char *pcm_buffer = (unsigned char*)malloc(sample_count);
|
||||
unsigned char *mixed_pcm_buffer = (unsigned char*)malloc(sample_count);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
|
47
src/Sound.h
47
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);
|
||||
|
|
Loading…
Add table
Reference in a new issue