2001-02-08 00:38:41 +00:00
/* libFLAC - Free Lossless Audio Codec library
2013-05-25 17:11:19 +10:00
* Copyright ( C ) 2000 - 2009 Josh Coalson
2014-11-24 22:07:15 +11:00
* Copyright ( C ) 2011 - 2014 Xiph . Org Foundation
2000-12-10 04:09:52 +00:00
*
2003-01-31 23:34:56 +00:00
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
2000-12-10 04:09:52 +00:00
*
2003-01-31 23:34:56 +00:00
* - Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
2000-12-10 04:09:52 +00:00
*
2003-01-31 23:34:56 +00:00
* - 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 the Xiph . org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission .
*
* 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 FOUNDATION 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 .
2000-12-10 04:09:52 +00:00
*/
2014-03-23 21:59:46 +11:00
# ifdef HAVE_CONFIG_H
2006-05-24 04:41:36 +00:00
# include <config.h>
# endif
2000-12-10 04:09:52 +00:00
# include <math.h>
2013-03-06 22:17:46 +11:00
2001-05-31 20:11:02 +00:00
# include "FLAC/assert.h"
2000-12-10 04:09:52 +00:00
# include "FLAC/format.h"
2013-03-06 22:17:46 +11:00
# include "share/compat.h"
2002-10-04 05:25:54 +00:00
# include "private/bitmath.h"
2000-12-10 04:09:52 +00:00
# include "private/lpc.h"
2012-04-07 19:24:21 -03:00
# include "private/macros.h"
2002-05-17 06:19:28 +00:00
# if defined DEBUG || defined FLAC__OVERFLOW_DETECT || defined FLAC__OVERFLOW_DETECT_VERBOSE
# include <stdio.h>
# endif
2000-12-10 04:09:52 +00:00
2009-01-07 07:03:17 +00:00
/* OPT: #undef'ing this may improve the speed on some architectures */
# define FLAC__LPC_UNROLLED_FILTER_LOOPS
2004-11-09 01:34:01 +00:00
# ifndef FLAC__INTEGER_ONLY_LIBRARY
2012-04-07 19:24:21 -03:00
# if !defined(HAVE_LROUND)
# if defined(_MSC_VER)
# include <float.h>
# define copysign _copysign
# elif defined(__GNUC__)
# define copysign __builtin_copysign
# endif
2013-01-03 06:25:21 +11:00
static inline long int lround ( double x ) {
2012-04-07 19:24:21 -03:00
return ( long ) ( x + copysign ( 0.5 , x ) ) ;
}
2014-06-28 09:10:28 +10:00
/* If this fails, we are in the presence of a mid 90's compiler, move along... */
2012-04-07 19:24:21 -03:00
# endif
2007-07-11 04:15:18 +00:00
2007-04-04 00:59:28 +00:00
void FLAC__lpc_window_data ( const FLAC__int32 in [ ] , const FLAC__real window [ ] , FLAC__real out [ ] , unsigned data_len )
2006-04-25 06:38:43 +00:00
{
unsigned i ;
for ( i = 0 ; i < data_len ; i + + )
out [ i ] = in [ i ] * window [ i ] ;
}
2001-06-23 03:03:24 +00:00
void FLAC__lpc_compute_autocorrelation ( const FLAC__real data [ ] , unsigned data_len , unsigned lag , FLAC__real autoc [ ] )
2000-12-10 04:09:52 +00:00
{
2001-05-10 19:29:41 +00:00
/* a readable, but slower, version */
#if 0
2001-06-23 03:03:24 +00:00
FLAC__real d ;
2000-12-10 04:09:52 +00:00
unsigned i ;
2001-05-31 20:11:02 +00:00
FLAC__ASSERT ( lag > 0 ) ;
FLAC__ASSERT ( lag < = data_len ) ;
2000-12-10 04:09:52 +00:00
2006-04-28 00:11:31 +00:00
/*
* Technically we should subtract the mean first like so :
* for ( i = 0 ; i < data_len ; i + + )
* data [ i ] - = mean ;
* but it appears not to make enough of a difference to matter , and
* most signals are already closely centered around zero
*/
2000-12-10 04:09:52 +00:00
while ( lag - - ) {
for ( i = lag , d = 0.0 ; i < data_len ; i + + )
d + = data [ i ] * data [ i - lag ] ;
autoc [ lag ] = d ;
}
2001-05-10 19:29:41 +00:00
# endif
/*
* this version tends to run faster because of better data locality
* ( ' data_len ' is usually much larger than ' lag ' )
*/
2014-03-23 19:58:44 +11:00
FLAC__real d ;
2001-05-10 19:29:41 +00:00
unsigned sample , coeff ;
const unsigned limit = data_len - lag ;
2001-05-31 20:11:02 +00:00
FLAC__ASSERT ( lag > 0 ) ;
FLAC__ASSERT ( lag < = data_len ) ;
2001-05-10 19:29:41 +00:00
for ( coeff = 0 ; coeff < lag ; coeff + + )
autoc [ coeff ] = 0.0 ;
2001-05-16 19:23:35 +00:00
for ( sample = 0 ; sample < = limit ; sample + + ) {
2001-05-10 19:29:41 +00:00
d = data [ sample ] ;
2014-03-23 19:58:44 +11:00
for ( coeff = 0 ; coeff < lag ; coeff + + )
autoc [ coeff ] + = d * data [ sample + coeff ] ;
2001-05-10 19:29:41 +00:00
}
2001-05-16 19:23:35 +00:00
for ( ; sample < data_len ; sample + + ) {
2001-05-10 19:29:41 +00:00
d = data [ sample ] ;
2014-03-23 19:58:44 +11:00
for ( coeff = 0 ; coeff < data_len - sample ; coeff + + )
autoc [ coeff ] + = d * data [ sample + coeff ] ;
2001-05-10 19:29:41 +00:00
}
2000-12-10 04:09:52 +00:00
}
2006-11-27 16:27:41 +00:00
void FLAC__lpc_compute_lp_coefficients ( const FLAC__real autoc [ ] , unsigned * max_order , FLAC__real lp_coeff [ ] [ FLAC__MAX_LPC_ORDER ] , FLAC__double error [ ] )
2000-12-10 04:09:52 +00:00
{
unsigned i , j ;
2012-02-01 19:58:09 +11:00
FLAC__double r , err , lpc [ FLAC__MAX_LPC_ORDER ] ;
2000-12-10 04:09:52 +00:00
2006-11-27 16:27:41 +00:00
FLAC__ASSERT ( 0 ! = max_order ) ;
FLAC__ASSERT ( 0 < * max_order ) ;
FLAC__ASSERT ( * max_order < = FLAC__MAX_LPC_ORDER ) ;
2001-05-31 20:11:02 +00:00
FLAC__ASSERT ( autoc [ 0 ] ! = 0.0 ) ;
2000-12-10 04:09:52 +00:00
err = autoc [ 0 ] ;
2006-11-27 16:27:41 +00:00
for ( i = 0 ; i < * max_order ; i + + ) {
2000-12-10 04:09:52 +00:00
/* Sum up this iteration's reflection coefficient. */
2001-05-24 19:27:08 +00:00
r = - autoc [ i + 1 ] ;
2000-12-10 04:09:52 +00:00
for ( j = 0 ; j < i ; j + + )
r - = lpc [ j ] * autoc [ i - j ] ;
2012-10-12 22:02:49 +11:00
r / = err ;
2000-12-10 04:09:52 +00:00
/* Update LPC coefficients and total error. */
lpc [ i ] = r ;
for ( j = 0 ; j < ( i > > 1 ) ; j + + ) {
2004-10-20 00:21:50 +00:00
FLAC__double tmp = lpc [ j ] ;
2000-12-10 04:09:52 +00:00
lpc [ j ] + = r * lpc [ i - 1 - j ] ;
lpc [ i - 1 - j ] + = r * tmp ;
}
if ( i & 1 )
lpc [ j ] + = lpc [ j ] * r ;
err * = ( 1.0 - r * r ) ;
/* save this order */
for ( j = 0 ; j < = i ; j + + )
2001-07-03 04:37:18 +00:00
lp_coeff [ i ] [ j ] = ( FLAC__real ) ( - lpc [ j ] ) ; /* negate FIR filter coeff to get predictor coeff */
2004-10-20 00:21:50 +00:00
error [ i ] = err ;
2006-11-27 16:27:41 +00:00
2014-06-28 09:12:06 +10:00
/* see SF bug https://sourceforge.net/p/flac/bugs/234/ */
2006-11-27 16:27:41 +00:00
if ( err = = 0.0 ) {
* max_order = i + 1 ;
return ;
}
2000-12-10 04:09:52 +00:00
}
}
2002-10-04 05:25:54 +00:00
int FLAC__lpc_quantize_coefficients ( const FLAC__real lp_coeff [ ] , unsigned order , unsigned precision , FLAC__int32 qlp_coeff [ ] , int * shift )
2000-12-10 04:09:52 +00:00
{
unsigned i ;
2007-02-02 06:14:41 +00:00
FLAC__double cmax ;
2001-07-03 04:10:21 +00:00
FLAC__int32 qmax , qmin ;
2001-02-28 23:56:03 +00:00
2001-05-31 20:11:02 +00:00
FLAC__ASSERT ( precision > 0 ) ;
FLAC__ASSERT ( precision > = FLAC__MIN_QLP_COEFF_PRECISION ) ;
2001-02-28 23:56:03 +00:00
/* drop one bit for the sign; from here on out we consider only |lp_coeff[i]| */
precision - - ;
2001-07-03 04:10:21 +00:00
qmax = 1 < < precision ;
qmin = - qmax ;
qmax - - ;
2001-02-28 23:56:03 +00:00
2007-02-02 06:14:41 +00:00
/* calc cmax = max( |lp_coeff[i]| ) */
cmax = 0.0 ;
2001-02-28 23:56:03 +00:00
for ( i = 0 ; i < order ; i + + ) {
2007-02-02 06:14:41 +00:00
const FLAC__double d = fabs ( lp_coeff [ i ] ) ;
2001-02-28 23:56:03 +00:00
if ( d > cmax )
cmax = d ;
}
2007-02-02 06:14:41 +00:00
2001-07-18 23:47:19 +00:00
if ( cmax < = 0.0 ) {
2001-03-01 19:14:05 +00:00
/* => coefficients are all 0, which means our constant-detect didn't work */
2001-02-28 23:56:03 +00:00
return 2 ;
}
else {
2007-02-02 06:14:41 +00:00
const int max_shiftlimit = ( 1 < < ( FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN - 1 ) ) - 1 ;
const int min_shiftlimit = - max_shiftlimit - 1 ;
2001-07-19 17:07:13 +00:00
int log2cmax ;
2001-02-28 23:56:03 +00:00
2002-08-27 05:46:11 +00:00
( void ) frexp ( cmax , & log2cmax ) ;
2001-07-19 17:07:13 +00:00
log2cmax - - ;
* shift = ( int ) precision - log2cmax - 1 ;
2001-02-28 23:56:03 +00:00
2007-02-04 04:18:55 +00:00
if ( * shift > max_shiftlimit )
* shift = max_shiftlimit ;
else if ( * shift < min_shiftlimit )
return 1 ;
2001-02-28 23:56:03 +00:00
}
2001-07-06 00:37:57 +00:00
if ( * shift > = 0 ) {
2007-02-02 06:14:41 +00:00
FLAC__double error = 0.0 ;
FLAC__int32 q ;
2001-07-06 00:37:57 +00:00
for ( i = 0 ; i < order ; i + + ) {
2007-02-02 06:14:41 +00:00
error + = lp_coeff [ i ] * ( 1 < < * shift ) ;
2007-02-09 16:12:20 +00:00
q = lround ( error ) ;
2012-04-07 19:24:21 -03:00
2001-07-03 04:10:21 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2007-02-09 16:12:20 +00:00
if ( q > qmax + 1 ) /* we expect q==qmax+1 occasionally due to rounding */
2007-02-02 06:14:41 +00:00
fprintf ( stderr , " FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f \n " , q , qmax , * shift , cmax , precision + 1 , i , lp_coeff [ i ] ) ;
else if ( q < qmin )
fprintf ( stderr , " FLAC__lpc_quantize_coefficients: quantizer overflow: q<qmin %d<%d shift=%d cmax=%f precision=%u lpc[%u]=%f \n " , q , qmin , * shift , cmax , precision + 1 , i , lp_coeff [ i ] ) ;
2001-07-03 04:10:21 +00:00
# endif
2007-02-02 06:14:41 +00:00
if ( q > qmax )
q = qmax ;
else if ( q < qmin )
q = qmin ;
error - = q ;
qlp_coeff [ i ] = q ;
2001-07-03 04:10:21 +00:00
}
2001-07-06 00:37:57 +00:00
}
2007-02-02 06:14:41 +00:00
/* negative shift is very rare but due to design flaw, negative shift is
* a NOP in the decoder , so it must be handled specially by scaling down
* coeffs
*/
else {
2001-07-06 00:37:57 +00:00
const int nshift = - ( * shift ) ;
2007-02-02 06:14:41 +00:00
FLAC__double error = 0.0 ;
FLAC__int32 q ;
2001-07-12 21:27:40 +00:00
# ifdef DEBUG
2007-02-03 02:53:29 +00:00
fprintf ( stderr , " FLAC__lpc_quantize_coefficients: negative shift=%d order=%u cmax=%f \n " , * shift , order , cmax ) ;
2001-07-12 21:27:40 +00:00
# endif
2001-07-06 00:37:57 +00:00
for ( i = 0 ; i < order ; i + + ) {
2007-02-02 06:14:41 +00:00
error + = lp_coeff [ i ] / ( 1 < < nshift ) ;
2007-02-09 16:12:20 +00:00
q = lround ( error ) ;
2001-07-03 04:10:21 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2007-02-09 16:12:20 +00:00
if ( q > qmax + 1 ) /* we expect q==qmax+1 occasionally due to rounding */
2007-02-02 06:14:41 +00:00
fprintf ( stderr , " FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f \n " , q , qmax , * shift , cmax , precision + 1 , i , lp_coeff [ i ] ) ;
else if ( q < qmin )
fprintf ( stderr , " FLAC__lpc_quantize_coefficients: quantizer overflow: q<qmin %d<%d shift=%d cmax=%f precision=%u lpc[%u]=%f \n " , q , qmin , * shift , cmax , precision + 1 , i , lp_coeff [ i ] ) ;
2001-07-03 04:10:21 +00:00
# endif
2007-02-02 06:14:41 +00:00
if ( q > qmax )
q = qmax ;
else if ( q < qmin )
q = qmin ;
error - = q ;
qlp_coeff [ i ] = q ;
2001-07-03 04:10:21 +00:00
}
2007-02-02 06:14:41 +00:00
* shift = 0 ;
2000-12-10 04:09:52 +00:00
}
2001-07-06 00:37:57 +00:00
2000-12-10 04:09:52 +00:00
return 0 ;
}
2014-04-11 06:18:47 +10:00
# if defined(_MSC_VER)
// silence MSVC warnings about __restrict modifier
# pragma warning ( disable : 4028 )
# endif
2013-10-10 18:24:19 +11:00
void FLAC__lpc_compute_residual_from_qlp_coefficients ( const FLAC__int32 * flac_restrict data , unsigned data_len , const FLAC__int32 * flac_restrict qlp_coeff , unsigned order , int lp_quantization , FLAC__int32 * flac_restrict residual )
2007-07-11 04:15:18 +00:00
# if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS)
2000-12-10 04:09:52 +00:00
{
2001-06-23 03:03:24 +00:00
FLAC__int64 sumo ;
2000-12-10 04:09:52 +00:00
unsigned i , j ;
2001-06-23 03:03:24 +00:00
FLAC__int32 sum ;
const FLAC__int32 * history ;
2000-12-10 04:09:52 +00:00
2001-04-24 22:54:07 +00:00
# ifdef FLAC__OVERFLOW_DETECT_VERBOSE
2000-12-10 04:09:52 +00:00
fprintf ( stderr , " FLAC__lpc_compute_residual_from_qlp_coefficients: data_len=%d, order=%u, lpq=%d " , data_len , order , lp_quantization ) ;
for ( i = 0 ; i < order ; i + + )
fprintf ( stderr , " , q[%u]=%d " , i , qlp_coeff [ i ] ) ;
fprintf ( stderr , " \n " ) ;
# endif
2001-05-31 20:11:02 +00:00
FLAC__ASSERT ( order > 0 ) ;
2000-12-10 04:09:52 +00:00
for ( i = 0 ; i < data_len ; i + + ) {
sumo = 0 ;
sum = 0 ;
history = data ;
for ( j = 0 ; j < order ; j + + ) {
sum + = qlp_coeff [ j ] * ( * ( - - history ) ) ;
2001-06-23 03:03:24 +00:00
sumo + = ( FLAC__int64 ) qlp_coeff [ j ] * ( FLAC__int64 ) ( * history ) ;
2012-02-01 21:46:35 +11:00
fprintf ( stderr , " FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=% " PRId64 " \n " , i , j , qlp_coeff [ j ] , * history , sumo ) ;
2000-12-10 04:09:52 +00:00
}
* ( residual + + ) = * ( data + + ) - ( sum > > lp_quantization ) ;
}
2001-02-08 00:26:45 +00:00
/* Here's a slower but clearer version:
2000-12-10 04:09:52 +00:00
for ( i = 0 ; i < data_len ; i + + ) {
sum = 0 ;
for ( j = 0 ; j < order ; j + + )
2001-02-08 00:26:45 +00:00
sum + = qlp_coeff [ j ] * data [ i - j - 1 ] ;
2000-12-10 04:09:52 +00:00
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
*/
}
2007-03-13 06:33:52 +00:00
# else /* fully unrolled version for normal use */
{
2007-06-14 06:21:44 +00:00
int i ;
2007-03-13 06:33:52 +00:00
FLAC__int32 sum ;
FLAC__ASSERT ( order > 0 ) ;
FLAC__ASSERT ( order < = 32 ) ;
/*
* We do unique versions up to 12 th order since that ' s the subset limit .
* Also they are roughly ordered to match frequency of occurrence to
* minimize branching .
*/
if ( order < = 12 ) {
if ( order > 8 ) {
if ( order > 10 ) {
if ( order = = 12 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 11 ] * data [ i - 12 ] ;
sum + = qlp_coeff [ 10 ] * data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
else { /* order == 11 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 10 ] * data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 10 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 9 ] * data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
else { /* order == 9 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
}
}
else if ( order > 4 ) {
if ( order > 6 ) {
if ( order = = 8 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
else { /* order == 7 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 6 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
else { /* order == 5 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
}
}
else {
if ( order > 2 ) {
if ( order = = 4 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
else { /* order == 3 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 2 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
else { /* order == 1 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + )
2007-03-13 06:33:52 +00:00
residual [ i ] = data [ i ] - ( ( qlp_coeff [ 0 ] * data [ i - 1 ] ) > > lp_quantization ) ;
}
}
}
}
else { /* order > 12 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
switch ( order ) {
case 32 : sum + = qlp_coeff [ 31 ] * data [ i - 32 ] ;
case 31 : sum + = qlp_coeff [ 30 ] * data [ i - 31 ] ;
case 30 : sum + = qlp_coeff [ 29 ] * data [ i - 30 ] ;
case 29 : sum + = qlp_coeff [ 28 ] * data [ i - 29 ] ;
case 28 : sum + = qlp_coeff [ 27 ] * data [ i - 28 ] ;
case 27 : sum + = qlp_coeff [ 26 ] * data [ i - 27 ] ;
case 26 : sum + = qlp_coeff [ 25 ] * data [ i - 26 ] ;
case 25 : sum + = qlp_coeff [ 24 ] * data [ i - 25 ] ;
case 24 : sum + = qlp_coeff [ 23 ] * data [ i - 24 ] ;
case 23 : sum + = qlp_coeff [ 22 ] * data [ i - 23 ] ;
case 22 : sum + = qlp_coeff [ 21 ] * data [ i - 22 ] ;
case 21 : sum + = qlp_coeff [ 20 ] * data [ i - 21 ] ;
case 20 : sum + = qlp_coeff [ 19 ] * data [ i - 20 ] ;
case 19 : sum + = qlp_coeff [ 18 ] * data [ i - 19 ] ;
case 18 : sum + = qlp_coeff [ 17 ] * data [ i - 18 ] ;
case 17 : sum + = qlp_coeff [ 16 ] * data [ i - 17 ] ;
case 16 : sum + = qlp_coeff [ 15 ] * data [ i - 16 ] ;
case 15 : sum + = qlp_coeff [ 14 ] * data [ i - 15 ] ;
case 14 : sum + = qlp_coeff [ 13 ] * data [ i - 14 ] ;
case 13 : sum + = qlp_coeff [ 12 ] * data [ i - 13 ] ;
sum + = qlp_coeff [ 11 ] * data [ i - 12 ] ;
sum + = qlp_coeff [ 10 ] * data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
}
residual [ i ] = data [ i ] - ( sum > > lp_quantization ) ;
}
}
}
# endif
2000-12-10 04:09:52 +00:00
2013-10-10 18:24:19 +11:00
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide ( const FLAC__int32 * flac_restrict data , unsigned data_len , const FLAC__int32 * flac_restrict qlp_coeff , unsigned order , int lp_quantization , FLAC__int32 * flac_restrict residual )
2007-07-11 04:15:18 +00:00
# if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS)
2002-10-04 05:25:54 +00:00
{
unsigned i , j ;
FLAC__int64 sum ;
const FLAC__int32 * history ;
# ifdef FLAC__OVERFLOW_DETECT_VERBOSE
fprintf ( stderr , " FLAC__lpc_compute_residual_from_qlp_coefficients_wide: data_len=%d, order=%u, lpq=%d " , data_len , order , lp_quantization ) ;
for ( i = 0 ; i < order ; i + + )
fprintf ( stderr , " , q[%u]=%d " , i , qlp_coeff [ i ] ) ;
fprintf ( stderr , " \n " ) ;
# endif
FLAC__ASSERT ( order > 0 ) ;
for ( i = 0 ; i < data_len ; i + + ) {
sum = 0 ;
history = data ;
for ( j = 0 ; j < order ; j + + )
sum + = ( FLAC__int64 ) qlp_coeff [ j ] * ( FLAC__int64 ) ( * ( - - history ) ) ;
if ( FLAC__bitmath_silog2_wide ( sum > > lp_quantization ) > 32 ) {
2012-02-01 21:46:35 +11:00
fprintf ( stderr , " FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=% " PRId64 " \n " , i , ( sum > > lp_quantization ) ) ;
2002-10-04 05:25:54 +00:00
break ;
}
if ( FLAC__bitmath_silog2_wide ( ( FLAC__int64 ) ( * data ) - ( sum > > lp_quantization ) ) > 32 ) {
2013-09-15 10:22:01 +10:00
fprintf ( stderr , " FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=% " PRId64 " , residual=% " PRId64 " \n " , i , * data , ( int64_t ) ( sum > > lp_quantization ) , ( ( FLAC__int64 ) ( * data ) - ( sum > > lp_quantization ) ) ) ;
2002-10-04 05:25:54 +00:00
break ;
}
* ( residual + + ) = * ( data + + ) - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
2007-03-13 06:33:52 +00:00
# else /* fully unrolled version for normal use */
{
2007-09-08 22:28:09 +00:00
int i ;
2007-03-13 06:33:52 +00:00
FLAC__int64 sum ;
FLAC__ASSERT ( order > 0 ) ;
FLAC__ASSERT ( order < = 32 ) ;
/*
* We do unique versions up to 12 th order since that ' s the subset limit .
* Also they are roughly ordered to match frequency of occurrence to
* minimize branching .
*/
if ( order < = 12 ) {
if ( order > 8 ) {
if ( order > 10 ) {
if ( order = = 12 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 11 ] * ( FLAC__int64 ) data [ i - 12 ] ;
sum + = qlp_coeff [ 10 ] * ( FLAC__int64 ) data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * ( FLAC__int64 ) data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 11 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 10 ] * ( FLAC__int64 ) data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * ( FLAC__int64 ) data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 10 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 9 ] * ( FLAC__int64 ) data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 9 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
}
else if ( order > 4 ) {
if ( order > 6 ) {
if ( order = = 8 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 7 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 6 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 5 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
}
else {
if ( order > 2 ) {
if ( order = = 4 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 3 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 2 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 1 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + )
2007-03-13 06:33:52 +00:00
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( ( qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ) > > lp_quantization ) ;
}
}
}
}
else { /* order > 12 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
switch ( order ) {
case 32 : sum + = qlp_coeff [ 31 ] * ( FLAC__int64 ) data [ i - 32 ] ;
case 31 : sum + = qlp_coeff [ 30 ] * ( FLAC__int64 ) data [ i - 31 ] ;
case 30 : sum + = qlp_coeff [ 29 ] * ( FLAC__int64 ) data [ i - 30 ] ;
case 29 : sum + = qlp_coeff [ 28 ] * ( FLAC__int64 ) data [ i - 29 ] ;
case 28 : sum + = qlp_coeff [ 27 ] * ( FLAC__int64 ) data [ i - 28 ] ;
case 27 : sum + = qlp_coeff [ 26 ] * ( FLAC__int64 ) data [ i - 27 ] ;
case 26 : sum + = qlp_coeff [ 25 ] * ( FLAC__int64 ) data [ i - 26 ] ;
case 25 : sum + = qlp_coeff [ 24 ] * ( FLAC__int64 ) data [ i - 25 ] ;
case 24 : sum + = qlp_coeff [ 23 ] * ( FLAC__int64 ) data [ i - 24 ] ;
case 23 : sum + = qlp_coeff [ 22 ] * ( FLAC__int64 ) data [ i - 23 ] ;
case 22 : sum + = qlp_coeff [ 21 ] * ( FLAC__int64 ) data [ i - 22 ] ;
case 21 : sum + = qlp_coeff [ 20 ] * ( FLAC__int64 ) data [ i - 21 ] ;
case 20 : sum + = qlp_coeff [ 19 ] * ( FLAC__int64 ) data [ i - 20 ] ;
case 19 : sum + = qlp_coeff [ 18 ] * ( FLAC__int64 ) data [ i - 19 ] ;
case 18 : sum + = qlp_coeff [ 17 ] * ( FLAC__int64 ) data [ i - 18 ] ;
case 17 : sum + = qlp_coeff [ 16 ] * ( FLAC__int64 ) data [ i - 17 ] ;
case 16 : sum + = qlp_coeff [ 15 ] * ( FLAC__int64 ) data [ i - 16 ] ;
case 15 : sum + = qlp_coeff [ 14 ] * ( FLAC__int64 ) data [ i - 15 ] ;
case 14 : sum + = qlp_coeff [ 13 ] * ( FLAC__int64 ) data [ i - 14 ] ;
case 13 : sum + = qlp_coeff [ 12 ] * ( FLAC__int64 ) data [ i - 13 ] ;
sum + = qlp_coeff [ 11 ] * ( FLAC__int64 ) data [ i - 12 ] ;
sum + = qlp_coeff [ 10 ] * ( FLAC__int64 ) data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * ( FLAC__int64 ) data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
}
residual [ i ] = data [ i ] - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
# endif
2002-10-04 05:25:54 +00:00
2004-11-09 01:34:01 +00:00
# endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
2013-10-10 18:24:19 +11:00
void FLAC__lpc_restore_signal ( const FLAC__int32 * flac_restrict residual , unsigned data_len , const FLAC__int32 * flac_restrict qlp_coeff , unsigned order , int lp_quantization , FLAC__int32 * flac_restrict data )
2007-07-11 04:15:18 +00:00
# if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS)
2000-12-10 04:09:52 +00:00
{
2001-06-23 03:03:24 +00:00
FLAC__int64 sumo ;
2000-12-10 04:09:52 +00:00
unsigned i , j ;
2001-06-23 03:03:24 +00:00
FLAC__int32 sum ;
2006-11-20 07:19:15 +00:00
const FLAC__int32 * r = residual , * history ;
2000-12-10 04:09:52 +00:00
2001-04-24 22:54:07 +00:00
# ifdef FLAC__OVERFLOW_DETECT_VERBOSE
2000-12-10 04:09:52 +00:00
fprintf ( stderr , " FLAC__lpc_restore_signal: data_len=%d, order=%u, lpq=%d " , data_len , order , lp_quantization ) ;
for ( i = 0 ; i < order ; i + + )
fprintf ( stderr , " , q[%u]=%d " , i , qlp_coeff [ i ] ) ;
fprintf ( stderr , " \n " ) ;
# endif
2001-05-31 20:11:02 +00:00
FLAC__ASSERT ( order > 0 ) ;
2000-12-10 04:09:52 +00:00
for ( i = 0 ; i < data_len ; i + + ) {
sumo = 0 ;
sum = 0 ;
2001-02-08 00:26:45 +00:00
history = data ;
2000-12-10 04:09:52 +00:00
for ( j = 0 ; j < order ; j + + ) {
sum + = qlp_coeff [ j ] * ( * ( - - history ) ) ;
2001-06-23 03:03:24 +00:00
sumo + = ( FLAC__int64 ) qlp_coeff [ j ] * ( FLAC__int64 ) ( * history ) ;
2001-07-09 18:22:46 +00:00
if ( sumo > 2147483647ll | | sumo < - 2147483648ll )
2012-02-01 21:46:35 +11:00
fprintf ( stderr , " FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=% " PRId64 " \n " , i , j , qlp_coeff [ j ] , * history , sumo ) ;
2000-12-10 04:09:52 +00:00
}
2006-11-20 07:19:15 +00:00
* ( data + + ) = * ( r + + ) + ( sum > > lp_quantization ) ;
2001-02-08 00:26:45 +00:00
}
/* Here's a slower but clearer version:
for ( i = 0 ; i < data_len ; i + + ) {
sum = 0 ;
for ( j = 0 ; j < order ; j + + )
sum + = qlp_coeff [ j ] * data [ i - j - 1 ] ;
2000-12-10 04:09:52 +00:00
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
2001-02-08 00:26:45 +00:00
*/
2000-12-10 04:09:52 +00:00
}
2007-03-13 06:33:52 +00:00
# else /* fully unrolled version for normal use */
{
2007-06-14 06:21:44 +00:00
int i ;
2007-03-13 06:33:52 +00:00
FLAC__int32 sum ;
FLAC__ASSERT ( order > 0 ) ;
FLAC__ASSERT ( order < = 32 ) ;
/*
* We do unique versions up to 12 th order since that ' s the subset limit .
* Also they are roughly ordered to match frequency of occurrence to
* minimize branching .
*/
if ( order < = 12 ) {
if ( order > 8 ) {
if ( order > 10 ) {
if ( order = = 12 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 11 ] * data [ i - 12 ] ;
sum + = qlp_coeff [ 10 ] * data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
else { /* order == 11 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 10 ] * data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 10 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 9 ] * data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
else { /* order == 9 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
}
}
else if ( order > 4 ) {
if ( order > 6 ) {
if ( order = = 8 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
else { /* order == 7 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 6 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
else { /* order == 5 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
}
}
else {
if ( order > 2 ) {
if ( order = = 4 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
else { /* order == 3 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 2 ) {
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
else { /* order == 1 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + )
2007-03-13 06:33:52 +00:00
data [ i ] = residual [ i ] + ( ( qlp_coeff [ 0 ] * data [ i - 1 ] ) > > lp_quantization ) ;
}
}
}
}
else { /* order > 12 */
2007-06-14 06:21:44 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
switch ( order ) {
case 32 : sum + = qlp_coeff [ 31 ] * data [ i - 32 ] ;
case 31 : sum + = qlp_coeff [ 30 ] * data [ i - 31 ] ;
case 30 : sum + = qlp_coeff [ 29 ] * data [ i - 30 ] ;
case 29 : sum + = qlp_coeff [ 28 ] * data [ i - 29 ] ;
case 28 : sum + = qlp_coeff [ 27 ] * data [ i - 28 ] ;
case 27 : sum + = qlp_coeff [ 26 ] * data [ i - 27 ] ;
case 26 : sum + = qlp_coeff [ 25 ] * data [ i - 26 ] ;
case 25 : sum + = qlp_coeff [ 24 ] * data [ i - 25 ] ;
case 24 : sum + = qlp_coeff [ 23 ] * data [ i - 24 ] ;
case 23 : sum + = qlp_coeff [ 22 ] * data [ i - 23 ] ;
case 22 : sum + = qlp_coeff [ 21 ] * data [ i - 22 ] ;
case 21 : sum + = qlp_coeff [ 20 ] * data [ i - 21 ] ;
case 20 : sum + = qlp_coeff [ 19 ] * data [ i - 20 ] ;
case 19 : sum + = qlp_coeff [ 18 ] * data [ i - 19 ] ;
case 18 : sum + = qlp_coeff [ 17 ] * data [ i - 18 ] ;
case 17 : sum + = qlp_coeff [ 16 ] * data [ i - 17 ] ;
case 16 : sum + = qlp_coeff [ 15 ] * data [ i - 16 ] ;
case 15 : sum + = qlp_coeff [ 14 ] * data [ i - 15 ] ;
case 14 : sum + = qlp_coeff [ 13 ] * data [ i - 14 ] ;
case 13 : sum + = qlp_coeff [ 12 ] * data [ i - 13 ] ;
sum + = qlp_coeff [ 11 ] * data [ i - 12 ] ;
sum + = qlp_coeff [ 10 ] * data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * data [ i - 1 ] ;
}
data [ i ] = residual [ i ] + ( sum > > lp_quantization ) ;
}
}
}
# endif
2000-12-10 04:09:52 +00:00
2013-10-10 18:24:19 +11:00
void FLAC__lpc_restore_signal_wide ( const FLAC__int32 * flac_restrict residual , unsigned data_len , const FLAC__int32 * flac_restrict qlp_coeff , unsigned order , int lp_quantization , FLAC__int32 * flac_restrict data )
2007-07-11 04:15:18 +00:00
# if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS)
2002-10-04 05:25:54 +00:00
{
unsigned i , j ;
FLAC__int64 sum ;
2006-11-20 07:19:15 +00:00
const FLAC__int32 * r = residual , * history ;
2002-10-04 05:25:54 +00:00
# ifdef FLAC__OVERFLOW_DETECT_VERBOSE
fprintf ( stderr , " FLAC__lpc_restore_signal_wide: data_len=%d, order=%u, lpq=%d " , data_len , order , lp_quantization ) ;
for ( i = 0 ; i < order ; i + + )
fprintf ( stderr , " , q[%u]=%d " , i , qlp_coeff [ i ] ) ;
fprintf ( stderr , " \n " ) ;
# endif
FLAC__ASSERT ( order > 0 ) ;
for ( i = 0 ; i < data_len ; i + + ) {
sum = 0 ;
history = data ;
for ( j = 0 ; j < order ; j + + )
sum + = ( FLAC__int64 ) qlp_coeff [ j ] * ( FLAC__int64 ) ( * ( - - history ) ) ;
if ( FLAC__bitmath_silog2_wide ( sum > > lp_quantization ) > 32 ) {
2012-02-01 21:46:35 +11:00
fprintf ( stderr , " FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=% " PRId64 " \n " , i , ( sum > > lp_quantization ) ) ;
2002-10-04 05:25:54 +00:00
break ;
}
2006-11-20 07:19:15 +00:00
if ( FLAC__bitmath_silog2_wide ( ( FLAC__int64 ) ( * r ) + ( sum > > lp_quantization ) ) > 32 ) {
2012-02-01 21:46:35 +11:00
fprintf ( stderr , " FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=% " PRId64 " , data=% " PRId64 " \n " , i , * r , ( sum > > lp_quantization ) , ( ( FLAC__int64 ) ( * r ) + ( sum > > lp_quantization ) ) ) ;
2002-10-04 05:25:54 +00:00
break ;
}
2006-11-20 07:19:15 +00:00
* ( data + + ) = * ( r + + ) + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
2002-10-04 05:25:54 +00:00
}
}
2007-03-13 06:33:52 +00:00
# else /* fully unrolled version for normal use */
{
2007-09-08 22:28:09 +00:00
int i ;
2007-03-13 06:33:52 +00:00
FLAC__int64 sum ;
FLAC__ASSERT ( order > 0 ) ;
FLAC__ASSERT ( order < = 32 ) ;
/*
* We do unique versions up to 12 th order since that ' s the subset limit .
* Also they are roughly ordered to match frequency of occurrence to
* minimize branching .
*/
if ( order < = 12 ) {
if ( order > 8 ) {
if ( order > 10 ) {
if ( order = = 12 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 11 ] * ( FLAC__int64 ) data [ i - 12 ] ;
sum + = qlp_coeff [ 10 ] * ( FLAC__int64 ) data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * ( FLAC__int64 ) data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 11 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 10 ] * ( FLAC__int64 ) data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * ( FLAC__int64 ) data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 10 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 9 ] * ( FLAC__int64 ) data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 9 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
}
else if ( order > 4 ) {
if ( order > 6 ) {
if ( order = = 8 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 7 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 6 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 5 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
}
else {
if ( order > 2 ) {
if ( order = = 4 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 3 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
else {
if ( order = = 2 ) {
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
else { /* order == 1 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + )
2007-03-13 06:33:52 +00:00
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( ( qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ) > > lp_quantization ) ;
}
}
}
}
else { /* order > 12 */
2007-09-08 22:28:09 +00:00
for ( i = 0 ; i < ( int ) data_len ; i + + ) {
2007-03-13 06:33:52 +00:00
sum = 0 ;
switch ( order ) {
case 32 : sum + = qlp_coeff [ 31 ] * ( FLAC__int64 ) data [ i - 32 ] ;
case 31 : sum + = qlp_coeff [ 30 ] * ( FLAC__int64 ) data [ i - 31 ] ;
case 30 : sum + = qlp_coeff [ 29 ] * ( FLAC__int64 ) data [ i - 30 ] ;
case 29 : sum + = qlp_coeff [ 28 ] * ( FLAC__int64 ) data [ i - 29 ] ;
case 28 : sum + = qlp_coeff [ 27 ] * ( FLAC__int64 ) data [ i - 28 ] ;
case 27 : sum + = qlp_coeff [ 26 ] * ( FLAC__int64 ) data [ i - 27 ] ;
case 26 : sum + = qlp_coeff [ 25 ] * ( FLAC__int64 ) data [ i - 26 ] ;
case 25 : sum + = qlp_coeff [ 24 ] * ( FLAC__int64 ) data [ i - 25 ] ;
case 24 : sum + = qlp_coeff [ 23 ] * ( FLAC__int64 ) data [ i - 24 ] ;
case 23 : sum + = qlp_coeff [ 22 ] * ( FLAC__int64 ) data [ i - 23 ] ;
case 22 : sum + = qlp_coeff [ 21 ] * ( FLAC__int64 ) data [ i - 22 ] ;
case 21 : sum + = qlp_coeff [ 20 ] * ( FLAC__int64 ) data [ i - 21 ] ;
case 20 : sum + = qlp_coeff [ 19 ] * ( FLAC__int64 ) data [ i - 20 ] ;
case 19 : sum + = qlp_coeff [ 18 ] * ( FLAC__int64 ) data [ i - 19 ] ;
case 18 : sum + = qlp_coeff [ 17 ] * ( FLAC__int64 ) data [ i - 18 ] ;
case 17 : sum + = qlp_coeff [ 16 ] * ( FLAC__int64 ) data [ i - 17 ] ;
case 16 : sum + = qlp_coeff [ 15 ] * ( FLAC__int64 ) data [ i - 16 ] ;
case 15 : sum + = qlp_coeff [ 14 ] * ( FLAC__int64 ) data [ i - 15 ] ;
case 14 : sum + = qlp_coeff [ 13 ] * ( FLAC__int64 ) data [ i - 14 ] ;
case 13 : sum + = qlp_coeff [ 12 ] * ( FLAC__int64 ) data [ i - 13 ] ;
sum + = qlp_coeff [ 11 ] * ( FLAC__int64 ) data [ i - 12 ] ;
sum + = qlp_coeff [ 10 ] * ( FLAC__int64 ) data [ i - 11 ] ;
sum + = qlp_coeff [ 9 ] * ( FLAC__int64 ) data [ i - 10 ] ;
sum + = qlp_coeff [ 8 ] * ( FLAC__int64 ) data [ i - 9 ] ;
sum + = qlp_coeff [ 7 ] * ( FLAC__int64 ) data [ i - 8 ] ;
sum + = qlp_coeff [ 6 ] * ( FLAC__int64 ) data [ i - 7 ] ;
sum + = qlp_coeff [ 5 ] * ( FLAC__int64 ) data [ i - 6 ] ;
sum + = qlp_coeff [ 4 ] * ( FLAC__int64 ) data [ i - 5 ] ;
sum + = qlp_coeff [ 3 ] * ( FLAC__int64 ) data [ i - 4 ] ;
sum + = qlp_coeff [ 2 ] * ( FLAC__int64 ) data [ i - 3 ] ;
sum + = qlp_coeff [ 1 ] * ( FLAC__int64 ) data [ i - 2 ] ;
sum + = qlp_coeff [ 0 ] * ( FLAC__int64 ) data [ i - 1 ] ;
}
data [ i ] = residual [ i ] + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
}
# endif
2002-10-04 05:25:54 +00:00
2014-04-11 06:18:47 +10:00
# if defined(_MSC_VER)
# pragma warning ( default : 4028 )
# endif
2004-11-09 01:34:01 +00:00
# ifndef FLAC__INTEGER_ONLY_LIBRARY
2004-10-20 00:21:50 +00:00
FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample ( FLAC__double lpc_error , unsigned total_samples )
2000-12-10 04:09:52 +00:00
{
2004-10-20 00:21:50 +00:00
FLAC__double error_scale ;
2000-12-10 04:09:52 +00:00
2001-05-31 20:11:02 +00:00
FLAC__ASSERT ( total_samples > 0 ) ;
2000-12-10 04:09:52 +00:00
2004-10-20 00:21:50 +00:00
error_scale = 0.5 * M_LN2 * M_LN2 / ( FLAC__double ) total_samples ;
2000-12-10 04:09:52 +00:00
2002-06-05 05:53:17 +00:00
return FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale ( lpc_error , error_scale ) ;
2001-05-24 19:27:08 +00:00
}
2004-10-20 00:21:50 +00:00
FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale ( FLAC__double lpc_error , FLAC__double error_scale )
2001-05-24 19:27:08 +00:00
{
if ( lpc_error > 0.0 ) {
2004-10-20 00:21:50 +00:00
FLAC__double bps = ( FLAC__double ) 0.5 * log ( error_scale * lpc_error ) / M_LN2 ;
2001-05-24 19:27:08 +00:00
if ( bps > = 0.0 )
return bps ;
else
return 0.0 ;
}
2004-10-20 00:21:50 +00:00
else if ( lpc_error < 0.0 ) { /* error should not be negative but can happen due to inadequate floating-point resolution */
return 1e32 ;
2001-05-24 19:27:08 +00:00
}
2001-02-08 00:26:45 +00:00
else {
2000-12-10 04:09:52 +00:00
return 0.0 ;
2001-02-08 00:26:45 +00:00
}
2000-12-10 04:09:52 +00:00
}
2006-04-28 00:11:31 +00:00
unsigned FLAC__lpc_compute_best_order ( const FLAC__double lpc_error [ ] , unsigned max_order , unsigned total_samples , unsigned overhead_bits_per_order )
2000-12-10 04:09:52 +00:00
{
2013-04-05 20:21:22 +11:00
unsigned order , indx , best_index ; /* 'index' the index into lpc_error; index==order-1 since lpc_error[0] is for order==1, lpc_error[1] is for order==2, etc */
2006-04-28 00:11:31 +00:00
FLAC__double bits , best_bits , error_scale ;
2000-12-10 04:09:52 +00:00
2001-05-31 20:11:02 +00:00
FLAC__ASSERT ( max_order > 0 ) ;
FLAC__ASSERT ( total_samples > 0 ) ;
2001-05-24 19:27:08 +00:00
2004-10-20 00:21:50 +00:00
error_scale = 0.5 * M_LN2 * M_LN2 / ( FLAC__double ) total_samples ;
2000-12-10 04:09:52 +00:00
2006-04-28 00:11:31 +00:00
best_index = 0 ;
best_bits = ( unsigned ) ( - 1 ) ;
2000-12-10 04:09:52 +00:00
2013-04-05 20:21:22 +11:00
for ( indx = 0 , order = 1 ; indx < max_order ; indx + + , order + + ) {
bits = FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale ( lpc_error [ indx ] , error_scale ) * ( FLAC__double ) ( total_samples - order ) + ( FLAC__double ) ( order * overhead_bits_per_order ) ;
2006-04-28 00:11:31 +00:00
if ( bits < best_bits ) {
2013-04-05 20:21:22 +11:00
best_index = indx ;
2006-04-28 00:11:31 +00:00
best_bits = bits ;
2000-12-10 04:09:52 +00:00
}
}
2013-04-05 20:21:22 +11:00
return best_index + 1 ; /* +1 since indx of lpc_error[] is order-1 */
2000-12-10 04:09:52 +00:00
}
2004-11-09 01:34:01 +00:00
# endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */