mirror of
https://github.com/xiph/opus.git
synced 2025-05-31 15:47:43 +00:00

The SILK bitstream allowed coding 0 pulses in a shell block, but a non-zero number of LSb's, meaning some excitation coefficients could be non-zero, but would not have a corresponding sign. To fix this without breaking already-encoded bitstreams, this patch adds a set of sign PDFs for the 0 pulses case. This is occasionally more efficient than the normal encoding if there are a large number of coefficients with positive signs, since these cost more than 1 bit when using the > 0 pulse PDFs. It only saves 0.33 bits per second (on average: it does better at high rates), but that's probably enough to justify the two redundant ways of coding things (and it's too late now to remove the second one entirely, anyway). This patch does not include the encoder modifications required to check if this coding method is more efficient and switch to it.
115 lines
5.5 KiB
C
115 lines
5.5 KiB
C
/***********************************************************************
|
|
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, (subject to the limitations in the disclaimer below)
|
|
are permitted provided that the following conditions are met:
|
|
- Redistributions of source code must retain the above copyright notice,
|
|
this list of conditions and the following disclaimer.
|
|
- Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
- Neither the name of Skype Limited, nor the names of specific
|
|
contributors, may be used to endorse or promote products derived from
|
|
this software without specific prior written permission.
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
***********************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "main.h"
|
|
|
|
/*********************************************/
|
|
/* Decode quantization indices of excitation */
|
|
/*********************************************/
|
|
void silk_decode_pulses(
|
|
ec_dec *psRangeDec, /* I/O Compressor data structure */
|
|
opus_int pulses[], /* O Excitation signal */
|
|
const opus_int signalType, /* I Sigtype */
|
|
const opus_int quantOffsetType, /* I quantOffsetType */
|
|
const opus_int frame_length /* I Frame length */
|
|
)
|
|
{
|
|
opus_int i, j, k, iter, abs_q, nLS, RateLevelIndex;
|
|
opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ];
|
|
opus_int *pulses_ptr;
|
|
const opus_uint8 *cdf_ptr;
|
|
|
|
/*********************/
|
|
/* Decode rate level */
|
|
/*********************/
|
|
RateLevelIndex = ec_dec_icdf( psRangeDec, silk_rate_levels_iCDF[ signalType >> 1 ], 8 );
|
|
|
|
/* Calculate number of shell blocks */
|
|
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
|
|
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
|
|
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ){
|
|
silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
|
|
iter++;
|
|
}
|
|
|
|
/***************************************************/
|
|
/* Sum-Weighted-Pulses Decoding */
|
|
/***************************************************/
|
|
cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ];
|
|
for( i = 0; i < iter; i++ ) {
|
|
nLshifts[ i ] = 0;
|
|
sum_pulses[ i ] = ec_dec_icdf( psRangeDec, cdf_ptr, 8 );
|
|
|
|
/* LSB indication */
|
|
while( sum_pulses[ i ] == MAX_PULSES + 1 ) {
|
|
nLshifts[ i ]++;
|
|
/* When we've already got 10 LSBs, we shift the table to not allow (MAX_PULSES + 1) */
|
|
sum_pulses[ i ] = ec_dec_icdf( psRangeDec,
|
|
silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1] + (nLshifts[ i ]==10), 8 );
|
|
}
|
|
}
|
|
|
|
/***************************************************/
|
|
/* Shell decoding */
|
|
/***************************************************/
|
|
for( i = 0; i < iter; i++ ) {
|
|
if( sum_pulses[ i ] > 0 ) {
|
|
silk_shell_decoder( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRangeDec, sum_pulses[ i ] );
|
|
} else {
|
|
silk_memset( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( opus_int ) );
|
|
}
|
|
}
|
|
|
|
/***************************************************/
|
|
/* LSB Decoding */
|
|
/***************************************************/
|
|
for( i = 0; i < iter; i++ ) {
|
|
if( nLshifts[ i ] > 0 ) {
|
|
nLS = nLshifts[ i ];
|
|
pulses_ptr = &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ];
|
|
for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
|
|
abs_q = pulses_ptr[ k ];
|
|
for( j = 0; j < nLS; j++ ) {
|
|
abs_q = silk_LSHIFT( abs_q, 1 );
|
|
abs_q += ec_dec_icdf( psRangeDec, silk_lsb_iCDF, 8 );
|
|
}
|
|
pulses_ptr[ k ] = abs_q;
|
|
}
|
|
/* Mark the number of pulses non-zero for sign decoding. */
|
|
sum_pulses[ i ] |= nLS << 5;
|
|
}
|
|
}
|
|
|
|
/****************************************/
|
|
/* Decode and add signs to pulse signal */
|
|
/****************************************/
|
|
silk_decode_signs( psRangeDec, pulses, frame_length, signalType, quantOffsetType, sum_pulses );
|
|
}
|