mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
floating point mixer now working
the resampler is being badly abused for streams, and it's not yet properly autoconfiscated, but things are working. Better yet, at the correct pitch and speed.
This commit is contained in:
parent
de35661d5d
commit
65a748fc3c
12 changed files with 219 additions and 712 deletions
|
@ -54,8 +54,8 @@ typedef struct sfxstream_s sfxstream_t;
|
|||
/** Represent a sound sample in the mixer.
|
||||
*/
|
||||
struct portable_samplepair_s {
|
||||
int left; //!< left sample
|
||||
int right; //!< right sample
|
||||
float left; //!< left sample
|
||||
float right; //!< right sample
|
||||
};
|
||||
|
||||
/** communication structure between output drivers and renderer
|
||||
|
@ -82,10 +82,10 @@ struct dma_s {
|
|||
*/
|
||||
struct wavinfo_s {
|
||||
unsigned rate; //!< sample rate
|
||||
unsigned width; //!< bits per sample
|
||||
unsigned width; //!< bytes per sample
|
||||
unsigned channels; //!< number of channels
|
||||
unsigned loopstart; //!< start sample of loop. -1 = no loop
|
||||
unsigned samples; //!< size of sound in samples
|
||||
unsigned loopstart; //!< start frame of loop. -1 = no loop
|
||||
unsigned frames; //!< size of sound in frames
|
||||
unsigned dataofs; //!< chunk starts this many bytes from BOF
|
||||
unsigned datalen; //!< chunk bytes
|
||||
};
|
||||
|
@ -96,38 +96,38 @@ struct wavinfo_s {
|
|||
struct sfxbuffer_s {
|
||||
unsigned head; //!< ring buffer head position in sampels
|
||||
unsigned tail; //!< ring buffer tail position in sampels
|
||||
unsigned length; //!< length of buffer in samples
|
||||
unsigned length; //!< length of buffer in frames
|
||||
unsigned pos; //!< position of tail within full stream
|
||||
unsigned bps; //!< bytes per sample: 1 2 4 usually
|
||||
unsigned channels; //!< number of channels per frame
|
||||
/** paint samples into the mix buffer
|
||||
\param offset offset into the mix buffer at which to start mixing
|
||||
the channel
|
||||
\param ch sound channel
|
||||
\param buffer sound data
|
||||
\param count number of samples to paint
|
||||
\param count number of frames to paint
|
||||
*/
|
||||
void (*paint) (int offset, channel_t *ch, void *buffer,
|
||||
void (*paint) (int offset, channel_t *ch, float *buffer,
|
||||
unsigned count);
|
||||
/** Advance the position with the stream, updating the ring buffer as
|
||||
necessary. Null for chached sounds.
|
||||
\param buffer "this"
|
||||
\param count number of samples to advance
|
||||
\param count number of frames to advance
|
||||
*/
|
||||
void (*advance) (sfxbuffer_t *buffer, unsigned int count);
|
||||
/** Seek to an absolute position within the stream, resetting the ring
|
||||
buffer.
|
||||
\param buffer "this"
|
||||
\param pos sample position with the stream
|
||||
\param pos frame position with the stream
|
||||
*/
|
||||
void (*setpos) (sfxbuffer_t *buffer, unsigned int pos);
|
||||
sfx_t *sfx; //!< owning sfx_t instance
|
||||
/** Points to the beginning of the sample data within sample_data.
|
||||
*/
|
||||
byte *data;
|
||||
float *data;
|
||||
/** Sample data. The block at the beginning of the buffer (size depends on
|
||||
sample size) holds the state information for resampling.
|
||||
*/
|
||||
byte sample_data[4];
|
||||
float sample_data[1];
|
||||
};
|
||||
|
||||
/** Representation of sound loaded that is streamed in as needed.
|
||||
|
@ -136,27 +136,27 @@ struct sfxstream_s {
|
|||
sfx_t *sfx; //!< owning sfx_t instance
|
||||
void *file; //!< handle for "file" representing the stream
|
||||
wavinfo_t wavinfo; //!< description of sound data
|
||||
unsigned pos; //!< position of next sample within full stream
|
||||
unsigned pos; //!< position of next frame full stream
|
||||
/** Resample raw data into internal format.
|
||||
\param sc buffer to write resampled sound (sfxstream_s::buffer)
|
||||
\param data raw sample data
|
||||
\param length number of raw samples to resample
|
||||
\param length number of frames to resample
|
||||
\param prev pointer to end of last resample for smoothing
|
||||
*/
|
||||
void (*resample)(sfxbuffer_t *, byte *, int);
|
||||
void (*resample)(sfxbuffer_t *, float *, int);
|
||||
/** Read data from the stream.
|
||||
\param file handle for "file" representing the stream
|
||||
(sfxstream_s::file)
|
||||
\param data destination of read data
|
||||
\param bytes number of bytes to read from stream
|
||||
\param frames number of frames to read from stream
|
||||
\param info description of sound data (sfxstream_s::wavinfo)
|
||||
\return number of bytes read from stream
|
||||
\return number of frames read from stream
|
||||
*/
|
||||
int (*read)(void *file, byte *data, int bytes, wavinfo_t *info);
|
||||
int (*read)(void *file, float *data, int frames, wavinfo_t *info);
|
||||
/** Seek to an absolute position within the stream.
|
||||
\param file handle for "file" representing the stream
|
||||
(sfxstream_s::file)
|
||||
\param pos sample position with the stream
|
||||
\param pos frame position with the stream
|
||||
\param info description of sound data (sfxstream_s::wavinfo)
|
||||
*/
|
||||
int (*seek)(void *file, int pos, wavinfo_t *info);
|
||||
|
@ -251,7 +251,7 @@ void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
|||
\param close
|
||||
*/
|
||||
sfx_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||
int (*read)(void *, byte *, int, wavinfo_t *),
|
||||
int (*read)(void *, float *, int, wavinfo_t *),
|
||||
int (*seek)(void *, int, wavinfo_t *),
|
||||
void (*close) (sfx_t *));
|
||||
|
||||
|
@ -398,19 +398,22 @@ void SND_SetPaint (sfxbuffer_t *sc);
|
|||
\ingroup sound_render
|
||||
*/
|
||||
//@{
|
||||
/** Copy/resample mono data into sample buffer, resampling as necessary.
|
||||
/** Copy/resample data into buffer, resampling as necessary.
|
||||
\param sc buffer to write resampled sound
|
||||
\param data raw sample data
|
||||
\param length number of raw samples to resample
|
||||
\param length number of frames to resample
|
||||
*/
|
||||
void SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length);
|
||||
void SND_Resample (sfxbuffer_t *sc, float *data, int length);
|
||||
|
||||
/** Copy/resample stereo data into sample buffer, resampling as necessary.
|
||||
\param sc buffer to write resampled sound
|
||||
\param data raw sample data
|
||||
\param length number of raw samples to resample
|
||||
/** Convert integer sample data to float sample data.
|
||||
\param idata integer data buffer
|
||||
\param fdata float data buffer
|
||||
\param frames number of frames
|
||||
\param channels number of channels per frame
|
||||
\param width bytes per channel
|
||||
*/
|
||||
void SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length);
|
||||
void SND_Convert (byte *idata, float *fdata, int frames, int channels,
|
||||
int width);
|
||||
//@}
|
||||
|
||||
|
||||
|
@ -541,7 +544,7 @@ void SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos);
|
|||
\param allocator cache allocator function
|
||||
\return pointer to sound sample buffer (setup for block mode)
|
||||
*/
|
||||
sfxbuffer_t *SND_GetCache (long samples, int rate, int inwidth, int channels,
|
||||
sfxbuffer_t *SND_GetCache (long samples, int rate, int channels,
|
||||
sfxblock_t *block, cache_allocator_t allocator);
|
||||
//@}
|
||||
|
||||
|
|
|
@ -46,6 +46,6 @@ EXTRA_snd_render_default_la_SOURCES= $(extra_format_src)
|
|||
|
||||
snd_render_jack_la_LDFLAGS= $(plugin_ldflags)
|
||||
snd_render_jack_la_SOURCES= snd_jack.c $(snd_common) $(format_src)
|
||||
snd_render_jack_la_LIBADD= $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(LIBFLAC_LIBS) $(OGG_LIBS) $(WM_LIBS) $(JACK_LIBS) $(top_builddir)/libs/util/libQFutil.la $(top_builddir)/libs/models/libQFmodels.la
|
||||
snd_render_jack_la_LIBADD= $(SAMPLERATE_LIBS) $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(LIBFLAC_LIBS) $(OGG_LIBS) $(WM_LIBS) $(JACK_LIBS) $(top_builddir)/libs/util/libQFutil.la $(top_builddir)/libs/models/libQFmodels.la
|
||||
snd_render_jack_la_DEPENDENCIES=
|
||||
EXTRA_snd_render_jack_la_SOURCES= $(extra_format_src)
|
||||
|
|
|
@ -96,9 +96,9 @@ typedef struct {
|
|||
QFile *file;
|
||||
FLAC__StreamMetadata_StreamInfo info;
|
||||
FLAC__StreamMetadata *vorbis_info;
|
||||
byte *buffer;
|
||||
int size;
|
||||
int pos;
|
||||
float *buffer;
|
||||
int size; // in frames
|
||||
int pos; // in frames
|
||||
} flacfile_t;
|
||||
|
||||
static void
|
||||
|
@ -156,49 +156,21 @@ flac_write_func (const FLAC__StreamDecoder *decoder,
|
|||
void *client_data)
|
||||
{
|
||||
flacfile_t *ff = (flacfile_t *) client_data;
|
||||
int bps = ff->info.bits_per_sample / 8;
|
||||
float *out;
|
||||
float scale = 2.0 / (1 << ff->info.bits_per_sample);
|
||||
unsigned i, j;
|
||||
|
||||
if (!ff->buffer)
|
||||
ff->buffer = malloc (ff->info.max_blocksize * ff->info.channels * bps);
|
||||
if (ff->info.channels == 1) {
|
||||
unsigned i;
|
||||
const FLAC__int32 *in = buffer[0];
|
||||
ff->buffer = malloc (ff->info.max_blocksize * ff->info.channels
|
||||
* sizeof (float));
|
||||
for (j = 0; j < ff->info.channels; j++) {
|
||||
const FLAC__int32 *in = buffer[j];
|
||||
|
||||
if (ff->info.bits_per_sample == 8) {
|
||||
byte *out = ff->buffer;
|
||||
|
||||
for (i = 0; i < frame->header.blocksize; i++)
|
||||
*out++ = *in++ + 128;
|
||||
} else {
|
||||
short *out = (short *) ff->buffer;
|
||||
|
||||
for (i = 0; i < frame->header.blocksize; i++)
|
||||
*out++ = *in++;
|
||||
}
|
||||
} else {
|
||||
unsigned i;
|
||||
const FLAC__int32 *li = buffer[0];
|
||||
const FLAC__int32 *ri = buffer[1];
|
||||
|
||||
if (ff->info.bits_per_sample == 8) {
|
||||
char *lo = (char *) ff->buffer + 0;
|
||||
char *ro = (char *) ff->buffer + 1;
|
||||
|
||||
for (i = 0; i < frame->header.blocksize; i++, lo++, ro++) {
|
||||
*lo++ = *li++ + 128;
|
||||
*ro++ = *ri++ + 128;
|
||||
}
|
||||
} else {
|
||||
short *lo = (short *) ff->buffer + 0;
|
||||
short *ro = (short *) ff->buffer + 1;
|
||||
|
||||
for (i = 0; i < frame->header.blocksize; i++, lo++, ro++) {
|
||||
*lo++ = LittleShort (*li++);
|
||||
*ro++ = LittleShort (*ri++);
|
||||
}
|
||||
}
|
||||
out = ff->buffer + j;
|
||||
for (i = 0; i < frame->header.blocksize; i++, out += ff->info.channels)
|
||||
*out = *in++ * scale;
|
||||
}
|
||||
ff->size = frame->header.blocksize * bps * ff->info.channels;
|
||||
ff->size = frame->header.blocksize;
|
||||
ff->pos = 0;
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
@ -276,7 +248,7 @@ flac_close (flacfile_t *ff)
|
|||
}
|
||||
|
||||
static int
|
||||
flac_read (flacfile_t *ff, byte *buf, int len)
|
||||
flac_read (flacfile_t *ff, float *buf, int len)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -288,7 +260,8 @@ flac_read (flacfile_t *ff, byte *buf, int len)
|
|||
if (res > len)
|
||||
res = len;
|
||||
if (res > 0) {
|
||||
memcpy (buf, ff->buffer + ff->pos, res);
|
||||
memcpy (buf, ff->buffer + ff->pos * ff->info.channels,
|
||||
res * ff->info.channels * sizeof (float));
|
||||
count += res;
|
||||
len -= res;
|
||||
buf += res;
|
||||
|
@ -307,37 +280,23 @@ flac_read (flacfile_t *ff, byte *buf, int len)
|
|||
static sfxbuffer_t *
|
||||
flac_load (flacfile_t *ff, sfxblock_t *block, cache_allocator_t allocator)
|
||||
{
|
||||
byte *data;
|
||||
float *data;
|
||||
sfxbuffer_t *sc = 0;
|
||||
sfx_t *sfx = block->sfx;
|
||||
void (*resample)(sfxbuffer_t *, byte *, int);
|
||||
wavinfo_t *info = &block->wavinfo;
|
||||
|
||||
switch (ff->info.channels) {
|
||||
case 1:
|
||||
resample = SND_ResampleMono;
|
||||
break;
|
||||
case 2:
|
||||
resample = SND_ResampleStereo;
|
||||
break;
|
||||
default:
|
||||
Sys_Printf ("%s: unsupported channel count: %d\n",
|
||||
sfx->name, info->channels);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = malloc (info->datalen);
|
||||
if (!data)
|
||||
goto bail;
|
||||
sc = SND_GetCache (info->samples, info->rate, info->width, info->channels,
|
||||
sc = SND_GetCache (info->frames, info->rate, info->channels,
|
||||
block, allocator);
|
||||
if (!sc)
|
||||
goto bail;
|
||||
sc->sfx = sfx;
|
||||
if (flac_read (ff, data, info->datalen) < 0)
|
||||
if (flac_read (ff, data, info->frames) < 0)
|
||||
goto bail;
|
||||
SND_SetPaint (sc);
|
||||
resample (sc, data, info->samples);
|
||||
SND_Resample (sc, data, info->frames);
|
||||
sc->head = sc->length;
|
||||
bail:
|
||||
if (data)
|
||||
|
@ -374,7 +333,7 @@ flac_cache (sfx_t *sfx, char *realname, flacfile_t *ff, wavinfo_t info)
|
|||
}
|
||||
|
||||
static int
|
||||
flac_stream_read (void *file, byte *buf, int count, wavinfo_t *info)
|
||||
flac_stream_read (void *file, float *buf, int count, wavinfo_t *info)
|
||||
{
|
||||
return flac_read (file, buf, count);
|
||||
}
|
||||
|
@ -459,15 +418,15 @@ flac_get_info (flacfile_t *ff)
|
|||
info.width = ff->info.bits_per_sample / 8;
|
||||
info.channels = ff->info.channels;
|
||||
info.loopstart = sample_start;
|
||||
info.samples = samples;
|
||||
info.frames = samples;
|
||||
info.dataofs = 0;
|
||||
info.datalen = samples * 2;
|
||||
info.datalen = samples * info.channels * sizeof (float);
|
||||
|
||||
if (developer->int_val) {
|
||||
Sys_Printf ("\nBitstream is %d channel, %dHz\n",
|
||||
info.channels, info.rate);
|
||||
Sys_Printf ("\nDecoded length: %d samples (%d bytes)\n",
|
||||
info.samples, info.samples * info.channels * 2);
|
||||
info.frames, info.width);
|
||||
if (vc) {
|
||||
Sys_Printf ("Encoded by: %.*s\n\n",
|
||||
vc->vendor_string.length, vc->vendor_string.entry);
|
||||
|
@ -492,7 +451,7 @@ SND_LoadFLAC (QFile *file, sfx_t *sfx, char *realname)
|
|||
Sys_Printf ("unsupported number of channels");
|
||||
return -1;
|
||||
}
|
||||
if (info.samples / info.rate < 3) {
|
||||
if (info.frames / info.rate < 3) {
|
||||
Sys_DPrintf ("cache %s\n", realname);
|
||||
flac_cache (sfx, realname, ff, info);
|
||||
} else {
|
||||
|
|
|
@ -82,16 +82,25 @@ midi_get_info (void * handle) {
|
|||
info.width = 2;
|
||||
info.channels = 2;
|
||||
info.loopstart = -1;
|
||||
info.samples = wm_info->approx_total_samples;
|
||||
info.frames = wm_info->approx_total_samples;
|
||||
info.dataofs = 0;
|
||||
info.datalen = info.samples * 4;
|
||||
info.datalen = info.frames * info.channels * info.width;
|
||||
return info;
|
||||
}
|
||||
|
||||
static int
|
||||
midi_stream_read (void *file, byte *buf, int count, wavinfo_t *info)
|
||||
midi_stream_read (void *file, float *buf, int count, wavinfo_t *info)
|
||||
{
|
||||
return WildMidi_GetOutput (file, (char *)buf, (unsigned long int)count);
|
||||
int size = count * info->channels * info->width;
|
||||
int res;
|
||||
byte *data = alloca (size);
|
||||
|
||||
res = WildMidi_GetOutput (file, (char *)data, size);
|
||||
if (res > 0) {
|
||||
res /= info->channels * info->width;
|
||||
SND_Convert (data, buf, res, info->channels, info->width);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -72,110 +72,44 @@ static general_data_t plugin_info_general_data;
|
|||
|
||||
static snd_output_funcs_t *snd_output_funcs;
|
||||
|
||||
static int *snd_p, snd_linear_count, snd_vol;
|
||||
static short *snd_out;
|
||||
|
||||
static void
|
||||
SND_WriteLinearBlastStereo16 (void)
|
||||
{
|
||||
int val, i;
|
||||
|
||||
for (i = 0; i < snd_linear_count * 2; i += 2) {
|
||||
val = (snd_p[i] * snd_vol) >> 8;
|
||||
if (val > 0x7fff)
|
||||
snd_out[i] = 0x7fff;
|
||||
else if (val < (short) 0x8000)
|
||||
snd_out[i] = (short) 0x8000;
|
||||
else
|
||||
snd_out[i] = val;
|
||||
|
||||
val = (snd_p[i + 1] * snd_vol) >> 8;
|
||||
if (val > 0x7fff)
|
||||
snd_out[i + 1] = 0x7fff;
|
||||
else if (val < (short) 0x8000)
|
||||
snd_out[i + 1] = (short) 0x8000;
|
||||
else
|
||||
snd_out[i + 1] = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
s_xfer_stereo_16 (int endtime)
|
||||
{
|
||||
int lpaintedtime, lpos;
|
||||
short *pbuf;
|
||||
|
||||
snd_vol = snd_volume->value * 256;
|
||||
|
||||
snd_p = (int *) snd_paintbuffer;
|
||||
lpaintedtime = snd_paintedtime;
|
||||
|
||||
|
||||
pbuf = (short *) snd_shm->buffer;
|
||||
|
||||
while (lpaintedtime < endtime) {
|
||||
// handle recirculating buffer issues
|
||||
lpos = lpaintedtime & (snd_shm->frames - 1);
|
||||
|
||||
snd_out = pbuf + (lpos << 1);
|
||||
|
||||
snd_linear_count = snd_shm->frames - lpos;
|
||||
if (lpaintedtime + snd_linear_count > endtime)
|
||||
snd_linear_count = endtime - lpaintedtime;
|
||||
|
||||
// write a linear blast of samples
|
||||
SND_WriteLinearBlastStereo16 ();
|
||||
|
||||
snd_p += snd_linear_count << 1;
|
||||
lpaintedtime += snd_linear_count;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
s_xfer_paint_buffer (int endtime)
|
||||
{
|
||||
int count, out_idx, out_mask, snd_vol, step, val;
|
||||
int *p;
|
||||
unsigned int *pbuf;
|
||||
int count, out_idx, out_mask, step, val;
|
||||
float snd_vol;
|
||||
float *p;
|
||||
|
||||
if (snd_shm->samplebits == 16 && snd_shm->channels == 2) {
|
||||
s_xfer_stereo_16 (endtime);
|
||||
return;
|
||||
}
|
||||
|
||||
p = (int *) snd_paintbuffer;
|
||||
p = (float *) snd_paintbuffer;
|
||||
count = (endtime - snd_paintedtime) * snd_shm->channels;
|
||||
out_mask = snd_shm->frames - 1;
|
||||
out_idx = snd_paintedtime * snd_shm->channels & out_mask;
|
||||
step = 3 - snd_shm->channels;
|
||||
snd_vol = snd_volume->value * 256;
|
||||
|
||||
pbuf = (unsigned int *) snd_shm->buffer;
|
||||
snd_vol = snd_volume->value;
|
||||
|
||||
if (snd_shm->samplebits == 16) {
|
||||
short *out = (short *) pbuf;
|
||||
short *out = (short *) snd_shm->buffer;
|
||||
|
||||
while (count--) {
|
||||
val = (*p * snd_vol) >> 8;
|
||||
val = (*p * snd_vol) * 0x8000;
|
||||
p += step;
|
||||
if (val > 0x7fff)
|
||||
val = 0x7fff;
|
||||
else if (val < (short) 0x8000)
|
||||
val = (short) 0x8000;
|
||||
else if (val < -0x8000)
|
||||
val = -0x8000;
|
||||
out[out_idx] = val;
|
||||
out_idx = (out_idx + 1) & out_mask;
|
||||
}
|
||||
} else if (snd_shm->samplebits == 8) {
|
||||
unsigned char *out = (unsigned char *) pbuf;
|
||||
unsigned char *out = (unsigned char *) snd_shm->buffer;
|
||||
|
||||
while (count--) {
|
||||
val = (*p * snd_vol) >> 8;
|
||||
val = (*p * snd_vol) * 128;
|
||||
p += step;
|
||||
if (val > 0x7fff)
|
||||
val = 0x7fff;
|
||||
else if (val < (short) 0x8000)
|
||||
val = (short) 0x8000;
|
||||
out[out_idx] = (val >> 8) + 128;
|
||||
if (val > 0x7f)
|
||||
val = 0x7f;
|
||||
else if (val < -0x80)
|
||||
val = -0x80;
|
||||
out[out_idx] = val + 0x80;
|
||||
out_idx = (out_idx + 1) & out_mask;
|
||||
}
|
||||
}
|
||||
|
@ -352,10 +286,6 @@ s_startup (void)
|
|||
return;
|
||||
}
|
||||
snd_shm->xfer = s_xfer_paint_buffer;
|
||||
if (snd_shm->speed > 44100) {
|
||||
Sys_Printf ("FIXME clamping Sps to 44100 until resampling is fixed\n");
|
||||
snd_shm->speed = 44100;
|
||||
}
|
||||
|
||||
sound_started = 1;
|
||||
}
|
||||
|
@ -385,10 +315,6 @@ s_init (void)
|
|||
"Set to turn sound off");
|
||||
snd_volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL,
|
||||
"Set the volume for sound playback");
|
||||
snd_interp = Cvar_Get ("snd_interp", "1", CVAR_ARCHIVE, NULL,
|
||||
"control sample interpolation");
|
||||
snd_loadas8bit = Cvar_Get ("snd_loadas8bit", "0", CVAR_NONE, NULL,
|
||||
"Toggles loading sounds as 8-bit samples");
|
||||
snd_mixahead = Cvar_Get ("snd_mixahead", "0.1", CVAR_ARCHIVE, NULL,
|
||||
"Delay time for sounds");
|
||||
snd_noextraupdate = Cvar_Get ("snd_noextraupdate", "0", CVAR_NONE, NULL,
|
||||
|
@ -413,8 +339,6 @@ s_init (void)
|
|||
SND_SFX_Init ();
|
||||
SND_Channels_Init ();
|
||||
|
||||
SND_InitScaletable ();
|
||||
|
||||
s_stop_all_sounds ();
|
||||
}
|
||||
|
||||
|
|
|
@ -158,6 +158,7 @@ snd_jack_xfer (int endtime)
|
|||
{
|
||||
int i;
|
||||
int count;
|
||||
float snd_vol = snd_volume->value;
|
||||
|
||||
count = endtime - snd_paintedtime;
|
||||
if (snd_blocked) {
|
||||
|
@ -169,8 +170,8 @@ snd_jack_xfer (int endtime)
|
|||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
/* max is +/- 1.0. need to implement clamping. */
|
||||
*output[0]++ = 0.25 * snd_paintbuffer[i].left / 65536.0;
|
||||
*output[1]++ = 0.25 * snd_paintbuffer[i].right / 65536.0;
|
||||
*output[0]++ = snd_vol * snd_paintbuffer[i].left;
|
||||
*output[1]++ = snd_vol * snd_paintbuffer[i].right;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,10 +211,6 @@ s_init (void)
|
|||
|
||||
snd_volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL,
|
||||
"Set the volume for sound playback");
|
||||
snd_interp = Cvar_Get ("snd_interp", "1", CVAR_ARCHIVE, NULL,
|
||||
"control sample interpolation");
|
||||
snd_loadas8bit = Cvar_Get ("snd_loadas8bit", "0", CVAR_NONE, NULL,
|
||||
"Toggles loading sounds as 8-bit samples");
|
||||
snd_jack_server = Cvar_Get ("snd_jack_server", "default", CVAR_ROM, NULL,
|
||||
"The name of the JACK server to connect to");
|
||||
|
||||
|
@ -235,10 +232,6 @@ s_init (void)
|
|||
snd_shm->speed = jack_get_sample_rate (jack_handle);
|
||||
s_jack_activate ();
|
||||
Sys_Printf ("Connected to JACK: %d Sps\n", snd_shm->speed);
|
||||
if (snd_shm->speed > 44100) {
|
||||
Sys_Printf ("FIXME clamping Sps to 44100 until resampling is fixed\n");
|
||||
snd_shm->speed = 44100;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -166,23 +166,24 @@ read_samples (sfxbuffer_t *buffer, int count)
|
|||
read_samples (buffer, count);
|
||||
} else {
|
||||
float stepscale;
|
||||
int samples, size;
|
||||
int frames, size;
|
||||
sfx_t *sfx = buffer->sfx;
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
|
||||
stepscale = (float) info->rate / snd_shm->speed;
|
||||
|
||||
samples = count * stepscale;
|
||||
size = samples * info->width * info->channels;
|
||||
frames = count * stepscale;
|
||||
size = frames * info->channels * sizeof (float);
|
||||
|
||||
if (stream->resample) {
|
||||
byte *data = alloca (size);
|
||||
if (stream->read (stream->file, data, size, info) != size)
|
||||
float *data = alloca (size);
|
||||
if (stream->read (stream->file, data, frames, info) != frames)
|
||||
Sys_Printf ("%s r\n", sfx->name);
|
||||
stream->resample (buffer, data, samples);
|
||||
stream->resample (buffer, data, frames);
|
||||
} else {
|
||||
if (stream->read (stream->file, buffer->data, size, info) != size)
|
||||
float *data = buffer->data + buffer->head * info->channels;
|
||||
if (stream->read (stream->file, data, frames, info) != frames)
|
||||
Sys_Printf ("%s nr\n", sfx->name);
|
||||
}
|
||||
buffer->head += count;
|
||||
|
@ -211,20 +212,9 @@ fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer,
|
|||
samples -= loop_samples;
|
||||
}
|
||||
}
|
||||
if (samples) {
|
||||
if (buffer->head != buffer->tail) {
|
||||
int s = buffer->head - 1;
|
||||
if (!buffer->head)
|
||||
s += buffer->length;
|
||||
}
|
||||
if (samples)
|
||||
read_samples (buffer, samples);
|
||||
}
|
||||
if (loop_samples) {
|
||||
if (buffer->head != buffer->tail) {
|
||||
int s = buffer->head - 1;
|
||||
if (!buffer->head)
|
||||
s += buffer->length;
|
||||
}
|
||||
stream->seek (stream->file, info->loopstart, info);
|
||||
read_samples (buffer, loop_samples);
|
||||
}
|
||||
|
@ -381,25 +371,24 @@ bail:
|
|||
}
|
||||
|
||||
sfxbuffer_t *
|
||||
SND_GetCache (long samples, int rate, int inwidth, int channels,
|
||||
SND_GetCache (long frames, int rate, int channels,
|
||||
sfxblock_t *block, cache_allocator_t allocator)
|
||||
{
|
||||
int len, size, width;
|
||||
int len, size;
|
||||
float stepscale;
|
||||
sfxbuffer_t *sc;
|
||||
sfx_t *sfx = block->sfx;
|
||||
|
||||
width = snd_loadas8bit->int_val ? 1 : 2;
|
||||
stepscale = (float) rate / snd_shm->speed;
|
||||
len = size = samples / stepscale;
|
||||
// printf ("%ld %d\n", samples, size);
|
||||
size *= width * channels;
|
||||
len = size = frames / stepscale;
|
||||
// printf ("%ld %d\n", frames, size);
|
||||
size *= sizeof (float) * channels;
|
||||
sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name);
|
||||
if (!sc)
|
||||
return 0;
|
||||
memset (sc, 0, sizeof (sfxbuffer_t) + size);
|
||||
sc->length = len;
|
||||
sc->data = sc->sample_data;
|
||||
memcpy (sc->data + size, "\xde\xad\xbe\xef", 4);
|
||||
memcpy (sc->data + len * channels, "\xde\xad\xbe\xef", 4);
|
||||
return sc;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,10 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
#include "compat.h"
|
||||
#include "snd_render.h"
|
||||
|
||||
#define VOLSCALE 1024.0 // so mixing is less likely to overflow
|
||||
// note: must be >= 255 due to the channel
|
||||
// volumes being 0-255.
|
||||
|
||||
cvar_t *snd_volume;
|
||||
|
||||
unsigned snd_paintedtime; // sample PAIRS
|
||||
|
@ -54,7 +58,6 @@ unsigned snd_paintedtime; // sample PAIRS
|
|||
portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2];
|
||||
static int max_overpaint; // number of extra samples painted
|
||||
// due to phase shift
|
||||
static int snd_scaletable[32][256];
|
||||
|
||||
/* CHANNEL MIXING */
|
||||
|
||||
|
@ -78,7 +81,7 @@ snd_paint_channel (channel_t *ch, sfxbuffer_t *sc, int count)
|
|||
{
|
||||
unsigned pos;
|
||||
int offs = 0;
|
||||
byte *samps;
|
||||
float *samps;
|
||||
|
||||
if ((int) ch->pos < 0) {
|
||||
ch->pos += count;
|
||||
|
@ -91,7 +94,7 @@ snd_paint_channel (channel_t *ch, sfxbuffer_t *sc, int count)
|
|||
if (ch->pos < sc->pos || ch->pos - sc->pos >= sc->length)
|
||||
sc->setpos (sc, ch->pos);
|
||||
pos = (ch->pos - sc->pos + sc->tail) % sc->length;
|
||||
samps = sc->data + pos * sc->bps;
|
||||
samps = sc->data + pos * sc->channels;
|
||||
|
||||
if (pos + count > sc->length) {
|
||||
unsigned sub = sc->length - pos;
|
||||
|
@ -113,7 +116,10 @@ SND_PaintChannels (unsigned endtime)
|
|||
sfxbuffer_t *sc;
|
||||
|
||||
// clear the paint buffer
|
||||
memset (snd_paintbuffer, 0, sizeof (snd_paintbuffer));
|
||||
for (i = 0; i < PAINTBUFFER_SIZE * 2; i++) {
|
||||
snd_paintbuffer[i].left = 0;
|
||||
snd_paintbuffer[i].right = 0;
|
||||
}
|
||||
|
||||
while (snd_paintedtime < endtime) {
|
||||
// if snd_paintbuffer is smaller than DMA buffer
|
||||
|
@ -173,60 +179,20 @@ SND_PaintChannels (unsigned endtime)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
SND_InitScaletable (void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
for (j = 0; j < 256; j++)
|
||||
snd_scaletable[i][j] = ((signed char) j) * i * 8;
|
||||
}
|
||||
|
||||
static void
|
||||
snd_paint_mono_8 (int offs, channel_t *ch, void *bytes, unsigned count)
|
||||
snd_paint_mono (int offs, channel_t *ch, float *sfx, unsigned count)
|
||||
{
|
||||
byte *sfx;
|
||||
int data;
|
||||
unsigned i;
|
||||
int *lscale, *rscale;
|
||||
portable_samplepair_t *pair;
|
||||
|
||||
if (ch->leftvol > 255)
|
||||
ch->leftvol = 255;
|
||||
if (ch->rightvol > 255)
|
||||
ch->rightvol = 255;
|
||||
|
||||
lscale = snd_scaletable[ch->leftvol >> 3];
|
||||
rscale = snd_scaletable[ch->rightvol >> 3];
|
||||
sfx = (byte *) bytes;
|
||||
|
||||
pair = snd_paintbuffer + offs;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
data = sfx[i];
|
||||
pair[i].left += lscale[data];
|
||||
pair[i].right += rscale[data];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
snd_paint_mono_16 (int offs, channel_t *ch, void *bytes, unsigned count)
|
||||
{
|
||||
int leftvol, rightvol;
|
||||
float leftvol, rightvol;
|
||||
unsigned left_phase, right_phase; // Never allowed < 0 anyway
|
||||
unsigned i = 0;
|
||||
short *sfx;
|
||||
portable_samplepair_t *pair;
|
||||
|
||||
leftvol = ch->leftvol;
|
||||
rightvol = ch->rightvol;
|
||||
leftvol = ch->leftvol / VOLSCALE;
|
||||
rightvol = ch->rightvol / VOLSCALE;
|
||||
|
||||
max_overpaint = max (abs (ch->phase),
|
||||
max (abs (ch->oldphase), max_overpaint));
|
||||
|
||||
sfx = (signed short *) bytes;
|
||||
|
||||
pair = snd_paintbuffer + offs;
|
||||
|
||||
if (ch->phase >= 0) {
|
||||
|
@ -265,8 +231,8 @@ snd_paint_mono_16 (int offs, channel_t *ch, void *bytes, unsigned count)
|
|||
c = min (count, max (count_right, count_left));
|
||||
count -= c;
|
||||
while (c) {
|
||||
int left = (sfx[i] * leftvol) >> 8;
|
||||
int right = (sfx[i] * rightvol) >> 8;
|
||||
float left = sfx[i] * leftvol;
|
||||
float right = sfx[i] * rightvol;
|
||||
|
||||
if (new_phase_left < old_phase_left) {
|
||||
if (!(count_left & 1)) {
|
||||
|
@ -302,48 +268,22 @@ snd_paint_mono_16 (int offs, channel_t *ch, void *bytes, unsigned count)
|
|||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
pair[i + left_phase].left += (sfx[i] * leftvol) >> 8;
|
||||
pair[i + right_phase].right += (sfx[i] * rightvol) >> 8;
|
||||
pair[i + left_phase].left += sfx[i] * leftvol;
|
||||
pair[i + right_phase].right += sfx[i] * rightvol;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
snd_paint_stereo_8 (int offs, channel_t *ch, void *bytes, unsigned count)
|
||||
snd_paint_stereo (int offs, channel_t *ch, float *samp, unsigned count)
|
||||
{
|
||||
byte *samp;
|
||||
portable_samplepair_t *pair;
|
||||
int *lscale, *rscale;
|
||||
float leftvol = ch->leftvol / VOLSCALE;
|
||||
float rightvol = ch->rightvol / VOLSCALE;
|
||||
|
||||
if (ch->leftvol > 255)
|
||||
ch->leftvol = 255;
|
||||
if (ch->rightvol > 255)
|
||||
ch->rightvol = 255;
|
||||
|
||||
lscale = snd_scaletable[ch->leftvol >> 3];
|
||||
rscale = snd_scaletable[ch->rightvol >> 3];
|
||||
|
||||
samp = bytes;
|
||||
pair = snd_paintbuffer + offs;
|
||||
while (count-- > 0) {
|
||||
pair->left += lscale[*samp++];
|
||||
pair->right += rscale[*samp++];
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
snd_paint_stereo_16 (int offs, channel_t *ch, void *bytes, unsigned count)
|
||||
{
|
||||
short *samp;
|
||||
portable_samplepair_t *pair;
|
||||
int leftvol = ch->leftvol;
|
||||
int rightvol = ch->rightvol;
|
||||
|
||||
samp = (short *) bytes;
|
||||
pair = snd_paintbuffer + offs;
|
||||
while (count-- > 0) {
|
||||
pair->left += (*samp++ * leftvol) >> 8;
|
||||
pair->right += (*samp++ * rightvol) >> 8;
|
||||
pair->left += *samp++ * leftvol;
|
||||
pair->right += *samp++ * rightvol;
|
||||
pair++;
|
||||
}
|
||||
}
|
||||
|
@ -352,15 +292,8 @@ void
|
|||
SND_SetPaint (sfxbuffer_t *sc)
|
||||
{
|
||||
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||
if (snd_loadas8bit->int_val) {
|
||||
if (info->channels == 2)
|
||||
sc->paint = snd_paint_stereo_8;
|
||||
else
|
||||
sc->paint = snd_paint_mono_8;
|
||||
} else {
|
||||
if (info->channels == 2)
|
||||
sc->paint = snd_paint_stereo_16;
|
||||
else
|
||||
sc->paint = snd_paint_mono_16;
|
||||
}
|
||||
if (info->channels == 2)
|
||||
sc->paint = snd_paint_stereo;
|
||||
else
|
||||
sc->paint = snd_paint_mono;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <samplerate.h>
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/sound.h"
|
||||
|
@ -48,362 +50,64 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
#include "compat.h"
|
||||
#include "snd_render.h"
|
||||
|
||||
typedef struct {
|
||||
byte left;
|
||||
byte right;
|
||||
} stereo8_t;
|
||||
|
||||
typedef struct {
|
||||
short left;
|
||||
short right;
|
||||
} stereo16_t;
|
||||
|
||||
cvar_t *snd_loadas8bit;
|
||||
cvar_t *snd_interp;
|
||||
|
||||
static inline int
|
||||
snd_convert_8_to_8 (byte data)
|
||||
{
|
||||
return data - 128;
|
||||
}
|
||||
|
||||
static inline int
|
||||
snd_convert_8_to_16 (byte data)
|
||||
{
|
||||
return snd_convert_8_to_8 (data) << 8;
|
||||
}
|
||||
|
||||
static inline int
|
||||
snd_convert_16_to_16 (short data)
|
||||
{
|
||||
return LittleShort (data);
|
||||
}
|
||||
|
||||
static inline int
|
||||
snd_convert_16_to_8 (short data)
|
||||
{
|
||||
return snd_convert_16_to_16 (data) >> 8;
|
||||
}
|
||||
|
||||
#define FAST_RESAMPLE(in,out,count,convert) \
|
||||
do { \
|
||||
int i; \
|
||||
\
|
||||
for (i = 0; i < count; i++) { \
|
||||
*out++ = convert (*in++); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
check_buffer_integrity (sfxbuffer_t *sc, int width, const char *func)
|
||||
{
|
||||
byte *x = sc->data + sc->length * width;
|
||||
byte *x = (byte *) sc->data + sc->length * width;
|
||||
if (memcmp (x, "\xde\xad\xbe\xef", 4))
|
||||
Sys_Error ("%s screwed the pooch %02x%02x%02x%02x", func,
|
||||
x[0], x[1], x[2], x[3]);
|
||||
}
|
||||
|
||||
void
|
||||
SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length)
|
||||
SND_Resample (sfxbuffer_t *sc, float *data, int length)
|
||||
{
|
||||
void *prev = 0;
|
||||
byte *ib, *ob, *pb;
|
||||
int fracstep, outcount, sample, samplefrac, srcsample, i;
|
||||
float stepscale;
|
||||
short *is, *os, *ps;
|
||||
int outcount;
|
||||
double stepscale;
|
||||
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||
int inwidth = info->width;
|
||||
int inrate = info->rate;
|
||||
int outwidth;
|
||||
short zero_s[1];
|
||||
byte zero_b[1];
|
||||
SRC_DATA src_data;
|
||||
|
||||
if (sc->data != sc->sample_data)
|
||||
prev = sc->data;
|
||||
stepscale = (double) snd_shm->speed / inrate;
|
||||
|
||||
is = (short *) data;
|
||||
os = (short *) sc->data;
|
||||
ib = data;
|
||||
ob = sc->data;
|
||||
outcount = length * stepscale;
|
||||
|
||||
ps = zero_s;
|
||||
pb = zero_b;
|
||||
|
||||
if (!prev) {
|
||||
zero_s[0] = 0;
|
||||
zero_b[0] = 128;
|
||||
}
|
||||
|
||||
os += sc->head;
|
||||
ob += sc->head;
|
||||
|
||||
stepscale = (float) inrate / snd_shm->speed;
|
||||
|
||||
outcount = length / stepscale;
|
||||
|
||||
sc->sfx->length = info->samples / stepscale;
|
||||
sc->sfx->length = info->frames * stepscale;
|
||||
//printf ("%s %d %g %d\n", sc->sfx->name, length, stepscale, sc->sfx->length);
|
||||
if (info->loopstart != (unsigned int)-1)
|
||||
sc->sfx->loopstart = info->loopstart / stepscale;
|
||||
sc->sfx->loopstart = info->loopstart * stepscale;
|
||||
else
|
||||
sc->sfx->loopstart = (unsigned int)-1;
|
||||
|
||||
if (snd_loadas8bit->int_val)
|
||||
sc->bps = outwidth = 1;
|
||||
else
|
||||
sc->bps = outwidth = 2;
|
||||
|
||||
if (prev) {
|
||||
if (inwidth == 1)
|
||||
zero_b[0] = ((char *)prev)[0];
|
||||
else
|
||||
zero_s[0] = ((short *)prev)[0];
|
||||
}
|
||||
sc->channels = info->channels;
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
// resample / decimate to the current source rate
|
||||
if (stepscale == 1) {
|
||||
if (inwidth == 1) {
|
||||
if (outwidth == 1)
|
||||
FAST_RESAMPLE (ib, ob, outcount, snd_convert_8_to_8);
|
||||
else if (outwidth == 2)
|
||||
FAST_RESAMPLE (ib, os, outcount, snd_convert_8_to_16);
|
||||
else
|
||||
goto general_Mono;
|
||||
} else if (inwidth == 2) {
|
||||
if (outwidth == 1)
|
||||
FAST_RESAMPLE (is, ob, outcount, snd_convert_16_to_8);
|
||||
else if (outwidth == 2)
|
||||
FAST_RESAMPLE (is, os, outcount, snd_convert_16_to_16);
|
||||
else
|
||||
goto general_Mono;
|
||||
}
|
||||
} else { // general case
|
||||
general_Mono:
|
||||
if (snd_interp->int_val && stepscale < 1) {
|
||||
int j;
|
||||
int points = 1 / stepscale;
|
||||
src_data.data_in = data;
|
||||
src_data.data_out = sc->data + sc->head * sc->channels;
|
||||
src_data.input_frames = length;
|
||||
src_data.output_frames = outcount;
|
||||
src_data.src_ratio = stepscale;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
int s1, s2;
|
||||
src_simple (&src_data, SRC_LINEAR, sc->channels);
|
||||
|
||||
if (inwidth == 2) {
|
||||
s1 = snd_convert_16_to_16 (*ps);
|
||||
s2 = snd_convert_16_to_16 (*is);
|
||||
ps = is++;
|
||||
} else {
|
||||
s1 = snd_convert_8_to_16 (*pb);
|
||||
s2 = snd_convert_8_to_16 (*ib);
|
||||
pb = ib++;
|
||||
}
|
||||
for (j = 0; j < points; j++) {
|
||||
sample = s1 + (s2 - s1) * ((float) j) / points;
|
||||
if (outwidth == 2) {
|
||||
os[j] = sample;
|
||||
} else {
|
||||
ob[j] = sample >> 8;
|
||||
}
|
||||
}
|
||||
if (outwidth == 2) {
|
||||
os += points;
|
||||
} else {
|
||||
ob += points;
|
||||
}
|
||||
}
|
||||
if (prev) {
|
||||
if (inwidth == 1)
|
||||
((char *)prev)[0] = *pb;
|
||||
else
|
||||
((short *)prev)[0] = *ps;
|
||||
}
|
||||
} else {
|
||||
samplefrac = 0;
|
||||
fracstep = stepscale * 256;
|
||||
for (i = 0; i < outcount; i++) {
|
||||
srcsample = samplefrac >> 8;
|
||||
samplefrac += fracstep;
|
||||
if (inwidth == 2)
|
||||
sample = snd_convert_16_to_16 (is[srcsample]);
|
||||
else
|
||||
sample = snd_convert_8_to_16 (ib[srcsample]);
|
||||
if (outwidth == 2)
|
||||
os[i] = sample;
|
||||
else
|
||||
ob[i] = sample >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
outwidth = info->channels * sizeof (float);
|
||||
check_buffer_integrity (sc, outwidth, __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length)
|
||||
SND_Convert (byte *idata, float *fdata, int frames, int channels, int width)
|
||||
{
|
||||
void *prev = 0;
|
||||
int fracstep, outcount, outwidth, samplefrac, srcsample, sl, sr, i;
|
||||
float stepscale;
|
||||
stereo8_t *ib, *ob, *pb;
|
||||
stereo16_t *is, *os, *ps;
|
||||
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||
int inwidth = info->width;
|
||||
int inrate = info->rate;
|
||||
stereo16_t zero_s;
|
||||
stereo8_t zero_b;
|
||||
int i;
|
||||
|
||||
if (sc->data != sc->sample_data)
|
||||
prev = sc->data;
|
||||
|
||||
is = (stereo16_t *) data;
|
||||
os = (stereo16_t *) sc->data;
|
||||
ib = (stereo8_t *) data;
|
||||
ob = (stereo8_t *) sc->data;
|
||||
|
||||
ps = &zero_s;
|
||||
pb = &zero_b;
|
||||
|
||||
if (!prev) {
|
||||
zero_s.left = zero_s.right = 0;
|
||||
zero_b.left = zero_b.right = 128;
|
||||
if (width == 1) {
|
||||
for (i = 0; i < frames * channels; i++)
|
||||
*fdata++ = (*idata++ - 0x80) / 128.0;
|
||||
} else if (width == 2) {
|
||||
short *id = (short *) idata;
|
||||
for (i = 0; i < frames * channels; i++)
|
||||
*fdata++ = *id++ / 32768.0;
|
||||
}
|
||||
|
||||
os += sc->head;
|
||||
ob += sc->head;
|
||||
|
||||
stepscale = (float) inrate / snd_shm->speed;
|
||||
|
||||
outcount = length / stepscale;
|
||||
|
||||
sc->sfx->length = info->samples / stepscale;
|
||||
if (info->loopstart != (unsigned int)-1)
|
||||
sc->sfx->loopstart = info->loopstart / stepscale;
|
||||
else
|
||||
sc->sfx->loopstart = (unsigned int)-1;
|
||||
|
||||
if (snd_loadas8bit->int_val) {
|
||||
outwidth = 1;
|
||||
sc->bps = 2;
|
||||
} else {
|
||||
outwidth = 2;
|
||||
sc->bps = 4;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
if (inwidth == 1) {
|
||||
zero_b.left = ((char *)prev)[0];
|
||||
zero_b.right = ((char *)prev)[1];
|
||||
} else {
|
||||
zero_s.left = ((short *)prev)[0];
|
||||
zero_s.right = ((short *)prev)[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
// resample / decimate to the current source rate
|
||||
if (stepscale == 1) {
|
||||
if (inwidth == 1) {
|
||||
if (outwidth == 1) {
|
||||
for (i = 0; i < outcount; i++, ob++, ib++) {
|
||||
ob->left = ib->left - 128;
|
||||
ob->right = ib->right - 128;
|
||||
}
|
||||
} else if (outwidth == 2) {
|
||||
for (i = 0; i < outcount; i++, os++, ib++) {
|
||||
os->left = (ib->left - 128) << 8;
|
||||
os->right = (ib->right - 128) << 8;
|
||||
}
|
||||
} else {
|
||||
goto general_Stereo;
|
||||
}
|
||||
} else if (inwidth == 2) {
|
||||
if (outwidth == 1) {
|
||||
for (i = 0; i < outcount; i++, ob++, ib++) {
|
||||
ob->left = LittleShort (is->left) >> 8;
|
||||
ob->right = LittleShort (is->right) >> 8;
|
||||
}
|
||||
} else if (outwidth == 2) {
|
||||
for (i = 0; i < outcount; i++, os++, is++) {
|
||||
os->left = LittleShort (is->left);
|
||||
os->right = LittleShort (is->right);
|
||||
}
|
||||
} else {
|
||||
goto general_Stereo;
|
||||
}
|
||||
}
|
||||
} else { // general case
|
||||
general_Stereo:
|
||||
if (snd_interp->int_val && stepscale < 1) {
|
||||
int j;
|
||||
int points = 1 / stepscale;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
int sl1, sl2;
|
||||
int sr1, sr2;
|
||||
|
||||
if (inwidth == 2) {
|
||||
sl1 = LittleShort (ps->left);
|
||||
sr1 = LittleShort (ps->right);
|
||||
sl2 = LittleShort (is->left);
|
||||
sr2 = LittleShort (is->right);
|
||||
ps = is++;
|
||||
} else {
|
||||
sl1 = (pb->left - 128) << 8;
|
||||
sr1 = (pb->right - 128) << 8;
|
||||
sl2 = (ib->left - 128) << 8;
|
||||
sr2 = (ib->right - 128) << 8;
|
||||
pb = ib++;
|
||||
}
|
||||
for (j = 0; j < points; j++) {
|
||||
sl = sl1 + (sl2 - sl1) * ((float) j) / points;
|
||||
sr = sr1 + (sr2 - sr1) * ((float) j) / points;
|
||||
if (outwidth == 2) {
|
||||
os[j].left = sl;
|
||||
os[j].right = sr;
|
||||
} else {
|
||||
ob[j].left = sl >> 8;
|
||||
ob[j].right = sr >> 8;
|
||||
}
|
||||
}
|
||||
if (outwidth == 2) {
|
||||
os += points;
|
||||
} else {
|
||||
ob += points;
|
||||
}
|
||||
}
|
||||
if (prev) {
|
||||
if (inwidth == 1) {
|
||||
((char *)prev)[0] = pb->left;
|
||||
((char *)prev)[1] = pb->right;
|
||||
} else {
|
||||
((short *)prev)[0] = ps->left;
|
||||
((short *)prev)[1] = ps->right;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
samplefrac = 0;
|
||||
fracstep = stepscale * 256;
|
||||
for (i = 0; i < outcount; i++) {
|
||||
srcsample = samplefrac >> 8;
|
||||
samplefrac += fracstep;
|
||||
if (inwidth == 2) {
|
||||
sl = LittleShort (is[srcsample].left);
|
||||
sr = LittleShort (is[srcsample].right);
|
||||
} else {
|
||||
sl = (ib[srcsample].left - 128) << 8;
|
||||
sr = (ib[srcsample].right - 128) << 8;
|
||||
}
|
||||
if (outwidth == 2) {
|
||||
os[i].left = sl;
|
||||
os[i].right = sr;
|
||||
} else {
|
||||
ob[i].left = sl >> 8;
|
||||
ob[i].right = sr >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
check_buffer_integrity (sc, outwidth * 2, __FUNCTION__);
|
||||
}
|
||||
|
|
|
@ -111,15 +111,14 @@ SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
|||
|
||||
sfx_t *
|
||||
SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||
int (*read)(void *, byte *, int, wavinfo_t *),
|
||||
int (*read)(void *, float *, int, wavinfo_t *),
|
||||
int (*seek)(void *, int, wavinfo_t *),
|
||||
void (*close) (sfx_t *))
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
int samples;
|
||||
int frames;
|
||||
int size;
|
||||
int width;
|
||||
|
||||
sfx_t *new_sfx = calloc (1, sizeof (sfx_t));
|
||||
|
||||
|
@ -131,38 +130,27 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
|||
new_sfx->getbuffer = SND_StreamGetBuffer;
|
||||
new_sfx->close = close;
|
||||
|
||||
samples = snd_shm->speed * 0.3;
|
||||
samples = (samples + 255) & ~255;
|
||||
size = samples + 1; // one extra sample for the resampler
|
||||
width = 1;
|
||||
if (!snd_loadas8bit->int_val)
|
||||
width *= 2;
|
||||
if (info->channels == 2)
|
||||
width *= 2;
|
||||
size *= width;
|
||||
frames = snd_shm->speed * 0.3;
|
||||
frames = (frames + 255) & ~255;
|
||||
size = frames + 1; // one extra sample for the resampler
|
||||
size *= info->channels * sizeof (float);
|
||||
|
||||
stream = calloc (1, sizeof (sfxstream_t) + size);
|
||||
new_sfx->data.stream = stream;
|
||||
memcpy (stream->buffer.sample_data + size, "\xde\xad\xbe\xef", 4);
|
||||
memcpy ((byte *) stream->buffer.sample_data + size, "\xde\xad\xbe\xef", 4);
|
||||
stream->file = file;
|
||||
stream->sfx = new_sfx;
|
||||
stream->resample = info->channels == 2 ? SND_ResampleStereo
|
||||
: SND_ResampleMono;
|
||||
stream->resample = SND_Resample;
|
||||
stream->read = read;
|
||||
stream->seek = seek;
|
||||
|
||||
stream->wavinfo = *sfx->wavinfo (sfx);
|
||||
|
||||
stream->buffer.length = samples;
|
||||
stream->buffer.length = frames;
|
||||
stream->buffer.advance = SND_StreamAdvance;
|
||||
stream->buffer.setpos = SND_StreamSetPos;
|
||||
stream->buffer.sfx = new_sfx;
|
||||
stream->buffer.data = &stream->buffer.sample_data[width];
|
||||
if (info->width == 1) {
|
||||
stream->buffer.sample_data[0] = 128;
|
||||
if (info->channels == 2)
|
||||
stream->buffer.sample_data[1] = 128;
|
||||
}
|
||||
stream->buffer.data = &stream->buffer.sample_data[info->channels];
|
||||
SND_SetPaint (&stream->buffer);
|
||||
|
||||
stream->resample (&stream->buffer, 0, 0); // get sfx setup properly
|
||||
|
|
|
@ -106,18 +106,18 @@ vorbis_get_info (OggVorbis_File *vf)
|
|||
samples = sample_start + sample_count;
|
||||
|
||||
info.rate = vi->rate;
|
||||
info.width = 2;
|
||||
info.width = sizeof (float);
|
||||
info.channels = vi->channels;
|
||||
info.loopstart = sample_start;
|
||||
info.samples = samples;
|
||||
info.frames = samples;
|
||||
info.dataofs = 0;
|
||||
info.datalen = samples * 2;
|
||||
info.datalen = samples * info.channels * info.width;
|
||||
|
||||
if (developer->int_val) {
|
||||
Sys_Printf ("\nBitstream is %d channel, %dHz\n",
|
||||
info.channels, info.rate);
|
||||
Sys_Printf ("\nDecoded length: %d samples (%d bytes)\n",
|
||||
info.samples, info.samples * info.channels * 2);
|
||||
info.frames, info.width);
|
||||
Sys_Printf ("Encoded by: %s\n\n", ov_comment (vf, -1)->vendor);
|
||||
}
|
||||
|
||||
|
@ -125,18 +125,25 @@ vorbis_get_info (OggVorbis_File *vf)
|
|||
}
|
||||
|
||||
static int
|
||||
vorbis_read (OggVorbis_File *vf, byte *buf, int len)
|
||||
vorbis_read (OggVorbis_File *vf, float *buf, int len, wavinfo_t *info)
|
||||
{
|
||||
unsigned i;
|
||||
int j;
|
||||
int count = 0;
|
||||
int current_section;
|
||||
float **vbuf;
|
||||
|
||||
while (len) {
|
||||
int res = ov_read (vf, (char *) buf, len, 0, 2, 1,
|
||||
¤t_section);
|
||||
int res = ov_read_float (vf, &vbuf, len, ¤t_section);
|
||||
|
||||
if (res > 0) {
|
||||
for (i = 0; i < info->channels; i++)
|
||||
for (j = 0; j < res; j++) {
|
||||
buf[j * info->channels + i] = vbuf[i][j];
|
||||
}
|
||||
count += res;
|
||||
len -= res;
|
||||
buf += res;
|
||||
buf += res * info->channels;
|
||||
} else if (res < 0) {
|
||||
Sys_Printf ("vorbis error %d\n", res);
|
||||
return -1;
|
||||
|
@ -151,37 +158,23 @@ vorbis_read (OggVorbis_File *vf, byte *buf, int len)
|
|||
static sfxbuffer_t *
|
||||
vorbis_load (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator)
|
||||
{
|
||||
byte *data;
|
||||
float *data;
|
||||
sfxbuffer_t *sc = 0;
|
||||
sfx_t *sfx = block->sfx;
|
||||
void (*resample)(sfxbuffer_t *, byte *, int);
|
||||
wavinfo_t *info = &block->wavinfo;
|
||||
|
||||
switch (info->channels) {
|
||||
case 1:
|
||||
resample = SND_ResampleMono;
|
||||
break;
|
||||
case 2:
|
||||
resample = SND_ResampleStereo;
|
||||
break;
|
||||
default:
|
||||
Sys_Printf ("%s: unsupported channel count: %d\n",
|
||||
sfx->name, info->channels);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = malloc (info->datalen);
|
||||
if (!data)
|
||||
goto bail;
|
||||
sc = SND_GetCache (info->samples, info->rate, info->width, info->channels,
|
||||
sc = SND_GetCache (info->frames, info->rate, info->channels,
|
||||
block, allocator);
|
||||
if (!sc)
|
||||
goto bail;
|
||||
sc->sfx = sfx;
|
||||
if (vorbis_read (vf, data, info->datalen) < 0)
|
||||
if (vorbis_read (vf, data, info->frames, info) < 0)
|
||||
goto bail;
|
||||
SND_SetPaint (sc);
|
||||
resample (sc, data, info->samples);
|
||||
SND_Resample (sc, data, info->frames);
|
||||
sc->head = sc->length;
|
||||
bail:
|
||||
if (data)
|
||||
|
@ -218,9 +211,9 @@ vorbis_cache (sfx_t *sfx, char *realname, OggVorbis_File *vf, wavinfo_t info)
|
|||
}
|
||||
|
||||
static int
|
||||
vorbis_stream_read (void *file, byte *buf, int count, wavinfo_t *info)
|
||||
vorbis_stream_read (void *file, float *buf, int count, wavinfo_t *info)
|
||||
{
|
||||
return vorbis_read (file, buf, count);
|
||||
return vorbis_read (file, buf, count, info);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -285,7 +278,7 @@ SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname)
|
|||
Sys_Printf ("unsupported number of channels");
|
||||
return -1;
|
||||
}
|
||||
if (info.samples / info.rate < 3) {
|
||||
if (info.frames / info.rate < 3) {
|
||||
Sys_DPrintf ("cache %s\n", realname);
|
||||
vorbis_cache (sfx, realname, &vf, info);
|
||||
} else {
|
||||
|
|
|
@ -55,7 +55,9 @@ wav_callback_load (void *object, cache_allocator_t allocator)
|
|||
sfx_t *sfx = block->sfx;
|
||||
const char *name = (const char *) block->file;
|
||||
QFile *file;
|
||||
int len;
|
||||
byte *data;
|
||||
float *fdata;
|
||||
sfxbuffer_t *buffer;
|
||||
wavinfo_t *info = &block->wavinfo;
|
||||
|
||||
|
@ -64,18 +66,19 @@ wav_callback_load (void *object, cache_allocator_t allocator)
|
|||
return; //FIXME Sys_Error?
|
||||
|
||||
Qseek (file, info->dataofs, SEEK_SET);
|
||||
data = malloc (info->datalen);
|
||||
len = info->datalen + info->frames * info->channels * sizeof (float);
|
||||
data = malloc (len);
|
||||
fdata = (float *) (data + info->datalen);
|
||||
Qread (file, data, info->datalen);
|
||||
Qclose (file);
|
||||
|
||||
buffer = SND_GetCache (info->samples, info->rate, info->width,
|
||||
SND_Convert (data, fdata, info->frames, info->channels, info->width);
|
||||
|
||||
buffer = SND_GetCache (info->frames, info->rate,
|
||||
info->channels, block, allocator);
|
||||
buffer->sfx = sfx;
|
||||
SND_SetPaint (buffer);
|
||||
if (info->channels == 2)
|
||||
SND_ResampleStereo (buffer, data, info->samples);
|
||||
else
|
||||
SND_ResampleMono (buffer, data, info->samples);
|
||||
SND_Resample (buffer, fdata, info->frames);
|
||||
buffer->head = buffer->length;
|
||||
free (data);
|
||||
}
|
||||
|
@ -88,9 +91,18 @@ wav_cache (sfx_t *sfx, char *realname, void *file, wavinfo_t info)
|
|||
}
|
||||
|
||||
static int
|
||||
wav_stream_read (void *file, byte *buf, int count, wavinfo_t *info)
|
||||
wav_stream_read (void *file, float *buf, int count, wavinfo_t *info)
|
||||
{
|
||||
return Qread (file, buf, count);
|
||||
int res;
|
||||
int len = count * info->channels * info->width;
|
||||
byte *data = alloca (len);
|
||||
|
||||
res = Qread (file, data, len);
|
||||
if (res > 0) {
|
||||
res /= (info->channels * info->width);
|
||||
SND_Convert (data, buf, res, info->channels, info->width);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -214,16 +226,16 @@ wav_get_info (QFile *file)
|
|||
info.rate = dfmt->samples_per_sec;
|
||||
info.width = dfmt->bits_per_sample / 8;
|
||||
info.channels = dfmt->channels;
|
||||
info.samples = 0;
|
||||
info.frames = 0;
|
||||
if (cp) {
|
||||
info.loopstart = cp->sample_offset;
|
||||
if (dltxt)
|
||||
info.samples = info.loopstart + dltxt->len;
|
||||
info.frames = info.loopstart + dltxt->len;
|
||||
} else {
|
||||
info.loopstart = -1;
|
||||
}
|
||||
if (!info.samples)
|
||||
info.samples = data->ck.len / (info.width * info.channels);
|
||||
if (!info.frames)
|
||||
info.frames = data->ck.len / (info.width * info.channels);
|
||||
info.dataofs = *(int *)data->data;
|
||||
info.datalen = data->ck.len;
|
||||
|
||||
|
@ -242,7 +254,7 @@ SND_LoadWav (QFile *file, sfx_t *sfx, char *realname)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (info.samples / info.rate < 3) {
|
||||
if (info.frames / info.rate < 3) {
|
||||
Sys_DPrintf ("cache %s\n", realname);
|
||||
wav_cache (sfx, realname, file, info);
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue