diff --git a/sound.c b/sound.c --- a/sound.c +++ b/sound.c @@ -1,33 +1,13 @@ #include "stdafx.h" #include "ttd.h" #include "map.h" +#include "mixer.h" #include "sound.h" #include "vehicle.h" #include "window.h" #include "viewport.h" #include "fileio.h" -typedef struct MixerChannel { - // Mixer - Mixer *mx; - bool active; - - // pointer to allocated buffer memory - int8 *memory; - - // current position in memory - uint32 pos; - uint32 frac_pos; - uint32 frac_speed; - uint32 samples_left; - - // Mixing volume - uint volume_left; - uint volume_right; - - uint flags; -} MixerChannel; - typedef struct FileEntry { uint32 file_offset; uint32 file_size; @@ -36,150 +16,29 @@ typedef struct FileEntry { uint8 channels; } FileEntry; -struct Mixer { - uint32 play_rate; - FileEntry *files; - uint32 file_count; - MixerChannel channels[8]; -}; - -enum { - MX_AUTOFREE = 1, -// MX_8BIT = 2, -// MX_STEREO = 4, - MX_UNSIGNED = 8, -}; +static uint _file_count; +static FileEntry* _files; #define SOUND_SLOT 31 -static void mix_int8_to_int16(MixerChannel *sc, int16 *buffer, uint samples) -{ - int8 *b; - uint32 frac_pos; - uint32 frac_speed; - uint volume_left; - uint volume_right; - - if (samples > sc->samples_left) samples = sc->samples_left; - sc->samples_left -= samples; - assert(samples > 0); - - b = sc->memory + sc->pos; - frac_pos = sc->frac_pos; - frac_speed = sc->frac_speed; - volume_left = sc->volume_left; - volume_right = sc->volume_right; - - if (frac_speed == 0x10000) { - // Special case when frac_speed is 0x10000 - do { - buffer[0] += *b * volume_left >> 8; - buffer[1] += *b * volume_right >> 8; - b++; - buffer += 2; - } while (--samples > 0); - } else { - do { - buffer[0] += *b * volume_left >> 8; - buffer[1] += *b * volume_right >> 8; - buffer += 2; - frac_pos += frac_speed; - b += frac_pos >> 16; - frac_pos &= 0xffff; - } while (--samples > 0); - } - - sc->frac_pos = frac_pos; - sc->pos = b - sc->memory; -} - -static void MxCloseChannel(MixerChannel *mc) -{ - if (mc->flags & MX_AUTOFREE) free(mc->memory); - mc->memory = NULL; - mc->active = false; -} - -void MxMixSamples(Mixer *mx, void *buffer, uint samples) -{ - MixerChannel *mc; - - // Clear the buffer - memset(buffer, 0, sizeof(int16) * 2 * samples); - - // Mix each channel - for (mc = mx->channels; mc != endof(mx->channels); mc++) { - if (mc->active) { - mix_int8_to_int16(mc, buffer, samples); - if (mc->samples_left == 0) MxCloseChannel(mc); - } - } - - #if 0 - { - static FILE *out = NULL; - if (out == NULL) - out = fopen("d:\\dump.raw", "wb"); - fwrite(buffer, samples * 4, 1, out); - } - #endif -} - -static MixerChannel *MxAllocateChannel(Mixer *mx) -{ - MixerChannel *mc; - for (mc = mx->channels; mc != endof(mx->channels); mc++) - if (mc->memory == NULL) { - mc->active = false; - mc->mx = mx; - return mc; - } - return NULL; -} - -static void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, uint size, uint rate, uint flags) -{ - mc->memory = mem; - mc->flags = flags; - mc->frac_pos = 0; - mc->pos = 0; - - mc->frac_speed = (rate << 16) / mc->mx->play_rate; - - // adjust the magnitude to prevent overflow - while (size & 0xFFFF0000) { - size >>= 1; - rate = (rate >> 1) + 1; - } - - mc->samples_left = size * mc->mx->play_rate / rate; -} - -static void MxSetChannelVolume(MixerChannel *mc, uint left, uint right) -{ - mc->volume_left = left; - mc->volume_right = right; -} - -static void MxOpenBankFile(Mixer *mx, const char *filename) +static void OpenBankFile(const char *filename) { uint count, i; uint32 size, tag; FileEntry *fe; FioOpenFile(SOUND_SLOT, filename); - mx->file_count = count = FioReadDword() >> 3; - fe = mx->files = calloc(sizeof(FileEntry), count); + _file_count = count = FioReadDword() >> 3; + fe = _files = calloc(sizeof(FileEntry), count); FioSeekTo(0, SEEK_SET); - for (i = 0; i != count; i++, fe++) { - fe->file_offset = FioReadDword(); - fe->file_size = FioReadDword(); + for (i = 0; i != count; i++) { + fe[i].file_offset = FioReadDword(); + fe[i].file_size = FioReadDword(); } - fe = mx->files; for (i = 0; i != count; i++, fe++) { char name[255]; @@ -227,9 +86,9 @@ static void MxOpenBankFile(Mixer *mx, co } } -static bool MxSetBankSource(MixerChannel *mc, uint bank) +static bool SetBankSource(MixerChannel *mc, uint bank) { - FileEntry *fe = &mc->mx->files[bank]; + FileEntry *fe = &_files[bank]; int8 *mem; uint i; @@ -245,17 +104,14 @@ static bool MxSetBankSource(MixerChannel assert(fe->bits_per_sample == 8 && fe->channels == 1 && fe->file_size != 0 && fe->rate != 0); - MxSetChannelRawSrc(mc, mem, fe->file_size, fe->rate, MX_AUTOFREE | MX_UNSIGNED); + MxSetChannelRawSrc(mc, mem, fe->file_size, fe->rate, MX_AUTOFREE); return true; } -bool MxInitialize(uint rate, const char *filename) +bool SoundInitialize(const char *filename) { - static Mixer mx; - _mixer = &mx; - mx.play_rate = rate; - MxOpenBankFile(&mx, filename); + OpenBankFile(filename); return true; } @@ -266,9 +122,9 @@ static void StartSound(uint sound, uint MixerChannel *mc = MxAllocateChannel(_mixer); if (mc == NULL) return; - if (MxSetBankSource(mc, sound)) { + if (SetBankSource(mc, sound)) { MxSetChannelVolume(mc, volume << 8, volume << 8); - mc->active = true; + MxActivate(mc); } } }