shithub: dumb

Download patch

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 );
             }
         }
     }