From 699e0e39f5eae31160548fd4e3a8f3f9f722dbf7 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sat, 5 Jan 2013 19:00:22 +0100 Subject: [PATCH] Fixed problems in the ADPCM decoder. Sound is working. --- neo/sound/OpenAL/AL_SoundSample.cpp | 112 +++++++++++++++------------- neo/sound/OpenAL/AL_SoundSample.h | 5 +- 2 files changed, 65 insertions(+), 52 deletions(-) diff --git a/neo/sound/OpenAL/AL_SoundSample.cpp b/neo/sound/OpenAL/AL_SoundSample.cpp index f65b1402..d9758c25 100644 --- a/neo/sound/OpenAL/AL_SoundSample.cpp +++ b/neo/sound/OpenAL/AL_SoundSample.cpp @@ -1008,7 +1008,7 @@ ALenum idSoundSample_OpenAL::GetOpenALBufferFormat() const return alFormat; } -int32 idSoundSample_OpenAL::MS_ADPCM_nibble( MS_ADPCM_decodeState_t* state, int8 nybble, int16* coeff ) +int32 idSoundSample_OpenAL::MS_ADPCM_nibble( MS_ADPCM_decodeState_t* state, int8 nybble ) { const int32 max_audioval = ( ( 1 << ( 16 - 1 ) ) - 1 ); const int32 min_audioval = -( 1 << ( 16 - 1 ) ); @@ -1017,10 +1017,11 @@ int32 idSoundSample_OpenAL::MS_ADPCM_nibble( MS_ADPCM_decodeState_t* state, int8 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230 }; + int32 new_sample, delta; - new_sample = ( ( state->iSamp1 * coeff[0] ) + - ( state->iSamp2 * coeff[1] ) ) / 256; + new_sample = ( ( state->iSamp1 * state->coef1 ) + + ( state->iSamp2 * state->coef2 ) ) / 256; if( nybble & 0x08 ) { @@ -1055,12 +1056,13 @@ int32 idSoundSample_OpenAL::MS_ADPCM_nibble( MS_ADPCM_decodeState_t* state, int8 int idSoundSample_OpenAL::MS_ADPCM_decode( uint8** audio_buf, uint32* audio_len ) { - static MS_ADPCM_decodeState_t state[2]; + static MS_ADPCM_decodeState_t states[2]; + MS_ADPCM_decodeState_t* state[2]; + uint8* freeable, *encoded, *decoded; int32 encoded_len, samplesleft; int8 nybble; - bool stereo; - int16* coeff[2]; + int8 stereo; int32 new_sample; // Allocate the proper sized output buffer @@ -1068,12 +1070,6 @@ int idSoundSample_OpenAL::MS_ADPCM_decode( uint8** audio_buf, uint32* audio_len encoded = *audio_buf; freeable = *audio_buf; - /* - *audio_len = ( encoded_len / MS_ADPCM_state.wavefmt.blockalign ) * - MS_ADPCM_state.wSamplesPerBlock * - MS_ADPCM_state.wavefmt.channels * sizeof( int16 ); - */ - *audio_len = ( encoded_len / format.basic.blockSize ) * format.extra.adpcm.samplesPerBlock * format.basic.numChannels * sizeof( int16 ); *audio_buf = ( uint8* ) Mem_Alloc( *audio_len, TAG_AUDIO ); @@ -1084,65 +1080,79 @@ int idSoundSample_OpenAL::MS_ADPCM_decode( uint8** audio_buf, uint32* audio_len } decoded = *audio_buf; + assert( format.basic.numChannels == 1 || format.basic.numChannels == 2 ); + // Get ready... Go! - stereo = ( format.basic.numChannels == 2 ); - //state[0] = &MS_ADPCM_state.state[0]; - //state[1] = &MS_ADPCM_state.state[stereo]; + stereo = ( format.basic.numChannels == 2 ) ? 1 : 0; + state[0] = &states[0]; + state[1] = &states[stereo]; while( encoded_len >= format.basic.blockSize ) { // Grab the initial information for this block - state[0].hPredictor = *encoded++; + state[0]->hPredictor = *encoded++; + + assert( state[0]->hPredictor < format.extra.adpcm.numCoef ); + state[0]->hPredictor = idMath::ClampInt( 0, 6, state[0]->hPredictor ); + + state[0]->coef1 = format.extra.adpcm.aCoef[state[0]->hPredictor].coef1; + state[0]->coef2 = format.extra.adpcm.aCoef[state[0]->hPredictor].coef2; + if( stereo ) { - state[1].hPredictor = *encoded++; + state[1]->hPredictor = *encoded++; + + assert( state[1]->hPredictor < format.extra.adpcm.numCoef ); + state[1]->hPredictor = idMath::ClampInt( 0, 6, state[1]->hPredictor ); + + state[1]->coef1 = format.extra.adpcm.aCoef[state[1]->hPredictor].coef1; + state[1]->coef2 = format.extra.adpcm.aCoef[state[1]->hPredictor].coef2; } - state[0].iDelta = ( ( encoded[1] << 8 ) | encoded[0] ); + state[0]->iDelta = ( ( encoded[1] << 8 ) | encoded[0] ); encoded += sizeof( int16 ); if( stereo ) { - state[1].iDelta = ( ( encoded[1] << 8 ) | encoded[0] ); - encoded += sizeof( int16 ); - } - state[0].iSamp1 = ( ( encoded[1] << 8 ) | encoded[0] ); - encoded += sizeof( int16 ); - if( stereo ) - { - state[1].iSamp1 = ( ( encoded[1] << 8 ) | encoded[0] ); - encoded += sizeof( int16 ); - } - state[0].iSamp2 = ( ( encoded[1] << 8 ) | encoded[0] ); - encoded += sizeof( int16 ); - if( stereo ) - { - state[1].iSamp2 = ( ( encoded[1] << 8 ) | encoded[0] ); + state[1]->iDelta = ( ( encoded[1] << 8 ) | encoded[0] ); + encoded += sizeof( int16 ); + } + + state[0]->iSamp1 = ( ( encoded[1] << 8 ) | encoded[0] ); + encoded += sizeof( int16 ); + if( stereo ) + { + state[1]->iSamp1 = ( ( encoded[1] << 8 ) | encoded[0] ); + encoded += sizeof( int16 ); + } + + state[0]->iSamp2 = ( ( encoded[1] << 8 ) | encoded[0] ); + encoded += sizeof( int16 ); + if( stereo ) + { + state[1]->iSamp2 = ( ( encoded[1] << 8 ) | encoded[0] ); encoded += sizeof( int16 ); } - assert( state[0].hPredictor < format.extra.adpcm.numCoef ); - assert( state[1].hPredictor < format.extra.adpcm.numCoef ); - coeff[0] = &format.extra.adpcm.aCoef[state[0].hPredictor].coef1; - coeff[1] = &format.extra.adpcm.aCoef[state[1].hPredictor].coef2; // Store the two initial samples we start with - decoded[0] = state[0].iSamp2 & 0xFF; - decoded[1] = state[0].iSamp2 >> 8; + decoded[0] = state[0]->iSamp2 & 0xFF; + decoded[1] = ( state[0]->iSamp2 >> 8 ) & 0xFF; decoded += 2; if( stereo ) { - decoded[0] = state[1].iSamp2 & 0xFF; - decoded[1] = state[1].iSamp2 >> 8; + decoded[0] = state[1]->iSamp2 & 0xFF; + decoded[1] = ( state[1]->iSamp2 >> 8 ) & 0xFF; decoded += 2; } - decoded[0] = state[0].iSamp1 & 0xFF; - decoded[1] = state[0].iSamp1 >> 8; + + decoded[0] = state[0]->iSamp1 & 0xFF; + decoded[1] = ( state[0]->iSamp1 >> 8 ) & 0xFF; decoded += 2; if( stereo ) { - decoded[0] = state[1].iSamp1 & 0xFF; - decoded[1] = state[1].iSamp1 >> 8; + decoded[0] = state[1]->iSamp1 & 0xFF; + decoded[1] = ( state[1]->iSamp1 >> 8 ) & 0xFF; decoded += 2; } @@ -1152,17 +1162,17 @@ int idSoundSample_OpenAL::MS_ADPCM_decode( uint8** audio_buf, uint32* audio_len while( samplesleft > 0 ) { nybble = ( *encoded ) >> 4; - new_sample = MS_ADPCM_nibble( &state[0], nybble, coeff[0] ); + new_sample = MS_ADPCM_nibble( state[0], nybble ); + decoded[0] = new_sample & 0xFF; - new_sample >>= 8; - decoded[1] = new_sample & 0xFF; + decoded[1] = ( new_sample >> 8 ) & 0xFF; decoded += 2; nybble = ( *encoded ) & 0x0F; - new_sample = MS_ADPCM_nibble( &state[1], nybble, coeff[1] ); + new_sample = MS_ADPCM_nibble( state[1], nybble ); + decoded[0] = new_sample & 0xFF; - new_sample >>= 8; - decoded[1] = new_sample & 0xFF; + decoded[1] = ( new_sample >> 8 ) & 0xFF; decoded += 2; ++encoded; diff --git a/neo/sound/OpenAL/AL_SoundSample.h b/neo/sound/OpenAL/AL_SoundSample.h index 6174d34c..a64da4c9 100644 --- a/neo/sound/OpenAL/AL_SoundSample.h +++ b/neo/sound/OpenAL/AL_SoundSample.h @@ -163,12 +163,15 @@ protected: struct MS_ADPCM_decodeState_t { uint8 hPredictor; + int16 coef1; + int16 coef2; + uint16 iDelta; int16 iSamp1; int16 iSamp2; }; - int32 MS_ADPCM_nibble( MS_ADPCM_decodeState_t* state, int8 nybble, int16* coeff ); + int32 MS_ADPCM_nibble( MS_ADPCM_decodeState_t* state, int8 nybble ); int MS_ADPCM_decode( uint8** audio_buf, uint32* audio_len ); struct sampleBuffer_t