X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=snd_mem.c;h=37781bfa05d22cd24ee2f4bc35cfd0505afe864e;hb=165b7ec09d52c689655d3a042ca6a36bf522283f;hp=2b061f454330b6a5ab1d830cf1e60ff55f38ec5c;hpb=6f079ecb90e1e6b7597d4da1a98f95c5822aad8d;p=xonotic%2Fdarkplaces.git diff --git a/snd_mem.c b/snd_mem.c index 2b061f45..37781bfa 100644 --- a/snd_mem.c +++ b/snd_mem.c @@ -31,12 +31,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ResampleSfx ================ */ -size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* in_format, qbyte *out_data, const char* sfxname) +size_t ResampleSfx (const unsigned char *in_data, size_t in_length, const snd_format_t* in_format, unsigned char *out_data, const char* sfxname) { - size_t srclength, outcount, i; + size_t srclength, outcount; srclength = in_length * in_format->channels; - outcount = (double)in_length * shm->format.speed / in_format->speed; + outcount = (int)((double)in_length * shm->format.speed / in_format->speed); //Con_DPrintf("ResampleSfx(%s): %d samples @ %dHz -> %d samples @ %dHz\n", // sfxname, in_length, in_format->speed, outcount, shm->format.speed); @@ -46,6 +46,8 @@ size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* { if (in_format->width == 1) { + size_t i; + for (i = 0; i < srclength; i++) ((signed char*)out_data)[i] = in_data[i] - 128; } @@ -56,21 +58,21 @@ size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* // General case (linear interpolation with a fixed-point fractional // step, 18-bit integer part and 14-bit fractional part) // Can handle up to 2^18 (262144) samples per second (> 96KHz stereo) - #define FRACTIONAL_BITS 14 - #define FRACTIONAL_MASK ((1 << FRACTIONAL_BITS) - 1) - #define INTEGER_BITS (sizeof(samplefrac)*8 - FRACTIONAL_BITS) +# define FRACTIONAL_BITS 14 +# define FRACTIONAL_MASK ((1 << FRACTIONAL_BITS) - 1) +# define INTEGER_BITS (sizeof(samplefrac)*8 - FRACTIONAL_BITS) else { - const unsigned int fracstep = (double)in_format->speed / shm->format.speed * (1 << FRACTIONAL_BITS); + const unsigned int fracstep = (unsigned int)((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; + 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))", + Con_Printf ("ResampleSfx: sound quality too high for resampling (%uHz, %u channel(s))\n", in_format->speed, in_format->channels); return 0; } @@ -80,61 +82,110 @@ size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* // also to be able to handle very long sounds. while (total_out < outcount) { - size_t tmpcount; + 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 = (int)ceil((double)(((remain_in / in_format->channels) - 1) << FRACTIONAL_BITS) / fracstep); + if (interpolation_limit > tmpcount) + interpolation_limit = tmpcount; + } - // Convert up to 1 sec of sound - for (i = 0; i < tmpcount; i++) + // 16 bit samples + if (in_format->width == 2) { - unsigned int j = 0; - unsigned int srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels; - int a, b; + const short* in_ptr_short; - // 16 bit samples - if (in_format->width == 2) + // Interpolated part + for (i = 0; i < interpolation_limit; i++) { - for (j = 0; j < in_format->channels; j++, srcsample++) + srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels; + in_ptr_short = &((const short*)in_ptr)[srcsample]; + + for (j = 0; j < in_format->channels; j++) { - // 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]; + 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; } - // 8 bit samples - else // if (in_format->width == 1) + + // Non-interpolated part + for (/* nothing */; i < tmpcount; i++) { - for (j = 0; j < in_format->channels; j++, srcsample++) + srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels; + in_ptr_short = &((const short*)in_ptr)[srcsample]; + + for (j = 0; j < in_format->channels; j++) { - // 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; + *((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; } - 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 @@ -170,7 +221,7 @@ qboolean S_LoadSound (sfx_t *s, qboolean complain) if (s->fetcher != NULL) { if (s->format.speed != shm->format.speed) - Con_Printf ("S_LoadSound: sound %s hasn't been resampled (%uHz instead of %uHz)", s->name); + Con_Printf ("S_LoadSound: sound %s hasn't been resampled (%uHz instead of %uHz)\n", s->name); return true; } @@ -213,20 +264,3 @@ qboolean S_LoadSound (sfx_t *s, qboolean complain) Con_Printf("S_LoadSound: Couldn't load \"%s\"\n", s->name); return false; } - -void S_UnloadSound (sfx_t *s) -{ - if (s->fetcher != NULL) - { - unsigned int i; - - // Stop all channels that use this sound - for (i = 0; i < total_channels ; i++) - if (channels[i].sfx == s) - S_StopChannel (i); - - s->fetcher = NULL; - s->fetcher_data = NULL; - Mem_FreePool(&s->mempool); - } -}