- 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 unsigned char *in_ptr = in_data;
- unsigned char *out_ptr = out_data;
-
- // Check that we can handle one second of that sound
- if (in_format->speed * in_format->channels > (1 << INTEGER_BITS))
- {
- Con_Printf ("ResampleSfx: sound quality too high for resampling (%uHz, %u channel(s))\n",
- in_format->speed, in_format->channels);
- return 0;
- }
-
- // 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, interpolation_limit, i, j;
- unsigned int srcsample;
-
- samplefrac = 0;
-
- // If more than 1 sec of sound remains to be converted
- if (outcount - total_out > shm->format.speed)
- {
- tmpcount = shm->format.speed;
- interpolation_limit = tmpcount; // all samples can be interpolated
- }
- else
- {
- tmpcount = outcount - total_out;
- interpolation_limit = ceil((double)(((remain_in / in_format->channels) - 1) << FRACTIONAL_BITS) / fracstep);
- if (interpolation_limit > tmpcount)
- interpolation_limit = tmpcount;
- }
-
- // 16 bit samples
- if (in_format->width == 2)
- {
- const short* in_ptr_short;
-
- // Interpolated part
- for (i = 0; i < interpolation_limit; i++)
- {
- srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels;
- in_ptr_short = &((const short*)in_ptr)[srcsample];
-
- for (j = 0; j < in_format->channels; j++)
- {
- int a, b;
-
- a = *in_ptr_short;
- b = *(in_ptr_short + in_format->channels);
- *((short*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
-
- in_ptr_short++;
- out_ptr += sizeof (short);
- }
-
- samplefrac += fracstep;
- }
-
- // Non-interpolated part
- for (/* nothing */; i < tmpcount; i++)
- {
- srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels;
- in_ptr_short = &((const short*)in_ptr)[srcsample];
-
- for (j = 0; j < in_format->channels; j++)
- {
- *((short*)out_ptr) = *in_ptr_short;
-
- in_ptr_short++;
- out_ptr += sizeof (short);
- }
-
- samplefrac += fracstep;
- }
- }
- // 8 bit samples
- else // if (in_format->width == 1)
- {
- const unsigned char* in_ptr_byte;
-
- // Convert up to 1 sec of sound
- for (i = 0; i < interpolation_limit; i++)
- {
- srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels;
- in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
-
- for (j = 0; j < in_format->channels; j++)
- {
- int a, b;
-
- a = *in_ptr_byte - 128;
- b = *(in_ptr_byte + in_format->channels) - 128;
- *((signed char*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
-
- in_ptr_byte++;
- out_ptr += sizeof (signed char);
- }
-
- samplefrac += fracstep;
- }
-
- // Non-interpolated part
- for (/* nothing */; i < tmpcount; i++)
- {
- srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels;
- in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
-
- for (j = 0; j < in_format->channels; j++)
- {
- *((signed char*)out_ptr) = *in_ptr_byte - 128;
-
- in_ptr_byte++;
- 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;
- }