Per-channel audio buffers from DOS executable (#329)

* implements DOS-style per channel audio
This commit is contained in:
Dethrace Engineering Department 2023-05-19 11:58:41 +12:00 committed by GitHub
parent 07d517307a
commit 3b0f32284a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 245 additions and 122 deletions

View File

@ -145,15 +145,15 @@ void InitSound(void) {
}
if (gSound_detail_level != gOld_sound_detail_level) {
if (gCar_outlet) {
S3DisposeOutlet(gCar_outlet);
S3ReleaseOutlet(gCar_outlet);
gCar_outlet = 0;
}
if (gPedestrians_outlet) {
S3DisposeOutlet(gPedestrians_outlet);
S3ReleaseOutlet(gPedestrians_outlet);
gPedestrians_outlet = 0;
}
if (gEngine_outlet) {
S3DisposeOutlet(gEngine_outlet);
S3ReleaseOutlet(gEngine_outlet);
gEngine_outlet = 0;
}
if (gEngine_outlet == NULL) {
@ -240,7 +240,7 @@ int DRS3ChangeVolume(tS3_sound_tag pSound_tag, tS3_volume pNew_volume) {
if (gSound_enabled == 0) {
return 0;
}
return S3SetTagVolume(pSound_tag, pNew_volume);
return S3ChangeVolume(pSound_tag, pNew_volume);
}
// IDA: int __usercall DRS3ChangeLRVolume@<EAX>(tS3_sound_tag pSound_tag@<EAX>, tS3_volume pNew_Lvolume@<EDX>, tS3_volume pNew_Rvolume@<EBX>)
@ -296,7 +296,7 @@ int DRS3ReleaseSound(tS3_sound_id pThe_sound) {
if (gSound_enabled == 0) {
return 0;
}
return S3DisposeDescriptor(pThe_sound);
return S3ReleaseSound(pThe_sound);
}
// IDA: void __cdecl DRS3Service()
@ -497,7 +497,7 @@ void DisposeSoundSources(void) {
if (the_car->driver == eDriver_local_human || gSound_detail_level == 2 || cat == eVehicle_rozzer) {
if (the_car->sound_source) {
S3UpdateSoundSource(gEngine_outlet, -1, the_car->sound_source, 0.0f, 0, 0, 0, 0x10000, 0x10000);
S3DisposeSoundSource(the_car->sound_source);
S3ReleaseSoundSource(the_car->sound_source);
}
the_car->sound_source = NULL;
}

View File

@ -1,5 +1,6 @@
#include "3d.h"
#include "audio.h"
#include "harness/trace.h"
#include "resource.h"
#include "s3sound.h"
#include <math.h>
@ -105,7 +106,7 @@ void S3UpdateListenerVectors(void) {
}
}
void S3ServiceSoundSources(void) {
void S3ServiceAmbientSoundSources(void) {
tS3_sound_source* s; // [esp+Ch] [ebp-4h]
for (s = gS3_sound_sources; s; s = s->next) {
@ -120,6 +121,7 @@ void S3ServiceSoundSources(void) {
s->channel = NULL;
s->tag = 0;
}
if (s->channel == NULL) {
if (s->time_since_last_played <= s->period || !s->period || s->tag) {
if ((s->ambient_repeats == 0 || s->period == 0) && s->tag == 0) {
@ -142,7 +144,6 @@ void S3ServiceSoundSources(void) {
int S3UpdateSpatialSound(tS3_channel* chan) {
int close_enough_to_play; // [esp+10h] [ebp-4h]
if (chan->sound_source_ptr && chan->sound_source_ptr->ambient) {
close_enough_to_play = S3Calculate3D(chan, 1);
} else {
@ -238,8 +239,8 @@ void S3UpdateSoundSource(tS3_outlet* outlet, tS3_sound_tag tag, tS3_sound_source
src->pitch = pPitch;
if (chan && chan->descriptor && chan->descriptor->type == eS3_ST_sample) {
chan->initial_pitch = S3IRandomBetweenLog(chan->descriptor->min_pitch, chan->descriptor->max_pitch, ((tS3_sample*)chan->descriptor->sound_data)->rate);
chan->initial_pitch = ldexpf(src->pitch, -16) * chan->initial_pitch;
chan->initial_pitch = ldexpf(src->speed, -16) * chan->initial_pitch;
chan->initial_pitch *= ldexpf(src->pitch, -16);
chan->initial_pitch *= ldexpf(src->speed, -16);
}
}
if (pAmbient_repeats != -1) {
@ -331,6 +332,7 @@ tS3_sound_tag S3ServiceSoundSource(tS3_sound_source* src) {
if (src->speed < 0) {
src->speed = 0x10000;
}
gS3_channel_template.rate = ldexp(src->pitch, -16) * gS3_channel_template.rate;
if (!outlet->independent_pitch) {
gS3_channel_template.rate = ldexp(src->speed, -16) * gS3_channel_template.rate;
@ -341,7 +343,6 @@ tS3_sound_tag S3ServiceSoundSource(tS3_sound_source* src) {
S3CopyVector3(&gS3_channel_template.lastpos, src->position_ptr, src->brender_vector);
}
gS3_channel_template.pMax_distance_squared = src->max_distance_sq;
if (S3Calculate3D(&gS3_channel_template, 1) == 0) {
src->tag = 0;
src->channel = NULL;
@ -443,6 +444,7 @@ tS3_sound_tag S3StartSound3D(tS3_outlet* pOutlet, tS3_sound_id pSound, tS3_vecto
gS3_channel_template.initial_pitch = gS3_channel_template.rate;
gS3_channel_template.position = *pInitial_position;
gS3_channel_template.velocity = *pInitial_velocity;
if (S3Calculate3D(&gS3_channel_template, 0) == 0) {
return 0;
}
@ -526,6 +528,7 @@ int S3Calculate3D(tS3_channel* chan, int pIs_ambient) {
} else {
chan->rate = chan->initial_pitch;
}
vol_multiplier = 1.0f / (dist / 6.0f + 1.0f);
if (!gS3_inside_cockpit) {
vol_multiplier = vol_multiplier * 1.3f;

View File

@ -7,7 +7,7 @@
void S3Set3DSoundEnvironment(float a1, float a2, float a3);
void S3UpdateListenerVectors(void);
void S3ServiceSoundSources(void);
void S3ServiceAmbientSoundSources(void);
int S3UpdateSpatialSound(tS3_channel* chan);
int S3BindAmbientSoundToOutlet(tS3_outlet* pOutlet, int pSound, tS3_sound_source* source, float pMax_distance, int pPeriod, int pRepeats, int pVolume, int pPitch, int pSpeed);
void S3UpdateSoundSource(tS3_outlet* outlet, tS3_sound_tag tag, tS3_sound_source* src, float pMax_distance_squared, int pPeriod, tS3_repeats pAmbient_repeats, tS3_volume pVolume, int pPitch, tS3_speed pSpeed);

View File

@ -103,14 +103,14 @@ void S3Shutdown(void) {
S3Disable();
for (descriptor = gS3_descriptors; descriptor != NULL; descriptor = next_descriptor) {
next_descriptor = descriptor->next;
S3DisposeDescriptor(descriptor->id);
S3ReleaseSound(descriptor->id);
S3MemFree(descriptor);
}
for (outlet = gS3_outlets; outlet != NULL; outlet = next_outlet) {
next_outlet = outlet->next;
S3DisposeOutlet(outlet);
S3ReleaseOutlet(outlet);
}
S3DisposeUnboundChannels();
S3ReleaseUnboundChannels();
}
if (gS3_opened_output_devices) {
S3CloseDevices();
@ -138,10 +138,7 @@ int S3OpenOutputDevices(void) {
S3OpenCDADevice();
gS3_hardware_info.timer_installed = 0;
gS3_hardware_info.device_installed = 1;
// changed by dethrace
// gS3_hardware_info.independent_pitch = 0;
gS3_hardware_info.independent_pitch = 1;
gS3_hardware_info.independent_pitch = 0;
return 1;
}
@ -190,10 +187,11 @@ void S3CloseDevices(void) {
ma_engine_uninit(&miniaudio_engine);
}
int S3DisposeDescriptor(tS3_sound_id id) {
int S3ReleaseSound(tS3_sound_id id) {
tS3_channel* c; // [esp+Ch] [ebp-10h]
tS3_outlet* o; // [esp+10h] [ebp-Ch]
tS3_descriptor* desc; // [esp+14h] [ebp-8h]
tS3_sample* sample_ptr;
if (!gS3_enabled) {
return 0;
@ -207,18 +205,19 @@ int S3DisposeDescriptor(tS3_sound_id id) {
for (o = gS3_outlets; o; o = o->next) {
for (c = o->channel_list; c; c = c->next) {
if (c->descriptor && c->descriptor->id == id) {
S3DisposeMIDIChannel(c->tag);
S3ReleaseMIDI(c->tag);
}
}
}
} else if (desc->type == eS3_ST_sample) {
if (desc->sound_data == NULL) {
sample_ptr = (tS3_sample*)desc->sound_data;
if (sample_ptr == NULL) {
return 0;
}
S3MemFree(desc->sound_data);
S3MemFree(sample_ptr->freeptr);
S3MemFree(sample_ptr);
desc->sound_data = NULL;
}
return 0;
}
@ -343,7 +342,7 @@ int S3SoundBankReadEntry(tS3_soundbank_read_ctx* ctx, char* dir_name, int low_me
int char_count; // [esp+2Ch] [ebp-4h] BYREF
char cda_dir_name[4];
desc = S3AllocateDescriptor();
desc = S3CreateDescriptor();
if (!desc) {
return gS3_last_error;
}
@ -439,7 +438,7 @@ int S3SoundBankReadEntry(tS3_soundbank_read_ctx* ctx, char* dir_name, int low_me
return 1;
}
tS3_descriptor* S3AllocateDescriptor(void) {
tS3_descriptor* S3CreateDescriptor(void) {
tS3_descriptor* root;
tS3_descriptor* d;
@ -538,7 +537,7 @@ int S3CreateOutletChannels(tS3_outlet* outlet, int pChannel_count) {
memset(chan, 0, sizeof(tS3_channel));
chan->owner_outlet = outlet;
if (sub_49D837(chan) == 0) {
if (S3CreateTypeStructs(chan) == 0) {
S3MemFree(chan);
return pChannel_count;
}
@ -554,7 +553,7 @@ int S3CreateOutletChannels(tS3_outlet* outlet, int pChannel_count) {
return 0;
}
void S3DisposeOutlet(tS3_outlet* outlet) {
void S3ReleaseOutlet(tS3_outlet* outlet) {
tS3_outlet* next;
tS3_outlet* prev;
@ -586,7 +585,7 @@ int S3UnbindChannels(tS3_outlet* outlet) {
for (chan = outlet->channel_list; chan; chan = next) {
next = chan->next;
sub_49D84C(chan);
S3ReleaseTypeStructs(chan);
if (gS3_unbound_channels) {
gS3_last_unbound_channel->next = chan;
} else {
@ -599,7 +598,7 @@ int S3UnbindChannels(tS3_outlet* outlet) {
return 1;
}
void S3DisposeUnboundChannels(void) {
void S3ReleaseUnboundChannels(void) {
tS3_channel* channel; // [esp+Ch] [ebp-8h]
tS3_channel* next_channel; // [esp+10h] [ebp-4h]
@ -686,7 +685,7 @@ int S3StopChannel(tS3_channel* chan) {
}
if ((chan->descriptor->flags & 2) != 0) {
S3DisposeDescriptor(chan->descriptor->id);
S3ReleaseSound(chan->descriptor->id);
}
chan->repetitions = 1;
return 0;
@ -732,7 +731,7 @@ tS3_sound_source* S3CreateSoundSource(void* pPosition, void* pVelocity, tS3_outl
return src;
}
int S3DisposeSoundSource(tS3_sound_source* src) {
int S3ReleaseSoundSource(tS3_sound_source* src) {
tS3_sound_source* prev; // [esp+Ch] [ebp-8h]
tS3_sound_source* next; // [esp+10h] [ebp-4h]
@ -781,14 +780,14 @@ void S3Service(int inside_cockpit, int unk1) {
S3ServiceOutlets();
if (unk1 == 1) {
S3UpdateListenerVectors();
S3ServiceSoundSources();
S3ServiceAmbientSoundSources();
}
for (o = gS3_outlets; o; o = o->next) {
for (c = o->channel_list; c; c = c->next) {
if (c->needs_service) {
c->needs_service = 0;
if (c->descriptor && c->descriptor->flags == 2) {
S3DisposeDescriptor(c->descriptor->id);
S3ReleaseSound(c->descriptor->id);
}
c->active = 0;
if (c->type != eS3_ST_midi) {
@ -834,9 +833,12 @@ void S3ServiceOutlets(void) {
}
int S3ServiceChannel(tS3_channel* chan) {
tS3_sample_struct_miniaudio* miniaudio;
if (chan->type == eS3_ST_sample) {
miniaudio = (tS3_sample_struct_miniaudio*)chan->type_struct_sample;
if (chan->descriptor && chan->descriptor->type == chan->type) {
if (ma_sound_is_playing(chan->descriptor->sound_buffer)) {
if (ma_sound_is_playing(&miniaudio->sound)) {
return 1;
}
}
@ -898,7 +900,7 @@ tS3_sound_tag S3StartSound(tS3_outlet* pOutlet, tS3_sound_id pSound) {
}
}
if (chan->descriptor && chan->descriptor->type == 1 && chan->descriptor->id != pSound) {
S3DisposeMIDIChannel(chan->tag);
S3ReleaseMIDI(chan->tag);
}
chan->spatial_sound = 0;
chan->sound_source_ptr = 0;
@ -982,7 +984,7 @@ tS3_sound_tag S3StartSound2(tS3_outlet* pOutlet, tS3_sound_id pSound, tS3_repeat
if (chan->descriptor && chan->descriptor->type == eS3_ST_midi) {
if (chan->descriptor->id != pSound) {
S3DisposeMIDIChannel(chan->tag);
S3ReleaseMIDI(chan->tag);
}
}
chan->spatial_sound = 0;
@ -1078,8 +1080,8 @@ int S3IRandomBetweenLog(int pMin, int pMax, int pDefault) {
if (pMin == -1 || pMin >= pMax) {
return pDefault;
}
v4 = S3FRandomBetween(logf(pMin), logf(pMax));
return ldexpf(expf(v4), -16) * pDefault;
v4 = S3FRandomBetween(log(pMin), log(pMax));
return ldexp(exp(v4), -16) * pDefault;
}
// duplicate of S3FRandomBetween2
@ -1146,7 +1148,7 @@ int S3StopSound(tS3_sound_tag pTag) {
}
if ((chan->descriptor->flags & 2) != 0) {
S3DisposeDescriptor(chan->descriptor->id);
S3ReleaseSound(chan->descriptor->id);
}
chan->repetitions = 1;
return 0;
@ -1215,7 +1217,7 @@ int S3SetOutletVolume(tS3_outlet* pOutlet, tS3_volume pVolume) {
for (c = pOutlet->channel_list; c; c = c->next) {
c->volume_multiplier = pVolume / 150.0f;
if (c->active) {
S3SetTagVolume(c->tag, pVolume);
S3ChangeVolume(c->tag, pVolume);
}
}
return 0;
@ -1242,7 +1244,7 @@ tS3_channel* S3GetChannelForTag(tS3_sound_tag tag) {
return 0;
}
int S3SetTagVolume(tS3_sound_tag pTag, tS3_volume pVolume) {
int S3ChangeVolume(tS3_sound_tag pTag, tS3_volume pVolume) {
tS3_channel* chan; // [esp+14h] [ebp-4h]
if (!gS3_enabled) {

View File

@ -24,17 +24,17 @@ int S3OpenSampleDevice(void);
void S3CloseDevices(void);
tS3_outlet* S3CreateOutlet(int unk1, int pChannel_count);
int S3CreateOutletChannels(tS3_outlet* outlet, int pChannel_count);
void S3DisposeOutlet(tS3_outlet* outlet);
void S3ReleaseOutlet(tS3_outlet* outlet);
int S3UnbindChannels(tS3_outlet* outlet);
void S3DisposeUnboundChannels(void);
void S3ReleaseUnboundChannels(void);
tS3_channel* S3AllocateChannel(tS3_outlet* outlet, int priority);
int S3StopChannel(tS3_channel* chan);
void S3DisposeOutlet(tS3_outlet* outlet);
void S3ReleaseOutlet(tS3_outlet* outlet);
int S3StopOutletSound(tS3_outlet* pOutlet);
void S3StopAllOutletSounds(void);
int S3DisposeDescriptor(tS3_sound_id id);
int S3ReleaseSound(tS3_sound_id id);
char* S3LoadSoundBankFile(char* pThe_path);
int S3LoadSoundbank(const char* pSoundbank_filename, int pLow_memory_mode);
@ -46,7 +46,7 @@ void S3SoundBankReaderAdvance(tS3_soundbank_read_ctx* buffer, int bytes_read);
int S3SoundBankReaderReadFilename(char** filename, tS3_soundbank_read_ctx* ctx, const char* dir_name);
int S3SoundBankReadEntry(tS3_soundbank_read_ctx* ctx, char* dir_name, int low_memory_mode);
tS3_descriptor* S3AllocateDescriptor(void);
tS3_descriptor* S3CreateDescriptor(void);
tS3_descriptor* S3GetDescriptorByID(tS3_sound_id id);
char* S3GetCurrentDir(void);
@ -57,10 +57,10 @@ int S3IRandomBetweenLog(int pMin, int pMax, int pDefault);
double S3FRandomBetween(double pMin, double pMax);
int S3GenerateTag(tS3_outlet* outlet);
int S3DisposeDescriptor(tS3_sound_id id);
int S3ReleaseSound(tS3_sound_id id);
int S3SetOutletVolume(tS3_outlet* pOutlet, tS3_volume pVolume);
tS3_channel* S3GetChannelForTag(tS3_sound_tag tag);
int S3SetTagVolume(tS3_sound_tag pTag, tS3_volume pVolume);
int S3ChangeVolume(tS3_sound_tag pTag, tS3_volume pVolume);
void S3ServiceOutlets(void);
int S3ServiceChannel(tS3_channel* chan);

View File

@ -5,7 +5,7 @@
typedef float tF32;
typedef struct tS3_sound_source tS3_sound_source;
typedef tS3_sound_source *tS3_sound_source_ptr;
typedef tS3_sound_source* tS3_sound_source_ptr;
typedef int tS3_sound_tag;
typedef int tS3_sound_id;
typedef int tS3_type;
@ -38,11 +38,11 @@ int S3BindAmbientSoundToOutlet(tS3_outlet_ptr pOutlet, int pSound, tS3_sound_sou
tS3_sound_tag S3StartSound3D(tS3_outlet_ptr pOutlet, tS3_sound_id pSound, tS3_vector3* pInitial_position, tS3_vector3* pInitial_velocity, tS3_repeats pRepeats, tS3_volume pVolume, tS3_pitch pPitch, tS3_speed pSpeed);
tS3_outlet_ptr S3CreateOutlet(int unk1, int pChannel_count);
void S3DisposeOutlet(tS3_outlet_ptr outlet);
int S3DisposeDescriptor(tS3_sound_id id);
int S3DisposeSoundSource(tS3_sound_source_ptr src);
void S3ReleaseOutlet(tS3_outlet_ptr outlet);
int S3ReleaseSound(tS3_sound_id id);
int S3ReleaseSoundSource(tS3_sound_source_ptr src);
int S3SetTagVolume(tS3_sound_tag pTag, tS3_volume pVolume);
int S3ChangeVolume(tS3_sound_tag pTag, tS3_volume pVolume);
void S3Service(int inside_cockpit, int unk1);

View File

@ -3,6 +3,7 @@
#include "s3/s3.h"
#include <miniaudio/miniaudio.h>
#include <stdint.h>
// extern int PDGetTotalTime();
@ -131,8 +132,8 @@ typedef struct tS3_descriptor {
int memory_proxy;
char* sound_data;
char* filename;
// LPDIRECTSOUNDBUFFER for example
void* sound_buffer;
// win95 only
// LPDIRECTSOUNDBUFFER sound_buffer;
} tS3_descriptor;
typedef struct tS3_sound_source {
@ -175,7 +176,7 @@ typedef struct tS3_hardware_info {
int independent_pitch;
} tS3_hardware_info;
// Added by dethrace
// Everything below added by dethrace
typedef struct tS3_soundbank_read_ctx {
int data_len;
int unk1;
@ -183,7 +184,6 @@ typedef struct tS3_soundbank_read_ctx {
char* data;
} tS3_soundbank_read_ctx;
// Everything below added by dethrace
#pragma pack(push, 1)
typedef struct tWAVEFORMATEX_ {
int16_t wFormatTag;
@ -196,4 +196,33 @@ typedef struct tWAVEFORMATEX_ {
} tWAVEFORMATEX_;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct wav_header {
// RIFF Header
char riff_header[4]; // Contains "RIFF"
int32_t wav_size; // Size of the wav portion of the file, which follows the first 8 bytes. File size - 8
char wave_header[4]; // Contains "WAVE"
// Format Header
char fmt_header[4]; // Contains "fmt " (includes trailing space)
int32_t fmt_chunk_size; // Should be 16 for PCM
int16_t audio_format; // Should be 1 for PCM. 3 for IEEE Float
int16_t num_channels;
int32_t sample_rate;
int32_t byte_rate; // Number of bytes per second. sample_rate * num_channels * Bytes Per Sample
int16_t sample_alignment; // num_channels * Bytes Per Sample
int16_t bit_depth; // Number of bits per sample
// Data
char data_header[4]; // Contains "data"
int32_t data_bytes; // Number of bytes in data. Number of samples * num_channels * sample byte size
} wav_header;
#pragma pack(pop)
typedef struct tS3_sample_struct_miniaudio {
ma_audio_buffer_ref buffer_ref;
ma_sound sound;
int initialized;
} tS3_sample_struct_miniaudio;
#endif

View File

@ -12,7 +12,7 @@ void S3StopMIDIOutlets(void) {
STUB();
}
void S3DisposeMIDIChannel(tS3_sound_tag tag) {
void S3ReleaseMIDI(tS3_sound_tag tag) {
}
int S3PlayMIDI(tS3_channel* chan) {

View File

@ -5,7 +5,7 @@
void S3DisableMIDI(void);
void S3StopMIDIOutlets(void);
void S3DisposeMIDIChannel(tS3_sound_tag);
void S3ReleaseMIDI(tS3_sound_tag);
int S3PlayMIDI(tS3_channel* chan);
int S3MIDILoadSong(tS3_channel* chan);
int S3SetMIDIVolume(tS3_channel* chan);

View File

@ -11,6 +11,7 @@
extern void dr_dprintf(char* fmt_string, ...);
int gS3_sample_filter_funcs_registered;
long gS3_last_file_length;
tS3_sample_filter* gS3_sample_filter_func;
tS3_sample_filter* gS3_sample_filter_disable_func;
@ -21,9 +22,10 @@ int S3LoadSample(tS3_sound_id id) {
// changed by dethrace for compatibility
// char filename[80]; // [esp+10h] [ebp-5Ch] BYREF
char filename[MAX_PATH_LENGTH];
tS3_descriptor* descriptor; // [esp+60h] [ebp-Ch]
tS3_sample* sample; // [esp+68h] [ebp-4h]
// LPDIRECTSOUNDBUFFER WavFile; // eax
tS3_descriptor* descriptor;
tS3_sample* sample;
char* buf;
// LPDIRECTSOUNDBUFFER dsound_buffer; // win95 only
if (!gS3_enabled) {
return 0;
@ -46,12 +48,33 @@ int S3LoadSample(tS3_sound_id id) {
}
memset(sample, 0, sizeof(tS3_sample));
descriptor->sound_buffer = S3LoadWavFile(filename, sample);
if (!descriptor->sound_buffer) {
buf = S3LoadWavFile_DOS(filename);
if (buf == NULL) {
S3MemFree(sample);
return gS3_last_error;
}
sample->freeptr = buf;
if (memcmp(buf, "RIFF", 4) == 0) {
wav_header* hdr = (wav_header*)buf;
sample->dataptr = &buf[sizeof(wav_header)];
sample->size = hdr->data_bytes;
sample->rate = hdr->sample_rate;
sample->resolution = hdr->bit_depth;
sample->channels = hdr->num_channels;
} else {
sample->rate = 16000;
sample->resolution = 8;
sample->channels = 1;
sample->dataptr = buf;
sample->size = gS3_last_file_length;
}
// win95
// descriptor->sound_buffer = S3LoadWavFile(filename, sample);
// if (!descriptor->sound_buffer) {
// S3MemFree(sample);
// return gS3_last_error;
// }
descriptor->special_fx = 0;
descriptor->sound_data = (char*)sample;
return eS3_error_none;
@ -118,7 +141,40 @@ int S3ReadWavHeader(char* buf, tWAVEFORMATEX_** pWav_format, char** data_ptr, in
return 0;
}
void* S3LoadWavFile(char* pFile_name, tS3_sample* pSample) {
void* S3LoadWavFile_DOS(char* pFile_name) {
FILE* f;
long file_len;
size_t bytes_read;
char* buf;
f = fopen(pFile_name, "rb");
if (f == NULL) {
gS3_last_error = eS3_error_readfile;
return 0;
}
fseek(f, 0, SEEK_END);
file_len = ftell(f);
fseek(f, 0, SEEK_SET);
buf = S3MemAllocate(file_len + 1, kMem_S3_sample);
if (buf) {
bytes_read = fread(buf, 1, file_len, f);
if (bytes_read == file_len) {
gS3_last_file_length = file_len;
fclose(f);
return buf;
} else {
gS3_last_error = 4;
}
} else {
fclose(f);
gS3_last_error = eS3_error_memory;
}
return 0;
}
void* S3LoadWavFile_Win95(char* pFile_name, tS3_sample* pSample) {
FILE* f; // [esp+Ch] [ebp-C8h]
size_t bytes_read; // [esp+14h] [ebp-C0h] BYREF
// unsigned int locked_buffer_data_len; // [esp+18h] [ebp-BCh] BYREF
@ -132,7 +188,7 @@ void* S3LoadWavFile(char* pFile_name, tS3_sample* pSample) {
// char* locked_buffer_data; // [esp+CCh] [ebp-8h] BYREF
size_t file_len; // [esp+D0h] [ebp-4h]
f = fopen(pFile_name, "r");
f = fopen(pFile_name, "rb");
if (f == NULL) {
gS3_last_error = eS3_error_readfile;
return 0;
@ -170,16 +226,6 @@ void* S3LoadWavFile(char* pFile_name, tS3_sample* pSample) {
pSample->channels = BrSwap32(pSample->channels);
#endif
ma_sound* sound = malloc(sizeof(ma_sound));
// TOOD: load from memory - we've already read the file data
if (ma_sound_init_from_file(&miniaudio_engine, pFile_name, MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_NO_SPATIALIZATION, NULL, NULL, sound) != MA_SUCCESS) {
return NULL; // Failed to load sound.
}
S3MemFree(buf);
return sound;
// S3MemFree(buf);
// buffer_desc.dwReserved = 0;
// buffer_desc.dwSize = 20;
// buffer_desc.dwFlags = 226;
@ -207,19 +253,27 @@ void* S3LoadWavFile(char* pFile_name, tS3_sample* pSample) {
}
int S3StopSample(tS3_channel* chan) {
if (chan->descriptor && chan->descriptor->type == chan->type) {
ma_sound_stop(chan->descriptor->sound_buffer);
ma_sound_seek_to_pcm_frame(chan->descriptor->sound_buffer, 0);
tS3_sample_struct_miniaudio* miniaudio;
// dsound_buffer = chan->descriptor->dsound_buffer;
// if (dsound_buffer) {
// dsound_buffer->lpVtbl->Stop(dsound_buffer);
// dsound_buffer->lpVtbl->SetCurrentPosition(dsound_buffer, 0);
// }
if (chan->tag == 0) {
return 1;
}
if (chan->active) {
chan->needs_service = 1;
miniaudio = (tS3_sample_struct_miniaudio*)chan->type_struct_sample;
if (miniaudio == NULL) {
return 0;
}
if (miniaudio->initialized) {
ma_sound_stop(&miniaudio->sound);
ma_sound_uninit(&miniaudio->sound);
ma_audio_buffer_ref_uninit(&miniaudio->buffer_ref);
miniaudio->initialized = 0;
if (chan->active) {
chan->needs_service = 1;
}
}
return 1;
}
@ -236,44 +290,72 @@ int S3ExecuteSampleFilterFuncs(tS3_channel* chan) {
int S3PlaySample(tS3_channel* chan) {
tS3_sample_struct_miniaudio* miniaudio;
tS3_sample* sample_data;
ma_result result;
S3SyncSampleVolume(chan);
S3SyncSampleRate(chan);
if (chan->descriptor && chan->descriptor->type == chan->type) {
ma_sound_seek_to_pcm_frame(chan->descriptor->sound_buffer, 0);
ma_sound_set_looping(chan->descriptor->sound_buffer, chan->repetitions == 0);
ma_sound_start(chan->descriptor->sound_buffer);
// Mix_PlayChannel(chan->id, chan->descriptor->sound_buffer, 0);
miniaudio = (tS3_sample_struct_miniaudio*)chan->type_struct_sample;
sample_data = (tS3_sample*)chan->descriptor->sound_data;
result = ma_audio_buffer_ref_init(ma_format_u8, sample_data->channels, sample_data->dataptr, sample_data->size / sample_data->channels, &miniaudio->buffer_ref);
miniaudio->buffer_ref.sampleRate = sample_data->rate;
if (result != MA_SUCCESS) {
return 0;
}
result = ma_sound_init_from_data_source(&miniaudio_engine, &miniaudio->buffer_ref, MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_NO_SPATIALIZATION, NULL, &miniaudio->sound);
if (result != MA_SUCCESS) {
return 0;
}
miniaudio->initialized = 1;
ma_sound_set_looping(&miniaudio->sound, chan->repetitions == 0);
ma_sound_start(&miniaudio->sound);
// dsound_buffer = chan->descriptor->dsound_buffer;
// if (dsound_buffer) {
// dsound_buffer->lpVtbl->SetCurrentPosition(dsound_buffer, 0);
// play_flags = chan->repetitions == 0; // 1 = DSBPLAY_LOOPING
// dsound_buffer->lpVtbl->Play(dsound_buffer, 0, 0, play_flags);
// if (!dsound_buffer->lpVtbl->GetStatus(dsound_buffer, (LPDWORD)&status)) {
// if ((status & 1) != 0) // DSBSTATUS_PLAYING
// {
// dsound_buffer->lpVtbl->SetCurrentPosition(dsound_buffer, 0);
// } else {
// dsound_buffer->lpVtbl->Play(dsound_buffer, 0, 0, play_flags);
// }
// }
// }
}
// BOOL play_flags; // [esp+Ch] [ebp-Ch]
// int status; // [esp+10h] [ebp-8h] BYREF
// LPDIRECTSOUNDBUFFER dsound_buffer; // [esp+14h] [ebp-4h]
// S3SampleSyncVolume(chan);
// S3SampleSyncRate(chan);
// if (chan->descriptor && chan->descriptor->type == chan->type) {
// dsound_buffer = chan->descriptor->dsound_buffer;
// if (dsound_buffer) {
// dsound_buffer->lpVtbl->SetCurrentPosition(dsound_buffer, 0);
// play_flags = chan->repetitions == 0; // 1 = DSBPLAY_LOOPING
// dsound_buffer->lpVtbl->Play(dsound_buffer, 0, 0, play_flags);
// if (!dsound_buffer->lpVtbl->GetStatus(dsound_buffer, (LPDWORD)&status)) {
// if ((status & 1) != 0) // DSBSTATUS_PLAYING
// {
// dsound_buffer->lpVtbl->SetCurrentPosition(dsound_buffer, 0);
// } else {
// dsound_buffer->lpVtbl->Play(dsound_buffer, 0, 0, play_flags);
// }
// }
// }
// }
return 1;
}
int sub_49D837(tS3_channel* chan) {
// this function was only called in DOS build
int S3CreateTypeStructs(tS3_channel* chan) {
tS3_sample_struct_miniaudio* sample_struct;
sample_struct = S3MemAllocate(sizeof(tS3_sample_struct_miniaudio), kMem_S3_DOS_SOS_channel);
if (sample_struct == NULL) {
return 0;
}
memset(sample_struct, 0, sizeof(tS3_sample_struct_miniaudio));
chan->type_struct_midi = NULL;
chan->type_struct_cda = NULL;
chan->type_struct_sample = (char*)sample_struct;
return 1;
}
int sub_49D84C(tS3_channel* chan) {
int S3ReleaseTypeStructs(tS3_channel* chan) {
if (chan->type_struct_sample) {
S3MemFree(chan->type_struct_sample);
chan->type_struct_sample = NULL;
}
if (chan->type_struct_cda) {
S3MemFree(chan->type_struct_cda);
chan->type_struct_cda = NULL;
}
return 1;
}
@ -285,6 +367,7 @@ int S3SyncSampleVolume(tS3_channel* chan) {
int volume_db;
int pan;
float linear_volume;
tS3_sample_struct_miniaudio* miniaudio;
if (chan->type != eS3_ST_sample) {
return 1;
@ -300,8 +383,9 @@ int S3SyncSampleVolume(tS3_channel* chan) {
}
// convert from directsound -10000-0 volume scale
miniaudio = (tS3_sample_struct_miniaudio*)chan->type_struct_sample;
linear_volume = ma_volume_db_to_linear(volume_db / 100.0f);
ma_sound_set_volume(chan->descriptor->sound_buffer, linear_volume);
ma_sound_set_volume(&miniaudio->sound, linear_volume);
if (chan->spatial_sound) {
if (chan->left_volume != 0 && chan->right_volume > chan->left_volume) {
@ -318,25 +402,29 @@ int S3SyncSampleVolume(tS3_channel* chan) {
} else {
pan = 10000;
}
ma_sound_set_pan(chan->descriptor->sound_buffer, pan / 10000.0f);
ma_sound_set_pan(&miniaudio->sound, pan / 10000.0f);
}
}
return 1;
}
int S3SyncSampleRate(tS3_channel* chan) {
tS3_sample_struct_miniaudio* miniaudio;
if (chan->type != eS3_ST_sample) {
return 1;
}
if (chan->descriptor && chan->descriptor->type == chan->type) {
if (chan->descriptor->sound_buffer != NULL) {
miniaudio = (tS3_sample_struct_miniaudio*)chan->type_struct_sample;
if (miniaudio != NULL) {
int rate = chan->rate;
if (rate >= 100000) {
rate = 100000;
}
// sound_buffer->lpVtbl->SetFrequency(sound_buffer, rate);
// miniaudio uses a linear pitch scale instead of sample rate, so scale it down
ma_sound_set_pitch(chan->descriptor->sound_buffer, (rate / (float)((tS3_sample*)chan->descriptor->sound_data)->rate));
ma_sound_set_pitch(&miniaudio->sound, (rate / (float)((tS3_sample*)chan->descriptor->sound_data)->rate));
}
}
return 1;

View File

@ -8,10 +8,11 @@ extern tS3_sample_filter* gS3_sample_filter_func;
extern tS3_sample_filter* gS3_sample_filter_disable_func;
int S3LoadSample(tS3_sound_id id);
void* S3LoadWavFile(char* pFile_name, tS3_sample* pSample);
void* S3LoadWavFile_DOS(char* pFile_name);
void* S3LoadWavFile_Win95(char* pFile_name, tS3_sample* pSample);
int S3PlaySample(tS3_channel* chan);
int sub_49D837(tS3_channel* chan);
int sub_49D84C(tS3_channel* chan);
int S3CreateTypeStructs(tS3_channel* chan);
int S3ReleaseTypeStructs(tS3_channel* chan);
int S3StopSample(tS3_channel* chan);
int S3ExecuteSampleFilterFuncs(tS3_channel* chan);
int S3SyncSampleVolume(tS3_channel* chan);