making slow progress on sound quality

streamed oggs playback cleaning when not resampling, but flacs are still crap
This commit is contained in:
Bill Currie 2010-08-11 23:45:09 +00:00 committed by Jeff Teunissen
parent 65a748fc3c
commit 7502cd9ec5
7 changed files with 79 additions and 29 deletions

View file

@ -121,13 +121,13 @@ struct sfxbuffer_s {
*/ */
void (*setpos) (sfxbuffer_t *buffer, unsigned int pos); void (*setpos) (sfxbuffer_t *buffer, unsigned int pos);
sfx_t *sfx; //!< owning sfx_t instance sfx_t *sfx; //!< owning sfx_t instance
/** Points to the beginning of the sample data within sample_data. /** resampler state information
*/ */
float *data; void *state;
/** Sample data. The block at the beginning of the buffer (size depends on /** Sample data. The block at the beginning of the buffer (size depends on
sample size) holds the state information for resampling. sample size)
*/ */
float sample_data[1]; float data[1];
}; };
/** Representation of sound loaded that is streamed in as needed. /** Representation of sound loaded that is streamed in as needed.
@ -398,6 +398,12 @@ void SND_SetPaint (sfxbuffer_t *sc);
\ingroup sound_render \ingroup sound_render
*/ */
//@{ //@{
/** Set up the various parameters that depend on the actual sample rate.
\param sc buffer to setup
\param streamed non-zero if this is for a stream.
*/
void SND_SetupResampler (sfxbuffer_t *sc, int streamed);
/** Copy/resample data into buffer, resampling as necessary. /** Copy/resample data into buffer, resampling as necessary.
\param sc buffer to write resampled sound \param sc buffer to write resampled sound
\param data raw sample data \param data raw sample data

View file

@ -158,20 +158,21 @@ flac_write_func (const FLAC__StreamDecoder *decoder,
flacfile_t *ff = (flacfile_t *) client_data; flacfile_t *ff = (flacfile_t *) client_data;
float *out; float *out;
float scale = 2.0 / (1 << ff->info.bits_per_sample); float scale = 2.0 / (1 << ff->info.bits_per_sample);
int step = ff->info.channels;
unsigned i, j; unsigned i, j;
if (!ff->buffer) if (!ff->buffer)
ff->buffer = malloc (ff->info.max_blocksize * ff->info.channels ff->buffer = calloc (ff->info.max_blocksize * ff->info.channels,
* sizeof (float)); sizeof (float));
ff->size = frame->header.blocksize;
ff->pos = 0;
for (j = 0; j < ff->info.channels; j++) { for (j = 0; j < ff->info.channels; j++) {
const FLAC__int32 *in = buffer[j]; const FLAC__int32 *in = buffer[j];
out = ff->buffer + j; out = ff->buffer + j;
for (i = 0; i < frame->header.blocksize; i++, out += ff->info.channels) for (i = 0; i < ff->size; i++, out += step)
*out = *in++ * scale; *out = *in++ * scale;
} }
ff->size = frame->header.blocksize;
ff->pos = 0;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
} }
@ -296,6 +297,7 @@ flac_load (flacfile_t *ff, sfxblock_t *block, cache_allocator_t allocator)
if (flac_read (ff, data, info->frames) < 0) if (flac_read (ff, data, info->frames) < 0)
goto bail; goto bail;
SND_SetPaint (sc); SND_SetPaint (sc);
SND_SetupResampler (sc, 0);
SND_Resample (sc, data, info->frames); SND_Resample (sc, data, info->frames);
sc->head = sc->length; sc->head = sc->length;
bail: bail:

View file

@ -381,14 +381,12 @@ SND_GetCache (long frames, int rate, int channels,
stepscale = (float) rate / snd_shm->speed; stepscale = (float) rate / snd_shm->speed;
len = size = frames / stepscale; len = size = frames / stepscale;
// printf ("%ld %d\n", frames, size);
size *= sizeof (float) * channels; size *= sizeof (float) * channels;
sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name); sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name);
if (!sc) if (!sc)
return 0; return 0;
memset (sc, 0, sizeof (sfxbuffer_t) + size); memset (sc, 0, sizeof (sfxbuffer_t) + size);
sc->length = len; sc->length = len;
sc->data = sc->sample_data;
memcpy (sc->data + len * channels, "\xde\xad\xbe\xef", 4); memcpy (sc->data + len * channels, "\xde\xad\xbe\xef", 4);
return sc; return sc;
} }

View file

@ -70,21 +70,8 @@ SND_Resample (sfxbuffer_t *sc, float *data, int length)
SRC_DATA src_data; SRC_DATA src_data;
stepscale = (double) snd_shm->speed / inrate; stepscale = (double) snd_shm->speed / inrate;
outcount = length * stepscale; outcount = length * 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;
else
sc->sfx->loopstart = (unsigned int)-1;
sc->channels = info->channels;
if (!length)
return;
src_data.data_in = data; src_data.data_in = data;
src_data.data_out = sc->data + sc->head * sc->channels; src_data.data_out = sc->data + sc->head * sc->channels;
src_data.input_frames = length; src_data.input_frames = length;
@ -97,6 +84,63 @@ SND_Resample (sfxbuffer_t *sc, float *data, int length)
check_buffer_integrity (sc, outwidth, __FUNCTION__); check_buffer_integrity (sc, outwidth, __FUNCTION__);
} }
static void
SND_ResampleStream (sfxbuffer_t *sc, float *data, int length)
{
SRC_DATA src_data;
SRC_STATE *state = (SRC_STATE *) sc->state;
int outcount;
double stepscale;
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
int inrate = info->rate;
stepscale = (double) snd_shm->speed / inrate;
outcount = length * 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;
src_data.end_of_input = 0; //XXX
src_process (state, &src_data);
}
void
SND_SetupResampler (sfxbuffer_t *sc, int streamed)
{
double stepscale;
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
int inrate = info->rate;
stepscale = (double) snd_shm->speed / inrate;
sc->sfx->length = info->frames * stepscale;
if (info->loopstart != (unsigned int)-1)
sc->sfx->loopstart = info->loopstart * stepscale;
else
sc->sfx->loopstart = (unsigned int)-1;
sc->channels = info->channels;
if (streamed) {
int err;
sfxstream_t *stream = sc->sfx->data.stream;
if (snd_shm->speed == inrate) {
sc->state = 0;
stream->resample = 0;
} else {
sc->state = src_new (SRC_LINEAR, info->channels, &err);
stream->resample = SND_ResampleStream;
}
} else {
sc->state = 0;
}
}
void void
SND_Convert (byte *idata, float *fdata, int frames, int channels, int width) SND_Convert (byte *idata, float *fdata, int frames, int channels, int width)
{ {

View file

@ -132,12 +132,11 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
frames = snd_shm->speed * 0.3; frames = snd_shm->speed * 0.3;
frames = (frames + 255) & ~255; frames = (frames + 255) & ~255;
size = frames + 1; // one extra sample for the resampler size = frames * info->channels * sizeof (float);
size *= info->channels * sizeof (float);
stream = calloc (1, sizeof (sfxstream_t) + size); stream = calloc (1, sizeof (sfxstream_t) + size);
new_sfx->data.stream = stream; new_sfx->data.stream = stream;
memcpy ((byte *) stream->buffer.sample_data + size, "\xde\xad\xbe\xef", 4); memcpy ((byte *) stream->buffer.data + size, "\xde\xad\xbe\xef", 4);
stream->file = file; stream->file = file;
stream->sfx = new_sfx; stream->sfx = new_sfx;
stream->resample = SND_Resample; stream->resample = SND_Resample;
@ -150,10 +149,9 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
stream->buffer.advance = SND_StreamAdvance; stream->buffer.advance = SND_StreamAdvance;
stream->buffer.setpos = SND_StreamSetPos; stream->buffer.setpos = SND_StreamSetPos;
stream->buffer.sfx = new_sfx; stream->buffer.sfx = new_sfx;
stream->buffer.data = &stream->buffer.sample_data[info->channels];
SND_SetPaint (&stream->buffer); SND_SetPaint (&stream->buffer);
stream->resample (&stream->buffer, 0, 0); // get sfx setup properly SND_SetupResampler (&stream->buffer, 1); // get sfx setup properly
stream->buffer.setpos (&stream->buffer, 0); // pre-fill the buffer stream->buffer.setpos (&stream->buffer, 0); // pre-fill the buffer
return new_sfx; return new_sfx;

View file

@ -174,6 +174,7 @@ vorbis_load (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator)
if (vorbis_read (vf, data, info->frames, info) < 0) if (vorbis_read (vf, data, info->frames, info) < 0)
goto bail; goto bail;
SND_SetPaint (sc); SND_SetPaint (sc);
SND_SetupResampler (sc, 0);
SND_Resample (sc, data, info->frames); SND_Resample (sc, data, info->frames);
sc->head = sc->length; sc->head = sc->length;
bail: bail:

View file

@ -78,6 +78,7 @@ wav_callback_load (void *object, cache_allocator_t allocator)
info->channels, block, allocator); info->channels, block, allocator);
buffer->sfx = sfx; buffer->sfx = sfx;
SND_SetPaint (buffer); SND_SetPaint (buffer);
SND_SetupResampler (buffer, 0);
SND_Resample (buffer, fdata, info->frames); SND_Resample (buffer, fdata, info->frames);
buffer->head = buffer->length; buffer->head = buffer->length;
free (data); free (data);