Per-channel audio buffers from DOS executable (#329)
* implements DOS-style per channel audio
This commit is contained in:
parent
07d517307a
commit
3b0f32284a
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
13
src/S3/3d.c
13
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 <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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
206
src/S3/s3sound.c
206
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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue