/* ================ ResampleSfx resample / decimate to the current source rate ================ */ static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboolean compressed ) { int outcount; int srcsample; float stepscale; int i; int sample, samplefrac, fracstep; int part; sndBuffer *chunk; stepscale = ( float ) inrate / dma.speed; // this is usually 0.5, 1, or 2 outcount = sfx->soundLength / stepscale; sfx->soundLength = outcount; samplefrac = 0; fracstep = stepscale * 256; chunk = sfx->soundData; for ( i = 0; i < outcount; i++ ) { srcsample = samplefrac >> 8; samplefrac += fracstep; if ( inwidth == 2 ) { sample = LittleShort( ( ( short * ) data ) [ srcsample ] ); } else { sample = ( int )( ( unsigned char )( data[ srcsample ] ) - 128 ) << 8; } part = ( i & ( SND_CHUNK_SIZE - 1 ) ); if ( part == 0 ) { sndBuffer *newchunk; newchunk = SND_malloc(); if ( chunk == NULL ) { sfx->soundData = newchunk; } else { chunk->next = newchunk; } chunk = newchunk; } chunk->sndChunk[ part ] = sample; } }
/* ================= S_DefaultSound ================= */ static void S_DefaultSound( sfx_t *sfx ) { int i; sfx->soundLength = 512; sfx->soundData = SND_malloc(); sfx->soundData->next = NULL; for ( i = 0 ; i < sfx->soundLength ; i++ ) { sfx->soundData->sndChunk[i] = i; } }
/* ==================== S_AdpcmEncodeSound ==================== */ void S_AdpcmEncodeSound(sfx_t *sfx, short *samples) { adpcm_state_t state; int inOffset; int count; int n; sndBuffer *newchunk, *chunk; byte *out; inOffset = 0; count = sfx->soundLength; state.index = 0; state.sample = samples[0]; chunk = NULL; while(count) { n = count; if(n > SND_CHUNK_SIZE_BYTE * 2) { n = SND_CHUNK_SIZE_BYTE * 2; } newchunk = SND_malloc(); if(sfx->soundData == NULL) { sfx->soundData = newchunk; } else { chunk->next = newchunk; } chunk = newchunk; // output the header chunk->adpcm.index = state.index; chunk->adpcm.sample = state.sample; out = (byte *)chunk->sndChunk; // encode the samples S_AdpcmEncode(samples + inOffset, (char *)out, n, &state); //DAJ added (char*) inOffset += n; count -= n; } }
/* ================ ResampleSfx resample / decimate to the current source rate ================ */ static int ResampleSfx( sfx_t *sfx, int channels, int inrate, int inwidth, int samples, byte *data, qboolean compressed ) { int outcount; int srcsample; float stepscale; int i, j; int sample, samplefrac, fracstep; int part; sndBuffer *chunk; stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 outcount = samples / stepscale; srcsample = 0; samplefrac = 0; fracstep = stepscale * 256 * channels; chunk = sfx->soundData; for (i=0 ; i<outcount ; i++) { srcsample += samplefrac >> 8; samplefrac &= 255; samplefrac += fracstep; for (j=0 ; j<channels ; j++) { if( inwidth == 2 ) { sample = ( ((short *)data)[srcsample+j] ); } else { sample = (int)( (unsigned char)(data[srcsample+j]) - 128) << 8; } part = (i*channels+j)&(SND_CHUNK_SIZE-1); if (part == 0) { sndBuffer *newchunk; newchunk = SND_malloc(); if (chunk == NULL) { sfx->soundData = newchunk; } else { chunk->next = newchunk; } chunk = newchunk; } chunk->sndChunk[part] = sample; } } return outcount; }
/* ================ ResampleSfx resample / decimate to the current source rate ================ */ static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboolean compressed ) { int outcount; int srcsample; float stepscale; int i; int sample, samplefrac, fracstep; int part; sndBuffer *chunk; stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 outcount = sfx->soundLength / stepscale; sfx->soundLength = outcount; samplefrac = 0; fracstep = stepscale * 256; chunk = sfx->soundData; #if defined RTCW_ET // Gordon: use the littleshort version only if we need to if (!rtcw::Endian::is_little()) { for ( i = 0 ; i < outcount ; i++ ) { srcsample = samplefrac >> 8; samplefrac += fracstep; if ( inwidth == 2 ) { sample = ( (short *)data )[srcsample]; } else { sample = (int)( ( unsigned char )( data[srcsample] ) - 128 ) << 8; } part = ( i & ( SND_CHUNK_SIZE - 1 ) ); if ( part == 0 ) { sndBuffer *newchunk; newchunk = SND_malloc(); if ( chunk == NULL ) { sfx->soundData = newchunk; } else { chunk->next = newchunk; } chunk = newchunk; } chunk->sndChunk[part] = sample; } } else { #endif // RTCW_XX for ( i = 0 ; i < outcount ; i++ )
/* ================ ResampleSfx resample / decimate to the current source rate ================ */ static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboolean compressed ) { int outcount; int srcsample; float stepscale; unsigned int i; int sample, samplefrac, fracstep; int part; sndBuffer *chunk; //slightly faster and better resample for that case if (inrate == 22050 && dma.speed == 44100) { sfx->soundLength = sfx->soundLength * 2; chunk = sfx->soundData; for ( i=0 ; i < sfx->soundLength ; i++) { if( inwidth == 2 ) { if ( (i&1)==0 ) sample = ((short *)data)[i/2]; else if ( i == (unsigned)(sfx->soundLength-1) ) sample = (((short *)data)[0] + ((short *)data)[i/2])/2; else sample = (((short *)data)[i/2] + ((short *)data)[(i/2)+1])/2; } else { sample = (int)( (unsigned char)(data[i/2]) - 128) << 8; } part = (i&(SND_CHUNK_SIZE-1)); if (part == 0) { sndBuffer *newchunk; newchunk = SND_malloc(); if (chunk == NULL) { sfx->soundData = newchunk; } else { chunk->next = newchunk; } chunk = newchunk; } chunk->sndChunk[part] = sample; } } else { stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 outcount = sfx->soundLength / stepscale; sfx->soundLength = outcount; samplefrac = 0; fracstep = stepscale * 256; chunk = sfx->soundData; for (i=0 ; i<outcount ; i++) { srcsample = samplefrac >> 8; samplefrac += fracstep; if( inwidth == 2 ) { sample = ( ((short *)data)[srcsample] ); } else { sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8; } part = (i&(SND_CHUNK_SIZE-1)); if (part == 0) { sndBuffer *newchunk; newchunk = SND_malloc(); if (chunk == NULL) { sfx->soundData = newchunk; } else { chunk->next = newchunk; } chunk = newchunk; } chunk->sndChunk[part] = sample; } } }
// a file has been loaded in memory, see if we want to keep it as MP3, else as normal WAV... // // return = qtrue if keeping as MP3 // // (note: the reason I pass in the unpacked size rather than working it out here is simply because I already have it) // qboolean MP3Stream_InitFromFile( sfx_t* sfx, byte *pbSrcData, int iSrcDatalen, const char *psSrcDataFilename, int iMP3UnPackedSize, qboolean bStereoDesired /* = qfalse */ ) { // first, make a decision based on size here as to whether or not it's worth it because of MP3 buffer space // making small files much bigger (and therefore best left as WAV)... // if (cv_MP3overhead && ( //iSrcDatalen + sizeof(MP3STREAM) + FUZZY_AMOUNT < iMP3UnPackedSize iSrcDatalen + cv_MP3overhead->value < iMP3UnPackedSize ) ) { // ok, let's keep it as MP3 then... // float fMaxVol = 128; // seems to be a reasonable typical default for maxvol (for lip synch). Naturally there's no #define I can use instead... MP3_ReadSpecialTagInfo(pbSrcData, iSrcDatalen, NULL, NULL, &fMaxVol ); // try and read a read maxvol from MP3 header // fill in some sfx_t fields... // // Q_strncpyz( sfx->name, psSrcDataFilename, sizeof(sfx->name) ); sfx->eSoundCompressionMethod = ct_MP3; sfx->fVolRange = fMaxVol; //sfx->width = 2; sfx->iSoundLengthInSamples = ((iMP3UnPackedSize / 2/*sfx->width*/) / (44100 / dma.speed)) / (bStereoDesired?2:1); // // alloc mem for data and store it (raw MP3 in this case)... // sfx->pSoundData = (short *) SND_malloc( iSrcDatalen, sfx ); memcpy( sfx->pSoundData, pbSrcData, iSrcDatalen ); // now init the low-level MP3 stuff... // MP3STREAM SFX_MP3Stream = {0}; // important to init to all zeroes! char *psError = C_MP3Stream_DecodeInit( &SFX_MP3Stream, /*sfx->data*/ /*sfx->soundData*/ pbSrcData, iSrcDatalen, dma.speed,//(s_khz->value == 44)?44100:(s_khz->value == 22)?22050:11025, 2/*sfx->width*/ * 8, bStereoDesired ); SFX_MP3Stream.pbSourceData = (byte *) sfx->pSoundData; if (psError) { // This should never happen, since any errors or problems with the MP3 file would have stopped us getting // to this whole function, but just in case... // Com_Printf(va(S_COLOR_YELLOW"File \"%s\": %s\n",psSrcDataFilename,psError)); // This will leave iSrcDatalen bytes on the hunk stack (since you can't dealloc that), but MP3 files are // usually small, and like I say, it should never happen. // // Strictly speaking, I should do a Z_Malloc above, then I could do a Z_Free if failed, else do a Hunk_Alloc // to copy the Z_Malloc data into, then Z_Free, but for something that shouldn't happen it seemed bad to // penalise the rest of the game with extra alloc demands. // return qfalse; } // success ( ...on a plate). // // make a copy of the filled-in stream struct and attach to the sfx_t struct... // sfx->pMP3StreamHeader = (MP3STREAM *) Z_Malloc( sizeof(MP3STREAM), TAG_SND_MP3STREAMHDR ); memcpy( sfx->pMP3StreamHeader, &SFX_MP3Stream, sizeof(MP3STREAM) ); // return qtrue; } return qfalse; }