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

This commit is contained in:
Clownacy 2019-08-28 07:55:42 +01:00
parent e67c1e3640
commit 470c5d86d5
7 changed files with 1207 additions and 714 deletions

View file

@ -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=""

View file

@ -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

View file

@ -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())

File diff suppressed because it is too large Load diff

View file

@ -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();

View file

@ -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;
}

View file

@ -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);