summaryrefslogtreecommitdiff
path: root/src/i_sdlsound.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i_sdlsound.c')
-rw-r--r--src/i_sdlsound.c249
1 files changed, 154 insertions, 95 deletions
diff --git a/src/i_sdlsound.c b/src/i_sdlsound.c
index b6fc9787..b26fb1b2 100644
--- a/src/i_sdlsound.c
+++ b/src/i_sdlsound.c
@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
//
// Copyright(C) 1993-1996 Id Software, Inc.
-// Copyright(C) 2005 Simon Howard
+// Copyright(C) 2005-8 Simon Howard
// Copyright(C) 2008 David Flater
//
// This program is free software; you can redistribute it and/or
@@ -38,28 +38,30 @@
#include <samplerate.h>
#endif
-#include "deh_main.h"
+#include "deh_str.h"
+#include "i_sound.h"
#include "i_system.h"
-#include "s_sound.h"
#include "m_argv.h"
#include "w_wad.h"
#include "z_zone.h"
-#include "doomdef.h"
+#include "doomtype.h"
#define LOW_PASS_FILTER
#define NUM_CHANNELS 16
static boolean sound_initialised = false;
-static Mix_Chunk sound_chunks[NUMSFX];
-static int channels_playing[NUM_CHANNELS];
+static sfxinfo_t *channels_playing[NUM_CHANNELS];
static int mixer_freq;
static Uint16 mixer_format;
static int mixer_channels;
-static uint32_t (*ExpandSoundData)(byte *data, int samplerate, int length,
- Mix_Chunk *destination) = NULL;
+static boolean use_sfx_prefix;
+static void (*ExpandSoundData)(sfxinfo_t *sfxinfo,
+ byte *data,
+ int samplerate,
+ int length) = NULL;
int use_libsamplerate = 0;
@@ -70,26 +72,50 @@ int use_libsamplerate = 0;
static void ReleaseSoundOnChannel(int channel)
{
int i;
- int id = channels_playing[channel];
+ sfxinfo_t *sfxinfo = channels_playing[channel];
- if (!id)
+ if (sfxinfo == NULL)
{
return;
}
- channels_playing[channel] = sfx_None;
+ channels_playing[channel] = NULL;
for (i=0; i<NUM_CHANNELS; ++i)
{
// Playing on this channel? if so, don't release.
- if (channels_playing[i] == id)
+ if (channels_playing[i] == sfxinfo)
return;
}
// Not used on any channel, and can be safely released
-
- Z_ChangeTag(sound_chunks[id].abuf, PU_CACHE);
+
+ Z_ChangeTag(sfxinfo->driver_data, PU_CACHE);
+}
+
+// Allocate a new Mix_Chunk along with its data, storing
+// the result in the variable pointed to by variable
+
+static Mix_Chunk *AllocateChunk(sfxinfo_t *sfxinfo, uint32_t len)
+{
+ Mix_Chunk *chunk;
+
+ // Allocate the chunk and the audio buffer together
+
+ chunk = Z_Malloc(len + sizeof(Mix_Chunk),
+ PU_STATIC,
+ &sfxinfo->driver_data);
+ sfxinfo->driver_data = chunk;
+
+ // Skip past the chunk structure for the audio buffer
+
+ chunk->abuf = (byte *) (chunk + 1);
+ chunk->alen = len;
+ chunk->allocated = 1;
+ chunk->volume = MIX_MAX_VOLUME;
+
+ return chunk;
}
#ifdef HAVE_LIBSAMPLERATE
@@ -128,15 +154,17 @@ static int SRC_ConversionMode(void)
// Returns number of clipped samples.
// DWF 2008-02-10 with cleanups by Simon Howard.
-static uint32_t ExpandSoundData_SRC(byte *data,
- int samplerate,
- int length,
- Mix_Chunk *destination)
+static void ExpandSoundData_SRC(sfxinfo_t *sfxinfo,
+ byte *data,
+ int samplerate,
+ int length)
{
SRC_DATA src_data;
uint32_t i, abuf_index=0, clipped=0;
+ uint32_t alen;
int retn;
int16_t *expanded;
+ Mix_Chunk *chunk;
src_data.input_frames = length;
src_data.data_in = malloc(length * sizeof(float));
@@ -163,12 +191,14 @@ static uint32_t ExpandSoundData_SRC(byte *data,
retn = src_simple(&src_data, SRC_ConversionMode(), 1);
assert(retn == 0);
- // Convert the result back into 16-bit integers.
+ // Allocate the new chunk.
+
+ alen = src_data.output_frames_gen * 4;
- destination->alen = src_data.output_frames_gen * 4;
- destination->abuf = Z_Malloc(destination->alen, PU_STATIC,
- &destination->abuf);
- expanded = (int16_t *) destination->abuf;
+ chunk = AllocateChunk(sfxinfo, src_data.output_frames_gen * 4);
+ expanded = (int16_t *) chunk->abuf;
+
+ // Convert the result back into 16-bit integers.
for (i=0; i<src_data.output_frames_gen; ++i)
{
@@ -197,12 +227,15 @@ static uint32_t ExpandSoundData_SRC(byte *data,
int32_t cvtval_i = cvtval_f + (cvtval_f < 0 ? -0.5 : 0.5);
// Asymmetrical sound worries me, so we won't use -32768.
- if (cvtval_i < -INT16_MAX) {
- cvtval_i = -INT16_MAX;
- ++clipped;
- } else if (cvtval_i > INT16_MAX) {
- cvtval_i = INT16_MAX;
- ++clipped;
+ if (cvtval_i < -INT16_MAX)
+ {
+ cvtval_i = -INT16_MAX;
+ ++clipped;
+ }
+ else if (cvtval_i > INT16_MAX)
+ {
+ cvtval_i = INT16_MAX;
+ ++clipped;
}
// Left and right channels
@@ -213,7 +246,13 @@ static uint32_t ExpandSoundData_SRC(byte *data,
free(src_data.data_in);
free(src_data.data_out);
- return clipped;
+
+ if (clipped > 0)
+ {
+ fprintf(stderr, "Sound '%s': clipped %u samples (%0.2f %%)\n",
+ sfxinfo->name, clipped,
+ 400.0 * clipped / chunk->alen);
+ }
}
#endif
@@ -250,12 +289,13 @@ static boolean ConvertibleRatio(int freq1, int freq2)
// Generic sound expansion function for any sample rate.
// Returns number of clipped samples (always 0).
-static uint32_t ExpandSoundData_SDL(byte *data,
- int samplerate,
- int length,
- Mix_Chunk *destination)
+static void ExpandSoundData_SDL(sfxinfo_t *sfxinfo,
+ byte *data,
+ int samplerate,
+ int length)
{
SDL_AudioCVT convertor;
+ Mix_Chunk *chunk;
uint32_t expanded_length;
// Calculate the length of the expanded version of the sample.
@@ -266,9 +306,9 @@ static uint32_t ExpandSoundData_SDL(byte *data,
expanded_length *= 4;
- destination->alen = expanded_length;
- destination->abuf
- = Z_Malloc(expanded_length, PU_STATIC, &destination->abuf);
+ // Allocate a chunk in which to expand the sound
+
+ chunk = AllocateChunk(sfxinfo, expanded_length);
// If we can, use the standard / optimised SDL conversion routines.
@@ -278,7 +318,7 @@ static uint32_t ExpandSoundData_SDL(byte *data,
AUDIO_U8, 1, samplerate,
mixer_format, mixer_channels, mixer_freq))
{
- convertor.buf = destination->abuf;
+ convertor.buf = chunk->abuf;
convertor.len = length;
memcpy(convertor.buf, data, length);
@@ -286,7 +326,7 @@ static uint32_t ExpandSoundData_SDL(byte *data,
}
else
{
- Sint16 *expanded = (Sint16 *) destination->abuf;
+ Sint16 *expanded = (Sint16 *) chunk->abuf;
int expanded_length;
int expand_ratio;
int i;
@@ -344,25 +384,22 @@ static uint32_t ExpandSoundData_SDL(byte *data,
}
#endif /* #ifdef LOW_PASS_FILTER */
}
-
- return 0;
}
// Load and convert a sound effect
// Returns true if successful
-static boolean CacheSFX(int sound)
+static boolean CacheSFX(sfxinfo_t *sfxinfo)
{
int lumpnum;
unsigned int lumplen;
int samplerate;
- int clipped;
unsigned int length;
byte *data;
// need to load the sound
- lumpnum = S_sfx[sound].lumpnum;
+ lumpnum = sfxinfo->lumpnum;
data = W_CacheLumpNum(lumpnum, PU_STATIC);
lumplen = W_LumpLength(lumpnum);
@@ -390,23 +427,8 @@ static boolean CacheSFX(int sound)
}
// Sample rate conversion
- // DWF 2008-02-10: sound_chunks[sound].alen and abuf are determined
- // by ExpandSoundData.
- sound_chunks[sound].allocated = 1;
- sound_chunks[sound].volume = MIX_MAX_VOLUME;
-
- clipped = ExpandSoundData(data + 8,
- samplerate,
- length,
- &sound_chunks[sound]);
-
- if (clipped)
- {
- fprintf(stderr, "Sound %d: clipped %u samples (%0.2f %%)\n",
- sound, clipped,
- 400.0 * clipped / sound_chunks[sound].alen);
- }
+ ExpandSoundData(sfxinfo, data + 8, samplerate, length);
// don't need the original lump any more
@@ -415,18 +437,47 @@ static boolean CacheSFX(int sound)
return true;
}
+static void GetSfxLumpName(sfxinfo_t *sfx, char *buf)
+{
+ // Linked sfx lumps? Get the lump number for the sound linked to.
+
+ if (sfx->link != NULL)
+ {
+ sfx = sfx->link;
+ }
+
+ // Doom adds a DS* prefix to sound lumps; Heretic and Hexen don't
+ // do this.
+
+ if (use_sfx_prefix)
+ {
+ sprintf(buf, "ds%s", DEH_String(sfx->name));
+ }
+ else
+ {
+ strcpy(buf, DEH_String(sfx->name));
+ }
+}
+
#ifdef HAVE_LIBSAMPLERATE
// Preload all the sound effects - stops nasty ingame freezes
-static void I_PrecacheSounds(void)
+static void I_SDL_PrecacheSounds(sfxinfo_t *sounds, int num_sounds)
{
char namebuf[9];
int i;
- printf("I_PrecacheSounds: Precaching all sound effects..");
+ // Don't need to precache the sounds unless we are using libsamplerate.
- for (i=sfx_pistol; i<NUMSFX; ++i)
+ if (use_libsamplerate == 0)
+ {
+ return;
+ }
+
+ printf("I_SDL_PrecacheSounds: Precaching all sound effects..");
+
+ for (i=0; i<num_sounds; ++i)
{
if ((i % 6) == 0)
{
@@ -434,17 +485,17 @@ static void I_PrecacheSounds(void)
fflush(stdout);
}
- sprintf(namebuf, "ds%s", DEH_String(S_sfx[i].name));
+ GetSfxLumpName(&sounds[i], namebuf);
- S_sfx[i].lumpnum = W_CheckNumForName(namebuf);
+ sounds[i].lumpnum = W_CheckNumForName(namebuf);
- if (S_sfx[i].lumpnum != -1)
+ if (sounds[i].lumpnum != -1)
{
- CacheSFX(i);
+ // Try to cache the sound and then release it as cache
- if (sound_chunks[i].abuf != NULL)
+ if (CacheSFX(&sounds[i]))
{
- Z_ChangeTag(sound_chunks[i].abuf, PU_CACHE);
+ Z_ChangeTag(sounds[i].driver_data, PU_CACHE);
}
}
}
@@ -452,37 +503,49 @@ static void I_PrecacheSounds(void)
printf("\n");
}
+#else
+
+static void I_SDL_PrecacheSounds(sfxinfo_t *sounds, int num_sounds)
+{
+ // no-op
+}
+
#endif
-static Mix_Chunk *GetSFXChunk(int sound_id)
+// Load a SFX chunk into memory and ensure that it is locked.
+
+static boolean LockSound(sfxinfo_t *sfxinfo)
{
- if (sound_chunks[sound_id].abuf == NULL)
+ // If the sound isn't loaded, load it now
+
+ if (sfxinfo->driver_data == NULL)
{
- if (!CacheSFX(sound_id))
- return NULL;
+ if (!CacheSFX(sfxinfo))
+ {
+ return false;
+ }
}
else
{
- // don't free the sound while it is playing!
+ // Lock the sound effect into memory
- Z_ChangeTag(sound_chunks[sound_id].abuf, PU_STATIC);
+ Z_ChangeTag(sfxinfo->driver_data, PU_STATIC);
}
- return &sound_chunks[sound_id];
+ return true;
}
-
//
// Retrieve the raw data lump index
// for a given SFX name.
//
-static int I_SDL_GetSfxLumpNum(sfxinfo_t* sfx)
+static int I_SDL_GetSfxLumpNum(sfxinfo_t *sfx)
{
char namebuf[9];
- sprintf(namebuf, "ds%s", DEH_String(sfx->name));
-
+ GetSfxLumpName(sfx, namebuf);
+
return W_GetNumForName(namebuf);
}
@@ -515,7 +578,7 @@ static void I_SDL_UpdateSoundParams(int handle, int vol, int sep)
// is set, but currently not used by mixing.
//
-static int I_SDL_StartSound(int id, int channel, int vol, int sep)
+static int I_SDL_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep)
{
Mix_Chunk *chunk;
@@ -531,18 +594,18 @@ static int I_SDL_StartSound(int id, int channel, int vol, int sep)
// Get the sound data
- chunk = GetSFXChunk(id);
-
- if (chunk == NULL)
+ if (!LockSound(sfxinfo))
{
- return -1;
+ return -1;
}
+ chunk = (Mix_Chunk *) sfxinfo->driver_data;
+
// play sound
Mix_PlayChannelTimed(channel, chunk, 0, -1);
- channels_playing[channel] = id;
+ channels_playing[channel] = sfxinfo;
// set separation, etc.
@@ -613,20 +676,17 @@ static void I_SDL_ShutdownSound(void)
}
-static boolean I_SDL_InitSound(void)
+static boolean I_SDL_InitSound(boolean _use_sfx_prefix)
{
int i;
- // No sounds yet
+ use_sfx_prefix = _use_sfx_prefix;
- for (i=0; i<NUMSFX; ++i)
- {
- sound_chunks[i].abuf = NULL;
- }
+ // No sounds yet
for (i=0; i<NUM_CHANNELS; ++i)
{
- channels_playing[i] = sfx_None;
+ channels_playing[i] = NULL;
}
if (SDL_Init(SDL_INIT_AUDIO) < 0)
@@ -655,8 +715,6 @@ static boolean I_SDL_InitSound(void)
}
ExpandSoundData = ExpandSoundData_SRC;
-
- I_PrecacheSounds();
}
#else
if (use_libsamplerate != 0)
@@ -698,5 +756,6 @@ sound_module_t sound_sdl_module =
I_SDL_StartSound,
I_SDL_StopSound,
I_SDL_SoundIsPlaying,
+ I_SDL_PrecacheSounds,
};