- const unsigned int fracstep = (double)in_format->speed / shm->format.speed * (1 << FRACTIONAL_BITS);
- size_t remain_in = srclength, total_out = 0;
- unsigned int samplefrac;
- const qbyte *in_ptr = in_data;
- qbyte *out_ptr = out_data;
-
- // Check that we can handle one second of that sound
- if (in_format->speed * in_format->channels > (1 << INTEGER_BITS))
- Sys_Error ("ResampleSfx: sound quality too high for resampling (%uHz, %u channel(s))",
- in_format->speed, in_format->channels);
-
- // We work 1 sec at a time to make sure we don't accumulate any
- // significant error when adding "fracstep" over several seconds, and
- // also to be able to handle very long sounds.
- while (total_out < outcount)
- {
- size_t tmpcount;
-
- samplefrac = 0;
-
- // If more than 1 sec of sound remains to be converted
- if (outcount - total_out > shm->format.speed)
- tmpcount = shm->format.speed;
- else
- tmpcount = outcount - total_out;
-
- // Convert up to 1 sec of sound
- for (i = 0; i < tmpcount; i++)
- {
- unsigned int j = 0;
- unsigned int srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels;
- int a, b;
-
- // 16 bit samples
- if (in_format->width == 2)
- {
- for (j = 0; j < in_format->channels; j++, srcsample++)
- {
- // No value to interpolate with?
- if (srcsample + in_format->channels < remain_in)
- {
- a = ((const short*)in_ptr)[srcsample];
- b = ((const short*)in_ptr)[srcsample + in_format->channels];
- *((short*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
- }
- else
- *((short*)out_ptr) = ((const short*)in_ptr)[srcsample];
-
- out_ptr += sizeof (short);
- }
- }
- // 8 bit samples
- else // if (in_format->width == 1)
- {
- for (j = 0; j < in_format->channels; j++, srcsample++)
- {
- // No more value to interpolate with?
- if (srcsample + in_format->channels < remain_in)
- {
- a = ((const qbyte*)in_ptr)[srcsample] - 128;
- b = ((const qbyte*)in_ptr)[srcsample + in_format->channels] - 128;
- *((signed char*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
- }
- else
- *((signed char*)out_ptr) = ((const qbyte*)in_ptr)[srcsample] - 128;
-
- out_ptr += sizeof (signed char);
- }
- }
-
- samplefrac += fracstep;
- }
-
- // Update the counters and the buffer position
- remain_in -= in_format->speed * in_format->channels;
- in_ptr += in_format->speed * in_format->channels * in_format->width;
- total_out += tmpcount;
- }