From 73dc94480cbadf6e90d94e858b32282e49b08650 Mon Sep 17 00:00:00 2001 From: Fabian Greffrath Date: Tue, 10 Jan 2023 07:48:33 +0100 Subject: [PATCH] use SDL_ConvertAudio() to convert sound samples to target format (#863) * properly cache sound lump numbers * initialize original_S_sfx[] array using macros * rename channelinfo[].id -> channelinfo[].sfx * rename LINKED_SOUND -> SOUND_LINK * use SDL_ConvertAudio() to convert sound samples to target format Fixes #858 * precache_sounds is not an option anymore * lowpass_filter is not an option anymore * rename channel -> handle and other clean-up * some more clean-up * fix pitch-shifted sounds * set SDL_HINT_AUDIO_RESAMPLING_MODE to "default" * set SDL_HINT_AUDIO_RESAMPLING_MODE to "linear", with a comment * clear out cvt target buffer * de-obfuscate steptable[pitch] generation * make snd_samplerate and snd_resampling_mode configurable * simplify SOUND_LINK macro call * set default sampling mode to "default" * cosmetics * comments * correct snd_resampling_mode choice name * replace some redundant variables by a single SDL_AudioSpec * forgotten parenthesis * minor polish --- src/d_main.c | 4 - src/i_sound.c | 822 ++++++++++++++++++++++---------------------------- src/i_sound.h | 11 +- src/m_menu.c | 2 +- src/m_misc.c | 22 +- src/s_sound.c | 4 +- src/sounds.c | 647 ++++++++++++++++++++------------------- 7 files changed, 703 insertions(+), 809 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 50cd5862..dc5905b8 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -2721,10 +2721,6 @@ void D_DoomMain(void) // Sound mixing for the buffer is snychronous. I_UpdateSound(); - - // Synchronous sound output is explicitly called. - // Update sound output. - I_SubmitSound(); } } diff --git a/src/i_sound.c b/src/i_sound.c index 41baad80..42c3474e 100644 --- a/src/i_sound.c +++ b/src/i_sound.c @@ -5,7 +5,7 @@ // // Copyright (C) 1999 by // id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman -// Copyright(C) 2020-2021 Fabian Greffrath +// Copyright(C) 2020-2023 Fabian Greffrath // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -35,18 +35,6 @@ #include "doomstat.h" #include "i_sound.h" #include "w_wad.h" -#include "d_main.h" - -#ifndef M_PI -#define M_PI 3.14 -#endif - -// [FG] precache all sound effects -boolean precache_sounds; -// [FG] optional low-pass filter -boolean lowpass_filter; -// [FG] variable pitch bend range -int pitch_bend_range; // Music modules extern music_module_t music_win_module; @@ -78,15 +66,18 @@ static music_module_t *active_module = NULL; // haleyjd: safety variables to keep changes to *_card from making // these routines think that sound has been initialized when it hasn't -boolean snd_init = false; +static boolean snd_init = false; // haleyjd 10/28/05: updated for Julian's music code, need full quality now -int snd_samplerate = 44100; +int snd_samplerate; +char *snd_resampling_mode; +static Uint16 mix_format; +static int mix_channels; typedef struct { // SFX id of the playing sound effect. // Used to catch duplicates (like chainsaw). - sfxinfo_t *id; + sfxinfo_t *sfx; // The channel data pointer. unsigned char* data; // [FG] let SDL_Mixer do the actual sound mixing @@ -98,371 +89,290 @@ typedef struct { channel_info_t channelinfo[MAX_CHANNELS]; // Pitch to stepping lookup, unused. -int steptable[256]; +float steptable[256]; // -// stopchan +// StopChannel // // cph // Stops a sound, unlocks the data // -static void stopchan(int handle) +static void StopChannel(int channel) { - int cnum; + int cnum; #ifdef RANGECHECK - // haleyjd 02/18/05: bounds checking - if(handle < 0 || handle >= MAX_CHANNELS) - return; + // haleyjd 02/18/05: bounds checking + if (channel < 0 || channel >= MAX_CHANNELS) + return; #endif - if(channelinfo[handle].data) - { - Mix_HaltChannel(handle); - // [FG] immediately free samples not connected to a sound SFX - if (channelinfo[handle].id == NULL) - { - Z_Free(channelinfo[handle].data); - } - channelinfo[handle].data = NULL; + if (channelinfo[channel].data) + { + Mix_HaltChannel(channel); - if(channelinfo[handle].id) - { - // haleyjd 06/03/06: see if we can free the sound - for(cnum = 0; cnum < MAX_CHANNELS; ++cnum) - { - if(cnum == handle) - continue; - if(channelinfo[cnum].id && - channelinfo[cnum].id->data == channelinfo[handle].id->data) - return; // still being used by some channel - } - - // set sample to PU_CACHE level - if (!precache_sounds) - { - Z_ChangeTag(channelinfo[handle].id->data, PU_CACHE); - } - } - } + // [FG] immediately free samples not connected to a sound SFX + if (channelinfo[channel].sfx == NULL) + { + free(channelinfo[channel].data); + } + channelinfo[channel].data = NULL; - channelinfo[handle].id = NULL; + if (channelinfo[channel].sfx) + { + // haleyjd 06/03/06: see if we can free the sound + for (cnum = 0; cnum < MAX_CHANNELS; cnum++) + { + if (cnum == channel) + continue; + + if (channelinfo[cnum].sfx && + channelinfo[cnum].sfx->data == channelinfo[channel].sfx->data) + { + return; // still being used by some channel + } + } + } + } + + channelinfo[channel].sfx = NULL; } -static int SOUNDHDRSIZE = 8; +#define SOUNDHDRSIZE 8 // -// addsfx -// -// This function adds a sound to the -// list of currently active sounds, -// which is maintained as a given number -// (eight, usually) of internal channels. -// Returns a handle. +// CacheSound // // haleyjd: needs to take a sfxinfo_t ptr, not a sound id num // haleyjd 06/03/06: changed to return boolean for failure or success // -static boolean addsfx(sfxinfo_t *sfx, int channel, int pitch) +static boolean CacheSound(sfxinfo_t *sfx, int channel, int pitch) { - size_t lumplen; - int lump; - // [FG] do not connect pitch-shifted samples to a sound SFX - unsigned int sfx_alen; - unsigned int bits; - void *sfx_data; + int lumpnum, lumplen; + Uint8 *lumpdata = NULL, *wavdata = NULL; + Mix_Chunk *const chunk = &channelinfo[channel].chunk; #ifdef RANGECHECK - if(channel < 0 || channel >= MAX_CHANNELS) - I_Error("addsfx: channel out of range!\n"); + if (channel < 0 || channel >= MAX_CHANNELS) + { + I_Error("CacheSound: channel out of range!\n"); + } #endif - // haleyjd 02/18/05: null ptr check - if(!snd_init || !sfx) - return false; + // haleyjd 02/18/05: null ptr check + if (!snd_init || !sfx) + { + return false; + } - stopchan(channel); - - // We will handle the new SFX. - // Set pointer to raw data. + StopChannel(channel); - // haleyjd: Eternity sfxinfo_t does not have a lumpnum field - lump = I_GetSfxLumpNum(sfx); - - // replace missing sounds with a reasonable default - if(lump == -1) - lump = W_GetNumForName("DSPISTOL"); - - lumplen = W_LumpLength(lump); - - // haleyjd 10/08/04: do not play zero-length sound lumps - if(lumplen <= SOUNDHDRSIZE) - return false; + lumpnum = I_GetSfxLumpNum(sfx); - // haleyjd 06/03/06: rewrote again to make sound data properly freeable - if(sfx->data == NULL || pitch != NORM_PITCH) - { - byte *data; - Uint32 samplerate, samplelen, samplecount; - Uint8 *wav_buffer = NULL; + if (lumpnum == -1) + { + return false; + } - // haleyjd: this should always be called (if lump is already loaded, - // W_CacheLumpNum handles that for us). - data = (byte *)W_CacheLumpNum(lump, PU_STATIC); + lumplen = W_LumpLength(lumpnum); - // [crispy] Check if this is a valid RIFF wav file - if (lumplen > 44 && memcmp(data, "RIFF", 4) == 0 && memcmp(data + 8, "WAVEfmt ", 8) == 0) - { - SDL_RWops *RWops; - SDL_AudioSpec wav_spec; + // haleyjd 10/08/04: do not play zero-length sound lumps + if (lumplen <= SOUNDHDRSIZE) + { + return false; + } - RWops = SDL_RWFromMem(data, lumplen); + // haleyjd 06/03/06: rewrote again to make sound data properly freeable + while (sfx->data == NULL) + { + SDL_AudioSpec sample; + SDL_AudioCVT cvt; + Uint8 *sampledata; + Uint32 samplelen; - Z_ChangeTag(data, PU_CACHE); + // haleyjd: this should always be called (if lump is already loaded, + // W_CacheLumpNum handles that for us). + lumpdata = (Uint8 *)W_CacheLumpNum(lumpnum, PU_STATIC); - if (SDL_LoadWAV_RW(RWops, 1, &wav_spec, &wav_buffer, &samplelen) == NULL) - { - fprintf(stderr, "Could not open wav file: %s\n", SDL_GetError()); - return false; - } - - if (wav_spec.channels != 1) - { - fprintf(stderr, "Only mono WAV file is supported"); - SDL_FreeWAV(wav_buffer); - return false; - } - - if (!SDL_AUDIO_ISINT(wav_spec.format)) - { - SDL_FreeWAV(wav_buffer); - return false; - } - - bits = SDL_AUDIO_BITSIZE(wav_spec.format); - if (bits != 8 && bits != 16) - { - fprintf(stderr, "Only 8 or 16 bit WAV files are supported"); - SDL_FreeWAV(wav_buffer); - return false; - } - - samplerate = wav_spec.freq; - data = wav_buffer; - SOUNDHDRSIZE = 0; - } - // Check the header, and ensure this is a valid sound - else if(data[0] == 0x03 && data[1] == 0x00) - { - samplerate = (data[3] << 8) | data[2]; - samplelen = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]; - - // All Doom sounds are 8-bit - bits = 8; - - SOUNDHDRSIZE = 8; - } - else - { - Z_ChangeTag(data, PU_CACHE); - return false; - } + // Check the header, and ensure this is a valid sound + if (lumpdata[0] == 0x03 && lumpdata[1] == 0x00) + { + sample.freq = (lumpdata[3] << 8) | lumpdata[2]; + samplelen = (lumpdata[7] << 24) | (lumpdata[6] << 16) | + (lumpdata[5] << 8) | lumpdata[4]; // don't play sounds that think they're longer than they really are - if(samplelen > lumplen - SOUNDHDRSIZE) + if (samplelen > lumplen - SOUNDHDRSIZE) { - Z_ChangeTag(data, PU_CACHE); - return false; + break; } - samplecount = samplelen / (bits / 8); + sampledata = lumpdata + SOUNDHDRSIZE; - // [FG] do not connect pitch-shifted samples to a sound SFX - if (pitch == NORM_PITCH) + // All Doom sounds are 8-bit + sample.format = AUDIO_U8; + sample.channels = 1; + } + else + { + SDL_RWops *RWops; + + if ((RWops = SDL_RWFromMem(lumpdata, lumplen)) == NULL) { - sfx_alen = (Uint32)(((uint64_t)samplecount * snd_samplerate) / samplerate); - // [FG] double up twice: 8 -> 16 bit and mono -> stereo - sfx->alen = 4 * sfx_alen; - sfx->data = precache_sounds ? malloc(sfx->alen) : Z_Malloc(sfx->alen, PU_STATIC, &sfx->data); - sfx_data = sfx->data; + fprintf(stderr, "SDL_RWFromMem: %s\n", SDL_GetError()); + break; } - else + + if (SDL_LoadWAV_RW(RWops, 1, &sample, &wavdata, &samplelen) == NULL) // 1 = will call SDL_RWclose(RWops) for us { - // [FG] spoof sound samplerate if using randomly pitched sounds - samplerate = (Uint32)(((uint64_t)samplerate * steptable[pitch]) >> 16); - sfx_alen = (Uint32)(((uint64_t)samplecount * snd_samplerate) / samplerate); - // [FG] double up twice: 8 -> 16 bit and mono -> stereo - channelinfo[channel].data = Z_Malloc(4 * sfx_alen, PU_STATIC, (void **)&channelinfo[channel].data); - sfx_data = channelinfo[channel].data; + fprintf(stderr, "SDL_LoadWAV_RW: %s\n", SDL_GetError()); + break; } - // haleyjd 04/23/08: Convert sound to target samplerate - { - unsigned int i; - Sint16 sample = 0; - Sint16 *dest = (Sint16 *)sfx_data; - byte *src = data + SOUNDHDRSIZE; - - unsigned int step = (samplerate << 16) / snd_samplerate; - unsigned int stepremainder = 0, j = 0; - - // do linear filtering operation - for(i = 0; i < sfx_alen && j < samplelen - 1; ++i) - { - int d; - - if (bits == 16) - { - d = ((Sint16)(src[j ] | (src[j+1] << 8)) * (0x10000 - stepremainder) + - (Sint16)(src[j+2] | (src[j+3] << 8)) * stepremainder) >> 16; - - sample = d; - } - else - { - d = (((unsigned int)src[j ] * (0x10000 - stepremainder)) + - ((unsigned int)src[j+1] * stepremainder)) >> 8; - - // [FG] interpolate sfx in a 16-bit int domain, convert to signed - sample = d - (1<<15); - } - - dest[2*i] = dest[2*i+1] = sample; - - stepremainder += step; - if (bits == 16) - j += (stepremainder >> 16) * 2; - else - j += (stepremainder >> 16); - - stepremainder &= 0xffff; - } - // fill remainder (if any) with final sample byte - for(; i < sfx_alen; ++i) - dest[2*i] = dest[2*i+1] = sample; - - // Perform a low-pass filter on the upscaled sound to filter - // out high-frequency noise from the conversion process. - - if (lowpass_filter) - { - float rc, dt, alpha; - - // Low-pass filter for cutoff frequency f: - // - // For sampling rate r, dt = 1 / r - // rc = 1 / 2*pi*f - // alpha = dt / (rc + dt) - - // Filter to the half sample rate of the original sound effect - // (maximum frequency, by nyquist) - - dt = 1.0f / snd_samplerate; - rc = 1.0f / (M_PI * samplerate); - alpha = dt / (rc + dt); - - // Both channels are processed in parallel, hence [i-2]: - - for (i = 2; i < sfx_alen * 2; ++i) - { - dest[i] = (Sint16) (alpha * dest[i] - + (1.0f - alpha) * dest[i-2]); - } - } + if (sample.channels != 1) + { + fprintf(stderr, "Only mono WAV files are supported\n"); + break; } - // [FG] double up twice: 8 -> 16 bit and mono -> stereo - sfx_alen *= 4; - if (wav_buffer) - SDL_FreeWAV(wav_buffer); - else - // haleyjd 06/03/06: don't need original lump data any more - Z_ChangeTag(data, PU_CACHE); - } - else - if (!precache_sounds) - Z_ChangeTag(sfx->data, PU_STATIC); // reset to static cache level + sampledata = wavdata; + } - // [FG] let SDL_Mixer do the actual sound mixing - channelinfo[channel].chunk.allocated = 1; - channelinfo[channel].chunk.volume = MIX_MAX_VOLUME; + // Convert sound to target samplerate + if (SDL_BuildAudioCVT(&cvt, + sample.format, sample.channels, sample.freq, + mix_format, mix_channels, snd_samplerate) < 0) + { + fprintf(stderr, "SDL_BuildAudioCVT: %s\n", SDL_GetError()); + break; + } - // [FG] do not connect pitch-shifted samples to a sound SFX - if (pitch == NORM_PITCH) - { - channelinfo[channel].data = sfx->data; + cvt.len = samplelen; + cvt.buf = (Uint8 *)malloc(cvt.len * cvt.len_mult); + // [FG] clear buffer (cvt.len * cvt.len_mult >= cvt.len_cvt) + memset(cvt.buf, 0, cvt.len * cvt.len_mult); + memcpy(cvt.buf, sampledata, cvt.len); - channelinfo[channel].chunk.abuf = sfx->data; - channelinfo[channel].chunk.alen = sfx->alen; + if (SDL_ConvertAudio(&cvt) < 0) + { + fprintf(stderr, "SDL_ConvertAudio: %s\n", SDL_GetError()); + break; + } - // Preserve sound SFX id - channelinfo[channel].id = sfx; - } - else - { - channelinfo[channel].chunk.abuf = sfx_data; - channelinfo[channel].chunk.alen = sfx_alen; + sfx->data = cvt.buf; + sfx->alen = cvt.len_cvt; + } - channelinfo[channel].id = NULL; - } + // don't need original lump data any more + if (lumpdata) + { + Z_Free(lumpdata); + } + if (wavdata) + { + SDL_FreeWAV(wavdata); + } - return true; + if (sfx->data == NULL) + { + return false; + } + + // [FG] let SDL_Mixer do the actual sound mixing + chunk->allocated = 1; + chunk->volume = MIX_MAX_VOLUME; + + // Allocate a new sound chunk and pitch-shift an existing sound up-or-down + // into it, based on chocolate-doom/src/i_sdlsound.c:PitchShift(). + if (pitch != NORM_PITCH) + { + Sint16 *inp, *outp; + Sint16 *srcbuf, *dstbuf; + Uint32 srclen, dstlen; + + srcbuf = (Sint16 *)sfx->data; + srclen = sfx->alen; + + dstlen = (int)(srclen * steptable[pitch]); + + // ensure that the new buffer is an even length + if ((dstlen % 2) == 0) + { + dstlen++; + } + + dstbuf = (Sint16 *)malloc(dstlen); + + // loop over output buffer. find corresponding input cell, copy over + for (outp = dstbuf; outp < dstbuf + dstlen/2; outp++) + { + inp = srcbuf + (int)((float)(outp - dstbuf) * srclen / dstlen); + *outp = *inp; + } + + chunk->abuf = (Uint8 *)dstbuf; + chunk->alen = dstlen; + + // [FG] do not connect pitch-shifted samples to a sound SFX + channelinfo[channel].sfx = NULL; + } + else + { + chunk->abuf = sfx->data; + chunk->alen = sfx->alen; + + // Preserve sound SFX id + channelinfo[channel].sfx = sfx; + } + + channelinfo[channel].data = chunk->abuf; + + return true; } int forceFlipPan; // -// updateSoundParams +// I_UpdateSoundParams // // Changes sound parameters in response to stereo panning and relative location // change. // -static void updateSoundParams(int handle, int volume, int separation, int pitch) +void I_UpdateSoundParams(int channel, int volume, int separation) { - int rightvol; - int leftvol; - - if(!snd_init) - return; + int rightvol; + int leftvol; + + if (!snd_init) + return; #ifdef RANGECHECK - if(handle < 0 || handle >= MAX_CHANNELS) - I_Error("I_UpdateSoundParams: handle out of range"); + if (channel < 0 || channel >= MAX_CHANNELS) + I_Error("I_UpdateSoundParams: channel out of range"); #endif - // SoM 7/1/02: forceFlipPan accounted for here - if(forceFlipPan) - separation = 254 - separation; + // SoM 7/1/02: forceFlipPan accounted for here + if (forceFlipPan) + separation = 254 - separation; - // [FG] linear stereo volume separation - leftvol = ((254 - separation) * volume) / 127; - rightvol = ((separation) * volume) / 127; + // [FG] linear stereo volume separation + leftvol = ((254 - separation) * volume) / 127; + rightvol = ((separation) * volume) / 127; - if (leftvol < 0) leftvol = 0; - else if (leftvol > 255) leftvol = 255; - if (rightvol < 0) rightvol = 0; - else if (rightvol > 255) rightvol = 255; + if (leftvol < 0) + leftvol = 0; + else if (leftvol > 255) + leftvol = 255; + if (rightvol < 0) + rightvol = 0; + else if (rightvol > 255) + rightvol = 255; - Mix_SetPanning(handle, leftvol, rightvol); + Mix_SetPanning(channel, leftvol, rightvol); } -// -// SFX API -// - -// -// I_UpdateSoundParams -// -// Update the sound parameters. Used to control volume, -// pan, and pitch changes such as when a player turns. -// -void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) -{ - if(!snd_init) - return; - - updateSoundParams(handle, vol, sep, pitch); -} +// [FG] variable pitch bend range +int pitch_bend_range; // // I_SetChannels @@ -473,22 +383,20 @@ void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) // void I_SetChannels(void) { - int i; - - int *steptablemid = steptable + 128; - const double base = pitch_bend_range / 100.0; - - // Okay, reset internal mixing channels to zero. - for(i = 0; i < MAX_CHANNELS; ++i) - { - memset(&channelinfo[i], 0, sizeof(channel_info_t)); - } - - // This table provides step widths for pitch parameters. - for(i=-128 ; i<128 ; i++) - { - steptablemid[i] = (int)(pow(base, (double)i / 64.0) * 65536.0); // [FG] variable pitch bend range - } + int i; + const double base = pitch_bend_range / 100.0; + + // Okay, reset internal mixing channels to zero. + for (i = 0; i < MAX_CHANNELS; i++) + { + memset(&channelinfo[i], 0, sizeof(channel_info_t)); + } + + // This table provides step widths for pitch parameters. + for (i = 0; i < arrlen(steptable); i++) + { + steptable[i] = pow(base, (double)(2 * (i - NORM_PITCH)) / NORM_PITCH); // [FG] variable pitch bend range + } } // @@ -501,8 +409,8 @@ void I_SetSfxVolume(int volume) // the menu/config file setting // to the state variable used in // the mixing. - - snd_SfxVolume = volume; + + snd_SfxVolume = volume; } // jff 1/21/98 moved music volume down into MUSIC API with the rest @@ -515,14 +423,19 @@ void I_SetSfxVolume(int volume) // int I_GetSfxLumpNum(sfxinfo_t *sfx) { - char namebuf[16]; + if (sfx->lumpnum == -1) + { + char namebuf[16]; - memset(namebuf, 0, sizeof(namebuf)); + memset(namebuf, 0, sizeof(namebuf)); - strcpy(namebuf, "DS"); - strcpy(namebuf+2, sfx->name); + strcpy(namebuf, "DS"); + strcpy(namebuf+2, sfx->name); - return W_CheckNumForName(namebuf); + sfx->lumpnum = W_CheckNumForName(namebuf); + } + + return sfx->lumpnum; } // Almost all of the sound code from this point on was @@ -534,45 +447,38 @@ int I_GetSfxLumpNum(sfxinfo_t *sfx) // // This function adds a sound to the list of currently // active sounds, which is maintained as a given number -// of internal channels. Returns a handle. +// of internal channels. Returns a free channel. // -int I_StartSound(sfxinfo_t *sound, int cnum, int vol, int sep, int pitch, int pri, boolean loop) +int I_StartSound(sfxinfo_t *sound, int vol, int sep, int pitch, boolean loop) { - static unsigned int id = 0; - int handle; - - if(!snd_init) - return -1; + static unsigned int id = 0; + int channel; - // haleyjd: turns out this is too simplistic. see below. - /* - // SoM: reimplement hardware channel wrap-around - if(++handle >= MAX_CHANNELS) - handle = 0; - */ + if (!snd_init) + return -1; - // haleyjd 06/03/06: look for an unused hardware channel - for(handle = 0; handle < MAX_CHANNELS; ++handle) - { - if(channelinfo[handle].data == NULL) - break; - } + // haleyjd 06/03/06: look for an unused hardware channel + for (channel = 0; channel < MAX_CHANNELS; channel++) + { + if (channelinfo[channel].data == NULL) + break; + } - // all used? don't play the sound. It's preferable to miss a sound - // than it is to cut off one already playing, which sounds weird. - if(handle == MAX_CHANNELS) - return -1; + // all used? don't play the sound. It's preferable to miss a sound + // than it is to cut off one already playing, which sounds weird. + if (channel == MAX_CHANNELS) + return -1; - if(addsfx(sound, handle, pitch)) - { - channelinfo[handle].idnum = id++; // give the sound a unique id - Mix_PlayChannelTimed(handle, &channelinfo[handle].chunk, loop ? -1 : 0, -1); - updateSoundParams(handle, vol, sep, pitch); - } - else - handle = -1; - - return handle; + if (CacheSound(sound, channel, pitch)) + { + channelinfo[channel].idnum = id++; // give the sound a unique id + Mix_PlayChannelTimed(channel, &channelinfo[channel].chunk, loop ? -1 : 0, -1); + I_UpdateSoundParams(channel, vol, sep); + } + else + channel = -1; + + return channel; } // @@ -581,17 +487,17 @@ int I_StartSound(sfxinfo_t *sound, int cnum, int vol, int sep, int pitch, int pr // Stop the sound. Necessary to prevent runaway chainsaw, // and to stop rocket launches when an explosion occurs. // -void I_StopSound(int handle) +void I_StopSound(int channel) { - if(!snd_init) - return; + if (!snd_init) + return; #ifdef RANGECHECK - if(handle < 0 || handle >= MAX_CHANNELS) - I_Error("I_StopSound: handle out of range"); + if (channel < 0 || channel >= MAX_CHANNELS) + I_Error("I_StopSound: channel out of range"); #endif - - stopchan(handle); + + StopChannel(channel); } // @@ -599,17 +505,17 @@ void I_StopSound(int handle) // // haleyjd: wow, this can actually do something in the Windows version :P // -int I_SoundIsPlaying(int handle) +int I_SoundIsPlaying(int channel) { - if(!snd_init) - return false; + if (!snd_init) + return false; #ifdef RANGECHECK - if(handle < 0 || handle >= MAX_CHANNELS) - I_Error("I_SoundIsPlaying: handle out of range"); + if (channel < 0 || channel >= MAX_CHANNELS) + I_Error("I_SoundIsPlaying: channel out of range"); #endif - - return Mix_Playing(handle); + + return Mix_Playing(channel); } // @@ -620,17 +526,17 @@ int I_SoundIsPlaying(int handle) // that the higher-level sound code doesn't start updating sounds that have // been displaced without it noticing. // -int I_SoundID(int handle) +int I_SoundID(int channel) { - if(!snd_init) - return 0; + if (!snd_init) + return 0; #ifdef RANGECHECK - if(handle < 0 || handle >= MAX_CHANNELS) - I_Error("I_SoundID: handle out of range\n"); + if (channel < 0 || channel >= MAX_CHANNELS) + I_Error("I_SoundID: channel out of range\n"); #endif - return channelinfo[handle].idnum; + return channelinfo[channel].idnum; } // This function loops all active (internal) sound @@ -647,32 +553,20 @@ int I_SoundID(int handle) void I_UpdateSound(void) { - int i; + int i; - // Check all channels to see if a sound has finished + // Check all channels to see if a sound has finished - for (i=0; i 8 ? (SDL_AUDIO_ISBIGENDIAN(mix_format) ? "MSB" : "LSB") : "", + mix_channels); + + // [FG] let SDL_Mixer do the actual sound mixing + Mix_AllocateChannels(MAX_CHANNELS); + + I_AtExit(I_ShutdownSound, true); + + snd_init = true; + + // [FG] precache all sound effects + if (!nosfxparm) + { + int i; + + printf("Precaching all sound effects..."); + for (i = 1; i < num_sfx; i++) { - printf("Couldn't initialize SDL audio: %s\n", SDL_GetError()); - return; + // DEHEXTRA has turned S_sfx into a sparse array + if (!S_sfx[i].name) + continue; + + CacheSound(&S_sfx[i], 0, NORM_PITCH); } - - if (Mix_OpenAudioDevice(snd_samplerate, AUDIO_S16SYS, 2, GetSliceSize(), NULL, - SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0) - { - printf("Couldn't open audio with desired format.\n"); - return; - } - - // [FG] feed actual sample frequency back into config variable - Mix_QuerySpec(&snd_samplerate, &mix_format, &mix_channels); - printf("Configured audio device with %.1f kHz (%s%d%s), %d channels.\n", - (float)snd_samplerate / 1000, - SDL_AUDIO_ISFLOAT(mix_format) ? "F" : SDL_AUDIO_ISSIGNED(mix_format) ? "S" : "U", - (int)SDL_AUDIO_BITSIZE(mix_format), - SDL_AUDIO_BITSIZE(mix_format) > 8 ? (SDL_AUDIO_ISBIGENDIAN(mix_format) ? "MSB" : "LSB") : "", - mix_channels); - - // [FG] let SDL_Mixer do the actual sound mixing - Mix_AllocateChannels(MAX_CHANNELS); - - I_AtExit(I_ShutdownSound, true); - - snd_init = true; - - // [FG] precache all sound effects - if (!nosfxparm && precache_sounds) - { - int i; - - printf("Precaching all sound effects..."); - for (i = 1; i < num_sfx; i++) - { - // DEHEXTRA has turned S_sfx into a sparse array - if (!S_sfx[i].name) - continue; - - addsfx(&S_sfx[i], 0, NORM_PITCH); - } - stopchan(0); - printf("done.\n"); - } - } + StopChannel(0); + printf("done.\n"); + } + } } int midi_player; // current music module diff --git a/src/i_sound.h b/src/i_sound.h index 4b3dd1d5..3edaf5aa 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -45,11 +45,8 @@ #define S_STEREO_SWING (96<link; // sf: skip thru link(s) // Assigns the handle to one of the channels in the mix/output buffer. - handle = I_StartSound(sfx, cnum, volume, sep, pitch, priority, loop); + handle = I_StartSound(sfx, volume, sep, pitch, loop); // haleyjd: check to see if the sound was started if(handle >= 0) @@ -585,7 +585,7 @@ void S_UpdateSounds(const mobj_t *listener) S_StopChannel(cnum); else { - I_UpdateSoundParams(c->handle, volume, sep, pitch); + I_UpdateSoundParams(c->handle, volume, sep); c->priority = pri; // haleyjd } } diff --git a/src/sounds.c b/src/sounds.c index 0a2c1de2..5a52d9b9 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -125,328 +125,343 @@ musicinfo_t S_music[] = { // killough 12/98: // Reimplemented 'singularity' flag, adjusting many sounds below -sfxinfo_t original_S_sfx[NUMSFX] = { - { 0 }, // S_sfx[0] needs to be a dummy for odd reasons. +#define SOUND_LINK(n, s, p, l, i) \ + {.name = n, \ + .singularity = s, \ + .priority = p, \ + .link = l ? &original_S_sfx[l] : NULL, \ + .pitch = i, \ + .volume = -1, \ + .data = NULL, \ + .usefulness = -1, \ + .lumpnum = -1, \ + .alen = 0} - { "pistol", sg_none, 64, 0, -1, -1, 0 }, - { "shotgn", sg_none, 64, 0, -1, -1, 0 }, - { "sgcock", sg_none, 64, 0, -1, -1, 0 }, - { "dshtgn", sg_none, 64, 0, -1, -1, 0 }, - { "dbopn", sg_none, 64, 0, -1, -1, 0 }, - { "dbcls", sg_none, 64, 0, -1, -1, 0 }, - { "dbload", sg_none, 64, 0, -1, -1, 0 }, - { "plasma", sg_none, 64, 0, -1, -1, 0 }, - { "bfg", sg_none, 64, 0, -1, -1, 0 }, - { "sawup", sg_none, 64, 0, -1, -1, 0 }, - { "sawidl", sg_none, 118, 0, -1, -1, 0 }, - { "sawful", sg_none, 64, 0, -1, -1, 0 }, - { "sawhit", sg_none, 64, 0, -1, -1, 0 }, - { "rlaunc", sg_none, 64, 0, -1, -1, 0 }, - { "rxplod", sg_none, 70, 0, -1, -1, 0 }, - { "firsht", sg_none, 70, 0, -1, -1, 0 }, - { "firxpl", sg_none, 70, 0, -1, -1, 0 }, - { "pstart", sg_none, 100, 0, -1, -1, 0 }, - { "pstop", sg_none, 100, 0, -1, -1, 0 }, - { "doropn", sg_none, 100, 0, -1, -1, 0 }, - { "dorcls", sg_none, 100, 0, -1, -1, 0 }, - { "stnmov", sg_none, 119, 0, -1, -1, 0 }, - { "swtchn", sg_none, 78, 0, -1, -1, 0 }, - { "swtchx", sg_none, 78, 0, -1, -1, 0 }, - { "plpain", sg_none, 96, 0, -1, -1, 0 }, - { "dmpain", sg_none, 96, 0, -1, -1, 0 }, - { "popain", sg_none, 96, 0, -1, -1, 0 }, - { "vipain", sg_none, 96, 0, -1, -1, 0 }, - { "mnpain", sg_none, 96, 0, -1, -1, 0 }, - { "pepain", sg_none, 96, 0, -1, -1, 0 }, - { "slop", sg_none, 78, 0, -1, -1, 0 }, - { "itemup", sg_itemup, 78, 0, -1, -1, 0 }, - { "wpnup", sg_wpnup, 78, 0, -1, -1, 0 }, - { "oof", sg_oof, 96, 0, -1, -1, 0 }, - { "telept", sg_none, 32, 0, -1, -1, 0 }, - { "posit1", sg_none, 98, 0, -1, -1, 0 }, - { "posit2", sg_none, 98, 0, -1, -1, 0 }, - { "posit3", sg_none, 98, 0, -1, -1, 0 }, - { "bgsit1", sg_none, 98, 0, -1, -1, 0 }, - { "bgsit2", sg_none, 98, 0, -1, -1, 0 }, - { "sgtsit", sg_none, 98, 0, -1, -1, 0 }, - { "cacsit", sg_none, 98, 0, -1, -1, 0 }, - { "brssit", sg_none, 94, 0, -1, -1, 0 }, - { "cybsit", sg_none, 92, 0, -1, -1, 0 }, - { "spisit", sg_none, 90, 0, -1, -1, 0 }, - { "bspsit", sg_none, 90, 0, -1, -1, 0 }, - { "kntsit", sg_none, 90, 0, -1, -1, 0 }, - { "vilsit", sg_none, 90, 0, -1, -1, 0 }, - { "mansit", sg_none, 90, 0, -1, -1, 0 }, - { "pesit", sg_none, 90, 0, -1, -1, 0 }, - { "sklatk", sg_none, 70, 0, -1, -1, 0 }, - { "sgtatk", sg_none, 70, 0, -1, -1, 0 }, - { "skepch", sg_none, 70, 0, -1, -1, 0 }, - { "vilatk", sg_none, 70, 0, -1, -1, 0 }, - { "claw", sg_none, 70, 0, -1, -1, 0 }, - { "skeswg", sg_none, 70, 0, -1, -1, 0 }, - { "pldeth", sg_none, 32, 0, -1, -1, 0 }, - { "pdiehi", sg_none, 32, 0, -1, -1, 0 }, - { "podth1", sg_none, 70, 0, -1, -1, 0 }, - { "podth2", sg_none, 70, 0, -1, -1, 0 }, - { "podth3", sg_none, 70, 0, -1, -1, 0 }, - { "bgdth1", sg_none, 70, 0, -1, -1, 0 }, - { "bgdth2", sg_none, 70, 0, -1, -1, 0 }, - { "sgtdth", sg_none, 70, 0, -1, -1, 0 }, - { "cacdth", sg_none, 70, 0, -1, -1, 0 }, - { "skldth", sg_none, 70, 0, -1, -1, 0 }, - { "brsdth", sg_none, 32, 0, -1, -1, 0 }, - { "cybdth", sg_none, 32, 0, -1, -1, 0 }, - { "spidth", sg_none, 32, 0, -1, -1, 0 }, - { "bspdth", sg_none, 32, 0, -1, -1, 0 }, - { "vildth", sg_none, 32, 0, -1, -1, 0 }, - { "kntdth", sg_none, 32, 0, -1, -1, 0 }, - { "pedth", sg_none, 32, 0, -1, -1, 0 }, - { "skedth", sg_none, 32, 0, -1, -1, 0 }, - { "posact", sg_none, 120, 0, -1, -1, 0 }, - { "bgact", sg_none, 120, 0, -1, -1, 0 }, - { "dmact", sg_none, 120, 0, -1, -1, 0 }, - { "bspact", sg_none, 100, 0, -1, -1, 0 }, - { "bspwlk", sg_none, 100, 0, -1, -1, 0 }, - { "vilact", sg_none, 100, 0, -1, -1, 0 }, - { "noway", sg_oof, 78, 0, -1, -1, 0 }, - { "barexp", sg_none, 60, 0, -1, -1, 0 }, - { "punch", sg_none, 64, 0, -1, -1, 0 }, - { "hoof", sg_none, 70, 0, -1, -1, 0 }, - { "metal", sg_none, 70, 0, -1, -1, 0 }, - { "chgun", sg_none, 64, &original_S_sfx[sfx_pistol], 150, 0, 0 }, - { "tink", sg_none, 60, 0, -1, -1, 0 }, - { "bdopn", sg_none, 100, 0, -1, -1, 0 }, - { "bdcls", sg_none, 100, 0, -1, -1, 0 }, - { "itmbk", sg_none, 100, 0, -1, -1, 0 }, - { "flame", sg_none, 32, 0, -1, -1, 0 }, - { "flamst", sg_none, 32, 0, -1, -1, 0 }, - { "getpow", sg_getpow, 60, 0, -1, -1, 0 }, - { "bospit", sg_none, 70, 0, -1, -1, 0 }, - { "boscub", sg_none, 70, 0, -1, -1, 0 }, - { "bossit", sg_none, 70, 0, -1, -1, 0 }, - { "bospn", sg_none, 70, 0, -1, -1, 0 }, - { "bosdth", sg_none, 70, 0, -1, -1, 0 }, - { "manatk", sg_none, 70, 0, -1, -1, 0 }, - { "mandth", sg_none, 70, 0, -1, -1, 0 }, - { "sssit", sg_none, 70, 0, -1, -1, 0 }, - { "ssdth", sg_none, 70, 0, -1, -1, 0 }, - { "keenpn", sg_none, 70, 0, -1, -1, 0 }, - { "keendt", sg_none, 70, 0, -1, -1, 0 }, - { "skeact", sg_none, 70, 0, -1, -1, 0 }, - { "skesit", sg_none, 70, 0, -1, -1, 0 }, - { "skeatk", sg_none, 70, 0, -1, -1, 0 }, - { "radio", sg_none, 60, 0, -1, -1, 0 }, +#define SOUND(n, s, p) \ + SOUND_LINK(n, s, p, 0, -1) + +sfxinfo_t original_S_sfx[NUMSFX] = { + SOUND("none", sg_none, 0), // S_sfx[0] needs to be a dummy for odd reasons. + + SOUND("pistol", sg_none, 64), + SOUND("shotgn", sg_none, 64), + SOUND("sgcock", sg_none, 64), + SOUND("dshtgn", sg_none, 64), + SOUND("dbopn", sg_none, 64), + SOUND("dbcls", sg_none, 64), + SOUND("dbload", sg_none, 64), + SOUND("plasma", sg_none, 64), + SOUND("bfg", sg_none, 64), + SOUND("sawup", sg_none, 64), + SOUND("sawidl", sg_none, 118), + SOUND("sawful", sg_none, 64), + SOUND("sawhit", sg_none, 64), + SOUND("rlaunc", sg_none, 64), + SOUND("rxplod", sg_none, 70), + SOUND("firsht", sg_none, 70), + SOUND("firxpl", sg_none, 70), + SOUND("pstart", sg_none, 100), + SOUND("pstop", sg_none, 100), + SOUND("doropn", sg_none, 100), + SOUND("dorcls", sg_none, 100), + SOUND("stnmov", sg_none, 119), + SOUND("swtchn", sg_none, 78), + SOUND("swtchx", sg_none, 78), + SOUND("plpain", sg_none, 96), + SOUND("dmpain", sg_none, 96), + SOUND("popain", sg_none, 96), + SOUND("vipain", sg_none, 96), + SOUND("mnpain", sg_none, 96), + SOUND("pepain", sg_none, 96), + SOUND("slop", sg_none, 78), + SOUND("itemup", sg_itemup, 78), + SOUND("wpnup", sg_wpnup, 78), + SOUND("oof", sg_oof, 96), + SOUND("telept", sg_none, 32), + SOUND("posit1", sg_none, 98), + SOUND("posit2", sg_none, 98), + SOUND("posit3", sg_none, 98), + SOUND("bgsit1", sg_none, 98), + SOUND("bgsit2", sg_none, 98), + SOUND("sgtsit", sg_none, 98), + SOUND("cacsit", sg_none, 98), + SOUND("brssit", sg_none, 94), + SOUND("cybsit", sg_none, 92), + SOUND("spisit", sg_none, 90), + SOUND("bspsit", sg_none, 90), + SOUND("kntsit", sg_none, 90), + SOUND("vilsit", sg_none, 90), + SOUND("mansit", sg_none, 90), + SOUND("pesit", sg_none, 90), + SOUND("sklatk", sg_none, 70), + SOUND("sgtatk", sg_none, 70), + SOUND("skepch", sg_none, 70), + SOUND("vilatk", sg_none, 70), + SOUND("claw", sg_none, 70), + SOUND("skeswg", sg_none, 70), + SOUND("pldeth", sg_none, 32), + SOUND("pdiehi", sg_none, 32), + SOUND("podth1", sg_none, 70), + SOUND("podth2", sg_none, 70), + SOUND("podth3", sg_none, 70), + SOUND("bgdth1", sg_none, 70), + SOUND("bgdth2", sg_none, 70), + SOUND("sgtdth", sg_none, 70), + SOUND("cacdth", sg_none, 70), + SOUND("skldth", sg_none, 70), + SOUND("brsdth", sg_none, 32), + SOUND("cybdth", sg_none, 32), + SOUND("spidth", sg_none, 32), + SOUND("bspdth", sg_none, 32), + SOUND("vildth", sg_none, 32), + SOUND("kntdth", sg_none, 32), + SOUND("pedth", sg_none, 32), + SOUND("skedth", sg_none, 32), + SOUND("posact", sg_none, 120), + SOUND("bgact", sg_none, 120), + SOUND("dmact", sg_none, 120), + SOUND("bspact", sg_none, 100), + SOUND("bspwlk", sg_none, 100), + SOUND("vilact", sg_none, 100), + SOUND("noway", sg_oof, 78), + SOUND("barexp", sg_none, 60), + SOUND("punch", sg_none, 64), + SOUND("hoof", sg_none, 70), + SOUND("metal", sg_none, 70), + SOUND_LINK("chgun", sg_none, 64, sfx_pistol, 150), + SOUND("tink", sg_none, 60), + SOUND("bdopn", sg_none, 100), + SOUND("bdcls", sg_none, 100), + SOUND("itmbk", sg_none, 100), + SOUND("flame", sg_none, 32), + SOUND("flamst", sg_none, 32), + SOUND("getpow", sg_getpow, 60), + SOUND("bospit", sg_none, 70), + SOUND("boscub", sg_none, 70), + SOUND("bossit", sg_none, 70), + SOUND("bospn", sg_none, 70), + SOUND("bosdth", sg_none, 70), + SOUND("manatk", sg_none, 70), + SOUND("mandth", sg_none, 70), + SOUND("sssit", sg_none, 70), + SOUND("ssdth", sg_none, 70), + SOUND("keenpn", sg_none, 70), + SOUND("keendt", sg_none, 70), + SOUND("skeact", sg_none, 70), + SOUND("skesit", sg_none, 70), + SOUND("skeatk", sg_none, 70), + SOUND("radio", sg_none, 60), // killough 11/98: dog sounds - { "dgsit", sg_none, 98, 0, -1, -1, 0 }, - { "dgatk", sg_none, 70, 0, -1, -1, 0 }, - { "dgact", sg_none, 120, 0, -1, -1, 0 }, - { "dgdth", sg_none, 70, 0, -1, -1, 0 }, - { "dgpain", sg_none, 96, 0, -1, -1, 0 }, + SOUND("dgsit", sg_none, 98), + SOUND("dgatk", sg_none, 70), + SOUND("dgact", sg_none, 120), + SOUND("dgdth", sg_none, 70), + SOUND("dgpain", sg_none, 96), // [crispy] play DSSECRET if available - { "secret", sg_none, 100, 0, -1, -1, 0 }, + SOUND("secret", sg_none, 100), - [500] = { "fre000", sg_none, 127, 0, -1, -1, 0 }, - [501] = { "fre001", sg_none, 127, 0, -1, -1, 0 }, - [502] = { "fre002", sg_none, 127, 0, -1, -1, 0 }, - [503] = { "fre003", sg_none, 127, 0, -1, -1, 0 }, - [504] = { "fre004", sg_none, 127, 0, -1, -1, 0 }, - [505] = { "fre005", sg_none, 127, 0, -1, -1, 0 }, - [506] = { "fre006", sg_none, 127, 0, -1, -1, 0 }, - [507] = { "fre007", sg_none, 127, 0, -1, -1, 0 }, - [508] = { "fre008", sg_none, 127, 0, -1, -1, 0 }, - [509] = { "fre009", sg_none, 127, 0, -1, -1, 0 }, - [510] = { "fre010", sg_none, 127, 0, -1, -1, 0 }, - [511] = { "fre011", sg_none, 127, 0, -1, -1, 0 }, - [512] = { "fre012", sg_none, 127, 0, -1, -1, 0 }, - [513] = { "fre013", sg_none, 127, 0, -1, -1, 0 }, - [514] = { "fre014", sg_none, 127, 0, -1, -1, 0 }, - [515] = { "fre015", sg_none, 127, 0, -1, -1, 0 }, - [516] = { "fre016", sg_none, 127, 0, -1, -1, 0 }, - [517] = { "fre017", sg_none, 127, 0, -1, -1, 0 }, - [518] = { "fre018", sg_none, 127, 0, -1, -1, 0 }, - [519] = { "fre019", sg_none, 127, 0, -1, -1, 0 }, - [520] = { "fre020", sg_none, 127, 0, -1, -1, 0 }, - [521] = { "fre021", sg_none, 127, 0, -1, -1, 0 }, - [522] = { "fre022", sg_none, 127, 0, -1, -1, 0 }, - [523] = { "fre023", sg_none, 127, 0, -1, -1, 0 }, - [524] = { "fre024", sg_none, 127, 0, -1, -1, 0 }, - [525] = { "fre025", sg_none, 127, 0, -1, -1, 0 }, - [526] = { "fre026", sg_none, 127, 0, -1, -1, 0 }, - [527] = { "fre027", sg_none, 127, 0, -1, -1, 0 }, - [528] = { "fre028", sg_none, 127, 0, -1, -1, 0 }, - [529] = { "fre029", sg_none, 127, 0, -1, -1, 0 }, - [530] = { "fre030", sg_none, 127, 0, -1, -1, 0 }, - [531] = { "fre031", sg_none, 127, 0, -1, -1, 0 }, - [532] = { "fre032", sg_none, 127, 0, -1, -1, 0 }, - [533] = { "fre033", sg_none, 127, 0, -1, -1, 0 }, - [534] = { "fre034", sg_none, 127, 0, -1, -1, 0 }, - [535] = { "fre035", sg_none, 127, 0, -1, -1, 0 }, - [536] = { "fre036", sg_none, 127, 0, -1, -1, 0 }, - [537] = { "fre037", sg_none, 127, 0, -1, -1, 0 }, - [538] = { "fre038", sg_none, 127, 0, -1, -1, 0 }, - [539] = { "fre039", sg_none, 127, 0, -1, -1, 0 }, - [540] = { "fre040", sg_none, 127, 0, -1, -1, 0 }, - [541] = { "fre041", sg_none, 127, 0, -1, -1, 0 }, - [542] = { "fre042", sg_none, 127, 0, -1, -1, 0 }, - [543] = { "fre043", sg_none, 127, 0, -1, -1, 0 }, - [544] = { "fre044", sg_none, 127, 0, -1, -1, 0 }, - [545] = { "fre045", sg_none, 127, 0, -1, -1, 0 }, - [546] = { "fre046", sg_none, 127, 0, -1, -1, 0 }, - [547] = { "fre047", sg_none, 127, 0, -1, -1, 0 }, - [548] = { "fre048", sg_none, 127, 0, -1, -1, 0 }, - [549] = { "fre049", sg_none, 127, 0, -1, -1, 0 }, - [550] = { "fre050", sg_none, 127, 0, -1, -1, 0 }, - [551] = { "fre051", sg_none, 127, 0, -1, -1, 0 }, - [552] = { "fre052", sg_none, 127, 0, -1, -1, 0 }, - [553] = { "fre053", sg_none, 127, 0, -1, -1, 0 }, - [554] = { "fre054", sg_none, 127, 0, -1, -1, 0 }, - [555] = { "fre055", sg_none, 127, 0, -1, -1, 0 }, - [556] = { "fre056", sg_none, 127, 0, -1, -1, 0 }, - [557] = { "fre057", sg_none, 127, 0, -1, -1, 0 }, - [558] = { "fre058", sg_none, 127, 0, -1, -1, 0 }, - [559] = { "fre059", sg_none, 127, 0, -1, -1, 0 }, - [560] = { "fre060", sg_none, 127, 0, -1, -1, 0 }, - [561] = { "fre061", sg_none, 127, 0, -1, -1, 0 }, - [562] = { "fre062", sg_none, 127, 0, -1, -1, 0 }, - [563] = { "fre063", sg_none, 127, 0, -1, -1, 0 }, - [564] = { "fre064", sg_none, 127, 0, -1, -1, 0 }, - [565] = { "fre065", sg_none, 127, 0, -1, -1, 0 }, - [566] = { "fre066", sg_none, 127, 0, -1, -1, 0 }, - [567] = { "fre067", sg_none, 127, 0, -1, -1, 0 }, - [568] = { "fre068", sg_none, 127, 0, -1, -1, 0 }, - [569] = { "fre069", sg_none, 127, 0, -1, -1, 0 }, - [570] = { "fre070", sg_none, 127, 0, -1, -1, 0 }, - [571] = { "fre071", sg_none, 127, 0, -1, -1, 0 }, - [572] = { "fre072", sg_none, 127, 0, -1, -1, 0 }, - [573] = { "fre073", sg_none, 127, 0, -1, -1, 0 }, - [574] = { "fre074", sg_none, 127, 0, -1, -1, 0 }, - [575] = { "fre075", sg_none, 127, 0, -1, -1, 0 }, - [576] = { "fre076", sg_none, 127, 0, -1, -1, 0 }, - [577] = { "fre077", sg_none, 127, 0, -1, -1, 0 }, - [578] = { "fre078", sg_none, 127, 0, -1, -1, 0 }, - [579] = { "fre079", sg_none, 127, 0, -1, -1, 0 }, - [580] = { "fre080", sg_none, 127, 0, -1, -1, 0 }, - [581] = { "fre081", sg_none, 127, 0, -1, -1, 0 }, - [582] = { "fre082", sg_none, 127, 0, -1, -1, 0 }, - [583] = { "fre083", sg_none, 127, 0, -1, -1, 0 }, - [584] = { "fre084", sg_none, 127, 0, -1, -1, 0 }, - [585] = { "fre085", sg_none, 127, 0, -1, -1, 0 }, - [586] = { "fre086", sg_none, 127, 0, -1, -1, 0 }, - [587] = { "fre087", sg_none, 127, 0, -1, -1, 0 }, - [588] = { "fre088", sg_none, 127, 0, -1, -1, 0 }, - [589] = { "fre089", sg_none, 127, 0, -1, -1, 0 }, - [590] = { "fre090", sg_none, 127, 0, -1, -1, 0 }, - [591] = { "fre091", sg_none, 127, 0, -1, -1, 0 }, - [592] = { "fre092", sg_none, 127, 0, -1, -1, 0 }, - [593] = { "fre093", sg_none, 127, 0, -1, -1, 0 }, - [594] = { "fre094", sg_none, 127, 0, -1, -1, 0 }, - [595] = { "fre095", sg_none, 127, 0, -1, -1, 0 }, - [596] = { "fre096", sg_none, 127, 0, -1, -1, 0 }, - [597] = { "fre097", sg_none, 127, 0, -1, -1, 0 }, - [598] = { "fre098", sg_none, 127, 0, -1, -1, 0 }, - [599] = { "fre099", sg_none, 127, 0, -1, -1, 0 }, - [600] = { "fre100", sg_none, 127, 0, -1, -1, 0 }, - [601] = { "fre101", sg_none, 127, 0, -1, -1, 0 }, - [602] = { "fre102", sg_none, 127, 0, -1, -1, 0 }, - [603] = { "fre103", sg_none, 127, 0, -1, -1, 0 }, - [604] = { "fre104", sg_none, 127, 0, -1, -1, 0 }, - [605] = { "fre105", sg_none, 127, 0, -1, -1, 0 }, - [606] = { "fre106", sg_none, 127, 0, -1, -1, 0 }, - [607] = { "fre107", sg_none, 127, 0, -1, -1, 0 }, - [608] = { "fre108", sg_none, 127, 0, -1, -1, 0 }, - [609] = { "fre109", sg_none, 127, 0, -1, -1, 0 }, - [610] = { "fre110", sg_none, 127, 0, -1, -1, 0 }, - [611] = { "fre111", sg_none, 127, 0, -1, -1, 0 }, - [612] = { "fre112", sg_none, 127, 0, -1, -1, 0 }, - [613] = { "fre113", sg_none, 127, 0, -1, -1, 0 }, - [614] = { "fre114", sg_none, 127, 0, -1, -1, 0 }, - [615] = { "fre115", sg_none, 127, 0, -1, -1, 0 }, - [616] = { "fre116", sg_none, 127, 0, -1, -1, 0 }, - [617] = { "fre117", sg_none, 127, 0, -1, -1, 0 }, - [618] = { "fre118", sg_none, 127, 0, -1, -1, 0 }, - [619] = { "fre119", sg_none, 127, 0, -1, -1, 0 }, - [620] = { "fre120", sg_none, 127, 0, -1, -1, 0 }, - [621] = { "fre121", sg_none, 127, 0, -1, -1, 0 }, - [622] = { "fre122", sg_none, 127, 0, -1, -1, 0 }, - [623] = { "fre123", sg_none, 127, 0, -1, -1, 0 }, - [624] = { "fre124", sg_none, 127, 0, -1, -1, 0 }, - [625] = { "fre125", sg_none, 127, 0, -1, -1, 0 }, - [626] = { "fre126", sg_none, 127, 0, -1, -1, 0 }, - [627] = { "fre127", sg_none, 127, 0, -1, -1, 0 }, - [628] = { "fre128", sg_none, 127, 0, -1, -1, 0 }, - [629] = { "fre129", sg_none, 127, 0, -1, -1, 0 }, - [630] = { "fre130", sg_none, 127, 0, -1, -1, 0 }, - [631] = { "fre131", sg_none, 127, 0, -1, -1, 0 }, - [632] = { "fre132", sg_none, 127, 0, -1, -1, 0 }, - [633] = { "fre133", sg_none, 127, 0, -1, -1, 0 }, - [634] = { "fre134", sg_none, 127, 0, -1, -1, 0 }, - [635] = { "fre135", sg_none, 127, 0, -1, -1, 0 }, - [636] = { "fre136", sg_none, 127, 0, -1, -1, 0 }, - [637] = { "fre137", sg_none, 127, 0, -1, -1, 0 }, - [638] = { "fre138", sg_none, 127, 0, -1, -1, 0 }, - [639] = { "fre139", sg_none, 127, 0, -1, -1, 0 }, - [640] = { "fre140", sg_none, 127, 0, -1, -1, 0 }, - [641] = { "fre141", sg_none, 127, 0, -1, -1, 0 }, - [642] = { "fre142", sg_none, 127, 0, -1, -1, 0 }, - [643] = { "fre143", sg_none, 127, 0, -1, -1, 0 }, - [644] = { "fre144", sg_none, 127, 0, -1, -1, 0 }, - [645] = { "fre145", sg_none, 127, 0, -1, -1, 0 }, - [646] = { "fre146", sg_none, 127, 0, -1, -1, 0 }, - [647] = { "fre147", sg_none, 127, 0, -1, -1, 0 }, - [648] = { "fre148", sg_none, 127, 0, -1, -1, 0 }, - [649] = { "fre149", sg_none, 127, 0, -1, -1, 0 }, - [650] = { "fre150", sg_none, 127, 0, -1, -1, 0 }, - [651] = { "fre151", sg_none, 127, 0, -1, -1, 0 }, - [652] = { "fre152", sg_none, 127, 0, -1, -1, 0 }, - [653] = { "fre153", sg_none, 127, 0, -1, -1, 0 }, - [654] = { "fre154", sg_none, 127, 0, -1, -1, 0 }, - [655] = { "fre155", sg_none, 127, 0, -1, -1, 0 }, - [656] = { "fre156", sg_none, 127, 0, -1, -1, 0 }, - [657] = { "fre157", sg_none, 127, 0, -1, -1, 0 }, - [658] = { "fre158", sg_none, 127, 0, -1, -1, 0 }, - [659] = { "fre159", sg_none, 127, 0, -1, -1, 0 }, - [660] = { "fre160", sg_none, 127, 0, -1, -1, 0 }, - [661] = { "fre161", sg_none, 127, 0, -1, -1, 0 }, - [662] = { "fre162", sg_none, 127, 0, -1, -1, 0 }, - [663] = { "fre163", sg_none, 127, 0, -1, -1, 0 }, - [664] = { "fre164", sg_none, 127, 0, -1, -1, 0 }, - [665] = { "fre165", sg_none, 127, 0, -1, -1, 0 }, - [666] = { "fre166", sg_none, 127, 0, -1, -1, 0 }, - [667] = { "fre167", sg_none, 127, 0, -1, -1, 0 }, - [668] = { "fre168", sg_none, 127, 0, -1, -1, 0 }, - [669] = { "fre169", sg_none, 127, 0, -1, -1, 0 }, - [670] = { "fre170", sg_none, 127, 0, -1, -1, 0 }, - [671] = { "fre171", sg_none, 127, 0, -1, -1, 0 }, - [672] = { "fre172", sg_none, 127, 0, -1, -1, 0 }, - [673] = { "fre173", sg_none, 127, 0, -1, -1, 0 }, - [674] = { "fre174", sg_none, 127, 0, -1, -1, 0 }, - [675] = { "fre175", sg_none, 127, 0, -1, -1, 0 }, - [676] = { "fre176", sg_none, 127, 0, -1, -1, 0 }, - [677] = { "fre177", sg_none, 127, 0, -1, -1, 0 }, - [678] = { "fre178", sg_none, 127, 0, -1, -1, 0 }, - [679] = { "fre179", sg_none, 127, 0, -1, -1, 0 }, - [680] = { "fre180", sg_none, 127, 0, -1, -1, 0 }, - [681] = { "fre181", sg_none, 127, 0, -1, -1, 0 }, - [682] = { "fre182", sg_none, 127, 0, -1, -1, 0 }, - [683] = { "fre183", sg_none, 127, 0, -1, -1, 0 }, - [684] = { "fre184", sg_none, 127, 0, -1, -1, 0 }, - [685] = { "fre185", sg_none, 127, 0, -1, -1, 0 }, - [686] = { "fre186", sg_none, 127, 0, -1, -1, 0 }, - [687] = { "fre187", sg_none, 127, 0, -1, -1, 0 }, - [688] = { "fre188", sg_none, 127, 0, -1, -1, 0 }, - [689] = { "fre189", sg_none, 127, 0, -1, -1, 0 }, - [690] = { "fre190", sg_none, 127, 0, -1, -1, 0 }, - [691] = { "fre191", sg_none, 127, 0, -1, -1, 0 }, - [692] = { "fre192", sg_none, 127, 0, -1, -1, 0 }, - [693] = { "fre193", sg_none, 127, 0, -1, -1, 0 }, - [694] = { "fre194", sg_none, 127, 0, -1, -1, 0 }, - [695] = { "fre195", sg_none, 127, 0, -1, -1, 0 }, - [696] = { "fre196", sg_none, 127, 0, -1, -1, 0 }, - [697] = { "fre197", sg_none, 127, 0, -1, -1, 0 }, - [698] = { "fre198", sg_none, 127, 0, -1, -1, 0 }, - [699] = { "fre199", sg_none, 127, 0, -1, -1, 0 }, + [500] = SOUND("fre000", sg_none, 127), + [501] = SOUND("fre001", sg_none, 127), + [502] = SOUND("fre002", sg_none, 127), + [503] = SOUND("fre003", sg_none, 127), + [504] = SOUND("fre004", sg_none, 127), + [505] = SOUND("fre005", sg_none, 127), + [506] = SOUND("fre006", sg_none, 127), + [507] = SOUND("fre007", sg_none, 127), + [508] = SOUND("fre008", sg_none, 127), + [509] = SOUND("fre009", sg_none, 127), + [510] = SOUND("fre010", sg_none, 127), + [511] = SOUND("fre011", sg_none, 127), + [512] = SOUND("fre012", sg_none, 127), + [513] = SOUND("fre013", sg_none, 127), + [514] = SOUND("fre014", sg_none, 127), + [515] = SOUND("fre015", sg_none, 127), + [516] = SOUND("fre016", sg_none, 127), + [517] = SOUND("fre017", sg_none, 127), + [518] = SOUND("fre018", sg_none, 127), + [519] = SOUND("fre019", sg_none, 127), + [520] = SOUND("fre020", sg_none, 127), + [521] = SOUND("fre021", sg_none, 127), + [522] = SOUND("fre022", sg_none, 127), + [523] = SOUND("fre023", sg_none, 127), + [524] = SOUND("fre024", sg_none, 127), + [525] = SOUND("fre025", sg_none, 127), + [526] = SOUND("fre026", sg_none, 127), + [527] = SOUND("fre027", sg_none, 127), + [528] = SOUND("fre028", sg_none, 127), + [529] = SOUND("fre029", sg_none, 127), + [530] = SOUND("fre030", sg_none, 127), + [531] = SOUND("fre031", sg_none, 127), + [532] = SOUND("fre032", sg_none, 127), + [533] = SOUND("fre033", sg_none, 127), + [534] = SOUND("fre034", sg_none, 127), + [535] = SOUND("fre035", sg_none, 127), + [536] = SOUND("fre036", sg_none, 127), + [537] = SOUND("fre037", sg_none, 127), + [538] = SOUND("fre038", sg_none, 127), + [539] = SOUND("fre039", sg_none, 127), + [540] = SOUND("fre040", sg_none, 127), + [541] = SOUND("fre041", sg_none, 127), + [542] = SOUND("fre042", sg_none, 127), + [543] = SOUND("fre043", sg_none, 127), + [544] = SOUND("fre044", sg_none, 127), + [545] = SOUND("fre045", sg_none, 127), + [546] = SOUND("fre046", sg_none, 127), + [547] = SOUND("fre047", sg_none, 127), + [548] = SOUND("fre048", sg_none, 127), + [549] = SOUND("fre049", sg_none, 127), + [550] = SOUND("fre050", sg_none, 127), + [551] = SOUND("fre051", sg_none, 127), + [552] = SOUND("fre052", sg_none, 127), + [553] = SOUND("fre053", sg_none, 127), + [554] = SOUND("fre054", sg_none, 127), + [555] = SOUND("fre055", sg_none, 127), + [556] = SOUND("fre056", sg_none, 127), + [557] = SOUND("fre057", sg_none, 127), + [558] = SOUND("fre058", sg_none, 127), + [559] = SOUND("fre059", sg_none, 127), + [560] = SOUND("fre060", sg_none, 127), + [561] = SOUND("fre061", sg_none, 127), + [562] = SOUND("fre062", sg_none, 127), + [563] = SOUND("fre063", sg_none, 127), + [564] = SOUND("fre064", sg_none, 127), + [565] = SOUND("fre065", sg_none, 127), + [566] = SOUND("fre066", sg_none, 127), + [567] = SOUND("fre067", sg_none, 127), + [568] = SOUND("fre068", sg_none, 127), + [569] = SOUND("fre069", sg_none, 127), + [570] = SOUND("fre070", sg_none, 127), + [571] = SOUND("fre071", sg_none, 127), + [572] = SOUND("fre072", sg_none, 127), + [573] = SOUND("fre073", sg_none, 127), + [574] = SOUND("fre074", sg_none, 127), + [575] = SOUND("fre075", sg_none, 127), + [576] = SOUND("fre076", sg_none, 127), + [577] = SOUND("fre077", sg_none, 127), + [578] = SOUND("fre078", sg_none, 127), + [579] = SOUND("fre079", sg_none, 127), + [580] = SOUND("fre080", sg_none, 127), + [581] = SOUND("fre081", sg_none, 127), + [582] = SOUND("fre082", sg_none, 127), + [583] = SOUND("fre083", sg_none, 127), + [584] = SOUND("fre084", sg_none, 127), + [585] = SOUND("fre085", sg_none, 127), + [586] = SOUND("fre086", sg_none, 127), + [587] = SOUND("fre087", sg_none, 127), + [588] = SOUND("fre088", sg_none, 127), + [589] = SOUND("fre089", sg_none, 127), + [590] = SOUND("fre090", sg_none, 127), + [591] = SOUND("fre091", sg_none, 127), + [592] = SOUND("fre092", sg_none, 127), + [593] = SOUND("fre093", sg_none, 127), + [594] = SOUND("fre094", sg_none, 127), + [595] = SOUND("fre095", sg_none, 127), + [596] = SOUND("fre096", sg_none, 127), + [597] = SOUND("fre097", sg_none, 127), + [598] = SOUND("fre098", sg_none, 127), + [599] = SOUND("fre099", sg_none, 127), + [600] = SOUND("fre100", sg_none, 127), + [601] = SOUND("fre101", sg_none, 127), + [602] = SOUND("fre102", sg_none, 127), + [603] = SOUND("fre103", sg_none, 127), + [604] = SOUND("fre104", sg_none, 127), + [605] = SOUND("fre105", sg_none, 127), + [606] = SOUND("fre106", sg_none, 127), + [607] = SOUND("fre107", sg_none, 127), + [608] = SOUND("fre108", sg_none, 127), + [609] = SOUND("fre109", sg_none, 127), + [610] = SOUND("fre110", sg_none, 127), + [611] = SOUND("fre111", sg_none, 127), + [612] = SOUND("fre112", sg_none, 127), + [613] = SOUND("fre113", sg_none, 127), + [614] = SOUND("fre114", sg_none, 127), + [615] = SOUND("fre115", sg_none, 127), + [616] = SOUND("fre116", sg_none, 127), + [617] = SOUND("fre117", sg_none, 127), + [618] = SOUND("fre118", sg_none, 127), + [619] = SOUND("fre119", sg_none, 127), + [620] = SOUND("fre120", sg_none, 127), + [621] = SOUND("fre121", sg_none, 127), + [622] = SOUND("fre122", sg_none, 127), + [623] = SOUND("fre123", sg_none, 127), + [624] = SOUND("fre124", sg_none, 127), + [625] = SOUND("fre125", sg_none, 127), + [626] = SOUND("fre126", sg_none, 127), + [627] = SOUND("fre127", sg_none, 127), + [628] = SOUND("fre128", sg_none, 127), + [629] = SOUND("fre129", sg_none, 127), + [630] = SOUND("fre130", sg_none, 127), + [631] = SOUND("fre131", sg_none, 127), + [632] = SOUND("fre132", sg_none, 127), + [633] = SOUND("fre133", sg_none, 127), + [634] = SOUND("fre134", sg_none, 127), + [635] = SOUND("fre135", sg_none, 127), + [636] = SOUND("fre136", sg_none, 127), + [637] = SOUND("fre137", sg_none, 127), + [638] = SOUND("fre138", sg_none, 127), + [639] = SOUND("fre139", sg_none, 127), + [640] = SOUND("fre140", sg_none, 127), + [641] = SOUND("fre141", sg_none, 127), + [642] = SOUND("fre142", sg_none, 127), + [643] = SOUND("fre143", sg_none, 127), + [644] = SOUND("fre144", sg_none, 127), + [645] = SOUND("fre145", sg_none, 127), + [646] = SOUND("fre146", sg_none, 127), + [647] = SOUND("fre147", sg_none, 127), + [648] = SOUND("fre148", sg_none, 127), + [649] = SOUND("fre149", sg_none, 127), + [650] = SOUND("fre150", sg_none, 127), + [651] = SOUND("fre151", sg_none, 127), + [652] = SOUND("fre152", sg_none, 127), + [653] = SOUND("fre153", sg_none, 127), + [654] = SOUND("fre154", sg_none, 127), + [655] = SOUND("fre155", sg_none, 127), + [656] = SOUND("fre156", sg_none, 127), + [657] = SOUND("fre157", sg_none, 127), + [658] = SOUND("fre158", sg_none, 127), + [659] = SOUND("fre159", sg_none, 127), + [660] = SOUND("fre160", sg_none, 127), + [661] = SOUND("fre161", sg_none, 127), + [662] = SOUND("fre162", sg_none, 127), + [663] = SOUND("fre163", sg_none, 127), + [664] = SOUND("fre164", sg_none, 127), + [665] = SOUND("fre165", sg_none, 127), + [666] = SOUND("fre166", sg_none, 127), + [667] = SOUND("fre167", sg_none, 127), + [668] = SOUND("fre168", sg_none, 127), + [669] = SOUND("fre169", sg_none, 127), + [670] = SOUND("fre170", sg_none, 127), + [671] = SOUND("fre171", sg_none, 127), + [672] = SOUND("fre172", sg_none, 127), + [673] = SOUND("fre173", sg_none, 127), + [674] = SOUND("fre174", sg_none, 127), + [675] = SOUND("fre175", sg_none, 127), + [676] = SOUND("fre176", sg_none, 127), + [677] = SOUND("fre177", sg_none, 127), + [678] = SOUND("fre178", sg_none, 127), + [679] = SOUND("fre179", sg_none, 127), + [680] = SOUND("fre180", sg_none, 127), + [681] = SOUND("fre181", sg_none, 127), + [682] = SOUND("fre182", sg_none, 127), + [683] = SOUND("fre183", sg_none, 127), + [684] = SOUND("fre184", sg_none, 127), + [685] = SOUND("fre185", sg_none, 127), + [686] = SOUND("fre186", sg_none, 127), + [687] = SOUND("fre187", sg_none, 127), + [688] = SOUND("fre188", sg_none, 127), + [689] = SOUND("fre189", sg_none, 127), + [690] = SOUND("fre190", sg_none, 127), + [691] = SOUND("fre191", sg_none, 127), + [692] = SOUND("fre192", sg_none, 127), + [693] = SOUND("fre193", sg_none, 127), + [694] = SOUND("fre194", sg_none, 127), + [695] = SOUND("fre195", sg_none, 127), + [696] = SOUND("fre196", sg_none, 127), + [697] = SOUND("fre197", sg_none, 127), + [698] = SOUND("fre198", sg_none, 127), + [699] = SOUND("fre199", sg_none, 127), }; //----------------------------------------------------------------------------