+
+ return ringbuffer;
+}
+
+
+/*
+====================
+Snd_CreateSndBuffer
+====================
+*/
+snd_buffer_t *Snd_CreateSndBuffer (const unsigned char *samples, unsigned int sampleframes, const snd_format_t* in_format, unsigned int sb_speed)
+{
+ size_t newsampleframes, memsize;
+ snd_buffer_t* sb;
+
+ newsampleframes = (size_t) ceil((double)sampleframes * (double)sb_speed / (double)in_format->speed);
+
+ memsize = newsampleframes * in_format->channels * in_format->width;
+ memsize += sizeof (*sb) - sizeof (sb->samples);
+
+ sb = (snd_buffer_t*)Mem_Alloc (snd_mempool, memsize);
+ sb->format.channels = in_format->channels;
+ sb->format.width = in_format->width;
+ sb->format.speed = sb_speed;
+ sb->maxframes = newsampleframes;
+ sb->nbframes = 0;
+
+ if (!Snd_AppendToSndBuffer (sb, samples, sampleframes, in_format))
+ {
+ Mem_Free (sb);
+ return NULL;
+ }
+
+ return sb;
+}
+
+
+/*
+====================
+Snd_AppendToSndBuffer
+====================
+*/
+qboolean Snd_AppendToSndBuffer (snd_buffer_t* sb, const unsigned char *samples, unsigned int sampleframes, const snd_format_t* format)
+{
+ size_t srclength, outcount;
+ unsigned char *out_data;
+
+ //Con_DPrintf("ResampleSfx: %d samples @ %dHz -> %d samples @ %dHz\n",
+ // sampleframes, format->speed, outcount, sb->format.speed);
+
+ // If the formats are incompatible
+ if (sb->format.channels != format->channels || sb->format.width != format->width)
+ {
+ Con_Print("AppendToSndBuffer: incompatible sound formats!\n");
+ return false;
+ }
+
+ outcount = (size_t) ((double)sampleframes * (double)sb->format.speed / (double)format->speed);
+
+ // If the sound buffer is too short
+ if (outcount > sb->maxframes - sb->nbframes)
+ {
+ Con_Print("AppendToSndBuffer: sound buffer too short!\n");
+ return false;
+ }
+
+ out_data = &sb->samples[sb->nbframes * sb->format.width * sb->format.channels];
+ srclength = sampleframes * format->channels;
+
+ // Trivial case (direct transfer)
+ if (format->speed == sb->format.speed)
+ {
+ if (format->width == 1)
+ {
+ size_t i;
+
+ for (i = 0; i < srclength; i++)
+ ((signed char*)out_data)[i] = samples[i] - 128;
+ }
+ else // if (format->width == 2)
+ memcpy (out_data, samples, srclength * format->width);
+ }
+
+ // 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)