|
|
@ -126,31 +126,7 @@ uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath ) |
|
|
|
return msecs; |
|
|
|
return msecs; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
#define drint( v ) (int)( v + 0.5 ) |
|
|
|
================ |
|
|
|
|
|
|
|
Sound_ConvertToSigned |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Convert unsigned data to signed |
|
|
|
|
|
|
|
================ |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
void Sound_ConvertToSigned( const byte *data, int channels, int samples ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( channels == 2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = 0; i < samples; i++ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
((signed char *)sound.tempbuffer)[i*2+0] = (int)((byte)(data[i*2+0]) - 128); |
|
|
|
|
|
|
|
((signed char *)sound.tempbuffer)[i*2+1] = (int)((byte)(data[i*2+1]) - 128); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = 0; i < samples; i++ ) |
|
|
|
|
|
|
|
((signed char *)sound.tempbuffer)[i] = (int)((unsigned char)(data[i]) - 128); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
================ |
|
|
|
================ |
|
|
@ -161,13 +137,15 @@ We need convert sound to signed even if nothing to resample |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth, int outrate, int outwidth ) |
|
|
|
qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth, int outrate, int outwidth ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
float stepscale; |
|
|
|
double stepscale, j; |
|
|
|
int outcount, srcsample; |
|
|
|
int outcount; |
|
|
|
int i, sample, sample2, samplefrac, fracstep; |
|
|
|
int i; |
|
|
|
byte *data; |
|
|
|
qboolean handled = false; |
|
|
|
|
|
|
|
|
|
|
|
data = sc->buffer; |
|
|
|
if( inrate == outrate && inwidth == outwidth ) |
|
|
|
stepscale = (float)inrate / outrate; // this is usually 0.5, 1, or 2
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stepscale = (double)inrate / outrate; // this is usually 0.5, 1, or 2
|
|
|
|
outcount = sc->samples / stepscale; |
|
|
|
outcount = sc->samples / stepscale; |
|
|
|
sc->size = outcount * outwidth * sc->channels; |
|
|
|
sc->size = outcount * outwidth * sc->channels; |
|
|
|
|
|
|
|
|
|
|
@ -177,69 +155,112 @@ qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth, int out |
|
|
|
if( sc->loopStart != -1 ) |
|
|
|
if( sc->loopStart != -1 ) |
|
|
|
sc->loopStart = sc->loopStart / stepscale; |
|
|
|
sc->loopStart = sc->loopStart / stepscale; |
|
|
|
|
|
|
|
|
|
|
|
// resample / decimate to the current source rate
|
|
|
|
if( inrate == outrate ) |
|
|
|
if( stepscale == 1.0f && inwidth == 1 && outwidth == 1 ) |
|
|
|
{ |
|
|
|
|
|
|
|
if( inwidth == 1 && outwidth == 2 ) // S8 to S16
|
|
|
|
{ |
|
|
|
{ |
|
|
|
Sound_ConvertToSigned( data, sc->channels, outcount ); |
|
|
|
for( i = 0; i < outcount * sc->channels; i++ ) |
|
|
|
|
|
|
|
((int16_t*)sound.tempbuffer)[i] = ((int8_t *)sc->buffer)[i] * 256; |
|
|
|
|
|
|
|
handled = true; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else if( inwidth == 2 && outwidth == 1 ) // S16 to S8
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// general case
|
|
|
|
for( i = 0; i < outcount * sc->channels; i++ ) |
|
|
|
samplefrac = 0; |
|
|
|
((int8_t*)sound.tempbuffer)[i] = ((int16_t *)sc->buffer)[i] / 256; |
|
|
|
fracstep = stepscale * 256; |
|
|
|
handled = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else // resample case
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( inwidth == 1 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int8_t *data = (int8_t *)sc->buffer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( outwidth == 1 ) |
|
|
|
|
|
|
|
{ |
|
|
|
if( sc->channels == 2 ) |
|
|
|
if( sc->channels == 2 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for( i = 0; i < outcount; i++ ) |
|
|
|
for( i = 0, j = 0; i < outcount; i++, j += stepscale ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
srcsample = samplefrac >> 8; |
|
|
|
((int8_t*)sound.tempbuffer)[i*2+0] = data[((int)j)*2+0]; |
|
|
|
samplefrac += fracstep; |
|
|
|
((int8_t*)sound.tempbuffer)[i*2+1] = data[((int)j)*2+1]; |
|
|
|
|
|
|
|
} |
|
|
|
if( inwidth == 2 ) |
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = 0, j = 0; i < outcount; i++, j += stepscale ) |
|
|
|
|
|
|
|
((int8_t*)sound.tempbuffer)[i] = data[(int)j]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
handled = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( outwidth == 2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( sc->channels == 2 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
sample = ((short *)data)[srcsample*2+0]; |
|
|
|
for( i = 0, j = 0; i < outcount; i++, j += stepscale ) |
|
|
|
sample2 = ((short *)data)[srcsample*2+1]; |
|
|
|
{ |
|
|
|
|
|
|
|
((int16_t*)sound.tempbuffer)[i*2+0] = data[((int)j)*2+0] * 256; |
|
|
|
|
|
|
|
((int16_t*)sound.tempbuffer)[i*2+1] = data[((int)j)*2+1] * 256; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
sample = (int)((char)(data[srcsample*2+0])) << 8; |
|
|
|
for( i = 0, j = 0; i < outcount; i++, j += stepscale ) |
|
|
|
sample2 = (int)((char)(data[srcsample*2+1])) << 8; |
|
|
|
((int16_t*)sound.tempbuffer)[i] = data[(int)j] * 256; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
handled = true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if( inwidth == 2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int16_t *data = (int16_t *)sc->buffer; |
|
|
|
|
|
|
|
|
|
|
|
if( outwidth == 2 ) |
|
|
|
if( outwidth == 1 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( sc->channels == 2 ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
((short *)sound.tempbuffer)[i*2+0] = sample; |
|
|
|
for( i = 0, j = 0; i < outcount; i++, j += stepscale ) |
|
|
|
((short *)sound.tempbuffer)[i*2+1] = sample2; |
|
|
|
{ |
|
|
|
|
|
|
|
((int8_t*)sound.tempbuffer)[i*2+0] = data[((int)j)*2+0] / 256; |
|
|
|
|
|
|
|
((int8_t*)sound.tempbuffer)[i*2+1] = data[((int)j)*2+1] / 256; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
((signed char *)sound.tempbuffer)[i*2+0] = sample >> 8; |
|
|
|
for( i = 0, j = 0; i < outcount; i++, j += stepscale ) |
|
|
|
((signed char *)sound.tempbuffer)[i*2+1] = sample2 >> 8; |
|
|
|
((int8_t*)sound.tempbuffer)[i] = data[(int)j] / 256; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
handled = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if( outwidth == 2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if( sc->channels == 2 ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for( i = 0, j = 0; i < outcount; i++, j += stepscale ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
((int16_t*)sound.tempbuffer)[i*2+0] = data[((int)j)*2+0]; |
|
|
|
|
|
|
|
((int16_t*)sound.tempbuffer)[i*2+1] = data[((int)j)*2+1]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
for( i = 0; i < outcount; i++ ) |
|
|
|
for( i = 0, j = 0; i < outcount; i++, j += stepscale ) |
|
|
|
{ |
|
|
|
((int16_t*)sound.tempbuffer)[i] = data[(int)j]; |
|
|
|
srcsample = samplefrac >> 8; |
|
|
|
} |
|
|
|
samplefrac += fracstep; |
|
|
|
handled = true; |
|
|
|
|
|
|
|
} |
|
|
|
if( inwidth == 2 ) sample = ((short *)data)[srcsample]; |
|
|
|
|
|
|
|
else sample = (int)( (char)(data[srcsample])) << 8; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( outwidth == 2 ) ((short *)sound.tempbuffer)[i] = sample; |
|
|
|
|
|
|
|
else ((signed char *)sound.tempbuffer)[i] = sample >> 8; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( handled ) |
|
|
|
Con_Reportf( "Sound_Resample: from [%d bit %d Hz] to [%d bit %d Hz]\n", inwidth * 8, inrate, outwidth * 8, outrate ); |
|
|
|
Con_Reportf( "Sound_Resample: from [%d bit %d Hz] to [%d bit %d Hz]\n", inwidth * 8, inrate, outwidth * 8, outrate ); |
|
|
|
} |
|
|
|
else |
|
|
|
|
|
|
|
Con_Reportf( S_ERROR "Sound_Resample: unsupported from [%d bit %d Hz] to [%d bit %d Hz]\n", inwidth * 8, inrate, outwidth * 8, outrate ); |
|
|
|
|
|
|
|
|
|
|
|
sc->rate = outrate; |
|
|
|
sc->rate = outrate; |
|
|
|
sc->width = outwidth; |
|
|
|
sc->width = outwidth; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return handled; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags ) |
|
|
|
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags ) |
|
|
|