Fixed problems in the ADPCM decoder. Sound is working.

This commit is contained in:
Robert Beckebans 2013-01-05 19:00:22 +01:00
parent 27b83db50d
commit 699e0e39f5
2 changed files with 65 additions and 52 deletions

View file

@ -1008,7 +1008,7 @@ ALenum idSoundSample_OpenAL::GetOpenALBufferFormat() const
return alFormat; 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 max_audioval = ( ( 1 << ( 16 - 1 ) ) - 1 );
const int32 min_audioval = -( 1 << ( 16 - 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, 230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230 768, 614, 512, 409, 307, 230, 230, 230
}; };
int32 new_sample, delta; int32 new_sample, delta;
new_sample = ( ( state->iSamp1 * coeff[0] ) + new_sample = ( ( state->iSamp1 * state->coef1 ) +
( state->iSamp2 * coeff[1] ) ) / 256; ( state->iSamp2 * state->coef2 ) ) / 256;
if( nybble & 0x08 ) 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 ) 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; uint8* freeable, *encoded, *decoded;
int32 encoded_len, samplesleft; int32 encoded_len, samplesleft;
int8 nybble; int8 nybble;
bool stereo; int8 stereo;
int16* coeff[2];
int32 new_sample; int32 new_sample;
// Allocate the proper sized output buffer // 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; encoded = *audio_buf;
freeable = *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_len = ( encoded_len / format.basic.blockSize ) * format.extra.adpcm.samplesPerBlock * format.basic.numChannels * sizeof( int16 );
*audio_buf = ( uint8* ) Mem_Alloc( *audio_len, TAG_AUDIO ); *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; decoded = *audio_buf;
assert( format.basic.numChannels == 1 || format.basic.numChannels == 2 );
// Get ready... Go! // Get ready... Go!
stereo = ( format.basic.numChannels == 2 ); stereo = ( format.basic.numChannels == 2 ) ? 1 : 0;
//state[0] = &MS_ADPCM_state.state[0]; state[0] = &states[0];
//state[1] = &MS_ADPCM_state.state[stereo]; state[1] = &states[stereo];
while( encoded_len >= format.basic.blockSize ) while( encoded_len >= format.basic.blockSize )
{ {
// Grab the initial information for this block // 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 ) 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 ); encoded += sizeof( int16 );
if( stereo ) if( stereo )
{ {
state[1].iDelta = ( ( encoded[1] << 8 ) | encoded[0] ); state[1]->iDelta = ( ( encoded[1] << 8 ) | encoded[0] );
encoded += sizeof( int16 ); encoded += sizeof( int16 );
} }
state[0].iSamp1 = ( ( encoded[1] << 8 ) | encoded[0] );
encoded += sizeof( int16 ); state[0]->iSamp1 = ( ( encoded[1] << 8 ) | encoded[0] );
if( stereo ) encoded += sizeof( int16 );
{ if( stereo )
state[1].iSamp1 = ( ( encoded[1] << 8 ) | encoded[0] ); {
encoded += sizeof( int16 ); 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[0]->iSamp2 = ( ( encoded[1] << 8 ) | encoded[0] );
{ encoded += sizeof( int16 );
state[1].iSamp2 = ( ( encoded[1] << 8 ) | encoded[0] ); if( stereo )
{
state[1]->iSamp2 = ( ( encoded[1] << 8 ) | encoded[0] );
encoded += sizeof( int16 ); 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 // Store the two initial samples we start with
decoded[0] = state[0].iSamp2 & 0xFF; decoded[0] = state[0]->iSamp2 & 0xFF;
decoded[1] = state[0].iSamp2 >> 8; decoded[1] = ( state[0]->iSamp2 >> 8 ) & 0xFF;
decoded += 2; decoded += 2;
if( stereo ) if( stereo )
{ {
decoded[0] = state[1].iSamp2 & 0xFF; decoded[0] = state[1]->iSamp2 & 0xFF;
decoded[1] = state[1].iSamp2 >> 8; decoded[1] = ( state[1]->iSamp2 >> 8 ) & 0xFF;
decoded += 2; 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; decoded += 2;
if( stereo ) if( stereo )
{ {
decoded[0] = state[1].iSamp1 & 0xFF; decoded[0] = state[1]->iSamp1 & 0xFF;
decoded[1] = state[1].iSamp1 >> 8; decoded[1] = ( state[1]->iSamp1 >> 8 ) & 0xFF;
decoded += 2; decoded += 2;
} }
@ -1152,17 +1162,17 @@ int idSoundSample_OpenAL::MS_ADPCM_decode( uint8** audio_buf, uint32* audio_len
while( samplesleft > 0 ) while( samplesleft > 0 )
{ {
nybble = ( *encoded ) >> 4; 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; decoded[0] = new_sample & 0xFF;
new_sample >>= 8; decoded[1] = ( new_sample >> 8 ) & 0xFF;
decoded[1] = new_sample & 0xFF;
decoded += 2; decoded += 2;
nybble = ( *encoded ) & 0x0F; 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; decoded[0] = new_sample & 0xFF;
new_sample >>= 8; decoded[1] = ( new_sample >> 8 ) & 0xFF;
decoded[1] = new_sample & 0xFF;
decoded += 2; decoded += 2;
++encoded; ++encoded;

View file

@ -163,12 +163,15 @@ protected:
struct MS_ADPCM_decodeState_t struct MS_ADPCM_decodeState_t
{ {
uint8 hPredictor; uint8 hPredictor;
int16 coef1;
int16 coef2;
uint16 iDelta; uint16 iDelta;
int16 iSamp1; int16 iSamp1;
int16 iSamp2; 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 ); int MS_ADPCM_decode( uint8** audio_buf, uint32* audio_len );
struct sampleBuffer_t struct sampleBuffer_t