]> git.sesse.net Git - mlt/blobdiff - src/modules/normalize/filter_volume.c
Fix compile error on Windows.
[mlt] / src / modules / normalize / filter_volume.c
index 2c129c6a4e25d2f3747041cbcdbd9ac11e852d10..8b0ccd6059dde0db3ca81ad380eb30af33474441 100644 (file)
@@ -18,8 +18,7 @@
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include "filter_volume.h"
-
+#include <framework/mlt_filter.h>
 #include <framework/mlt_frame.h>
 
 #include <stdio.h>
@@ -31,7 +30,7 @@
 #define MAX_CHANNELS 6
 #define EPSILON 0.00001
 
-/* The normalise functions come from the normalize utility:
+/* The following normalise functions come from the normalize utility:
    Copyright (C) 1999--2002 Chris Vaill */
 
 #define samp_width 16
@@ -101,7 +100,7 @@ static inline double get_smoothed_data( double *buf, int count )
                        j++;
                }
        }
-       smoothed /= j;
+       if (j) smoothed /= j;
 //     fprintf( stderr, "smoothed over %d values, result %f\n", j, smoothed );
 
        return smoothed;
@@ -164,29 +163,32 @@ double signal_max_power( int16_t *buffer, int channels, int samples, int16_t *pe
 /** Get the audio.
 */
 
-static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
-       // Get the properties of the a frame
-       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-       double gain = mlt_properties_get_double( properties, "volume.gain" );
-       double max_gain = mlt_properties_get_double( properties, "volume.max_gain" );
-       double limiter_level = 0.5; /* -6 dBFS */
-       int normalise =  mlt_properties_get_int( properties, "volume.normalise" );
-       double amplitude =  mlt_properties_get_double( properties, "volume.amplitude" );
-       int i, j;
-       double sample;
-       int16_t peak;
-
        // Get the filter from the frame
-       mlt_filter this = mlt_properties_get_data( properties, "filter_volume", NULL );
+       mlt_filter this = mlt_frame_pop_audio( frame );
 
        // Get the properties from the filter
        mlt_properties filter_props = MLT_FILTER_PROPERTIES( this );
 
-       if ( mlt_properties_get( properties, "volume.limiter" ) != NULL )
-               limiter_level = mlt_properties_get_double( properties, "volume.limiter" );
+       // Get the frame's filter instance properties
+       mlt_properties instance_props = mlt_frame_unique_properties( frame, MLT_FILTER_SERVICE( this ) );
+
+       // Get the parameters
+       double gain = mlt_properties_get_double( instance_props, "gain" );
+       double max_gain = mlt_properties_get_double( instance_props, "max_gain" );
+       double limiter_level = 0.5; /* -6 dBFS */
+       int normalise =  mlt_properties_get_int( instance_props, "normalise" );
+       double amplitude =  mlt_properties_get_double( instance_props, "amplitude" );
+       int i, j;
+       double sample;
+       int16_t peak;
+
+       if ( mlt_properties_get( instance_props, "limiter" ) != NULL )
+               limiter_level = mlt_properties_get_double( instance_props, "limiter" );
        
        // Get the producer's audio
+       *format = mlt_audio_s16;
        mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
 //     fprintf( stderr, "filter_volume: frequency %d\n", *frequency );
 
@@ -195,6 +197,8 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
        int samplemax = (1 << (bytes_per_samp * 8 - 1)) - 1;
        int samplemin = -samplemax - 1;
 
+       mlt_service_lock( MLT_FILTER_SERVICE( this ) );
+
        if ( normalise )
        {
                int window = mlt_properties_get_int( filter_props, "window" );
@@ -218,7 +222,7 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
                }
                else
                {
-                       gain *= amplitude / signal_max_power( *buffer, *channels, *samples, &peak );
+                       gain *= amplitude / signal_max_power( (int16_t*) *buffer, *channels, *samples, &peak );
                }
        }
        
@@ -229,23 +233,29 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
                gain = max_gain;
 
        // Initialise filter's previous gain value to prevent an inadvertant jump from 0
-       if ( mlt_properties_get( filter_props, "previous_gain" ) == NULL )
-               mlt_properties_set_double( filter_props, "previous_gain", gain );
+       mlt_position last_position = mlt_properties_get_position( filter_props, "_last_position" );
+       mlt_position current_position = mlt_frame_get_position( frame );
+       if ( mlt_properties_get( filter_props, "_previous_gain" ) == NULL
+            || current_position != last_position + 1 )
+               mlt_properties_set_double( filter_props, "_previous_gain", gain );
 
        // Start the gain out at the previous
-       double previous_gain = mlt_properties_get_double( filter_props, "previous_gain" );
+       double previous_gain = mlt_properties_get_double( filter_props, "_previous_gain" );
 
        // Determine ramp increment
        double gain_step = ( gain - previous_gain ) / *samples;
 //     fprintf( stderr, "filter_volume: previous gain %f current gain %f step %f\n", previous_gain, gain, gain_step );
 
        // Save the current gain for the next iteration
-       mlt_properties_set_double( filter_props, "previous_gain", gain );
+       mlt_properties_set_double( filter_props, "_previous_gain", gain );
+       mlt_properties_set_position( filter_props, "_last_position", current_position );
+
+       mlt_service_unlock( MLT_FILTER_SERVICE( this ) );
 
        // Ramp from the previous gain to the current
        gain = previous_gain;
 
-       int16_t *p = *buffer;
+       int16_t *p = (int16_t*) *buffer;
 
        // Apply the gain
        for ( i = 0; i < *samples; i++ )
@@ -280,66 +290,61 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
 
 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 {
-       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
        mlt_properties filter_props = MLT_FILTER_PROPERTIES( this );
+       mlt_properties instance_props = mlt_frame_unique_properties( frame, MLT_FILTER_SERVICE( this ) );
+
+       double gain = 1.0; // no adjustment
 
        // Parse the gain property
-       if ( mlt_properties_get( properties, "gain" ) == NULL )
+       if ( mlt_properties_get( filter_props, "gain" ) != NULL )
        {
-               double gain = 1.0; // no adjustment
-               
-               if ( mlt_properties_get( filter_props, "gain" ) != NULL )
+               char *p = mlt_properties_get( filter_props, "gain" );
+
+               if ( strncaseeq( p, "normalise", 9 ) )
+                       mlt_properties_set( filter_props, "normalise", "" );
+               else
                {
-                       char *p = mlt_properties_get( filter_props, "gain" );
-                       
-                       if ( strncaseeq( p, "normalise", 9 ) )
-                               mlt_properties_set( filter_props, "normalise", "" );
+                       if ( strcmp( p, "" ) != 0 )
+                               gain = strtod( p, &p );
+
+                       while ( isspace( *p ) )
+                               p++;
+
+                       /* check if "dB" is given after number */
+                       if ( strncaseeq( p, "db", 2 ) )
+                               gain = DBFSTOAMP( gain );
                        else
+                               gain = fabs( gain );
+
+                       // If there is an end adjust gain to the range
+                       if ( mlt_properties_get( filter_props, "end" ) != NULL )
                        {
+                               double end = -1;
+                               char *p = mlt_properties_get( filter_props, "end" );
                                if ( strcmp( p, "" ) != 0 )
-                                       gain = fabs( strtod( p, &p) );
+                                       end = strtod( p, &p );
 
                                while ( isspace( *p ) )
                                        p++;
 
                                /* check if "dB" is given after number */
                                if ( strncaseeq( p, "db", 2 ) )
-                                       gain = DBFSTOAMP( gain );
-                                       
-                               // If there is an end adjust gain to the range
-                               if ( mlt_properties_get( filter_props, "end" ) != NULL )
-                               {       
-                                       // Determine the time position of this frame in the transition duration
-                                       mlt_position in = mlt_filter_get_in( this );
-                                       mlt_position out = mlt_filter_get_out( this );
-                                       mlt_position time = mlt_frame_get_position( frame );
-                                       double position = ( double )( time - in ) / ( double )( out - in + 1 );
-
-                                       double end = -1;
-                                       char *p = mlt_properties_get( filter_props, "end" );
-                                       if ( strcmp( p, "" ) != 0 )
-                                               end = fabs( strtod( p, &p) );
-
-                                       while ( isspace( *p ) )
-                                               p++;
-
-                                       /* check if "dB" is given after number */
-                                       if ( strncaseeq( p, "db", 2 ) )
-                                               end = DBFSTOAMP( gain );
-
-                                       if ( end != -1 )
-                                               gain += ( end - gain ) * position;
-                               }
+                                       end = DBFSTOAMP( gain );
+                               else
+                                       end = fabs( end );
+
+                               if ( end != -1 )
+                                       gain += ( end - gain ) * mlt_filter_get_progress( this, frame );
                        }
                }
-               mlt_properties_set_double( properties, "volume.gain", gain );
        }
+       mlt_properties_set_double( instance_props, "gain", gain );
        
        // Parse the maximum gain property
        if ( mlt_properties_get( filter_props, "max_gain" ) != NULL )
        {
                char *p = mlt_properties_get( filter_props, "max_gain" );
-               double gain = fabs( strtod( p, &p) ); // 0 = no max
+               double gain = strtod( p, &p ); // 0 = no max
                        
                while ( isspace( *p ) )
                        p++;
@@ -347,8 +352,10 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
                /* check if "dB" is given after number */
                if ( strncaseeq( p, "db", 2 ) )
                        gain = DBFSTOAMP( gain );
+               else
+                       gain = fabs( gain );
                        
-               mlt_properties_set_double( properties, "volume.max_gain", gain );
+               mlt_properties_set_double( instance_props, "max_gain", gain );
        }
 
        // Parse the limiter property
@@ -374,7 +381,7 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
                        if ( level < 0 )
                                level = -level;
                }
-               mlt_properties_set_double( properties, "volume.limiter", level );
+               mlt_properties_set_double( instance_props, "limiter", level );
        }
 
        // Parse the normalise property
@@ -406,15 +413,10 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
                // If there is an end adjust gain to the range
                if ( mlt_properties_get( filter_props, "end" ) != NULL )
                {
-                       // Determine the time position of this frame in the transition duration
-                       mlt_position in = mlt_filter_get_in( this );
-                       mlt_position out = mlt_filter_get_out( this );
-                       mlt_position time = mlt_frame_get_position( frame );
-                       double position = ( double )( time - in ) / ( double )( out - in + 1 );
-                       amplitude *= position;
+                       amplitude *= mlt_filter_get_progress( this, frame );
                }
-               mlt_properties_set_int( properties, "volume.normalise", 1 );
-               mlt_properties_set_double( properties, "volume.amplitude", amplitude );
+               mlt_properties_set_int( instance_props, "normalise", 1 );
+               mlt_properties_set_double( instance_props, "amplitude", amplitude );
        }
 
        // Parse the window property and allocate smoothing buffer if needed
@@ -429,8 +431,8 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
                mlt_properties_set_data( filter_props, "smooth_buffer", smooth_buffer, 0, free, NULL );
        }
        
-       // Put a filter reference onto the frame
-       mlt_properties_set_data( properties, "filter_volume", this, 0, NULL, NULL );
+       // Push the filter onto the stack
+       mlt_frame_push_audio( frame, this );
 
        // Override the get_audio method
        mlt_frame_push_audio( frame, filter_get_audio );
@@ -441,9 +443,9 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 /** Constructor for the filter.
 */
 
-mlt_filter filter_volume_init( char *arg )
+mlt_filter filter_volume_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
-       mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
+       mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
        if ( this != NULL && mlt_filter_init( this, NULL ) == 0 )
        {
                mlt_properties properties = MLT_FILTER_PROPERTIES( this );