summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Howard2007-06-17 18:40:02 +0000
committerSimon Howard2007-06-17 18:40:02 +0000
commitbeab4eb58b667a5883166bd1dd7bc33369a005c7 (patch)
treea6574cd329b3caea7a600ec6ce9184cc79ffb494
parent5fc7913741e9f722e31735baea10f635fc18acce (diff)
downloadchocolate-doom-beab4eb58b667a5883166bd1dd7bc33369a005c7.tar.gz
chocolate-doom-beab4eb58b667a5883166bd1dd7bc33369a005c7.tar.bz2
chocolate-doom-beab4eb58b667a5883166bd1dd7bc33369a005c7.zip
Split i_sound.c into i_sdlsound.c, i_sdlmusic.c, with generic "sound
driver" modules, one for PC speaker and one for digital output. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 913
-rw-r--r--pcsound/pcsound.c8
-rw-r--r--pcsound/pcsound.h21
-rw-r--r--pcsound/pcsound_internal.h (renamed from src/i_pcsound.h)33
-rw-r--r--pcsound/pcsound_linux.c1
-rw-r--r--pcsound/pcsound_sdl.c63
-rw-r--r--pcsound/pcsound_win32.c1
-rw-r--r--src/Makefile.am7
-rw-r--r--src/d_main.c1
-rw-r--r--src/deh_sound.c8
-rw-r--r--src/i_music.h (renamed from src/i_sound.h)57
-rw-r--r--src/i_pcsound.c87
-rw-r--r--src/i_sdlmusic.c317
-rw-r--r--src/i_sdlsound.c (renamed from src/i_sound.c)438
-rw-r--r--src/s_sound.c235
-rw-r--r--src/s_sound.h44
15 files changed, 745 insertions, 576 deletions
diff --git a/pcsound/pcsound.c b/pcsound/pcsound.c
index 1491ff61..8c739b35 100644
--- a/pcsound/pcsound.c
+++ b/pcsound/pcsound.c
@@ -29,6 +29,7 @@
#include "config.h"
#include "pcsound.h"
+#include "pcsound_internal.h"
#ifdef _WIN32
extern pcsound_driver_t pcsound_win32_driver;
@@ -54,6 +55,13 @@ static pcsound_driver_t *drivers[] =
static pcsound_driver_t *pcsound_driver = NULL;
+int pcsound_sample_rate;
+
+void PCSound_SetSampleRate(int rate)
+{
+ pcsound_sample_rate = rate;
+}
+
int PCSound_Init(pcsound_callback_func callback_func)
{
char *driver_name;
diff --git a/pcsound/pcsound.h b/pcsound/pcsound.h
index 12a4ffe9..e64796b8 100644
--- a/pcsound/pcsound.h
+++ b/pcsound/pcsound.h
@@ -26,22 +26,21 @@
#ifndef PCSOUND_H
#define PCSOUND_H
-#define PCSOUND_8253_FREQUENCY 1193280
-
-typedef struct pcsound_driver_s pcsound_driver_t;
typedef void (*pcsound_callback_func)(int *duration, int *frequency);
-typedef int (*pcsound_init_func)(pcsound_callback_func callback);
-typedef void (*pcsound_shutdown_func)(void);
-struct pcsound_driver_s
-{
- char *name;
- pcsound_init_func init_func;
- pcsound_shutdown_func shutdown_func;
-};
+// Initialise the PC speaker subsystem. The given function is called
+// periodically to request more sound data to play.
int PCSound_Init(pcsound_callback_func callback_func);
+
+// Shut down the PC speaker subsystem.
+
void PCSound_Shutdown(void);
+// Set the preferred output sample rate when emulating a PC speaker.
+// This must be called before PCSound_Init.
+
+void PCSound_SetSampleRate(int rate);
+
#endif /* #ifndef PCSOUND_H */
diff --git a/src/i_pcsound.h b/pcsound/pcsound_internal.h
index 601f4ee5..c5ae90b6 100644
--- a/src/i_pcsound.h
+++ b/pcsound/pcsound_internal.h
@@ -19,22 +19,29 @@
// 02111-1307, USA.
//
// DESCRIPTION:
-// System interface for PC speaker sound.
+// PC speaker interface.
//
//-----------------------------------------------------------------------------
-#ifndef __I_PCSOUND_H__
-#define __I_PCSOUND_H__
+#ifndef PCSOUND_INTERNAL_H
+#define PCSOUND_INTERNAL_H
-int I_PCS_StartSound(int id,
- int channel,
- int vol,
- int sep,
- int pitch,
- int priority);
-void I_PCS_StopSound(int handle);
-int I_PCS_SoundIsPlaying(int handle);
-void I_PCS_InitSound(void);
+#include "pcsound.h"
-#endif /* #ifndef __I_PCSOUND_H__ */
+#define PCSOUND_8253_FREQUENCY 1193280
+
+typedef struct pcsound_driver_s pcsound_driver_t;
+typedef int (*pcsound_init_func)(pcsound_callback_func callback);
+typedef void (*pcsound_shutdown_func)(void);
+
+struct pcsound_driver_s
+{
+ char *name;
+ pcsound_init_func init_func;
+ pcsound_shutdown_func shutdown_func;
+};
+
+extern int pcsound_sample_rate;
+
+#endif /* #ifndef PCSOUND_INTERNAL_H */
diff --git a/pcsound/pcsound_linux.c b/pcsound/pcsound_linux.c
index 7c1abc7b..02ab47b5 100644
--- a/pcsound/pcsound_linux.c
+++ b/pcsound/pcsound_linux.c
@@ -40,6 +40,7 @@
#include "SDL_thread.h"
#include "pcsound.h"
+#include "pcsound_internal.h"
#define CONSOLE_DEVICE "/dev/console"
diff --git a/pcsound/pcsound_sdl.c b/pcsound/pcsound_sdl.c
index 50820394..f862dfa7 100644
--- a/pcsound/pcsound_sdl.c
+++ b/pcsound/pcsound_sdl.c
@@ -30,9 +30,17 @@
#include "SDL_mixer.h"
#include "pcsound.h"
+#include "pcsound_internal.h"
#define SQUARE_WAVE_AMP 0x2000
+// If true, we initialised SDL and have the responsibility to shut it
+// down
+
+static int sdl_was_initialised = 0;
+
+// Callback function to invoke when we want new sound data
+
static pcsound_callback_func callback;
// Output sound format
@@ -137,16 +145,57 @@ static void PCSound_Mix_Callback(void *udata, Uint8 *stream, int len)
}
}
+static int SDLIsInitialised(void)
+{
+ int freq, channels;
+ Uint16 format;
+
+ return Mix_QuerySpec(&freq, &format, &channels);
+}
+
+static void PCSound_SDL_Shutdown(void)
+{
+ if (sdl_was_initialised)
+ {
+ Mix_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ sdl_was_initialised = 0;
+ }
+}
+
static int PCSound_SDL_Init(pcsound_callback_func callback_func)
{
- // Check that SDL_mixer has been opened already
- // If not, fail
+ // Check if SDL_mixer has been opened already
+ // If not, we must initialise it now
- if (!Mix_QuerySpec(&mixing_freq, &mixing_format, &mixing_channels))
+ if (!SDLIsInitialised())
{
- return 0;
+ if (SDL_Init(SDL_INIT_AUDIO) < 0)
+ {
+ fprintf(stderr, "Unable to set up sound.\n");
+ return 0;
+ }
+
+ if (Mix_OpenAudio(pcsound_sample_rate, AUDIO_S16SYS, 2, 1024) < 0)
+ {
+ fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError());
+
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ return 0;
+ }
+
+ SDL_PauseAudio(0);
+
+ // When this module shuts down, it has the responsibility to
+ // shut down SDL.
+
+ sdl_was_initialised = 1;
}
+ // Get the mixer frequency, format and number of channels.
+
+ Mix_QuerySpec(&mixing_freq, &mixing_format, &mixing_channels);
+
// Only supports AUDIO_S16SYS
if (mixing_format != AUDIO_S16SYS || mixing_channels != 2)
@@ -154,6 +203,8 @@ static int PCSound_SDL_Init(pcsound_callback_func callback_func)
fprintf(stderr,
"PCSound_SDL only supports native signed 16-bit LSB, "
"stereo format!\n");
+
+ PCSound_SDL_Shutdown();
return 0;
}
@@ -166,10 +217,6 @@ static int PCSound_SDL_Init(pcsound_callback_func callback_func)
return 1;
}
-static void PCSound_SDL_Shutdown(void)
-{
-}
-
pcsound_driver_t pcsound_sdl_driver =
{
"SDL",
diff --git a/pcsound/pcsound_win32.c b/pcsound/pcsound_win32.c
index 48677d73..7976b444 100644
--- a/pcsound/pcsound_win32.c
+++ b/pcsound/pcsound_win32.c
@@ -29,6 +29,7 @@
#include <windows.h>
#include "pcsound.h"
+#include "pcsound_internal.h"
static SDL_Thread *sound_thread_handle;
static int sound_thread_running;
diff --git a/src/Makefile.am b/src/Makefile.am
index 75c08c05..031369a7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -95,6 +95,7 @@ r_sky.c r_sky.h \
r_state.h \
r_things.c r_things.h \
sounds.c sounds.h \
+s_sound.c s_sound.h \
st_lib.c st_lib.h \
st_stuff.c st_stuff.h \
tables.c tables.h \
@@ -146,9 +147,9 @@ w_merge.c w_merge.h
FEATURE_SOUND_SOURCE_FILES = \
i_pcsound.c i_pcsound.h \
-i_sound.c i_sound.h \
-mus2mid.c mus2mid.h \
-s_sound.c s_sound.h
+i_sdlsound.c \
+i_sdlmusic.c i_music.h \
+mus2mid.c mus2mid.h
SOURCE_FILES = $(MAIN_SOURCE_FILES) \
$(FEATURE_DEHACKED_SOURCE_FILES) \
diff --git a/src/d_main.c b/src/d_main.c
index 65cb6bb9..6981b884 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -59,7 +59,6 @@
#include "p_saveg.h"
#include "i_system.h"
-#include "i_sound.h"
#include "i_timer.h"
#include "i_video.h"
diff --git a/src/deh_sound.c b/src/deh_sound.c
index 7068d94a..761ed069 100644
--- a/src/deh_sound.c
+++ b/src/deh_sound.c
@@ -68,15 +68,7 @@ static void *DEH_SoundStart(deh_context_t *context, char *line)
"in Vanilla dehacked.", sound_number);
}
-#ifdef FEATURE_SOUND
-
return &S_sfx[sound_number];
-
-#else
-
- return NULL;
-
-#endif
}
static void DEH_SoundParseLine(deh_context_t *context, char *line, void *tag)
diff --git a/src/i_sound.h b/src/i_music.h
index ad3852ce..70664c9a 100644
--- a/src/i_sound.h
+++ b/src/i_music.h
@@ -21,7 +21,7 @@
//
//
// DESCRIPTION:
-// System interface, sound.
+// System interface, music.
//
//-----------------------------------------------------------------------------
@@ -32,59 +32,7 @@
#include "doomstat.h"
#include "sounds.h"
-
-
-
-// Init at program start...
-void I_InitSound();
-
-// ... update sound buffer and audio device at runtime...
-void I_UpdateSound(void);
-void I_SubmitSound(void);
-
-// ... shut down and relase at program termination.
-void I_ShutdownSound(void);
-
-
-//
-// SFX I/O
-//
-
-// Initialize channels?
-void I_SetChannels();
-
-// Get raw data lump index for sound descriptor.
-int I_GetSfxLumpNum (sfxinfo_t* sfxinfo );
-
-
-// Starts a sound in a particular sound channel.
-int
-I_StartSound
-( int id,
- int channel,
- int vol,
- int sep,
- int pitch,
- int priority );
-
-
-// Stops a sound channel.
-void I_StopSound(int handle);
-
-// Called by S_*() functions
-// to see if a channel is still playing.
-// Returns 0 if no longer playing, 1 if playing.
-int I_SoundIsPlaying(int handle);
-
-// Updates the volume, separation,
-// and pitch of a sound channel.
-void
-I_UpdateSoundParams
-( int handle,
- int vol,
- int sep,
- int pitch );
-
+#include "s_sound.h"
//
// MUSIC I/O
@@ -125,3 +73,4 @@ boolean I_QrySongPlaying(void *handle);
#endif
+
diff --git a/src/i_pcsound.c b/src/i_pcsound.c
index 0dced9c1..08ba92e9 100644
--- a/src/i_pcsound.c
+++ b/src/i_pcsound.c
@@ -28,8 +28,8 @@
#include "doomdef.h"
#include "doomtype.h"
-#include "i_pcsound.h"
-#include "i_sound.h"
+#include "deh_main.h"
+#include "s_sound.h"
#include "sounds.h"
#include "w_wad.h"
@@ -62,7 +62,7 @@ static float frequencies[] = {
#define NUM_FREQUENCIES (sizeof(frequencies) / sizeof(*frequencies))
-void PCSCallbackFunc(int *duration, int *freq)
+static void PCSCallbackFunc(int *duration, int *freq)
{
int tone;
@@ -144,12 +144,10 @@ static boolean CachePCSLump(int sound_id)
return true;
}
-int I_PCS_StartSound(int id,
- int channel,
- int vol,
- int sep,
- int pitch,
- int priority)
+static int I_PCS_StartSound(int id,
+ int channel,
+ int vol,
+ int sep)
{
int result;
@@ -192,7 +190,7 @@ int I_PCS_StartSound(int id,
}
}
-void I_PCS_StopSound(int handle)
+static void I_PCS_StopSound(int handle)
{
if (!pcs_initialised)
{
@@ -214,7 +212,22 @@ void I_PCS_StopSound(int handle)
SDL_UnlockMutex(sound_lock);
}
-int I_PCS_SoundIsPlaying(int handle)
+//
+// Retrieve the raw data lump index
+// for a given SFX name.
+//
+
+static int I_PCS_GetSfxLumpNum(sfxinfo_t* sfx)
+{
+ char namebuf[9];
+
+ sprintf(namebuf, "dp%s", DEH_String(sfx->name));
+
+ return W_GetNumForName(namebuf);
+}
+
+
+static boolean I_PCS_SoundIsPlaying(int handle)
{
if (!pcs_initialised)
{
@@ -229,10 +242,58 @@ int I_PCS_SoundIsPlaying(int handle)
return current_sound_lump != NULL && current_sound_remaining > 0;
}
-void I_PCS_InitSound(void)
+static boolean I_PCS_InitSound(void)
{
+ // Use the sample rate from the configuration file
+
+ PCSound_SetSampleRate(snd_samplerate);
+
+ // Initialise the PC speaker subsystem.
+
pcs_initialised = PCSound_Init(PCSCallbackFunc);
- sound_lock = SDL_CreateMutex();
+ if (pcs_initialised)
+ {
+ sound_lock = SDL_CreateMutex();
+ }
+
+ return pcs_initialised;
+}
+
+static void I_PCS_ShutdownSound(void)
+{
+ if (pcs_initialised)
+ {
+ PCSound_Shutdown();
+ }
+}
+
+static void I_PCS_UpdateSound(void)
+{
+ // no-op.
+}
+
+void I_PCS_UpdateSoundParams(int channel, int vol, int sep)
+{
+ // no-op.
}
+static snddevice_t sound_pcsound_devices[] =
+{
+ SNDDEVICE_PCSPEAKER,
+};
+
+sound_module_t sound_pcsound_module =
+{
+ sound_pcsound_devices,
+ sizeof(sound_pcsound_devices) / sizeof(*sound_pcsound_devices),
+ I_PCS_InitSound,
+ I_PCS_ShutdownSound,
+ I_PCS_GetSfxLumpNum,
+ I_PCS_UpdateSound,
+ I_PCS_UpdateSoundParams,
+ I_PCS_StartSound,
+ I_PCS_StopSound,
+ I_PCS_SoundIsPlaying,
+};
+
diff --git a/src/i_sdlmusic.c b/src/i_sdlmusic.c
new file mode 100644
index 00000000..d2471578
--- /dev/null
+++ b/src/i_sdlmusic.c
@@ -0,0 +1,317 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// DESCRIPTION:
+// System interface for music.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "SDL.h"
+#include "SDL_mixer.h"
+
+#include "doomdef.h"
+#include "memio.h"
+#include "mus2mid.h"
+
+#include "deh_main.h"
+#include "m_misc.h"
+#include "s_sound.h"
+#include "w_wad.h"
+#include "z_zone.h"
+
+#define MAXMIDLENGTH (96 * 1024)
+
+static boolean music_initialised = false;
+
+// If this is true, this module initialised SDL sound and has the
+// responsibility to shut it down
+
+static boolean sdl_was_initialised = false;
+
+static boolean musicpaused = false;
+static int current_music_volume;
+
+void I_ShutdownMusic(void)
+{
+ if (music_initialised)
+ {
+ Mix_HaltMusic();
+ music_initialised = false;
+
+ if (sdl_was_initialised)
+ {
+ Mix_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ sdl_was_initialised = false;
+ }
+ }
+}
+
+static boolean SDLIsInitialised(void)
+{
+ int freq, channels;
+ Uint16 format;
+
+ return Mix_QuerySpec(&freq, &format, &channels) != 0;
+}
+
+void I_InitMusic()
+{
+ // When trying to run with music enabled on OSX, display
+ // a warning message.
+
+#ifdef __MACOSX__
+ printf("\n"
+ " *** WARNING ***\n"
+ " Music playback on OSX may cause crashes and\n"
+ " is disabled by default.\n"
+ "\n");
+#endif
+
+ // If SDL_mixer is not initialised, we have to initialise it
+ // and have the responsibility to shut it down later on.
+
+ if (!SDLIsInitialised())
+ {
+ if (SDL_Init(SDL_INIT_AUDIO) < 0)
+ {
+ fprintf(stderr, "Unable to set up sound.\n");
+ return;
+ }
+
+ if (Mix_OpenAudio(snd_samplerate, AUDIO_S16SYS, 2, 1024) < 0)
+ {
+ fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError());
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ return;
+ }
+
+ SDL_PauseAudio(0);
+
+ sdl_was_initialised = true;
+ }
+
+ music_initialised = true;
+}
+
+//
+// SDL_mixer's native MIDI music playing does not pause properly.
+// As a workaround, set the volume to 0 when paused.
+//
+
+static void UpdateMusicVolume(void)
+{
+ int vol;
+
+ if (musicpaused)
+ {
+ vol = 0;
+ }
+ else
+ {
+ vol = (current_music_volume * MIX_MAX_VOLUME) / 127;
+ }
+
+ Mix_VolumeMusic(vol);
+}
+
+// MUSIC API - dummy. Some code from DOS version.
+void I_SetMusicVolume(int volume)
+{
+ // Internal state variable.
+ current_music_volume = volume;
+
+ UpdateMusicVolume();
+}
+
+void I_PlaySong(void *handle, int looping)
+{
+ Mix_Music *music = (Mix_Music *) handle;
+ int loops;
+
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ if (handle == NULL)
+ {
+ return;
+ }
+
+ if (looping)
+ {
+ loops = -1;
+ }
+ else
+ {
+ loops = 1;
+ }
+
+ Mix_PlayMusic(music, loops);
+}
+
+void I_PauseSong (void *handle)
+{
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ musicpaused = true;
+
+ UpdateMusicVolume();
+}
+
+void I_ResumeSong (void *handle)
+{
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ musicpaused = false;
+
+ UpdateMusicVolume();
+}
+
+void I_StopSong(void *handle)
+{
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ Mix_HaltMusic();
+}
+
+void I_UnRegisterSong(void *handle)
+{
+ Mix_Music *music = (Mix_Music *) handle;
+
+ if (!music_initialised)
+ {
+ return;
+ }
+
+ if (handle == NULL)
+ {
+ return;
+ }
+
+ Mix_FreeMusic(music);
+}
+
+// Determine whether memory block is a .mid file
+
+static boolean IsMid(byte *mem, int len)
+{
+ return len > 4 && !memcmp(mem, "MThd", 4);
+}
+
+static boolean ConvertMus(byte *musdata, int len, char *filename)
+{
+ MEMFILE *instream;
+ MEMFILE *outstream;
+ void *outbuf;
+ size_t outbuf_len;
+ int result;
+
+ instream = mem_fopen_read(musdata, len);
+ outstream = mem_fopen_write();
+
+ result = mus2mid(instream, outstream);
+
+ if (result == 0)
+ {
+ mem_get_buf(outstream, &outbuf, &outbuf_len);
+
+ M_WriteFile(filename, outbuf, outbuf_len);
+ }
+
+ mem_fclose(instream);
+ mem_fclose(outstream);
+
+ return result;
+}
+
+void *I_RegisterSong(void *data, int len)
+{
+ char *filename;
+ Mix_Music *music;
+
+ if (!music_initialised)
+ {
+ return NULL;
+ }
+
+ // MUS files begin with "MUS"
+ // Reject anything which doesnt have this signature
+
+ filename = M_TempFile("doom.mid");
+
+ if (IsMid(data, len) && len < MAXMIDLENGTH)
+ {
+ M_WriteFile(filename, data, len);
+ }
+ else
+ {
+ // Assume a MUS file and try to convert
+
+ ConvertMus(data, len, filename);
+ }
+
+ // Load the MIDI
+
+ music = Mix_LoadMUS(filename);
+
+ if (music == NULL)
+ {
+ // Failed to load
+
+ fprintf(stderr, "Error loading midi: %s\n", Mix_GetError());
+ }
+
+ // remove file now
+
+ remove(filename);
+
+ Z_Free(filename);
+
+ return music;
+}
+
+// Is the song playing?
+boolean I_QrySongPlaying(void *handle)
+{
+ if (!music_initialised)
+ {
+ return false;
+ }
+
+ return Mix_PlayingMusic();
+}
+
+
+
diff --git a/src/i_sound.c b/src/i_sdlsound.c
index c332c69f..920e74d2 100644
--- a/src/i_sound.c
+++ b/src/i_sdlsound.c
@@ -30,35 +30,17 @@
#include "SDL.h"
#include "SDL_mixer.h"
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
-#include "memio.h"
-#include "mus2mid.h"
-#include "z_zone.h"
-
-#include "i_system.h"
-#include "i_pcsound.h"
-#include "i_sound.h"
-#include "i_swap.h"
#include "deh_main.h"
#include "s_sound.h"
#include "m_argv.h"
-#include "m_misc.h"
#include "w_wad.h"
+#include "z_zone.h"
#include "doomdef.h"
#define NUM_CHANNELS 16
-#define MAXMIDLENGTH (96 * 1024)
-
-static boolean nosfxparm;
-static boolean nomusicparm;
-
static boolean sound_initialised = false;
-static boolean music_initialised = false;
static Mix_Chunk sound_chunks[NUMSFX];
static int channels_playing[NUM_CHANNELS];
@@ -67,19 +49,19 @@ static int mixer_freq;
static Uint16 mixer_format;
static int mixer_channels;
-int snd_samplerate = MIX_DEFAULT_FREQUENCY;
-
// 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.
-void ReleaseSoundOnChannel(int channel)
+static void ReleaseSoundOnChannel(int channel)
{
int i;
int id = channels_playing[channel];
if (!id)
+ {
return;
+ }
channels_playing[channel] = sfx_None;
@@ -265,27 +247,31 @@ static Mix_Chunk *GetSFXChunk(int sound_id)
// for a given SFX name.
//
-int I_GetSfxLumpNum(sfxinfo_t* sfx)
+static int I_SDL_GetSfxLumpNum(sfxinfo_t* sfx)
{
char namebuf[9];
- char *prefix;
- // Different prefix for PC speaker sound effects.
+ sprintf(namebuf, "ds%s", DEH_String(sfx->name));
+
+ return W_GetNumForName(namebuf);
+}
- if (snd_sfxdevice == SNDDEVICE_PCSPEAKER)
- {
- prefix = "dp";
- }
- else
+static void I_SDL_UpdateSoundParams(int handle, int vol, int sep)
+{
+ int left, right;
+
+ if (!sound_initialised)
{
- prefix = "ds";
+ return;
}
- sprintf(namebuf, "%s%s", prefix, DEH_String(sfx->name));
-
- return W_GetNumForName(namebuf);
+ left = ((254 - sep) * vol) / 127;
+ right = ((sep) * vol) / 127;
+
+ Mix_SetPanning(handle, left, right);
}
+
//
// Starting a sound means adding it
// to the current list of active sounds
@@ -299,23 +285,13 @@ int I_GetSfxLumpNum(sfxinfo_t* sfx)
// is set, but currently not used by mixing.
//
-int
-I_StartSound
-( int id,
- int channel,
- int vol,
- int sep,
- int pitch,
- int priority )
+static int I_SDL_StartSound(int id, int channel, int vol, int sep)
{
Mix_Chunk *chunk;
if (!sound_initialised)
- return 0;
-
- if (snd_sfxdevice == SNDDEVICE_PCSPEAKER)
{
- return I_PCS_StartSound(id, channel, vol, sep, pitch, priority);
+ return -1;
}
// Release a sound effect if there is already one playing
@@ -340,22 +316,18 @@ I_StartSound
// set separation, etc.
- I_UpdateSoundParams(channel, vol, sep, pitch);
+ I_SDL_UpdateSoundParams(channel, vol, sep);
return channel;
}
-void I_StopSound (int handle)
+static void I_SDL_StopSound (int handle)
{
if (!sound_initialised)
- return;
-
- if (snd_sfxdevice == SNDDEVICE_PCSPEAKER)
{
- I_PCS_StopSound(handle);
return;
}
-
+
Mix_HaltChannel(handle);
// Sound data is no longer needed; release the
@@ -365,48 +337,29 @@ void I_StopSound (int handle)
}
-int I_SoundIsPlaying(int handle)
+static boolean I_SDL_SoundIsPlaying(int handle)
{
- if (!sound_initialised)
- return false;
-
if (handle < 0)
- return false;
-
- if (snd_sfxdevice == SNDDEVICE_PCSPEAKER)
- {
- return I_PCS_SoundIsPlaying(handle);
- }
- else
{
- return Mix_Playing(handle);
+ return false;
}
-}
-
-
+ return Mix_Playing(handle);
+}
//
// Periodically called to update the sound system
//
-void I_UpdateSound( void )
+static void I_SDL_UpdateSound(void)
{
int i;
- if (!sound_initialised)
- return;
-
- if (snd_sfxdevice == SNDDEVICE_PCSPEAKER)
- {
- return;
- }
-
// Check all channels to see if a sound has finished
for (i=0; i<NUM_CHANNELS; ++i)
{
- if (channels_playing[i] && !I_SoundIsPlaying(i))
+ if (channels_playing[i] && !I_SDL_SoundIsPlaying(i))
{
// Sound has finished playing on this channel,
// but sound data has not been released to cache
@@ -416,65 +369,20 @@ void I_UpdateSound( void )
}
}
-
-//
-// This would be used to write out the mixbuffer
-// during each game loop update.
-// Updates sound buffer and audio device at runtime.
-// It is called during Timer interrupt with SNDINTR.
-// Mixing now done synchronous, and
-// only output be done asynchronous?
-//
-void
-I_SubmitSound(void)
-{
-}
-
-
-
-void
-I_UpdateSoundParams
-( int handle,
- int vol,
- int sep,
- int pitch)
-{
- int left, right;
-
+static void I_SDL_ShutdownSound(void)
+{
if (!sound_initialised)
- return;
-
- if (snd_sfxdevice == SNDDEVICE_PCSPEAKER)
{
return;
}
- left = ((254 - sep) * vol) / 127;
- right = ((sep) * vol) / 127;
-
- Mix_SetPanning(handle, left, right);
-}
-
-
-
-
-void I_ShutdownSound(void)
-{
- if (!sound_initialised && !music_initialised)
- return;
-
- Mix_HaltMusic();
Mix_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
sound_initialised = false;
- music_initialised = false;
}
-
-
-void
-I_InitSound()
+static boolean I_SDL_InitSound()
{
int i;
@@ -490,75 +398,16 @@ I_InitSound()
channels_playing[i] = sfx_None;
}
- //!
- // Disable music playback.
- //
-
- nomusicparm = M_CheckParm("-nomusic") > 0;
-
- if (snd_musicdevice < SNDDEVICE_ADLIB)
- {
- nomusicparm = true;
- }
-
- //!
- // Disable sound effects.
- //
-
- nosfxparm = M_CheckParm("-nosfx") > 0;
-
- // If the SFX device is 0 (none), then disable sound effects,
- // just like if we specified -nosfx. However, we still continue
- // with initialising digital sound output even if we are using
- // the PC speaker, because we might be using the SDL PC speaker
- // emulation.
-
- if (snd_sfxdevice == SNDDEVICE_NONE)
- {
- nosfxparm = true;
- }
-
- //!
- // Disable sound effects and music.
- //
-
- if (M_CheckParm("-nosound") > 0)
- {
- nosfxparm = true;
- nomusicparm = true;
- }
-
- // When trying to run with music enabled on OSX, display
- // a warning message.
-
-#ifdef __MACOSX__
- if (!nomusicparm)
- {
- printf("\n"
- " *** WARNING ***\n"
- " Music playback on OSX may cause crashes and\n"
- " is disabled by default.\n"
- "\n");
- }
-#endif
-
- // If music or sound is going to play, we need to at least
- // initialise SDL
- // No sound in screensaver mode.
-
- if (screensaver_mode || (nomusicparm && nosfxparm))
- return;
-
if (SDL_Init(SDL_INIT_AUDIO) < 0)
{
fprintf(stderr, "Unable to set up sound.\n");
- return;
+ return false;
}
if (Mix_OpenAudio(snd_samplerate, AUDIO_S16SYS, 2, 1024) < 0)
{
fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError());
- return;
+ return false;
}
Mix_QuerySpec(&mixer_freq, &mixer_format, &mixer_channels);
@@ -567,201 +416,32 @@ I_InitSound()
SDL_PauseAudio(0);
- // If we are using the PC speaker, we now need to initialise it.
-
- if (snd_sfxdevice == SNDDEVICE_PCSPEAKER)
- {
- I_PCS_InitSound();
- }
-
- if (!nomusicparm)
- music_initialised = true;
-
- if (!nosfxparm)
- sound_initialised = true;
-}
-
-
-
-
-//
-// MUSIC API.
-//
-
-static boolean musicpaused = false;
-static int currentMusicVolume;
-
-//
-// SDL_mixer's native MIDI music playing does not pause properly.
-// As a workaround, set the volume to 0 when paused.
-//
-
-static void UpdateMusicVolume(void)
-{
- int vol;
-
- if (musicpaused)
- vol = 0;
- else
- vol = (currentMusicVolume * MIX_MAX_VOLUME) / 127;
-
- Mix_VolumeMusic(vol);
-}
-
-// MUSIC API - dummy. Some code from DOS version.
-void I_SetMusicVolume(int volume)
-{
- // Internal state variable.
- currentMusicVolume = volume;
-
- UpdateMusicVolume();
-}
-
-void I_PlaySong(void *handle, int looping)
-{
- Mix_Music *music = (Mix_Music *) handle;
- int loops;
-
- if (!music_initialised)
- return;
-
- if (handle == NULL)
- return;
-
- if (looping)
- loops = -1;
- else
- loops = 1;
-
- Mix_PlayMusic(music, loops);
-}
-
-void I_PauseSong (void *handle)
-{
- if (!music_initialised)
- return;
+ sound_initialised = true;
- musicpaused = true;
-
- UpdateMusicVolume();
-}
-
-void I_ResumeSong (void *handle)
-{
- if (!music_initialised)
- return;
-
- musicpaused = false;
-
- UpdateMusicVolume();
-}
-
-void I_StopSong(void *handle)
-{
- if (!music_initialised)
- return;
-
- Mix_HaltMusic();
-}
-
-void I_UnRegisterSong(void *handle)
-{
- Mix_Music *music = (Mix_Music *) handle;
-
- if (!music_initialised)
- return;
-
- if (handle == NULL)
- return;
-
- Mix_FreeMusic(music);
-}
-
-// Determine whether memory block is a .mid file
-
-static boolean IsMid(byte *mem, int len)
-{
- return len > 4 && !memcmp(mem, "MThd", 4);
+ return true;
}
-static boolean ConvertMus(byte *musdata, int len, char *filename)
+static snddevice_t sound_sdl_devices[] =
{
- MEMFILE *instream;
- MEMFILE *outstream;
- void *outbuf;
- size_t outbuf_len;
- int result;
-
- instream = mem_fopen_read(musdata, len);
- outstream = mem_fopen_write();
-
- result = mus2mid(instream, outstream);
-
- if (result == 0)
- {
- mem_get_buf(outstream, &outbuf, &outbuf_len);
-
- M_WriteFile(filename, outbuf, outbuf_len);
- }
-
- mem_fclose(instream);
- mem_fclose(outstream);
-
- return result;
-}
-
-void *I_RegisterSong(void *data, int len)
+ SNDDEVICE_SB,
+ SNDDEVICE_PAS,
+ SNDDEVICE_GUS,
+ SNDDEVICE_WAVEBLASTER,
+ SNDDEVICE_SOUNDCANVAS,
+ SNDDEVICE_AWE32,
+};
+
+sound_module_t sound_sdl_module =
{
- char *filename;
- Mix_Music *music;
-
- if (!music_initialised)
- return NULL;
-
- // MUS files begin with "MUS"
- // Reject anything which doesnt have this signature
-
- filename = M_TempFile("doom.mid");
-
- if (IsMid(data, len) && len < MAXMIDLENGTH)
- {
- M_WriteFile(filename, data, len);
- }
- else
- {
- // Assume a MUS file and try to convert
-
- ConvertMus(data, len, filename);
- }
-
- // Load the MIDI
-
- music = Mix_LoadMUS(filename);
-
- if (music == NULL)
- {
- // Failed to load
-
- fprintf(stderr, "Error loading midi: %s\n", Mix_GetError());
- }
-
- // remove file now
-
- remove(filename);
-
- Z_Free(filename);
-
- return music;
-}
-
-// Is the song playing?
-boolean I_QrySongPlaying(void *handle)
-{
- if (!music_initialised)
- return false;
-
- return Mix_PlayingMusic();
-}
-
-
+ sound_sdl_devices,
+ sizeof(sound_sdl_devices) / sizeof(*sound_sdl_devices),
+ I_SDL_InitSound,
+ I_SDL_ShutdownSound,
+ I_SDL_GetSfxLumpNum,
+ I_SDL_UpdateSound,
+ I_SDL_UpdateSoundParams,
+ I_SDL_StartSound,
+ I_SDL_StopSound,
+ I_SDL_SoundIsPlaying,
+};
diff --git a/src/s_sound.c b/src/s_sound.c
index 1477415e..52462258 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -26,20 +26,24 @@
#include <stdio.h>
#include <stdlib.h>
+#include "i_music.h"
#include "i_system.h"
-#include "i_sound.h"
+
+#include "doomfeatures.h"
+#include "deh_main.h"
+
+#include "doomstat.h"
+#include "doomdef.h"
+
#include "sounds.h"
#include "s_sound.h"
-#include "deh_main.h"
-#include "z_zone.h"
#include "m_random.h"
-#include "w_wad.h"
+#include "m_argv.h"
-#include "doomdef.h"
#include "p_local.h"
-
-#include "doomstat.h"
+#include "w_wad.h"
+#include "z_zone.h"
// when to clip out sounds
// Does not fit the large outdoor areas.
@@ -74,10 +78,6 @@
#define DEFAULT_MUSIC_DEVICE SNDDEVICE_NONE
#endif
-int snd_musicdevice = DEFAULT_MUSIC_DEVICE;
-int snd_sfxdevice = SNDDEVICE_SB;
-
-
typedef struct
{
// sound information (if null, channel avail.)
@@ -91,6 +91,9 @@ typedef struct
} channel_t;
+// Low-level sound module we are using
+
+static sound_module_t *sound_module;
// The set of channels available
@@ -105,6 +108,10 @@ int sfxVolume = 8;
int musicVolume = 8;
+// Sound sample rate to use for digital output (Hz)
+
+int snd_samplerate = 22050;
+
// Internal volume level, ranging from 0-127
static int snd_SfxVolume;
@@ -121,6 +128,81 @@ static musicinfo_t *mus_playing = NULL;
int numChannels = 8;
+int snd_musicdevice = DEFAULT_MUSIC_DEVICE;
+int snd_sfxdevice = SNDDEVICE_SB;
+
+// Sound effect modules
+
+extern sound_module_t sound_sdl_module;
+extern sound_module_t sound_pcsound_module;
+
+// Compiled-in sound modules:
+
+static sound_module_t *sound_modules[] =
+{
+#ifdef FEATURE_SOUND
+ &sound_sdl_module,
+ &sound_pcsound_module,
+#endif
+};
+
+// Check if a sound device is in the given list of devices
+
+static boolean SndDeviceInList(snddevice_t device, snddevice_t *list,
+ int len)
+{
+ int i;
+
+ for (i=0; i<len; ++i)
+ {
+ if (device == list[i])
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Find and initialise a sound_module_t appropriate for the setting
+// in snd_sfxdevice.
+
+static void InitSfxModule(void)
+{
+ int i;
+
+ sound_module = NULL;
+
+ for (i=0; i<sizeof(sound_modules) / sizeof(*sound_modules); ++i)
+ {
+ // Is the sfx device in the list of devices supported by
+ // this module?
+
+ if (SndDeviceInList(snd_sfxdevice,
+ sound_modules[i]->sound_devices,
+ sound_modules[i]->num_sound_devices))
+ {
+ // Initialise the module
+
+ if (sound_modules[i]->Init())
+ {
+ sound_module = sound_modules[i];
+ return;
+ }
+ }
+ }
+}
+
+// Initialise music according to snd_musicdevice.
+
+static void InitMusicModule(void)
+{
+ if (snd_musicdevice >= SNDDEVICE_ADLIB)
+ {
+ I_InitMusic();
+ }
+}
+
//
// Initializes sound stuff, including volume
// Sets channels, SFX and music volume,
@@ -131,7 +213,20 @@ void S_Init(int sfxVolume, int musicVolume)
{
int i;
- I_InitSound();
+ // Initialise the sound and music subsystems.
+
+ if (M_CheckParm("-nosound") <= 0 && !screensaver_mode)
+ {
+ if (M_CheckParm("-nosfx") <= 0)
+ {
+ InitSfxModule();
+ }
+
+ if (M_CheckParm("-nomusic") <= 0)
+ {
+ InitMusicModule();
+ }
+ }
S_SetSfxVolume(sfxVolume);
S_SetMusicVolume(musicVolume);
@@ -159,7 +254,12 @@ void S_Init(int sfxVolume, int musicVolume)
void S_Shutdown(void)
{
- I_ShutdownSound();
+ if (sound_module != NULL)
+ {
+ sound_module->Shutdown();
+ }
+
+ I_ShutdownMusic();
}
static void S_StopChannel(int cnum)
@@ -172,9 +272,13 @@ static void S_StopChannel(int cnum)
if (c->sfxinfo)
{
// stop the sound playing
- if (I_SoundIsPlaying(c->handle))
+
+ if (sound_module != NULL)
{
- I_StopSound(c->handle);
+ if (sound_module->SoundIsPlaying(c->handle))
+ {
+ sound_module->StopSound(c->handle);
+ }
}
// check to see if other channels are playing the sound
@@ -228,15 +332,15 @@ void S_Start(void)
{
// Song - Who? - Where?
- mus_e3m4, // American e4m1
- mus_e3m2, // Romero e4m2
+ mus_e3m4, // American e4m1
+ mus_e3m2, // Romero e4m2
mus_e3m3, // Shawn e4m3
- mus_e1m5, // American e4m4
- mus_e2m7, // Tim e4m5
- mus_e2m4, // Romero e4m6
- mus_e2m6, // J.Anderson e4m7 CHIRON.WAD
+ mus_e1m5, // American e4m4
+ mus_e2m7, // Tim e4m5
+ mus_e2m4, // Romero e4m6
+ mus_e2m6, // J.Anderson e4m7 CHIRON.WAD
mus_e2m5, // Shawn e4m8
- mus_e1m9 // Tim e4m9
+ mus_e1m9, // Tim e4m9
};
if (gameepisode < 4)
@@ -326,14 +430,14 @@ static int S_GetChannel(mobj_t *origin, sfxinfo_t *sfxinfo)
}
//
-// Changes volume, stereo-separation, and pitch variables
+// Changes volume and stereo-separation variables
// from the norm of a sound effect to be played.
// If the sound is not audible, returns a 0.
// Otherwise, modifies parameters and returns 1.
//
static int S_AdjustSoundParams(mobj_t *listener, mobj_t *source,
- int *vol, int *sep, int *pitch)
+ int *vol, int *sep)
{
fixed_t approx_dist;
fixed_t adx;
@@ -406,7 +510,6 @@ void S_StartSound(void *origin_p, int sfx_id)
mobj_t *origin;
int rc;
int sep;
- int pitch;
int priority;
int cnum;
int volume;
@@ -425,7 +528,6 @@ void S_StartSound(void *origin_p, int sfx_id)
// Initialize sound parameters
if (sfx->link)
{
- pitch = sfx->pitch;
priority = sfx->priority;
volume += sfx->volume;
@@ -441,7 +543,6 @@ void S_StartSound(void *origin_p, int sfx_id)
}
else
{
- pitch = NORM_PITCH;
priority = NORM_PRIORITY;
}
@@ -453,8 +554,7 @@ void S_StartSound(void *origin_p, int sfx_id)
rc = S_AdjustSoundParams(players[consoleplayer].mo,
origin,
&volume,
- &sep,
- &pitch);
+ &sep);
if (origin->x == players[consoleplayer].mo->x
&& origin->y == players[consoleplayer].mo->y)
@@ -472,36 +572,6 @@ void S_StartSound(void *origin_p, int sfx_id)
sep = NORM_SEP;
}
- // hacks to vary the sfx pitches
- if (sfx_id >= sfx_sawup
- && sfx_id <= sfx_sawhit)
- {
- pitch += 8 - (M_Random()&15);
-
- if (pitch < 0)
- {
- pitch = 0;
- }
- else if (pitch > 255)
- {
- pitch = 255;
- }
- }
- else if (sfx_id != sfx_itemup
- && sfx_id != sfx_tink)
- {
- pitch += 16 - (M_Random()&31);
-
- if (pitch < 0)
- {
- pitch = 0;
- }
- else if (pitch > 255)
- {
- pitch = 255;
- }
- }
-
// kill old sound
S_StopSound(origin);
@@ -513,32 +583,29 @@ void S_StartSound(void *origin_p, int sfx_id)
return;
}
- //
- // This is supposed to handle the loading/caching.
- // For some odd reason, the caching is done nearly
- // each time the sound is needed?
- //
-
- // get lumpnum if necessary
- if (sfx->lumpnum < 0)
- {
- sfx->lumpnum = I_GetSfxLumpNum(sfx);
- }
-
// increase the usefulness
if (sfx->usefulness++ < 0)
{
sfx->usefulness = 1;
}
- // Assigns the handle to one of the channels in the
- // mix/output buffer.
- channels[cnum].handle = I_StartSound(sfx_id,
- cnum,
- volume,
- sep,
- pitch,
- priority);
+ if (sound_module != NULL)
+ {
+ // Get lumpnum if necessary
+
+ if (sfx->lumpnum < 0)
+ {
+ sfx->lumpnum = sound_module->GetSfxLumpNum(sfx);
+ }
+
+ // Assigns the handle to one of the channels in the
+ // mix/output buffer.
+
+ channels[cnum].handle = sound_module->StartSound(sfx_id,
+ cnum,
+ volume,
+ sep);
+ }
}
//
@@ -573,7 +640,6 @@ void S_UpdateSounds(mobj_t *listener)
int cnum;
int volume;
int sep;
- int pitch;
sfxinfo_t* sfx;
channel_t* c;
@@ -584,16 +650,14 @@ void S_UpdateSounds(mobj_t *listener)
if (c->sfxinfo)
{
- if (I_SoundIsPlaying(c->handle))
+ if (sound_module != NULL && sound_module->SoundIsPlaying(c->handle))
{
// initialize parameters
volume = snd_SfxVolume;
- pitch = NORM_PITCH;
sep = NORM_SEP;
if (sfx->link)
{
- pitch = sfx->pitch;
volume += sfx->volume;
if (volume < 1)
{
@@ -613,8 +677,7 @@ void S_UpdateSounds(mobj_t *listener)
audible = S_AdjustSoundParams(listener,
c->origin,
&volume,
- &sep,
- &pitch);
+ &sep);
if (!audible)
{
@@ -622,7 +685,7 @@ void S_UpdateSounds(mobj_t *listener)
}
else
{
- I_UpdateSoundParams(c->handle, volume, sep, pitch);
+ sound_module->UpdateSoundParams(c->handle, volume, sep);
}
}
}
diff --git a/src/s_sound.h b/src/s_sound.h
index c5460aed..8a5e2c6c 100644
--- a/src/s_sound.h
+++ b/src/s_sound.h
@@ -28,6 +28,8 @@
#ifndef __S_SOUND__
#define __S_SOUND__
+#include "p_mobj.h"
+#include "sounds.h"
typedef enum
{
@@ -43,8 +45,50 @@ typedef enum
SNDDEVICE_AWE32 = 9,
} snddevice_t;
+typedef struct
+{
+ snddevice_t *sound_devices;
+ int num_sound_devices;
+
+ // Initialise sound module
+ // Returns true if successfully initialised
+
+ boolean (*Init)(void);
+
+ // Shutdown sound module
+
+ void (*Shutdown)(void);
+
+ // Returns the lump index of the given sound.
+
+ int (*GetSfxLumpNum)(sfxinfo_t *sfxinfo);
+
+ // Called periodically to update the subsystem.
+
+ void (*Update)(void);
+
+ // Update the sound settings on the given channel.
+
+ void (*UpdateSoundParams)(int channel, int vol, int sep);
+
+ // Start a sound on a given channel. Returns the channel id
+ // or -1 on failure.
+
+ int (*StartSound)(int id, int channel, int vol, int sep);
+
+ // Stop the sound playing on the given channel.
+
+ void (*StopSound)(int channel);
+
+ // Query if a sound is playing on the given channel
+
+ boolean (*SoundIsPlaying)(int channel);
+
+} sound_module_t;
+
extern int snd_sfxdevice;
extern int snd_musicdevice;
+extern int snd_samplerate;
//
// Initializes sound stuff, including volume