make the resampling state a little more self-contained. this should make

This commit is contained in:
Bill Currie 2009-01-08 07:48:08 +00:00 committed by Jeff Teunissen
parent bfee029249
commit 0af43cf016
7 changed files with 126 additions and 79 deletions

View file

@ -120,7 +120,13 @@ struct sfxbuffer_s {
*/
void (*setpos) (sfxbuffer_t *buffer, unsigned int pos);
sfx_t *sfx; //!< owning sfx_t instance
byte data[4]; //!< sample data
/** Points to the beginning of the sample data within sample_data.
*/
byte *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];
};
/** Representation of sound loaded that is streamed in as needed.
@ -136,7 +142,7 @@ struct sfxstream_s {
\param length number of raw samples to resample
\param prev pointer to end of last resample for smoothing
*/
void (*resample)(sfxbuffer_t *, byte *, int, void *);
void (*resample)(sfxbuffer_t *, byte *, int);
/** Read data from the stream.
\param file handle for "file" representing the stream
(sfxstream_s::file)
@ -395,17 +401,15 @@ void SND_SetPaint (sfxbuffer_t *sc);
\param sc buffer to write resampled sound
\param data raw sample data
\param length number of raw samples to resample
\param prev pointer to end of last resample for smoothing
*/
void SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length, void *prev);
void SND_ResampleMono (sfxbuffer_t *sc, byte *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
\param prev pointer to end of last resample for smoothing
*/
void SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length, void *prev);
void SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length);
//@}

View file

@ -345,7 +345,7 @@ flac_load (flacfile_t *ff, sfxblock_t *block, cache_allocator_t allocator)
byte *data;
sfxbuffer_t *sc = 0;
sfx_t *sfx = block->sfx;
void (*resample)(sfxbuffer_t *, byte *, int, void *);
void (*resample)(sfxbuffer_t *, byte *, int);
wavinfo_t *info = &block->wavinfo;
switch (ff->info.channels) {
@ -372,7 +372,7 @@ flac_load (flacfile_t *ff, sfxblock_t *block, cache_allocator_t allocator)
if (flac_read (ff, data, info->datalen) < 0)
goto bail;
SND_SetPaint (sc);
resample (sc, data, info->samples, 0);
resample (sc, data, info->samples);
sc->head = sc->length;
bail:
if (data)

View file

@ -157,16 +157,13 @@ SND_StreamWavinfo (sfx_t *sfx)
}
static void
read_samples (sfxbuffer_t *buffer, int count, void *prev)
read_samples (sfxbuffer_t *buffer, int count)
{
if (buffer->head + count > buffer->length) {
int s = (buffer->length - 1);
count -= buffer->length - buffer->head;
read_samples (buffer, buffer->length - buffer->head, prev);
prev = buffer->data + s * buffer->bps;
read_samples (buffer, count, prev);
read_samples (buffer, buffer->length - buffer->head);
read_samples (buffer, count);
} else {
float stepscale;
int samples, size;
@ -183,7 +180,7 @@ read_samples (sfxbuffer_t *buffer, int count, void *prev)
byte *data = alloca (size);
if (stream->read (stream->file, data, size, info) != size)
Sys_Printf ("%s r\n", sfx->name);
stream->resample (buffer, data, samples, prev);
stream->resample (buffer, data, samples);
} else {
if (stream->read (stream->file, buffer->data, size, info) != size)
Sys_Printf ("%s nr\n", sfx->name);
@ -198,7 +195,6 @@ static void
fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer,
wavinfo_t *info, unsigned int headpos)
{
void *prev;
unsigned int samples;
unsigned int loop_samples = 0;
@ -220,23 +216,17 @@ fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer,
int s = buffer->head - 1;
if (!buffer->head)
s += buffer->length;
prev = buffer->data + s * buffer->bps;
} else {
prev = 0;
}
read_samples (buffer, samples, prev);
read_samples (buffer, samples);
}
if (loop_samples) {
if (buffer->head != buffer->tail) {
int s = buffer->head - 1;
if (!buffer->head)
s += buffer->length;
prev = buffer->data + s * buffer->bps;
} else {
prev = 0;
}
stream->seek (stream->file, info->loopstart, info);
read_samples (buffer, loop_samples, prev);
read_samples (buffer, loop_samples);
}
}
@ -403,6 +393,7 @@ SND_GetCache (long samples, int rate, int inwidth, int channels,
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);
return sc;
}

View file

@ -61,6 +61,39 @@ typedef struct {
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)
{
@ -71,8 +104,9 @@ check_buffer_integrity (sfxbuffer_t *sc, int width, const char *func)
}
void
SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length, void *prev)
SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length)
{
void *prev = 0;
byte *ib, *ob, *pb;
int fracstep, outcount, sample, samplefrac, srcsample, i;
float stepscale;
@ -84,6 +118,9 @@ SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length, void *prev)
short zero_s[1];
byte zero_b[1];
if (sc->data != sc->sample_data)
prev = sc->data;
is = (short *) data;
os = (short *) sc->data;
ib = data;
@ -111,18 +148,16 @@ SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length, void *prev)
else
sc->sfx->loopstart = (unsigned int)-1;
if (snd_loadas8bit->int_val) {
if (snd_loadas8bit->int_val)
sc->bps = outwidth = 1;
if (prev) {
zero_s[0] = ((char *)prev)[0];
zero_b[0] = ((char *)prev)[0] + 128;
}
} else {
else
sc->bps = outwidth = 2;
if (prev) {
if (prev) {
if (inwidth == 1)
zero_b[0] = ((char *)prev)[0];
else
zero_s[0] = ((short *)prev)[0];
zero_b[0] = (((short *)prev)[0] >> 8) + 128;
}
}
if (!length)
@ -131,29 +166,19 @@ SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length, void *prev)
// resample / decimate to the current source rate
if (stepscale == 1) {
if (inwidth == 1) {
if (outwidth == 1) {
for (i = 0; i < outcount; i++) {
*ob++ = *ib++ - 128;
}
} else if (outwidth == 2) {
for (i = 0; i < outcount; i++) {
*os++ = (*ib++ - 128) << 8;
}
} else {
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) {
for (i = 0; i < outcount; i++) {
*ob++ = LittleShort (*is++) >> 8;
}
} else if (outwidth == 2) {
for (i = 0; i < outcount; i++) {
*os++ = LittleShort (*is++);
}
} else {
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:
@ -165,12 +190,12 @@ general_Mono:
int s1, s2;
if (inwidth == 2) {
s1 = LittleShort (*ps);
s2 = LittleShort (*is);
s1 = snd_convert_16_to_16 (*ps);
s2 = snd_convert_16_to_16 (*is);
ps = is++;
} else {
s1 = (*pb - 128) << 8;
s2 = (*ib - 128) << 8;
s1 = snd_convert_8_to_16 (*pb);
s2 = snd_convert_8_to_16 (*ib);
pb = ib++;
}
for (j = 0; j < points; j++) {
@ -187,6 +212,12 @@ general_Mono:
ob += points;
}
}
if (prev) {
if (inwidth == 1)
((char *)prev)[0] = *pb;
else
((short *)prev)[0] = *ps;
}
} else {
samplefrac = 0;
fracstep = stepscale * 256;
@ -194,9 +225,9 @@ general_Mono:
srcsample = samplefrac >> 8;
samplefrac += fracstep;
if (inwidth == 2)
sample = LittleShort (is[srcsample]);
sample = snd_convert_16_to_16 (is[srcsample]);
else
sample = (ib[srcsample] - 128) << 8;
sample = snd_convert_8_to_16 (ib[srcsample]);
if (outwidth == 2)
os[i] = sample;
else
@ -208,8 +239,9 @@ general_Mono:
}
void
SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length, void *prev)
SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length)
{
void *prev = 0;
int fracstep, outcount, outwidth, samplefrac, srcsample, sl, sr, i;
float stepscale;
stereo8_t *ib, *ob, *pb;
@ -220,6 +252,9 @@ SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length, void *prev)
stereo16_t zero_s;
stereo8_t zero_b;
if (sc->data != sc->sample_data)
prev = sc->data;
is = (stereo16_t *) data;
os = (stereo16_t *) sc->data;
ib = (stereo8_t *) data;
@ -249,20 +284,18 @@ SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length, void *prev)
if (snd_loadas8bit->int_val) {
outwidth = 1;
sc->bps = 2;
if (prev) {
zero_s.left = ((char *)prev)[0];
zero_s.right = ((char *)prev)[1];
zero_b.left = ((char *)prev)[0] + 128;
zero_b.right = ((char *)prev)[1] + 128;
}
} else {
outwidth = 2;
sc->bps = 4;
if (prev) {
}
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];
zero_b.left = (((short *)prev)[0] >> 8) + 128;
zero_b.right = (((short *)prev)[1] >> 8) + 128;
}
}
@ -340,6 +373,15 @@ general_Stereo:
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;

View file

@ -119,6 +119,7 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
wavinfo_t *info = &stream->wavinfo;
int samples;
int size;
int width;
sfx_t *new_sfx = calloc (1, sizeof (sfx_t));
@ -131,15 +132,18 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
new_sfx->close = close;
samples = snd_shm->speed * 0.3;
size = samples = (samples + 255) & ~255;
samples = (samples + 255) & ~255;
size = samples + 1; // one extra sample for the resampler
width = 1;
if (!snd_loadas8bit->int_val)
size *= 2;
width *= 2;
if (info->channels == 2)
size *= 2;
width *= 2;
size *= width;
stream = calloc (1, sizeof (sfxstream_t) + size);
new_sfx->data.stream = stream;
memcpy (stream->buffer.data + size, "\xde\xad\xbe\xef", 4);
memcpy (stream->buffer.sample_data + size, "\xde\xad\xbe\xef", 4);
stream->file = file;
stream->sfx = new_sfx;
stream->resample = info->channels == 2 ? SND_ResampleStereo
@ -153,9 +157,15 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
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;
}
SND_SetPaint (&stream->buffer);
stream->resample (&stream->buffer, 0, 0, 0); // get sfx setup properly
stream->resample (&stream->buffer, 0, 0); // get sfx setup properly
stream->seek (stream->file, 0, &stream->wavinfo);
stream->buffer.advance (&stream->buffer, 0);

View file

@ -156,7 +156,7 @@ vorbis_load (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator)
byte *data;
sfxbuffer_t *sc = 0;
sfx_t *sfx = block->sfx;
void (*resample)(sfxbuffer_t *, byte *, int, void *);
void (*resample)(sfxbuffer_t *, byte *, int);
wavinfo_t *info = &block->wavinfo;
switch (info->channels) {
@ -183,7 +183,7 @@ vorbis_load (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator)
if (vorbis_read (vf, data, info->datalen) < 0)
goto bail;
SND_SetPaint (sc);
resample (sc, data, info->samples, 0);
resample (sc, data, info->samples);
sc->head = sc->length;
bail:
if (data)

View file

@ -73,9 +73,9 @@ wav_callback_load (void *object, cache_allocator_t allocator)
buffer->sfx = sfx;
SND_SetPaint (buffer);
if (info->channels == 2)
SND_ResampleStereo (buffer, data, info->samples, 0);
SND_ResampleStereo (buffer, data, info->samples);
else
SND_ResampleMono (buffer, data, info->samples, 0);
SND_ResampleMono (buffer, data, info->samples);
buffer->head = buffer->length;
free (data);
}