diff --git a/src/DETHRACE/common/sound.c b/src/DETHRACE/common/sound.c index dc4cae48..a74d215b 100644 --- a/src/DETHRACE/common/sound.c +++ b/src/DETHRACE/common/sound.c @@ -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@(tS3_sound_tag pSound_tag@, tS3_volume pNew_Lvolume@, tS3_volume pNew_Rvolume@) @@ -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; } diff --git a/src/S3/3d.c b/src/S3/3d.c index 57f9288e..57360eac 100644 --- a/src/S3/3d.c +++ b/src/S3/3d.c @@ -1,5 +1,6 @@ #include "3d.h" #include "audio.h" +#include "harness/trace.h" #include "resource.h" #include "s3sound.h" #include @@ -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; diff --git a/src/S3/3d.h b/src/S3/3d.h index b1225316..14631b76 100644 --- a/src/S3/3d.h +++ b/src/S3/3d.h @@ -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); diff --git a/src/S3/audio.c b/src/S3/audio.c index 8e747790..0ed08715 100644 --- a/src/S3/audio.c +++ b/src/S3/audio.c @@ -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) { diff --git a/src/S3/audio.h b/src/S3/audio.h index a231e4f9..09095e31 100644 --- a/src/S3/audio.h +++ b/src/S3/audio.h @@ -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); diff --git a/src/S3/include/s3/s3.h b/src/S3/include/s3/s3.h index 95e649d7..fb88185b 100644 --- a/src/S3/include/s3/s3.h +++ b/src/S3/include/s3/s3.h @@ -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); diff --git a/src/S3/s3_defs.h b/src/S3/s3_defs.h index 32d8a4a5..e565c824 100644 --- a/src/S3/s3_defs.h +++ b/src/S3/s3_defs.h @@ -3,6 +3,7 @@ #include "s3/s3.h" +#include #include // 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 diff --git a/src/S3/s3music.c b/src/S3/s3music.c index 008f77d9..f11bbb4c 100644 --- a/src/S3/s3music.c +++ b/src/S3/s3music.c @@ -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) { diff --git a/src/S3/s3music.h b/src/S3/s3music.h index 65e4db6c..36451684 100644 --- a/src/S3/s3music.h +++ b/src/S3/s3music.h @@ -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); diff --git a/src/S3/s3sound.c b/src/S3/s3sound.c index b4ab571f..c63f4e39 100644 --- a/src/S3/s3sound.c +++ b/src/S3/s3sound.c @@ -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; diff --git a/src/S3/s3sound.h b/src/S3/s3sound.h index f43ac73d..224e85cc 100644 --- a/src/S3/s3sound.h +++ b/src/S3/s3sound.h @@ -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);