summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in3
-rw-r--r--src/i_sdlsound.c123
-rw-r--r--src/m_misc.c5
3 files changed, 116 insertions, 15 deletions
diff --git a/configure.in b/configure.in
index 07efe457..322c4957 100644
--- a/configure.in
+++ b/configure.in
@@ -43,6 +43,9 @@ AC_CHECK_LIB(SDL_net,SDLNet_UDP_Send,[
exit -1
] ,$SDL_LIBS $SDLNET_LIBS)
+# DWF 2008-02-10: FIXME
+AC_CHECK_LIB(samplerate, src_new)
+
AC_CHECK_TOOL(WINDRES, windres, )
AM_CONDITIONAL(HAVE_WINDRES, test "$WINDRES" != "")
diff --git a/src/i_sdlsound.c b/src/i_sdlsound.c
index e10cb5ee..5c68d00f 100644
--- a/src/i_sdlsound.c
+++ b/src/i_sdlsound.c
@@ -3,6 +3,7 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005 Simon Howard
+// Copyright(C) 2008 David Flater
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -25,11 +26,18 @@
//-----------------------------------------------------------------------------
+#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
+#include <assert.h>
#include "SDL.h"
#include "SDL_mixer.h"
+#ifdef HAVE_LIBSAMPLERATE
+#include <samplerate.h>
+#endif
+
#include "deh_main.h"
#include "s_sound.h"
#include "m_argv.h"
@@ -48,6 +56,10 @@ static int channels_playing[NUM_CHANNELS];
static int mixer_freq;
static Uint16 mixer_format;
static int mixer_channels;
+static void (*ExpandSoundData)(byte *data, int samplerate, int length,
+ Mix_Chunk *destination) = NULL;
+
+int use_libsamplerate = 0;
// 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
@@ -78,6 +90,72 @@ static void ReleaseSoundOnChannel(int channel)
Z_ChangeTag(sound_chunks[id].abuf, PU_CACHE);
}
+#ifdef HAVE_LIBSAMPLERATE
+
+// libsamplerate-based generic sound expansion function for any sample rate
+// unsigned 8 bits --> signed 16 bits
+// mono --> stereo
+// samplerate --> mixer_freq
+// Rewritten by DWF 2008-02-10:
+
+static void ExpandSoundData_SRC(byte *data,
+ int samplerate,
+ int length,
+ Mix_Chunk *destination)
+{
+ SRC_DATA src_data;
+ uint32_t i, abuf_index=0;
+ int retn;
+ int16_t *expanded;
+
+ src_data.input_frames = length;
+ src_data.data_in = malloc(length * sizeof(float));
+ src_data.src_ratio = (double)mixer_freq / samplerate;
+ src_data.output_frames = src_data.src_ratio * length + samplerate;
+ src_data.data_out = malloc(src_data.output_frames * sizeof(float));
+
+ assert(src_data.data_in != NULL && src_data.data_out != NULL);
+
+ // Convert input data to floats
+
+ for (i=0; i<length; ++i)
+ {
+ src_data.data_in[i] = data[i] / 127.5 - 1;
+ }
+
+ // Do the sound conversion
+
+ retn = src_simple(&src_data, SRC_SINC_MEDIUM_QUALITY, 1);
+ assert(retn == 0);
+
+ // Convert the result back into 16-bit integers.
+
+ destination->alen = src_data.output_frames_gen * 4;
+ destination->abuf = Z_Malloc(destination->alen, PU_STATIC,
+ &destination->abuf);
+ expanded = (int16_t *) destination->abuf;
+
+ for (i=0; i<src_data.output_frames_gen; ++i)
+ {
+ // libsamplerate does not limit itself to the -1.0 .. 1.0 range
+ // on output, so some slack is required to avoid overflows or
+ // clipping. The amount of slack is a fudge factor.
+
+ float cvtval = src_data.data_out[i] * 20000;
+ cvtval += (cvtval < 0 ? -0.5 : 0.5);
+
+ // Left and right channels
+
+ expanded[abuf_index++] = cvtval;
+ expanded[abuf_index++] = cvtval;
+ }
+
+ free(src_data.data_in);
+ free(src_data.data_out);
+}
+
+#endif
+
static boolean ConvertibleRatio(int freq1, int freq2)
{
int ratio;
@@ -109,12 +187,27 @@ static boolean ConvertibleRatio(int freq1, int freq2)
// Generic sound expansion function for any sample rate
-static void ExpandSoundData(byte *data,
- int samplerate,
- int length,
- Mix_Chunk *destination)
+static void ExpandSoundData_SDL(byte *data,
+ int samplerate,
+ int length,
+ Mix_Chunk *destination)
{
SDL_AudioCVT convertor;
+ uint32_t expanded_length;
+
+ // Calculate the length of the expanded version of the sample.
+
+ expanded_length = (uint32_t) ((((uint64_t) length) * mixer_freq) / samplerate);
+
+ // Double up twice: 8 -> 16 bit and mono -> stereo
+
+ expanded_length *= 4;
+
+ destination->alen = expanded_length;
+ destination->abuf
+ = Z_Malloc(expanded_length, PU_STATIC, &destination->abuf);
+
+ // If we can, use the standard / optimised SDL conversion routines.
if (samplerate <= mixer_freq
&& ConvertibleRatio(samplerate, mixer_freq)
@@ -172,7 +265,6 @@ static boolean CacheSFX(int sound)
unsigned int lumplen;
int samplerate;
unsigned int length;
- unsigned int expanded_length;
byte *data;
// need to load the sound
@@ -205,19 +297,11 @@ static boolean CacheSFX(int sound)
}
// Sample rate conversion
-
- expanded_length = (uint32_t) ((((uint64_t) length) * mixer_freq) / samplerate);
-
- // Double up twice: 8 -> 16 bit and mono -> stereo
-
- expanded_length *= 4;
+ // DWF 2008-02-10: sound_chunks[sound].alen and abuf are determined
+ // by ExpandSoundData.
sound_chunks[sound].allocated = 1;
- sound_chunks[sound].alen = expanded_length;
- sound_chunks[sound].abuf
- = Z_Malloc(expanded_length, PU_STATIC, &sound_chunks[sound].abuf);
sound_chunks[sound].volume = MIX_MAX_VOLUME;
-
ExpandSoundData(data + 8,
samplerate,
length,
@@ -416,6 +500,15 @@ static boolean I_SDL_InitSound()
return false;
}
+ ExpandSoundData = ExpandSoundData_SDL;
+
+#ifdef HAVE_LIBSAMPLERATE
+ if (use_libsamplerate)
+ {
+ ExpandSoundData = ExpandSoundData_SRC;
+ }
+#endif
+
Mix_QuerySpec(&mixer_freq, &mixer_format, &mixer_channels);
Mix_AllocateChannels(NUM_CHANNELS);
diff --git a/src/m_misc.c b/src/m_misc.c
index d3f531b0..d1b9c567 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -299,6 +299,10 @@ extern int snd_musicdevice;
extern int snd_sfxdevice;
extern int snd_samplerate;
+// controls whether to use libsamplerate for sample rate conversions
+
+extern int use_libsamplerate;
+
// dos specific options: these are unused but should be maintained
// so that the config file can be shared between chocolate
// doom and doom.exe
@@ -444,6 +448,7 @@ static default_t extra_defaults_list[] =
{"mouseb_backward", &mousebbackward, DEFAULT_INT, 0, 0},
{"dclick_use", &dclick_use, DEFAULT_INT, 0, 0},
+ {"use_libsamplerate", &use_libsamplerate, DEFAULT_INT, 0, 0},
};
static default_collection_t extra_defaults =