From 580186f5d1495e305e6bdcbf48d8155b05860291 Mon Sep 17 00:00:00 2001 From: gewlitys Date: Mon, 14 Jul 2003 20:18:32 +0000 Subject: [PATCH] MixSDL now handles resampling correctly (less cracklings); added cubic interpolation for high quality mode; some cleanups git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1050 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/ChangeLog | 2 + sc2/src/sc2code/libs/sound/mixsdl/mixer.c | 542 +++++++++--------- sc2/src/sc2code/libs/sound/mixsdl/mixer.h | 6 +- sc2/src/sc2code/libs/sound/mixsdl/mixerint.h | 13 +- .../sc2code/libs/sound/mixsdl/sound_mixsdl.h | 1 - sc2/src/sc2code/libs/sound/sound_chooser.c | 12 - sc2/src/sc2code/libs/sound/sound_chooser.h | 4 - 7 files changed, 280 insertions(+), 300 deletions(-) diff --git a/sc2/ChangeLog b/sc2/ChangeLog index 8c450c012..a9e8cf78f 100644 --- a/sc2/ChangeLog +++ b/sc2/ChangeLog @@ -1,4 +1,6 @@ Changes towards version 0.3: +- MixSDL now handles resampling correctly (less cracklings); + added cubic interpolation for high quality mode -Mika - Removed the redundant "GameExiting" variable -Michael - Added quit options to ingame menu (bug #409), from Paxtez - Fix position of blinking save/load in melee (bug #406), from Paxtez diff --git a/sc2/src/sc2code/libs/sound/mixsdl/mixer.c b/sc2/src/sc2code/libs/sound/mixsdl/mixer.c index 3996c9c65..f80b4ac12 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/mixer.c +++ b/sc2/src/sc2code/libs/sound/mixsdl/mixer.c @@ -55,6 +55,7 @@ static uint32 mixer_chansize; static uint32 mixer_sampsize; static sint32 mixer_silence; static uint32 mixer_freq; +static mixSDL_Quality mixer_quality; /* mixer interim work-buffer; size in one-channel samples */ static uint32 mixer_datasize; @@ -253,6 +254,7 @@ mixSDL_OpenAudio (uint32 frequency, uint32 format, uint32 samples_buf, mixer_chansize, mixer_spec.channels); mixer_sampsize = mixer_chansize * mixer_spec.channels; mixer_freq = mixer_spec.freq; + mixer_quality = quality; /* 2x size the sound playback buffer should be enough for anything */ mixer_datasize = samples_buf * mixer_spec.channels * 2; @@ -348,8 +350,10 @@ mixSDL_GenSources (uint32 n, mixSDL_Object *psrcobj) src->cprocessed = 0; src->firstqueued = 0; src->nextqueued = 0; + src->prevqueued = 0; src->lastqueued = 0; src->curbufofs = 0; + src->curbufdelta = 0; *psrcobj = (mixSDL_Object) src; } @@ -483,6 +487,7 @@ mixSDL_Sourcei (mixSDL_Object srcobj, mixSDL_SourceProp pname, src->firstqueued = buf; src->nextqueued = src->firstqueued; + src->prevqueued = 0; src->lastqueued = src->nextqueued; if (src->lastqueued) src->lastqueued->next = 0; @@ -854,6 +859,7 @@ mixSDL_SourceQueueBuffers (mixSDL_Object srcobj, uint32 n, { src->firstqueued = buf; src->nextqueued = buf; + src->prevqueued = 0; } src->cqueued++; buf->state = MIX_BUF_QUEUED; @@ -924,6 +930,8 @@ mixSDL_SourceUnqueueBuffers (mixSDL_Object srcobj, uint32 n, /* remove buffer from the chain */ if (src->nextqueued == buf) src->nextqueued = buf->next; + if (src->prevqueued == buf) + src->prevqueued = 0; if (src->lastqueued == buf) src->lastqueued = 0; src->firstqueued = buf->next; @@ -983,10 +991,12 @@ mixSDL_SourceUnqueueAll (mixSDL_Source *src) src->firstqueued = 0; src->nextqueued = 0; + src->prevqueued = 0; src->lastqueued = 0; src->cqueued = 0; src->cprocessed = 0; src->curbufofs = 0; + src->curbufdelta = 0; } /* add the source to the active array */ @@ -1098,7 +1108,9 @@ mixSDL_SourceStop_internal (mixSDL_Source *src) src->lastqueued = 0; } src->nextqueued = 0; + src->prevqueued = 0; src->curbufofs = 0; + src->curbufdelta = 0; mixSDL_UnlockMutex (buf_mutex); } @@ -1124,38 +1136,61 @@ mixSDL_SourceRewind_internal (mixSDL_Source *src) mixSDL_UnlockMutex (buf_mutex); src->curbufofs = 0; + src->curbufdelta = 0; src->cprocessed = 0; src->nextqueued = src->firstqueued; + src->prevqueued = 0; src->state = MIX_INITIAL; } /* get the sample next in queue in internal format */ static __inline__ bool -mixSDL_SourceGetNextSample (mixSDL_Source *src, sint32* psamp) +mixSDL_SourceGetNextSample (mixSDL_Source *src, sint32* psamp, bool left) { /* fake the data if requested */ if (mixer_driverflags & MIX_DRIVER_FAKE_DATA) - return mixSDL_SourceGetFakeSample (src, psamp); + return mixSDL_SourceGetFakeSample (src, psamp, left); while (src->nextqueued) { mixSDL_Buffer *buf = src->nextqueued; uint8* data; double samp; - + if (!buf->data || buf->size < mixer_sampsize) { /* buffer invalid, go next */ buf->state = MIX_BUF_PROCESSED; src->curbufofs = 0; + src->curbufdelta = 0; + src->prevqueued = src->nextqueued; src->nextqueued = src->nextqueued->next; src->cprocessed++; continue; } - data = buf->data + src->curbufofs; - samp = mixSDL_GetSampleInt (data, mixer_chansize); - src->curbufofs += mixer_chansize; + if (mixer_freq == buf->orgfreq) + { + data = buf->data + (uint32)src->curbufofs; + samp = mixSDL_GetSampleInt (data, mixer_chansize); + src->curbufofs += mixer_chansize; + } + else if (mixer_freq > buf->orgfreq) + { + if (mixer_quality == MIX_QUALITY_DEFAULT) + samp = mixSDL_GetResampledInt_linear (src, left); + else if (mixer_quality == MIX_QUALITY_HIGH) + samp = mixSDL_GetResampledInt_cubic (src, left); + else + samp = mixSDL_GetResampledInt_nearest (src, left); + } + else + { + /* because currently linear and cubic resamplers do not work + for downsampling */ + samp = mixSDL_GetResampledInt_nearest (src, left); + } + samp *= src->gain; if (mixer_chansize == 2) @@ -1184,6 +1219,8 @@ mixSDL_SourceGetNextSample (mixSDL_Source *src, sint32* psamp) /* buffer exhausted, go next */ buf->state = MIX_BUF_PROCESSED; src->curbufofs = 0; + src->curbufdelta = 0; + src->prevqueued = src->nextqueued; src->nextqueued = src->nextqueued->next; src->cprocessed++; } @@ -1206,20 +1243,47 @@ mixSDL_SourceGetNextSample (mixSDL_Source *src, sint32* psamp) /* fake the next sample, but process buffers and states */ static __inline__ bool -mixSDL_SourceGetFakeSample (mixSDL_Source *src, sint32* psamp) +mixSDL_SourceGetFakeSample (mixSDL_Source *src, sint32* psamp, bool left) { while (src->nextqueued) { mixSDL_Buffer *buf = src->nextqueued; + if (mixer_freq == buf->orgfreq) + { + src->curbufofs += mixer_chansize; + } + else + { + double offset, intoffset; + if (MIX_FORMAT_CHANS (mixer_format) == 2) + { + if (!left) + { + offset = src->curbufdelta + + (double)src->nextqueued->orgfreq / mixer_freq; + src->curbufdelta = modf (offset, &intoffset); + src->curbufofs += (uint32)intoffset * mixer_sampsize; + } + } + else + { + offset = src->curbufdelta + + (double)src->nextqueued->orgfreq / mixer_freq; + src->curbufdelta = modf (offset, &intoffset); + src->curbufofs += (uint32)intoffset * mixer_sampsize; + } + } + *psamp = 0; - src->curbufofs += mixer_chansize; if (src->curbufofs >= buf->size) { /* buffer exhausted, go next */ buf->state = MIX_BUF_PROCESSED; src->curbufofs = 0; + src->curbufdelta = 0; + src->prevqueued = src->nextqueued; src->nextqueued = src->nextqueued->next; src->cprocessed++; } @@ -1498,12 +1562,11 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, buf->orgchannels = MIX_FORMAT_CHANS (format); buf->orgchansize = MIX_FORMAT_BPC (format); - conv.srcsamples = size / MIX_FORMAT_SAMPSIZE (format); - conv.dstsamples = (uint32) - ((double)conv.srcsamples * mixer_freq / freq); + conv.srcsamples = conv.dstsamples = + size / MIX_FORMAT_SAMPSIZE (format); if (conv.dstsamples > - UINT32_MAX / MIX_FORMAT_SAMPSIZE (mixer_format)) + UINT32_MAX / MIX_FORMAT_SAMPSIZE (format)) { mixSDL_SetError (MIX_INVALID_VALUE); } @@ -1518,7 +1581,7 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, { buf->data = HMalloc (dstsize); - if (format == mixer_format && freq == mixer_freq) + if (format == mixer_format) { /* format identical to internal */ buf->locked = true; @@ -1542,11 +1605,9 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, conv.srcfmt = format; conv.srcdata = data; conv.srcsize = size; - conv.srcfreq = freq; conv.dstfmt = mixer_format; conv.dstdata = buf->data; conv.dstsize = dstsize; - conv.dstfreq = mixer_freq; buf->locked = true; mixSDL_UnlockMutex (buf_mutex); @@ -1565,73 +1626,6 @@ mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, mixSDL_UnlockMutex (buf_mutex); } -/* convert a user buffer from one format to another */ -void -mixSDL_ConvertBuffer (uint32 srcfmt, void* srcdata, uint32 srcsize, - uint32 srcfreq, uint32 dstfmt, void* dstdata, - uint32 dstfreq, uint32 dstsize) -{ - mixSDL_Convertion conv; - uint32 reqsize; - - if (!srcdata || !dstdata) - { - mixSDL_SetError (MIX_INVALID_VALUE); - fprintf (stderr, "mixSDL_ConvertBuffer(): called " - "with null buffer\n"); - return; - } - - - conv.srcsamples = srcsize / MIX_FORMAT_SAMPSIZE (srcfmt); - conv.dstsamples = (uint32) - ((double)conv.srcsamples * dstfreq / srcfreq); - - if (conv.dstsamples > UINT32_MAX / MIX_FORMAT_SAMPSIZE (dstfmt)) - { - mixSDL_SetError (MIX_INVALID_VALUE); - return; - } - - reqsize = conv.dstsamples * MIX_FORMAT_SAMPSIZE (mixer_format); - - if (reqsize > dstsize) - { - mixSDL_SetError (MIX_INVALID_VALUE); - fprintf (stderr, "mixSDL_ConvertBuffer(): " - "destination buffer too small\n"); - return; - } - - if (srcfmt == dstfmt && srcfreq == dstfreq) - { - /* user buffer, no S8->U8 convertion */ - memcpy (dstdata, srcdata, srcsize); - } - else - { - conv.srcfmt = srcfmt; - conv.srcdata = srcdata; - conv.srcsize = srcsize; - conv.srcfreq = srcfreq; - conv.dstfmt = dstfmt; - conv.dstdata = dstdata; - conv.dstsize = dstsize; - conv.dstfreq = dstfreq; - - mixSDL_ConvertBuffer_internal (&conv); - - if (conv.dstbpc == 1) - { - /* converted buffer is in S8 format - * have to make it U8 - */ - uint8* dst; - for (dst = conv.dstdata; dstsize; dstsize--, dst++) - *dst ^= 0x80; - } - } -} /************************************************* * Buffer internals @@ -1690,24 +1684,7 @@ mixSDL_ConvertBuffer_internal (mixSDL_Convertion *conv) else if (conv->srcchans < conv->dstchans) conv->flags |= mixConvStereoUp; - if (conv->srcfreq == conv->dstfreq) - { - mixSDL_ResampleFlat (conv); - } - else if (conv->dstfreq > conv->srcfreq) - { - if (conv->dstfreq % conv->srcfreq == 0) - mixSDL_ResampleUp_fast (conv); - else - mixSDL_Resample_frac (conv); - } - else - { - if (conv->srcfreq % conv->dstfreq == 0) - mixSDL_ResampleDown_fast (conv); - else - mixSDL_Resample_frac (conv); - } + mixSDL_ResampleFlat (conv); } /************************************************* @@ -1760,6 +1737,184 @@ mixSDL_PutSampleInt (void *dst, uint32 bpc, sint32 samp) *(sint8 *)dst = samp; } +/* get a resampled sample from internal buffer (nearest neighbor) */ +static __inline__ sint32 +mixSDL_GetResampledInt_nearest (mixSDL_Source *src, bool left) +{ + uint8 *d0 = src->nextqueued->data + src->curbufofs; + double offset, intoffset; + + if (MIX_FORMAT_CHANS (mixer_format) == 2) + { + if (!left) + { + d0 += mixer_chansize; + offset = src->curbufdelta + + (double)src->nextqueued->orgfreq / mixer_freq; + src->curbufdelta = modf (offset, &intoffset); + src->curbufofs += (uint32)intoffset * mixer_sampsize; + } + } + else + { + offset = src->curbufdelta + + (double)src->nextqueued->orgfreq / mixer_freq; + src->curbufdelta = modf (offset, &intoffset); + src->curbufofs += (uint32)intoffset * mixer_sampsize; + } + + return mixSDL_GetSampleInt (d0, mixer_chansize); +} + +/* get a resampled sample from internal buffer (linear interpolation) */ +static __inline__ sint32 +mixSDL_GetResampledInt_linear (mixSDL_Source *src, bool left) +{ + // TODO: support for downsampling + + mixSDL_Buffer *curr = src->nextqueued; + mixSDL_Buffer *next = src->nextqueued->next; + uint8 *d0, *d1; + sint32 s0, s1, samp; + double offset, intoffset, delta; + + delta = src->curbufdelta; + d0 = curr->data + src->curbufofs; + + if (MIX_FORMAT_CHANS (mixer_format) == 2) + { + if (!left) + { + d0 += mixer_chansize; + offset = src->curbufdelta + + (double)src->nextqueued->orgfreq / mixer_freq; + src->curbufdelta = modf (offset, &intoffset); + src->curbufofs += (uint32)intoffset * mixer_sampsize; + } + } + else + { + offset = src->curbufdelta + + (double)src->nextqueued->orgfreq / mixer_freq; + src->curbufdelta = modf (offset, &intoffset); + src->curbufofs += (uint32)intoffset * mixer_sampsize; + } + + if (d0 + mixer_sampsize >= curr->data + curr->size) + { + if (next && next->data && next->size >= mixer_sampsize) + { + d1 = next->data; + if (!left) + d1 += mixer_chansize; + } + else + d1 = d0; + } + else + d1 = d0 + mixer_sampsize; + + s0 = mixSDL_GetSampleInt (d0, mixer_chansize); + s1 = mixSDL_GetSampleInt (d1, mixer_chansize); + samp = s0 + (sint32)(delta * (s1 - s0)); + + return samp; +} + +/* get a resampled sample from internal buffer (cubic interpolation) */ +static __inline__ sint32 +mixSDL_GetResampledInt_cubic (mixSDL_Source *src, bool left) +{ + // TODO: support for downsampling + + mixSDL_Buffer *prev = src->prevqueued; + mixSDL_Buffer *curr = src->nextqueued; + mixSDL_Buffer *next = src->nextqueued->next; + uint8 *d0, *d1, *d2, *d3; /* prev, curr, next, next + 1 */ + sint32 samp; + double offset, intoffset; + float delta, delta2, a, b, c, s0, s1, s2, s3; + + delta = (float)src->curbufdelta; + delta2 = delta * delta; + d1 = curr->data + src->curbufofs; + + if (MIX_FORMAT_CHANS (mixer_format) == 2) + { + if (!left) + { + d1 += mixer_chansize; + offset = src->curbufdelta + + (double)src->nextqueued->orgfreq / mixer_freq; + src->curbufdelta = modf (offset, &intoffset); + src->curbufofs += (uint32)intoffset * mixer_sampsize; + } + } + else + { + offset = src->curbufdelta + + (double)src->nextqueued->orgfreq / mixer_freq; + src->curbufdelta = modf (offset, &intoffset); + src->curbufofs += (uint32)intoffset * mixer_sampsize; + } + + if (d1 - mixer_sampsize < curr->data) + { + if (prev && prev->data && prev->size >= mixer_sampsize) + { + d0 = prev->data + prev->size - mixer_sampsize; + if (!left) + d0 += mixer_chansize; + } + else + d0 = d1; + } + else + d0 = d1 - mixer_sampsize; + + if (d1 + mixer_sampsize >= curr->data + curr->size) + { + if (next && next->data && next->size >= mixer_sampsize * 2) + { + d2 = next->data; + if (!left) + d2 += mixer_chansize; + d3 = d2 + mixer_sampsize; + } + else + d2 = d3 = d1; + } + else + { + d2 = d1 + mixer_sampsize; + if (d2 + mixer_sampsize >= curr->data + curr->size) + { + if (next && next->data && next->size >= mixer_sampsize) + { + d3 = next->data; + if (!left) + d3 += mixer_chansize; + } + else + d3 = d2; + } + else + d3 = d2 + mixer_sampsize; + } + + s0 = (float)mixSDL_GetSampleInt (d0, mixer_chansize); + s1 = (float)mixSDL_GetSampleInt (d1, mixer_chansize); + s2 = (float)mixSDL_GetSampleInt (d2, mixer_chansize); + s3 = (float)mixSDL_GetSampleInt (d3, mixer_chansize); + + a = (3.0f * (s1 - s2) - s0 + s3) * 0.5f; + b = 2.0f * s2 + s0 - ((5.0f * s1 + s3) * 0.5f); + c = (s2 - s0) * 0.5f; + + samp = (sint32)(a * delta2 * delta + b * delta2 + c * delta + s1); + return samp; +} + /* get next sample from external buffer * in internal format, while performing * convertion if necessary @@ -1811,88 +1966,6 @@ mixSDL_PutConvSample (uint8 **pdst, uint32 bpc, uint32 flags, sint32 samp) } } -/* resampling with fractional rate change */ -static void -mixSDL_Resample_frac (mixSDL_Convertion *conv) -{ - mixSDL_ConvFlags flags = conv->flags; - uint8 *src = conv->srcdata; - uint8 *dst = conv->dstdata; - uint32 srcsamples = conv->srcsamples; - uint32 srcbpc = conv->srcbpc; - uint32 dstbpc = conv->dstbpc; - double convrate = (double)conv->srcfreq / conv->dstfreq; - double dstpos = 0; - uint32 nextsrcpos; /* next position already read */ - sint32 sampl, sampr, nextsampl, nextsampr; - uint32 srcjump = srcbpc * conv->srcchans; - bool stereo = conv->srcchans == 2 && !(flags & mixConvStereoDown); - uint32 i; - - nextsampl = mixSDL_GetConvSample (&src, srcbpc, flags); - if (stereo) - nextsampr = mixSDL_GetConvSample (&src, srcbpc, flags); - else - nextsampr = 0; - nextsrcpos = 0; - - for (i = conv->dstsamples; i; i--) - { - double delta, intdstpos; - uint32 srcpos; - uint32 samp; - - delta = modf (dstpos, &intdstpos); - srcpos = (uint32) intdstpos; - - if (srcpos >= nextsrcpos) - { - if (srcpos == nextsrcpos) - { - sampl = nextsampl; - sampr = nextsampr; - nextsrcpos++; - } - else - { - src += srcjump * (srcpos - nextsrcpos - 1); - sampl = mixSDL_GetConvSample (&src, srcbpc, flags); - if (stereo) - sampr = mixSDL_GetConvSample (&src, srcbpc, flags); - nextsrcpos = srcpos + 1; - } - - if (nextsrcpos < srcsamples) - { - nextsampl = mixSDL_GetConvSample (&src, srcbpc, flags); - if (stereo) - nextsampr = mixSDL_GetConvSample (&src, srcbpc, flags); - } - else - { - /* theoretically, here we need to get the next sample - * somehow, which is in the next buffer in the stream; - * leaving the next sample equal to the previous should - * do for now; this will create some-20 minimal - * distortions per second - */ - /* nextsampl = nextsampr = 0; */ - } - } - - /* iterpolate */ - samp = sampl + (sint32) (delta * (nextsampl - sampl)); - mixSDL_PutConvSample (&dst, dstbpc, flags, samp); - if (stereo) - { - samp = sampr + (sint32) (delta * (nextsampr - sampr)); - mixSDL_PutConvSample (&dst, dstbpc, flags, samp); - } - - dstpos += convrate; - } -} - /* resampling with respect to sample size only */ static void mixSDL_ResampleFlat (mixSDL_Convertion *conv) @@ -1917,93 +1990,6 @@ mixSDL_ResampleFlat (mixSDL_Convertion *conv) } } -/* integer-periodic resampling with rate increase */ -static void -mixSDL_ResampleUp_fast (mixSDL_Convertion *conv) -{ - mixSDL_ConvFlags flags = conv->flags; - uint8 *src = conv->srcdata; - uint8 *dst = conv->dstdata; - uint32 srcbpc = conv->srcbpc; - uint32 dstbpc = conv->dstbpc; - uint32 convrate = conv->dstfreq / conv->srcfreq; - sint32 nextsampl, nextsampr; - bool stereo = conv->srcchans == 2 && !(flags & mixConvStereoDown); - uint32 i; - - /* read one sample ahead */ - nextsampl = mixSDL_GetConvSample (&src, srcbpc, flags); - if (stereo) - nextsampr = mixSDL_GetConvSample (&src, srcbpc, flags); - else - nextsampr = 0; - - for (i = conv->srcsamples; i; i--) - { - sint32 sampl = nextsampl; - sint32 sampr = nextsampr; - sint32 di; - - if (i > 1) - { - nextsampl = mixSDL_GetConvSample (&src, srcbpc, flags); - if (stereo) - nextsampr = mixSDL_GetConvSample (&src, srcbpc, flags); - } - else - { - /* theoretically, here we need to get the next sample - * somehow, which is in the next buffer in the stream; - * leaving the next sample equal to the previous should - * do for now; this will create some-20 minimal - * distortions per second - */ - /* nextsampl = nextsampr = 0; */ - } - - for (di = convrate; di > 0; di--) - { - mixSDL_PutConvSample (&dst, dstbpc, flags, sampl); - sampl += (nextsampl - sampl) / di; - if (stereo) - { - mixSDL_PutConvSample (&dst, dstbpc, flags, sampr); - sampr += (nextsampr - sampr) / di; - } - } - } -} - -/* integer-periodic resampling with rate decrease */ -static void -mixSDL_ResampleDown_fast (mixSDL_Convertion *conv) -{ - mixSDL_ConvFlags flags = conv->flags; - uint8 *src = conv->srcdata; - uint8 *dst = conv->dstdata; - uint32 srcbpc = conv->srcbpc; - uint32 dstbpc = conv->dstbpc; - uint32 convrate = conv->srcfreq / conv->dstfreq; - uint32 srcjump = (convrate - 1) * srcbpc * conv->srcchans; - bool stereo = conv->srcchans == 2 && !(flags & mixConvStereoDown); - uint32 i; - - for (i = conv->dstsamples; i; i--) - { - sint32 samp; - - samp = mixSDL_GetConvSample (&src, srcbpc, flags); - mixSDL_PutConvSample (&dst, dstbpc, flags, samp); - if (stereo) - { - samp = mixSDL_GetConvSample (&src, srcbpc, flags); - mixSDL_PutConvSample (&dst, dstbpc, flags, samp); - } - - src += srcjump; - } -} - /********************************************************** * THE mixer - higher quality; smoothed-out clipping @@ -2018,6 +2004,8 @@ mixSDL_mix_channels (void *userdata, uint8 *stream, sint32 len) sint32 *end_data = mixer_data + samples; sint32 *data; uint32 step; + bool left = true; + uint32 chans = MIX_FORMAT_CHANS (mixer_format); /* mixer_datasize < samples should not happen ever, but for now.. */ if (mixer_datasize < samples) @@ -2051,7 +2039,7 @@ mixSDL_mix_channels (void *userdata, uint8 *stream, sint32 len) for (; i < MAX_SOURCES && ( (src = active_sources[i]) == 0 || src->state != MIX_PLAYING - || !mixSDL_SourceGetNextSample (src, &samp)); + || !mixSDL_SourceGetNextSample (src, &samp, left)); i++) ; @@ -2063,6 +2051,8 @@ mixSDL_mix_channels (void *userdata, uint8 *stream, sint32 len) } *data = fullsamp; + if (chans == 2) + left = !left; } /* unclip work-buffer */ @@ -2176,6 +2166,8 @@ static void mixSDL_mix_lowq (void *userdata, uint8 *stream, sint32 len) { uint8 *end_stream = stream + len; + bool left = true; + uint32 chans = MIX_FORMAT_CHANS (mixer_format); /* keep this order or die */ mixSDL_LockMutex (src_mutex); @@ -2198,7 +2190,7 @@ mixSDL_mix_lowq (void *userdata, uint8 *stream, sint32 len) for (; i < MAX_SOURCES && ( (src = active_sources[i]) == 0 || src->state != MIX_PLAYING - || !mixSDL_SourceGetNextSample (src, &samp)); + || !mixSDL_SourceGetNextSample (src, &samp, left)); i++) ; @@ -2228,6 +2220,8 @@ mixSDL_mix_lowq (void *userdata, uint8 *stream, sint32 len) } mixSDL_PutSampleExt (stream, mixer_chansize, fullsamp); + if (chans == 2) + left = !left; } /* keep this order or die */ @@ -2243,6 +2237,8 @@ static void mixSDL_mix_fake (void *userdata, uint8 *stream, sint32 len) { uint8 *end_stream = stream + len; + bool left = true; + uint32 chans = MIX_FORMAT_CHANS (mixer_format); /* keep this order or die */ mixSDL_LockMutex (src_mutex); @@ -2262,10 +2258,12 @@ mixSDL_mix_fake (void *userdata, uint8 *stream, sint32 len) for (; i < MAX_SOURCES && ( (src = active_sources[i]) == 0 || src->state != MIX_PLAYING - || !mixSDL_SourceGetFakeSample (src, &samp)); + || !mixSDL_SourceGetFakeSample (src, &samp, left)); i++) ; } + if (chans == 2) + left = !left; } /* keep this order or die */ diff --git a/sc2/src/sc2code/libs/sound/mixsdl/mixer.h b/sc2/src/sc2code/libs/sound/mixsdl/mixer.h index debf246cd..561c66aeb 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/mixer.h +++ b/sc2/src/sc2code/libs/sound/mixsdl/mixer.h @@ -192,8 +192,10 @@ typedef struct uint32 cprocessed; mixSDL_Buffer *firstqueued; /* first buf in the queue */ mixSDL_Buffer *nextqueued; /* next to play, or 0 */ + mixSDL_Buffer *prevqueued; /* previously played */ mixSDL_Buffer *lastqueued; /* last in queue */ uint32 curbufofs; + double curbufdelta; } mixSDL_Source; @@ -258,10 +260,6 @@ void mixSDL_GetBufferi (mixSDL_Object bufobj, mixSDL_BufferProp pname, void mixSDL_BufferData (mixSDL_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq); -void mixSDL_ConvertBuffer (uint32 srcfmt, void* srcdata, uint32 srcsize, - uint32 srcfreq, uint32 dstfmt, void* dstdata, - uint32 dstsize, uint32 dstfreq); - /* Make sure the prop-value type is of suitable size * it must be able to store both int and void* diff --git a/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h b/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h index ec6e9a913..1ca48ff3b 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h +++ b/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h @@ -43,7 +43,6 @@ typedef struct uint32 srcfmt; void *srcdata; uint32 srcsize; - uint32 srcfreq; uint32 srcbpc; /* bytes/sample for 1 chan */ uint32 srcchans; uint32 srcsamples; @@ -51,7 +50,6 @@ typedef struct uint32 dstfmt; void *dstdata; uint32 dstsize; - uint32 dstfreq; uint32 dstbpc; /* bytes/sample for 1 chan */ uint32 dstchans; uint32 dstsamples; @@ -61,10 +59,7 @@ typedef struct } mixSDL_Convertion; static void mixSDL_ConvertBuffer_internal (mixSDL_Convertion *conv); -static void mixSDL_Resample_frac (mixSDL_Convertion *conv); static void mixSDL_ResampleFlat (mixSDL_Convertion *conv); -static void mixSDL_ResampleUp_fast (mixSDL_Convertion *conv); -static void mixSDL_ResampleDown_fast (mixSDL_Convertion *conv); static __inline__ sint32 mixSDL_GetSampleExt (void *src, uint32 bpc); static __inline__ sint32 mixSDL_GetSampleInt (void *src, uint32 bpc); @@ -73,6 +68,10 @@ static __inline__ void mixSDL_PutSampleInt (void *dst, uint32 bpc, static __inline__ void mixSDL_PutSampleExt (void *dst, uint32 bpc, sint32 samp); +static __inline__ sint32 mixSDL_GetResampledInt_nearest (mixSDL_Source *src, bool left); +static __inline__ sint32 mixSDL_GetResampledInt_linear (mixSDL_Source *src, bool left); +static __inline__ sint32 mixSDL_GetResampledInt_cubic (mixSDL_Source *src, bool left); + /* Source manipulation */ static void mixSDL_SourceUnqueueAll (mixSDL_Source *src); static void mixSDL_SourceStop_internal (mixSDL_Source *src); @@ -124,9 +123,9 @@ static void mixSDL_mix_fake (void *userdata, uint8 *stream, sint32 len); static void mixSDL_UnclipWorkBuffer (sint32 *data, sint32 *end_data, uint32 step); static __inline__ bool mixSDL_SourceGetNextSample (mixSDL_Source *src, - sint32* samp); + sint32* samp, bool left); static __inline__ bool mixSDL_SourceGetFakeSample (mixSDL_Source *src, - sint32* psamp); + sint32* psamp, bool left); /* SDL driver */ static const char* mixSDL_DriverGetName (void); diff --git a/sc2/src/sc2code/libs/sound/mixsdl/sound_mixsdl.h b/sc2/src/sc2code/libs/sound/mixsdl/sound_mixsdl.h index 8ed8ba549..863649e22 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/sound_mixsdl.h +++ b/sc2/src/sc2code/libs/sound/mixsdl/sound_mixsdl.h @@ -55,7 +55,6 @@ #define TFBSound_IsBuffer mixSDL_IsBuffer #define TFBSound_GetBufferi mixSDL_GetBufferi #define TFBSound_BufferData mixSDL_BufferData -#define TFBSound_ConvertBuffer mixSDL_ConvertBuffer #define TFBSOUND_GAIN MIX_GAIN #define TFBSOUND_BUFFER MIX_BUFFER diff --git a/sc2/src/sc2code/libs/sound/sound_chooser.c b/sc2/src/sc2code/libs/sound/sound_chooser.c index 659d8b0dd..2d15094c5 100644 --- a/sc2/src/sc2code/libs/sound/sound_chooser.c +++ b/sc2/src/sc2code/libs/sound/sound_chooser.c @@ -244,18 +244,6 @@ TFBSound_BufferData (TFBSound_Object bufobj, uint32 format, void* data, mixSDL_BufferData ((mixSDL_Object) bufobj, format, data, size, freq); } -void -TFBSound_ConvertBuffer (uint32 srcfmt, void* srcdata, uint32 srcsize, - uint32 srcfreq, uint32 dstfmt, void* dstdata, - uint32 dstsize, uint32 dstfreq) -{ - if (SoundDriver == TFB_SOUNDDRIVER_OPENAL) - fprintf (stderr, "ConvertBuffer is not supported bu openAL\n"); - else - mixSDL_ConvertBuffer (srcfmt, srcdata, srcsize, srcfreq, dstfmt, dstdata, - dstsize, dstfreq); -} - int TFB_choose_InitSound (int driver, int flags) { diff --git a/sc2/src/sc2code/libs/sound/sound_chooser.h b/sc2/src/sc2code/libs/sound/sound_chooser.h index 896b5cf3a..a4f6adfac 100644 --- a/sc2/src/sc2code/libs/sound/sound_chooser.h +++ b/sc2/src/sc2code/libs/sound/sound_chooser.h @@ -83,10 +83,6 @@ void TFBSound_GetBufferi (TFBSound_Object bufobj, TFBSound_BufferProp pname, void TFBSound_BufferData (TFBSound_Object bufobj, uint32 format, void* data, uint32 size, uint32 freq); -void TFBSound_ConvertBuffer (uint32 srcfmt, void* srcdata, uint32 srcsize, - uint32 srcfreq, uint32 dstfmt, void* dstdata, - uint32 dstsize, uint32 dstfreq); - #define TFBSound_BufferData_Linux alBufferWriteData_LOKI enum {