ref: 3267dd862062e755782f04eee5db47ef338fc5b8
parent: d5b0ced73cd72f99816b7db788cef63b2603bbe4
author: Chris Moeller <kode54@gmail.com>
date: Sat Jan 12 13:34:22 EST 2013
- Added silence padding for samples which are too short to predict padding for - Added extra comments
--- a/dumb/src/helpers/lpc.c
+++ b/dumb/src/helpers/lpc.c
@@ -160,11 +160,13 @@
#include "internal/dumb.h"
#include "internal/it.h"
-enum { lpc_max = 256 };
-enum { lpc_order = 32 };
-enum { lpc_extra = 64 };
+enum { lpc_max = 256 }; /* Maximum number of input samples to train the function */
+enum { lpc_order = 32 }; /* Order of the filter */
+enum { lpc_extra = 64 }; /* How many samples of padding to predict or silence */
+/* This extra sample padding is really only needed by the FIR resampler, but it helps the other resamplers as well. */
+
void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){
float lpc[lpc_order * 2];
float lpc_input[lpc_max * 2];
@@ -177,121 +179,141 @@
for ( n = 0; n < sigdata->n_samples; n++ ) {
IT_SAMPLE * sample = sigdata->sample + n;
- if ( ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS ) &&
- sample->length >= lpc_order ) {
- lpc_samples = sample->length;
- if (lpc_samples > lpc_max) lpc_samples = lpc_max;
- offset = sample->length - lpc_samples;
+ if ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS ) {
+ /* If we have enough sample data to train the filter, use the filter to generate the padding */
+ if ( sample->length >= lpc_order ) {
+ lpc_samples = sample->length;
+ if (lpc_samples > lpc_max) lpc_samples = lpc_max;
+ offset = sample->length - lpc_samples;
- if ( sample->flags & IT_SAMPLE_STEREO )
- {
- if ( sample->flags & IT_SAMPLE_16BIT )
+ if ( sample->flags & IT_SAMPLE_STEREO )
{
- s16 = ( signed short * ) sample->data;
- s16 += offset * 2;
- for ( o = 0; o < lpc_samples; o++ )
+ if ( sample->flags & IT_SAMPLE_16BIT )
{
- lpc_input[ o ] = s16[ o * 2 + 0 ];
- lpc_input[ o + lpc_max ] = s16[ o * 2 + 1 ];
+ s16 = ( signed short * ) sample->data;
+ s16 += offset * 2;
+ for ( o = 0; o < lpc_samples; o++ )
+ {
+ lpc_input[ o ] = s16[ o * 2 + 0 ];
+ lpc_input[ o + lpc_max ] = s16[ o * 2 + 1 ];
+ }
}
- }
- else
- {
- s8 = ( signed char * ) sample->data;
- s8 += offset * 2;
- for ( o = 0; o < lpc_samples; o++ )
+ else
{
- lpc_input[ o ] = s8[ o * 2 + 0 ];
- lpc_input[ o + lpc_max ] = s8[ o * 2 + 1 ];
+ s8 = ( signed char * ) sample->data;
+ s8 += offset * 2;
+ for ( o = 0; o < lpc_samples; o++ )
+ {
+ lpc_input[ o ] = s8[ o * 2 + 0 ];
+ lpc_input[ o + lpc_max ] = s8[ o * 2 + 1 ];
+ }
}
- }
- vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order );
- vorbis_lpc_from_data( lpc_input + lpc_max, lpc + lpc_order, lpc_samples, lpc_order );
+ vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order );
+ vorbis_lpc_from_data( lpc_input + lpc_max, lpc + lpc_order, lpc_samples, lpc_order );
- vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra );
- vorbis_lpc_predict( lpc + lpc_order, lpc_input + lpc_max + lpc_samples - lpc_order, lpc_order, lpc_output + lpc_extra, lpc_extra );
+ vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra );
+ vorbis_lpc_predict( lpc + lpc_order, lpc_input + lpc_max + lpc_samples - lpc_order, lpc_order, lpc_output + lpc_extra, lpc_extra );
- if ( sample->flags & IT_SAMPLE_16BIT )
- {
- s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) );
- sample->data = s16;
+ if ( sample->flags & IT_SAMPLE_16BIT )
+ {
+ s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) );
+ sample->data = s16;
- s16 += sample->length * 2;
- sample->length += lpc_extra;
+ s16 += sample->length * 2;
+ sample->length += lpc_extra;
- for ( o = 0; o < lpc_extra; o++ )
- {
- s16[ o * 2 + 0 ] = lpc_output[ o ];
- s16[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
+ for ( o = 0; o < lpc_extra; o++ )
+ {
+ s16[ o * 2 + 0 ] = lpc_output[ o ];
+ s16[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
+ }
}
- }
- else
- {
- s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 );
- sample->data = s8;
+ else
+ {
+ s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 );
+ sample->data = s8;
- s8 += sample->length * 2;
- sample->length += lpc_extra;
+ s8 += sample->length * 2;
+ sample->length += lpc_extra;
- for ( o = 0; o < lpc_extra; o++ )
- {
- s8[ o * 2 + 0 ] = lpc_output[ o ];
- s8[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
+ for ( o = 0; o < lpc_extra; o++ )
+ {
+ s8[ o * 2 + 0 ] = lpc_output[ o ];
+ s8[ o * 2 + 1 ] = lpc_output[ o + lpc_extra ];
+ }
}
}
- }
- else
- {
- if ( sample->flags & IT_SAMPLE_16BIT )
+ else
{
- s16 = ( signed short * ) sample->data;
- s16 += offset;
- for ( o = 0; o < lpc_samples; o++ )
+ if ( sample->flags & IT_SAMPLE_16BIT )
{
- lpc_input[ o ] = s16[ o ];
+ s16 = ( signed short * ) sample->data;
+ s16 += offset;
+ for ( o = 0; o < lpc_samples; o++ )
+ {
+ lpc_input[ o ] = s16[ o ];
+ }
}
- }
- else
- {
- s8 = ( signed char * ) sample->data;
- s8 += offset;
- for ( o = 0; o < lpc_samples; o++ )
+ else
{
- lpc_input[ o ] = s8[ o ];
+ s8 = ( signed char * ) sample->data;
+ s8 += offset;
+ for ( o = 0; o < lpc_samples; o++ )
+ {
+ lpc_input[ o ] = s8[ o ];
+ }
}
- }
- vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order );
+ vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order );
- vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra );
+ vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra );
- if ( sample->flags & IT_SAMPLE_16BIT )
- {
- s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) );
- sample->data = s16;
+ if ( sample->flags & IT_SAMPLE_16BIT )
+ {
+ s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) );
+ sample->data = s16;
- s16 += sample->length;
- sample->length += lpc_extra;
+ s16 += sample->length;
+ sample->length += lpc_extra;
- for ( o = 0; o < lpc_extra; o++ )
- {
- s16[ o ] = lpc_output[ o ];
+ for ( o = 0; o < lpc_extra; o++ )
+ {
+ s16[ o ] = lpc_output[ o ];
+ }
}
- }
- else
- {
- s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra );
- sample->data = s8;
+ else
+ {
+ s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra );
+ sample->data = s8;
- s8 += sample->length;
- sample->length += lpc_extra;
+ s8 += sample->length;
+ sample->length += lpc_extra;
- for ( o = 0; o < lpc_extra; o++ )
- {
- s8[ o ] = lpc_output[ o ];
+ for ( o = 0; o < lpc_extra; o++ )
+ {
+ s8[ o ] = lpc_output[ o ];
+ }
}
}
+ }
+ else
+ /* Otherwise, pad with silence. */
+ {
+ offset = sample->length;
+ lpc_samples = lpc_extra;
+
+ sample->length += lpc_samples;
+
+ n = 1;
+ if ( sample->flags & IT_SAMPLE_STEREO ) n *= 2;
+ if ( sample->flags & IT_SAMPLE_16BIT ) n *= 2;
+
+ offset *= n;
+ lpc_samples *= n;
+
+ sample->data = realloc( sample->data, offset + lpc_samples );
+ memset( (char*)sample->data + offset, 0, lpc_samples );
}
}
}