2001-02-08 00:38:41 +00:00
/* libFLAC - Free Lossless Audio Codec library
2006-04-25 06:59:33 +00:00
* Copyright ( C ) 2000 , 2001 , 2002 , 2003 , 2004 , 2005 , 2006 Josh Coalson
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
*/
2006-05-24 04:41:36 +00:00
# if HAVE_CONFIG_H
# include <config.h>
# endif
2000-12-10 04:09:52 +00:00
# include <math.h>
2001-05-31 20:11:02 +00:00
# include "FLAC/assert.h"
2000-12-10 04:09:52 +00:00
# include "FLAC/format.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"
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
2004-11-09 01:34:01 +00:00
# ifndef FLAC__INTEGER_ONLY_LIBRARY
2000-12-10 04:09:52 +00:00
# ifndef M_LN2
/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */
# define M_LN2 0.69314718055994530942
# endif
2006-04-25 06:38:43 +00:00
void FLAC__lpc_window_data ( const FLAC__real in [ ] , const FLAC__real window [ ] , FLAC__real out [ ] , unsigned data_len )
{
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 ' )
*/
2001-06-23 03:03:24 +00: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 ] ;
for ( coeff = 0 ; coeff < lag ; coeff + + )
autoc [ coeff ] + = d * data [ sample + coeff ] ;
}
2001-05-16 19:23:35 +00:00
for ( ; sample < data_len ; sample + + ) {
2001-05-10 19:29:41 +00:00
d = data [ sample ] ;
for ( coeff = 0 ; coeff < data_len - sample ; coeff + + )
autoc [ coeff ] + = d * data [ sample + coeff ] ;
}
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 ;
2004-10-20 00:21:50 +00:00
FLAC__double r , err , ref [ FLAC__MAX_LPC_ORDER ] , 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 ] ;
ref [ i ] = ( r / = err ) ;
/* 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
2007-01-28 17:37:55 +00:00
/* see SF bug #1601812 http://sourceforge.net/tracker/index.php?func=detail&aid=1601812&group_id=13478&atid=113478 */
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 ;
2004-10-20 00:21:50 +00:00
FLAC__double d , cmax = - 1e32 ;
2001-07-03 04:10:21 +00:00
FLAC__int32 qmax , qmin ;
const int max_shiftlimit = ( 1 < < ( FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN - 1 ) ) - 1 ;
const int min_shiftlimit = - max_shiftlimit - 1 ;
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
for ( i = 0 ; i < order ; i + + ) {
if ( lp_coeff [ i ] = = 0.0 )
continue ;
2001-08-13 23:10:06 +00:00
d = fabs ( lp_coeff [ i ] ) ;
2001-02-28 23:56:03 +00:00
if ( d > cmax )
cmax = d ;
}
2001-07-03 04:10:21 +00:00
redo_it :
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 {
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
if ( * shift < min_shiftlimit | | * shift > max_shiftlimit ) {
2002-10-04 05:25:54 +00:00
#if 0
/*@@@ this does not seem to help at all, but was not extensively tested either: */
if ( * shift > max_shiftlimit )
* shift = max_shiftlimit ;
else
# endif
return 1 ;
2001-02-28 23:56:03 +00:00
}
}
2001-07-06 00:37:57 +00:00
if ( * shift > = 0 ) {
for ( i = 0 ; i < order ; i + + ) {
2004-10-20 00:21:50 +00:00
qlp_coeff [ i ] = ( FLAC__int32 ) floor ( ( FLAC__double ) lp_coeff [ i ] * ( FLAC__double ) ( 1 < < * shift ) ) ;
2001-07-03 04:10:21 +00:00
2001-07-19 17:07:13 +00:00
/* double-check the result */
2001-07-06 00:37:57 +00:00
if ( qlp_coeff [ i ] > qmax | | qlp_coeff [ i ] < qmin ) {
2001-07-03 04:10:21 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2004-10-20 00:21:50 +00:00
fprintf ( stderr , " FLAC__lpc_quantize_coefficients: compensating for overflow, qlp_coeff[%u]=%d, lp_coeff[%u]=%f, cmax=%f, precision=%u, shift=%d, q=%f, f(q)=%f \n " , i , qlp_coeff [ i ] , i , lp_coeff [ i ] , cmax , precision , * shift , ( FLAC__double ) lp_coeff [ i ] * ( FLAC__double ) ( 1 < < * shift ) , floor ( ( FLAC__double ) lp_coeff [ i ] * ( FLAC__double ) ( 1 < < * shift ) ) ) ;
2001-07-03 04:10:21 +00:00
# endif
2001-07-06 00:37:57 +00:00
cmax * = 2.0 ;
goto redo_it ;
2001-07-03 04:10:21 +00:00
}
}
2001-07-06 00:37:57 +00:00
}
else { /* (*shift < 0) */
const int nshift = - ( * shift ) ;
2001-07-12 21:27:40 +00:00
# ifdef DEBUG
2001-07-06 00:37:57 +00:00
fprintf ( stderr , " FLAC__lpc_quantize_coefficients: negative shift = %d \n " , * shift ) ;
2001-07-12 21:27:40 +00:00
# endif
2001-07-06 00:37:57 +00:00
for ( i = 0 ; i < order ; i + + ) {
2004-10-20 00:21:50 +00:00
qlp_coeff [ i ] = ( FLAC__int32 ) floor ( ( FLAC__double ) lp_coeff [ i ] / ( FLAC__double ) ( 1 < < nshift ) ) ;
2001-07-06 00:37:57 +00:00
2001-07-19 17:07:13 +00:00
/* double-check the result */
2001-07-06 00:37:57 +00:00
if ( qlp_coeff [ i ] > qmax | | qlp_coeff [ i ] < qmin ) {
2001-07-03 04:10:21 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2004-10-20 00:21:50 +00:00
fprintf ( stderr , " FLAC__lpc_quantize_coefficients: compensating for overflow, qlp_coeff[%u]=%d, lp_coeff[%u]=%f, cmax=%f, precision=%u, shift=%d, q=%f, f(q)=%f \n " , i , qlp_coeff [ i ] , i , lp_coeff [ i ] , cmax , precision , * shift , ( FLAC__double ) lp_coeff [ i ] / ( FLAC__double ) ( 1 < < nshift ) , floor ( ( FLAC__double ) lp_coeff [ i ] / ( FLAC__double ) ( 1 < < nshift ) ) ) ;
2001-07-03 04:10:21 +00:00
# endif
2001-07-06 00:37:57 +00:00
cmax * = 2.0 ;
goto redo_it ;
2001-07-03 04:10:21 +00:00
}
}
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 ;
}
2005-01-26 04:04:38 +00:00
void FLAC__lpc_compute_residual_from_qlp_coefficients ( const FLAC__int32 * data , unsigned data_len , const FLAC__int32 qlp_coeff [ ] , unsigned order , int lp_quantization , FLAC__int32 residual [ ] )
2000-12-10 04:09:52 +00:00
{
2001-04-24 22:54:07 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2001-06-23 03:03:24 +00:00
FLAC__int64 sumo ;
2000-12-10 04:09:52 +00:00
# endif
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 + + ) {
2001-04-24 22:54:07 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2000-12-10 04:09:52 +00:00
sumo = 0 ;
# endif
sum = 0 ;
history = data ;
for ( j = 0 ; j < order ; j + + ) {
sum + = qlp_coeff [ j ] * ( * ( - - history ) ) ;
2001-04-24 22:54:07 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2001-06-23 03:03:24 +00:00
sumo + = ( FLAC__int64 ) qlp_coeff [ j ] * ( FLAC__int64 ) ( * history ) ;
2003-01-12 08:42:23 +00:00
# if defined _MSC_VER
2003-01-08 08:04:42 +00:00
if ( sumo > 2147483647 I64 | | sumo < - 2147483648 I64 )
2004-03-22 05:47:25 +00:00
fprintf ( stderr , " FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d \n " , i , j , qlp_coeff [ j ] , * history , sumo ) ;
2001-07-09 18:22:46 +00:00
# else
if ( sumo > 2147483647ll | | sumo < - 2147483648ll )
2006-11-17 06:52:19 +00:00
fprintf ( stderr , " FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld \n " , i , j , qlp_coeff [ j ] , * history , ( long long ) sumo ) ;
2004-03-22 05:47:25 +00:00
# endif
2000-12-10 04:09:52 +00:00
# endif
}
* ( 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 ) ;
}
*/
}
2005-01-26 04:04:38 +00:00
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide ( const FLAC__int32 * data , unsigned data_len , const FLAC__int32 qlp_coeff [ ] , unsigned order , int lp_quantization , FLAC__int32 residual [ ] )
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 ) ) ;
# ifdef FLAC__OVERFLOW_DETECT
if ( FLAC__bitmath_silog2_wide ( sum > > lp_quantization ) > 32 ) {
2006-11-17 06:52:19 +00:00
fprintf ( stderr , " FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%lld \n " , i , ( long long ) ( sum > > lp_quantization ) ) ;
2002-10-04 05:25:54 +00:00
break ;
}
if ( FLAC__bitmath_silog2_wide ( ( FLAC__int64 ) ( * data ) - ( sum > > lp_quantization ) ) > 32 ) {
2006-11-17 06:52:19 +00:00
fprintf ( stderr , " FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%lld, residual=%lld \n " , i , * data , ( long long ) ( sum > > lp_quantization ) , ( long long ) ( ( FLAC__int64 ) ( * data ) - ( sum > > lp_quantization ) ) ) ;
2002-10-04 05:25:54 +00:00
break ;
}
# endif
* ( residual + + ) = * ( data + + ) - ( FLAC__int32 ) ( sum > > lp_quantization ) ;
}
}
2004-11-09 01:34:01 +00:00
# endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
2001-06-23 03:03:24 +00:00
void FLAC__lpc_restore_signal ( const FLAC__int32 residual [ ] , unsigned data_len , const FLAC__int32 qlp_coeff [ ] , unsigned order , int lp_quantization , FLAC__int32 data [ ] )
2000-12-10 04:09:52 +00:00
{
2001-04-24 22:54:07 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2001-06-23 03:03:24 +00:00
FLAC__int64 sumo ;
2000-12-10 04:09:52 +00:00
# endif
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 + + ) {
2001-04-24 22:54:07 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2000-12-10 04:09:52 +00:00
sumo = 0 ;
# endif
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-04-24 22:54:07 +00:00
# ifdef FLAC__OVERFLOW_DETECT
2001-06-23 03:03:24 +00:00
sumo + = ( FLAC__int64 ) qlp_coeff [ j ] * ( FLAC__int64 ) ( * history ) ;
2003-01-12 08:42:23 +00:00
# if defined _MSC_VER
2003-01-08 08:04:42 +00:00
if ( sumo > 2147483647 I64 | | sumo < - 2147483648 I64 )
2004-03-22 05:47:25 +00:00
fprintf ( stderr , " FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d \n " , i , j , qlp_coeff [ j ] , * history , sumo ) ;
2001-07-09 18:22:46 +00:00
# else
if ( sumo > 2147483647ll | | sumo < - 2147483648ll )
2006-11-17 06:52:19 +00:00
fprintf ( stderr , " FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld \n " , i , j , qlp_coeff [ j ] , * history , ( long long ) sumo ) ;
2004-03-22 05:47:25 +00:00
# endif
2000-12-10 04:09:52 +00:00
# endif
}
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
}
2002-10-04 05:25:54 +00:00
void FLAC__lpc_restore_signal_wide ( const FLAC__int32 residual [ ] , unsigned data_len , const FLAC__int32 qlp_coeff [ ] , unsigned order , int lp_quantization , FLAC__int32 data [ ] )
{
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 ) ) ;
# ifdef FLAC__OVERFLOW_DETECT
if ( FLAC__bitmath_silog2_wide ( sum > > lp_quantization ) > 32 ) {
2006-11-17 06:52:19 +00:00
fprintf ( stderr , " FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%lld \n " , i , ( long long ) ( 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 ) {
fprintf ( stderr , " FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%lld, data=%lld \n " , i , * r , ( long long ) ( sum > > lp_quantization ) , ( long long ) ( ( FLAC__int64 ) ( * r ) + ( sum > > lp_quantization ) ) ) ;
2002-10-04 05:25:54 +00:00
break ;
}
# endif
2006-11-20 07:19:15 +00:00
* ( data + + ) = * ( r + + ) + ( FLAC__int32 ) ( sum > > lp_quantization ) ;
2002-10-04 05:25:54 +00:00
}
}
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
{
2006-04-28 00:11:31 +00:00
unsigned order , index , 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 */
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
2006-04-28 00:11:31 +00:00
for ( index = 0 , order = 1 ; index < max_order ; index + + , order + + ) {
bits = FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale ( lpc_error [ index ] , error_scale ) * ( FLAC__double ) ( total_samples - order ) + ( FLAC__double ) ( order * overhead_bits_per_order ) ;
if ( bits < best_bits ) {
best_index = index ;
best_bits = bits ;
2000-12-10 04:09:52 +00:00
}
}
2006-04-28 00:11:31 +00:00
return best_index + 1 ; /* +1 since index 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 */