shithub: choc

Download patch

ref: 3a708aa7fb7577ad8fed6ee39705567dcdc4e97e
parent: 609dca9fdf9a03500c0f4023da7bcc4389f36c52
author: Simon Howard <[email protected]>
date: Sun Sep 14 17:36:46 EDT 2008

Remove i_sdlsound.c dependency on doom/

Subversion-branch: /branches/raven-branch
Subversion-revision: 1229

--- a/src/doom/deh_sound.c
+++ b/src/doom/deh_sound.c
@@ -36,7 +36,7 @@
 
 DEH_BEGIN_MAPPING(sound_mapping, sfxinfo_t)
     DEH_UNSUPPORTED_MAPPING("Offset")
-    DEH_MAPPING("Zero/One", singularity)
+    DEH_UNSUPPORTED_MAPPING("Zero/One")
     DEH_MAPPING("Value", priority)
     DEH_MAPPING("Zero 1", link)
     DEH_MAPPING("Zero 2", pitch)
--- a/src/doom/s_sound.c
+++ b/src/doom/s_sound.c
@@ -125,6 +125,8 @@
     I_InitSound();
     I_InitMusic();
 
+    I_PrecacheSounds(S_sfx, NUMSFX);
+
     S_SetSfxVolume(sfxVolume);
     S_SetMusicVolume(musicVolume);
 
--- a/src/doom/sounds.c
+++ b/src/doom/sounds.c
@@ -116,115 +116,114 @@
 sfxinfo_t S_sfx[] =
 {
   // S_sfx[0] needs to be a dummy for odd reasons.
-  { "none", false,  0, 0, -1, -1, 0, 0, 0 },
-
-  { "pistol", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "shotgn", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "sgcock", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "dshtgn", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "dbopn", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "dbcls", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "dbload", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "plasma", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "bfg", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "sawup", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "sawidl", false, 118, 0, -1, -1, 0, 0, 0 },
-  { "sawful", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "sawhit", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "rlaunc", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "rxplod", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "firsht", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "firxpl", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "pstart", false, 100, 0, -1, -1, 0, 0, 0 },
-  { "pstop", false, 100, 0, -1, -1, 0, 0, 0 },
-  { "doropn", false, 100, 0, -1, -1, 0, 0, 0 },
-  { "dorcls", false, 100, 0, -1, -1, 0, 0, 0 },
-  { "stnmov", false, 119, 0, -1, -1, 0, 0, 0 },
-  { "swtchn", false, 78, 0, -1, -1, 0, 0, 0 },
-  { "swtchx", false, 78, 0, -1, -1, 0, 0, 0 },
-  { "plpain", false, 96, 0, -1, -1, 0, 0, 0 },
-  { "dmpain", false, 96, 0, -1, -1, 0, 0, 0 },
-  { "popain", false, 96, 0, -1, -1, 0, 0, 0 },
-  { "vipain", false, 96, 0, -1, -1, 0, 0, 0 },
-  { "mnpain", false, 96, 0, -1, -1, 0, 0, 0 },
-  { "pepain", false, 96, 0, -1, -1, 0, 0, 0 },
-  { "slop", false, 78, 0, -1, -1, 0, 0, 0 },
-  { "itemup", true, 78, 0, -1, -1, 0, 0, 0 },
-  { "wpnup", true, 78, 0, -1, -1, 0, 0, 0 },
-  { "oof", false, 96, 0, -1, -1, 0, 0, 0 },
-  { "telept", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "posit1", true, 98, 0, -1, -1, 0, 0, 0 },
-  { "posit2", true, 98, 0, -1, -1, 0, 0, 0 },
-  { "posit3", true, 98, 0, -1, -1, 0, 0, 0 },
-  { "bgsit1", true, 98, 0, -1, -1, 0, 0, 0 },
-  { "bgsit2", true, 98, 0, -1, -1, 0, 0, 0 },
-  { "sgtsit", true, 98, 0, -1, -1, 0, 0, 0 },
-  { "cacsit", true, 98, 0, -1, -1, 0, 0, 0 },
-  { "brssit", true, 94, 0, -1, -1, 0, 0, 0 },
-  { "cybsit", true, 92, 0, -1, -1, 0, 0, 0 },
-  { "spisit", true, 90, 0, -1, -1, 0, 0, 0 },
-  { "bspsit", true, 90, 0, -1, -1, 0, 0, 0 },
-  { "kntsit", true, 90, 0, -1, -1, 0, 0, 0 },
-  { "vilsit", true, 90, 0, -1, -1, 0, 0, 0 },
-  { "mansit", true, 90, 0, -1, -1, 0, 0, 0 },
-  { "pesit", true, 90, 0, -1, -1, 0, 0, 0 },
-  { "sklatk", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "sgtatk", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "skepch", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "vilatk", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "claw", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "skeswg", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "pldeth", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "pdiehi", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "podth1", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "podth2", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "podth3", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "bgdth1", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "bgdth2", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "sgtdth", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "cacdth", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "skldth", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "brsdth", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "cybdth", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "spidth", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "bspdth", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "vildth", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "kntdth", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "pedth", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "skedth", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "posact", true, 120, 0, -1, -1, 0, 0, 0 },
-  { "bgact", true, 120, 0, -1, -1, 0, 0, 0 },
-  { "dmact", true, 120, 0, -1, -1, 0, 0, 0 },
-  { "bspact", true, 100, 0, -1, -1, 0, 0, 0 },
-  { "bspwlk", true, 100, 0, -1, -1, 0, 0, 0 },
-  { "vilact", true, 100, 0, -1, -1, 0, 0, 0 },
-  { "noway", false, 78, 0, -1, -1, 0, 0, 0 },
-  { "barexp", false, 60, 0, -1, -1, 0, 0, 0 },
-  { "punch", false, 64, 0, -1, -1, 0, 0, 0 },
-  { "hoof", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "metal", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "chgun", false, 64, &S_sfx[sfx_pistol], 150, 0, 0, 0, 0 },
-  { "tink", false, 60, 0, -1, -1, 0, 0, 0 },
-  { "bdopn", false, 100, 0, -1, -1, 0, 0, 0 },
-  { "bdcls", false, 100, 0, -1, -1, 0, 0, 0 },
-  { "itmbk", false, 100, 0, -1, -1, 0, 0, 0 },
-  { "flame", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "flamst", false, 32, 0, -1, -1, 0, 0, 0 },
-  { "getpow", false, 60, 0, -1, -1, 0, 0, 0 },
-  { "bospit", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "boscub", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "bossit", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "bospn", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "bosdth", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "manatk", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "mandth", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "sssit", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "ssdth", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "keenpn", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "keendt", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "skeact", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "skesit", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "skeatk", false, 70, 0, -1, -1, 0, 0, 0 },
-  { "radio", false, 60, 0, -1, -1, 0, 0, 0 } 
+  { "none", 0, 0, -1, -1, 0, 0, 0, NULL },
+  { "pistol", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "shotgn", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "sgcock", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "dshtgn", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "dbopn", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "dbcls", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "dbload", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "plasma", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "bfg", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "sawup", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "sawidl", 118, 0, -1, -1, 0, 0, 0, NULL },
+  { "sawful", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "sawhit", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "rlaunc", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "rxplod", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "firsht", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "firxpl", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "pstart", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "pstop", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "doropn", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "dorcls", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "stnmov", 119, 0, -1, -1, 0, 0, 0, NULL },
+  { "swtchn", 78, 0, -1, -1, 0, 0, 0, NULL },
+  { "swtchx", 78, 0, -1, -1, 0, 0, 0, NULL },
+  { "plpain", 96, 0, -1, -1, 0, 0, 0, NULL },
+  { "dmpain", 96, 0, -1, -1, 0, 0, 0, NULL },
+  { "popain", 96, 0, -1, -1, 0, 0, 0, NULL },
+  { "vipain", 96, 0, -1, -1, 0, 0, 0, NULL },
+  { "mnpain", 96, 0, -1, -1, 0, 0, 0, NULL },
+  { "pepain", 96, 0, -1, -1, 0, 0, 0, NULL },
+  { "slop", 78, 0, -1, -1, 0, 0, 0, NULL },
+  { "itemup", 78, 0, -1, -1, 0, 0, 0, NULL },
+  { "wpnup", 78, 0, -1, -1, 0, 0, 0, NULL },
+  { "oof", 96, 0, -1, -1, 0, 0, 0, NULL },
+  { "telept", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "posit1", 98, 0, -1, -1, 0, 0, 0, NULL },
+  { "posit2", 98, 0, -1, -1, 0, 0, 0, NULL },
+  { "posit3", 98, 0, -1, -1, 0, 0, 0, NULL },
+  { "bgsit1", 98, 0, -1, -1, 0, 0, 0, NULL },
+  { "bgsit2", 98, 0, -1, -1, 0, 0, 0, NULL },
+  { "sgtsit", 98, 0, -1, -1, 0, 0, 0, NULL },
+  { "cacsit", 98, 0, -1, -1, 0, 0, 0, NULL },
+  { "brssit", 94, 0, -1, -1, 0, 0, 0, NULL },
+  { "cybsit", 92, 0, -1, -1, 0, 0, 0, NULL },
+  { "spisit", 90, 0, -1, -1, 0, 0, 0, NULL },
+  { "bspsit", 90, 0, -1, -1, 0, 0, 0, NULL },
+  { "kntsit", 90, 0, -1, -1, 0, 0, 0, NULL },
+  { "vilsit", 90, 0, -1, -1, 0, 0, 0, NULL },
+  { "mansit", 90, 0, -1, -1, 0, 0, 0, NULL },
+  { "pesit", 90, 0, -1, -1, 0, 0, 0, NULL },
+  { "sklatk", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "sgtatk", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "skepch", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "vilatk", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "claw", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "skeswg", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "pldeth", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "pdiehi", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "podth1", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "podth2", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "podth3", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "bgdth1", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "bgdth2", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "sgtdth", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "cacdth", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "skldth", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "brsdth", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "cybdth", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "spidth", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "bspdth", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "vildth", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "kntdth", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "pedth", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "skedth", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "posact", 120, 0, -1, -1, 0, 0, 0, NULL },
+  { "bgact", 120, 0, -1, -1, 0, 0, 0, NULL },
+  { "dmact", 120, 0, -1, -1, 0, 0, 0, NULL },
+  { "bspact", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "bspwlk", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "vilact", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "noway", 78, 0, -1, -1, 0, 0, 0, NULL },
+  { "barexp", 60, 0, -1, -1, 0, 0, 0, NULL },
+  { "punch", 64, 0, -1, -1, 0, 0, 0, NULL },
+  { "hoof", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "metal", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "chgun", 64, &S_sfx[sfx_pistol], 150, 0, 0, 0, 0, NULL },
+  { "tink", 60, 0, -1, -1, 0, 0, 0, NULL },
+  { "bdopn", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "bdcls", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "itmbk", 100, 0, -1, -1, 0, 0, 0, NULL },
+  { "flame", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "flamst", 32, 0, -1, -1, 0, 0, 0, NULL },
+  { "getpow", 60, 0, -1, -1, 0, 0, 0, NULL },
+  { "bospit", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "boscub", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "bossit", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "bospn", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "bosdth", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "manatk", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "mandth", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "sssit", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "ssdth", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "keenpn", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "keendt", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "skeact", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "skesit", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "skeatk", 70, 0, -1, -1, 0, 0, 0, NULL },
+  { "radio", 60, 0, -1, -1, 0, 0, 0, NULL } 
 };
 
--- 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
@@ -42,7 +42,6 @@
 #include "i_sound.h"
 #include "i_system.h"
 #include "m_argv.h"
-#include "sounds.h"
 #include "w_wad.h"
 #include "z_zone.h"
 
@@ -53,7 +52,6 @@
 
 static boolean sound_initialised = false;
 
-static Mix_Chunk sound_chunks[NUMSFX];
 static sfxinfo_t *channels_playing[NUM_CHANNELS];
 
 static int mixer_freq;
@@ -64,6 +62,27 @@
 
 int use_libsamplerate = 0;
 
+// The driver_data field is used to point to a Mix_Chunk structure that
+// has data about the expanded version of the sound effect.  These are
+// allocated on demand.
+
+static Mix_Chunk *GetSoundChunk(sfxinfo_t *sfxinfo)
+{
+    Mix_Chunk *chunk;
+
+    // No chunk for this structure yet? Allocate it.
+
+    if (sfxinfo->driver_data == NULL)
+    {
+	chunk = Z_Malloc(sizeof(Mix_Chunk), PU_STATIC, NULL);
+	chunk->abuf = NULL;
+	chunk->allocated = 0;
+        sfxinfo->driver_data = chunk;
+    }
+
+    return sfxinfo->driver_data;
+}
+
 // When a sound stops, check if it is still playing.  If it is not, 
 // we can mark the sound data as CACHE to be freed back for other
 // means.
@@ -72,7 +91,7 @@
 {
     int i;
     sfxinfo_t *sfxinfo = channels_playing[channel];
-    int id;
+    Mix_Chunk *chunk;
 
     if (sfxinfo == NULL)
     {
@@ -90,9 +109,9 @@
     }
 
     // Not used on any channel, and can be safely released
-    // TODO
-    id = sfxinfo - S_sfx;
-    Z_ChangeTag(sound_chunks[id].abuf, PU_CACHE);
+
+    chunk = GetSoundChunk(sfxinfo);
+    Z_ChangeTag(chunk->abuf, PU_CACHE);
 }
 
 #ifdef HAVE_LIBSAMPLERATE
@@ -356,12 +375,12 @@
 
 static boolean CacheSFX(sfxinfo_t *sfxinfo)
 {
+    Mix_Chunk *chunk;
     int lumpnum;
     unsigned int lumplen;
     int samplerate;
     int clipped;
     unsigned int length;
-    int sound_id;
     byte *data;
 
     // need to load the sound
@@ -394,23 +413,20 @@
     }
 
     // Sample rate conversion
-    // DWF 2008-02-10:  sound_chunks[sound].alen and abuf are determined
+    // DWF 2008-02-10:  chunk->alen and abuf are determined
     // by ExpandSoundData.
 
-    sound_id = sfxinfo - S_sfx;
-    sound_chunks[sound_id].allocated = 1;
-    sound_chunks[sound_id].volume = MIX_MAX_VOLUME;
+    chunk = GetSoundChunk(sfxinfo);
+    chunk->allocated = 1;
+    chunk->volume = MIX_MAX_VOLUME;
 
-    clipped = ExpandSoundData(data + 8, 
-                              samplerate, 
-                              length, 
-                              &sound_chunks[sound_id]);
+    clipped = ExpandSoundData(data + 8, samplerate, length, chunk);
 
     if (clipped)
     {
-        fprintf(stderr, "Sound %d: clipped %u samples (%0.2f %%)\n", 
-                        sound_id, clipped,
-                        400.0 * clipped / sound_chunks[sound_id].alen);
+        fprintf(stderr, "Sound '%s': clipped %u samples (%0.2f %%)\n", 
+                        sfxinfo->name, clipped,
+                        400.0 * clipped / chunk->alen);
     }
 
     // don't need the original lump any more
@@ -424,15 +440,23 @@
 
 // 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)
 {
+    Mix_Chunk *chunk;
     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)
         {
             printf(".");
@@ -439,17 +463,18 @@
             fflush(stdout);
         }
 
-        sprintf(namebuf, "ds%s", DEH_String(S_sfx[i].name));
+        sprintf(namebuf, "ds%s", DEH_String(sounds[i].name));
 
-        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(&S_sfx[i]);
+            CacheSFX(&sounds[i]);
+	    chunk = GetSoundChunk(&sounds[i]);
 
-            if (sound_chunks[i].abuf != NULL)
+            if (chunk->abuf != NULL)
             {
-                Z_ChangeTag(sound_chunks[i].abuf, PU_CACHE);
+                Z_ChangeTag(chunk->abuf, PU_CACHE);
             }
         }
     }
@@ -457,27 +482,40 @@
     printf("\n");
 }
 
+#else
+
+static void I_SDL_PrecacheSounds(sfxinfo_t *sounds, int num_sounds)
+{
+    // no-op
+}
+
 #endif
 
-static Mix_Chunk *GetSFXChunk(sfxinfo_t *sfxinfo)
+// Load a SFX chunk into memory and ensure that it is locked.
+
+static boolean LockSound(sfxinfo_t *sfxinfo)
 {
-    int sound_id;
+    Mix_Chunk *chunk;
 
-    sound_id = sfxinfo - S_sfx;
+    chunk = GetSoundChunk(sfxinfo);
 
-    if (sound_chunks[sound_id].abuf == NULL)
+    if (chunk->abuf == NULL)
     {
+        // Not yet loaded, or has been freed.  Load the sound data.
+
         if (!CacheSFX(sfxinfo))
-            return NULL;
+	{
+            return false;
+	}
     }
     else
     {
         // don't free the sound while it is playing!
    
-        Z_ChangeTag(sound_chunks[sound_id].abuf, PU_STATIC);
+        Z_ChangeTag(chunk->abuf, PU_STATIC);
     }
 
-    return &sound_chunks[sound_id];
+    return true;
 }
 
 
@@ -540,13 +578,13 @@
 
     // Get the sound data
 
-    chunk = GetSFXChunk(sfxinfo);
-
-    if (chunk == NULL)
+    if (!LockSound(sfxinfo))
     {
-        return -1;
+	return -1;
     }
 
+    chunk = GetSoundChunk(sfxinfo);
+
     // play sound
 
     Mix_PlayChannelTimed(channel, chunk, 0, -1);
@@ -628,14 +666,9 @@
     
     // No sounds yet
 
-    for (i=0; i<NUMSFX; ++i)
-    {
-        sound_chunks[i].abuf = NULL;
-    }
-
     for (i=0; i<NUM_CHANNELS; ++i)
     {
-        channels_playing[i] = sfx_None;
+        channels_playing[i] = NULL;
     }
 
     if (SDL_Init(SDL_INIT_AUDIO) < 0)
@@ -664,8 +697,6 @@
         }
 
         ExpandSoundData = ExpandSoundData_SRC;
-
-        I_PrecacheSounds();
     }
 #else
     if (use_libsamplerate != 0)
@@ -707,5 +738,6 @@
     I_SDL_StartSound,
     I_SDL_StopSound,
     I_SDL_SoundIsPlaying,
+    I_SDL_PrecacheSounds,
 };
 
--- a/src/i_sound.c
+++ b/src/i_sound.c
@@ -289,6 +289,14 @@
     }
 }
 
+void I_PrecacheSounds(sfxinfo_t *sounds, int num_sounds)
+{
+    if (sound_module != NULL && sound_module->CacheSounds != NULL)
+    {
+	sound_module->CacheSounds(sounds, num_sounds);
+    }
+}
+
 void I_InitMusic(void)
 {
 }
--- a/src/i_sound.h
+++ b/src/i_sound.h
@@ -41,9 +41,6 @@
     // up to 6-character name
     char *name;
 
-    // Sfx singularity (only one at a time)
-    int singularity;
-
     // Sfx priority
     int priority;
 
@@ -66,6 +63,9 @@
 
     // lump number of sfx
     int lumpnum;		
+
+    // data used by the low level code
+    void *driver_data;
 };
 
 //
@@ -144,6 +144,10 @@
 
     boolean (*SoundIsPlaying)(int channel);
 
+    // Called on startup to precache sound effects (if necessary)
+
+    void (*CacheSounds)(sfxinfo_t *sounds, int num_sounds);
+
 } sound_module_t;
 
 void I_InitSound(void);
@@ -154,6 +158,7 @@
 int I_StartSound(sfxinfo_t *sfxinfo, int channel, int vol, int sep);
 void I_StopSound(int channel);
 boolean I_SoundIsPlaying(int channel);
+void I_PrecacheSounds(sfxinfo_t *sounds, int num_sounds);
 
 // Interface for music modules