]> git.sesse.net Git - mlt/commitdiff
Refactor audio conversion and mixing.
authorDan Dennedy <dan@dennedy.org>
Tue, 4 Aug 2009 04:36:59 +0000 (21:36 -0700)
committerDan Dennedy <dan@dennedy.org>
Tue, 4 Aug 2009 04:36:59 +0000 (21:36 -0700)
Signed-off-by: Dan Dennedy <dan@dennedy.org>
30 files changed:
src/framework/Makefile
src/framework/mlt_consumer.c
src/framework/mlt_frame.c
src/framework/mlt_frame.h
src/framework/mlt_tractor.c
src/framework/mlt_types.h
src/mlt++/MltFrame.cpp
src/mlt++/MltFrame.h
src/mlt++/configure
src/modules/avformat/consumer_avformat.c
src/modules/avformat/filter_avresample.c
src/modules/avformat/producer_avformat.c
src/modules/core/Makefile
src/modules/core/factory.c
src/modules/core/filter_audioconvert.c [new file with mode: 0644]
src/modules/core/filter_channelcopy.c
src/modules/core/filter_mono.c
src/modules/core/filter_transition.c
src/modules/core/loader.ini
src/modules/core/producer_consumer.c
src/modules/core/transition_mix.c
src/modules/dv/consumer_libdv.c
src/modules/dv/producer_libdv.c
src/modules/jackrack/filter_jackrack.c
src/modules/jackrack/filter_ladspa.c
src/modules/normalize/filter_volume.c
src/modules/resample/filter_resample.c
src/modules/sdl/consumer_sdl.c
src/modules/sox/filter_sox.c
src/modules/vorbis/producer_vorbis.c

index 85f554dd4e1c73704fb1fce3a0a1484d0a22f8f6..b523e36e16de3aef13f0a5ef14b5bdc61de4c1fb 100644 (file)
@@ -69,7 +69,7 @@ SRCS := $(OBJS:.o=.c)
 
 CFLAGS += $(RDYNAMIC) -DPREFIX="\"$(prefix)\"" -DLIBDIR="\"$(libdir)\""
 
-LDFLAGS += -lm $(LIBDL) -lpthread
+LDFLAGS += $(LIBDL) -lpthread
 
 all:   $(TARGET)
 
index 93afe447d6a13c81ea9b00cb98c29d4799aa6d76..37e7d3fa0ad0392caf972b103fb28ffceb8c595d 100644 (file)
@@ -579,13 +579,13 @@ static void *consumer_read_ahead_thread( void *arg )
        int preview_format = mlt_properties_get_int( properties, "preview_format" );
 
        // Get the audio settings
-       mlt_audio_format afmt = mlt_audio_pcm;
+       mlt_audio_format afmt = mlt_audio_s16;
        int counter = 0;
        double fps = mlt_properties_get_double( properties, "fps" );
        int channels = mlt_properties_get_int( properties, "channels" );
        int frequency = mlt_properties_get_int( properties, "frequency" );
        int samples = 0;
-       int16_t *pcm = NULL;
+       void *audio = NULL;
 
        // See if audio is turned off
        int audio_off = mlt_properties_get_int( properties, "audio_off" );
@@ -631,7 +631,7 @@ static void *consumer_read_ahead_thread( void *arg )
        if ( !audio_off )
        {
                samples = mlt_sample_calculator( fps, frequency, counter++ );
-               mlt_frame_get_audio( frame, &pcm, &afmt, &frequency, &channels, &samples );
+               mlt_frame_get_audio( frame, &audio, &afmt, &frequency, &channels, &samples );
        }
 
        // Unlock the lock object
@@ -723,7 +723,7 @@ static void *consumer_read_ahead_thread( void *arg )
                if ( !audio_off )
                {
                        samples = mlt_sample_calculator( fps, frequency, counter++ );
-                       mlt_frame_get_audio( frame, &pcm, &afmt, &frequency, &channels, &samples );
+                       mlt_frame_get_audio( frame, &audio, &afmt, &frequency, &channels, &samples );
                }
 
                // Increment the time take for this frame
index 6bd5442c164aebb72f9064f821c6ea95809a2360..804f9b5d90b8d274c9f268e81bbee93cecad35e4 100644 (file)
@@ -30,7 +30,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <math.h>
 
 /** Constructor for a frame.
 */
@@ -400,24 +399,46 @@ uint8_t *mlt_frame_get_alpha_mask( mlt_frame this )
        return alpha;
 }
 
-int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+const char * mlt_audio_format_name( mlt_audio_format format )
+{
+       switch ( format )
+       {
+               case mlt_audio_none:   return "none";
+               case mlt_audio_s16:    return "s16";
+               case mlt_audio_s32:    return "s32";
+               case mlt_audio_float:  return "float";
+       }
+       return "invalid";
+}
+
+int mlt_frame_get_audio( mlt_frame this, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        mlt_get_audio get_audio = mlt_frame_pop_audio( this );
        mlt_properties properties = MLT_FRAME_PROPERTIES( this );
        int hide = mlt_properties_get_int( properties, "test_audio" );
+       mlt_audio_format requested_format = *format;
 
        if ( hide == 0 && get_audio != NULL )
        {
                mlt_position position = mlt_frame_get_position( this );
                get_audio( this, buffer, format, frequency, channels, samples );
                mlt_frame_set_position( this, position );
+               mlt_properties_set_int( properties, "audio_frequency", *frequency );
+               mlt_properties_set_int( properties, "audio_channels", *channels );
+               mlt_properties_set_int( properties, "audio_samples", *samples );
+               mlt_properties_set_int( properties, "audio_format", *format );
+               if ( this->convert_audio )
+                       this->convert_audio( this, buffer, format, requested_format );
        }
        else if ( mlt_properties_get_data( properties, "audio", NULL ) )
        {
                *buffer = mlt_properties_get_data( properties, "audio", NULL );
+               *format = mlt_properties_get_int( properties, "audio_format" );
                *frequency = mlt_properties_get_int( properties, "audio_frequency" );
                *channels = mlt_properties_get_int( properties, "audio_channels" );
                *samples = mlt_properties_get_int( properties, "audio_samples" );
+               if ( this->convert_audio )
+                       this->convert_audio( this, buffer, format, requested_format );
        }
        else
        {
@@ -425,19 +446,37 @@ int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *for
                *samples = *samples <= 0 ? 1920 : *samples;
                *channels = *channels <= 0 ? 2 : *channels;
                *frequency = *frequency <= 0 ? 48000 : *frequency;
-               size = *samples * *channels * sizeof( int16_t );
-               *buffer = mlt_pool_alloc( size );
-               if ( *buffer != NULL )
+               mlt_properties_set_int( properties, "audio_frequency", *frequency );
+               mlt_properties_set_int( properties, "audio_channels", *channels );
+               mlt_properties_set_int( properties, "audio_samples", *samples );
+               mlt_properties_set_int( properties, "audio_format", *format );
+
+               switch( *format )
+               {
+                       case mlt_image_none:
+                               size = 0;
+                               *buffer = NULL;
+                               break;
+                       case mlt_audio_s16:
+                               size = *samples * *channels * sizeof( int16_t );
+                               break;
+                       case mlt_audio_s32:
+                               size = *samples * *channels * sizeof( int32_t );
+                               break;
+                       case mlt_audio_float:
+                               size = *samples * *channels * sizeof( float );
+                               break;
+               }
+               if ( size )
+                       *buffer = mlt_pool_alloc( size );
+               if ( *buffer )
                        memset( *buffer, 0, size );
                mlt_properties_set_data( properties, "audio", *buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
                mlt_properties_set_int( properties, "test_audio", 1 );
        }
 
-       mlt_properties_set_int( properties, "audio_frequency", *frequency );
-       mlt_properties_set_int( properties, "audio_channels", *channels );
-       mlt_properties_set_int( properties, "audio_samples", *samples );
-
-       if ( mlt_properties_get( properties, "meta.volume" ) )
+       // TODO: This does not belong here
+       if ( *format == mlt_audio_s16 && mlt_properties_get( properties, "meta.volume" ) )
        {
                double value = mlt_properties_get_double( properties, "meta.volume" );
 
@@ -462,18 +501,24 @@ int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *for
        return 0;
 }
 
+int mlt_frame_set_audio( mlt_frame this, void *buffer, mlt_audio_format format, int size, mlt_destructor destructor )
+{
+       mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "audio_format", format );
+       return mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "audio", buffer, size, destructor, NULL );
+}
+
 unsigned char *mlt_frame_get_waveform( mlt_frame this, int w, int h )
 {
        int16_t *pcm = NULL;
        mlt_properties properties = MLT_FRAME_PROPERTIES( this );
-       mlt_audio_format format = mlt_audio_pcm;
+       mlt_audio_format format = mlt_audio_s16;
        int frequency = 32000; // lower frequency available?
        int channels = 2;
        double fps = mlt_profile_fps( NULL );
        int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( this ) );
 
        // Get the pcm data
-       mlt_frame_get_audio( this, &pcm, &format, &frequency, &channels, &samples );
+       mlt_frame_get_audio( this, (void**)&pcm, &format, &frequency, &channels, &samples );
 
        // Make an 8-bit buffer large enough to hold rendering
        int size = w * h;
@@ -539,139 +584,6 @@ void mlt_frame_close( mlt_frame this )
 
 /***** convenience functions *****/
 
-int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
-       int ret = 0;
-       int16_t *src, *dest;
-       int frequency_src = *frequency, frequency_dest = *frequency;
-       int channels_src = *channels, channels_dest = *channels;
-       int samples_src = *samples, samples_dest = *samples;
-       int i, j;
-       double d = 0, s = 0;
-
-       mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
-       mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
-
-       int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
-       mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
-       if ( silent )
-               memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
-
-       silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
-       mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
-       if ( silent )
-               memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
-
-       if ( channels_src > 6 )
-               channels_src = 0;
-       if ( channels_dest > 6 )
-               channels_dest = 0;
-       if ( samples_src > 4000 )
-               samples_src = 0;
-       if ( samples_dest > 4000 )
-               samples_dest = 0;
-
-       // determine number of samples to process
-       *samples = samples_src < samples_dest ? samples_src : samples_dest;
-       *channels = channels_src < channels_dest ? channels_src : channels_dest;
-       *buffer = dest;
-       *frequency = frequency_dest;
-
-       // Compute a smooth ramp over start to end
-       float weight = weight_start;
-       float weight_step = ( weight_end - weight_start ) / *samples;
-
-       if ( src == dest )
-       {
-               *samples = samples_src;
-               *channels = channels_src;
-               *buffer = src;
-               *frequency = frequency_src;
-               return ret;
-       }
-
-       // Mixdown
-       for ( i = 0; i < *samples; i++ )
-       {
-               for ( j = 0; j < *channels; j++ )
-               {
-                       if ( j < channels_dest )
-                               d = (double) dest[ i * channels_dest + j ];
-                       if ( j < channels_src )
-                               s = (double) src[ i * channels_src + j ];
-                       dest[ i * channels_dest + j ] = s * weight + d * ( 1.0 - weight );
-               }
-               weight += weight_step;
-       }
-
-       return ret;
-}
-
-// Replacement for broken mlt_frame_audio_mix - this filter uses an inline low pass filter
-// to allow mixing without volume hacking
-int mlt_frame_combine_audio( mlt_frame this, mlt_frame that, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
-       int ret = 0;
-       int16_t *src, *dest;
-       int frequency_src = *frequency, frequency_dest = *frequency;
-       int channels_src = *channels, channels_dest = *channels;
-       int samples_src = *samples, samples_dest = *samples;
-       int i, j;
-       double vp[ 6 ];
-       double b_weight = 1.0;
-
-       if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "meta.mixdown" ) )
-               b_weight = 1.0 - mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "meta.volume" );
-
-       mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
-       mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
-
-       int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
-       mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
-       if ( silent )
-               memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
-
-       silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
-       mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
-       if ( silent )
-               memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
-
-       if ( src == dest )
-       {
-               *samples = samples_src;
-               *channels = channels_src;
-               *buffer = src;
-               *frequency = frequency_src;
-               return ret;
-       }
-
-       // determine number of samples to process
-       *samples = samples_src < samples_dest ? samples_src : samples_dest;
-       *channels = channels_src < channels_dest ? channels_src : channels_dest;
-       *buffer = dest;
-       *frequency = frequency_dest;
-
-       for ( j = 0; j < *channels; j++ )
-               vp[ j ] = ( double )dest[ j ];
-
-       double Fc = 0.5;
-       double B = exp(-2.0 * M_PI * Fc);
-       double A = 1.0 - B;
-       double v;
-
-       for ( i = 0; i < *samples; i++ )
-       {
-               for ( j = 0; j < *channels; j++ )
-               {
-                       v = ( double )( b_weight * dest[ i * channels_dest + j ] + src[ i * channels_src + j ] );
-                       v = v < -32767 ? -32767 : v > 32768 ? 32768 : v;
-                       vp[ j ] = dest[ i * channels_dest + j ] = ( int16_t )( v * A + vp[ j ] * B );
-               }
-       }
-
-       return ret;
-}
-
 /* Will this break when mlt_position is converted to double? -Zach */
 int mlt_sample_calculator( float fps, int frequency, int64_t position )
 {
index 91aa79f435641000dcdeda02e255ce5bce8a0391..7def364dbba4f49c8b855723bf67ebbf4deca49b 100644 (file)
@@ -38,7 +38,7 @@ typedef int ( *mlt_get_image )( mlt_frame self, uint8_t **buffer, mlt_image_form
  *
  */
 
-typedef int ( *mlt_get_audio )( mlt_frame self, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
+typedef int ( *mlt_get_audio )( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
 
 /** \brief Frame class
  *
@@ -60,6 +60,7 @@ struct mlt_frame_s
        /* Virtual methods */
        uint8_t * ( *get_alpha_mask )( mlt_frame self );
        int ( *convert_image )( mlt_frame self, uint8_t **image, mlt_image_format *input, mlt_image_format output );
+       int ( *convert_audio )( mlt_frame self, void **audio, mlt_audio_format *input, mlt_audio_format output );
 
        /* Private properties */
        mlt_deque stack_image;
@@ -83,7 +84,8 @@ extern int mlt_frame_set_position( mlt_frame self, mlt_position value );
 extern void mlt_frame_replace_image( mlt_frame self, uint8_t *image, mlt_image_format format, int width, int height );
 extern int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable );
 extern uint8_t *mlt_frame_get_alpha_mask( mlt_frame self );
-extern int mlt_frame_get_audio( mlt_frame self, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
+extern int mlt_frame_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
+extern int mlt_frame_set_audio( mlt_frame self, void *buffer, mlt_audio_format, int size, mlt_destructor );
 extern unsigned char *mlt_frame_get_waveform( mlt_frame self, int w, int h );
 extern int mlt_frame_push_get_image( mlt_frame self, mlt_get_image get_image );
 extern mlt_get_image mlt_frame_pop_get_image( mlt_frame self );
@@ -100,11 +102,10 @@ extern mlt_producer mlt_frame_get_original_producer( mlt_frame self );
 extern void mlt_frame_close( mlt_frame self );
 
 /* convenience functions */
-extern int mlt_frame_mix_audio( mlt_frame self, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples  );
-extern int mlt_frame_combine_audio( mlt_frame self, mlt_frame that, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples  );
 extern int mlt_sample_calculator( float fps, int frequency, int64_t position );
 extern int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position );
 extern const char * mlt_image_format_name( mlt_image_format format );
+extern const char * mlt_audio_format_name( mlt_audio_format format );
 
 /** This macro scales rgb into the yuv gamut - y is scaled by 219/255 and uv by 224/255. */
 #define RGB2YUV(r, g, b, y, u, v)\
index 40c78215826772c5a9b32fb4832d044921aa3286..e3c79acfd8638e6f14184f95b7d9fbd3f70b95b6 100644 (file)
@@ -284,7 +284,7 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma
        return 0;
 }
 
-static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int producer_get_audio( mlt_frame this, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        mlt_properties properties = MLT_FRAME_PROPERTIES( this );
        mlt_frame frame = mlt_frame_pop_audio( this );
index 921dd4799bae00fd9f9be3adfedad9830d9e8406..05c7bf5c95e839b9c317ae70543bdcfb5a964c30 100644 (file)
@@ -49,7 +49,10 @@ mlt_image_format;
 typedef enum
 {
        mlt_audio_none = 0,/**< audio not available */
-       mlt_audio_pcm      /**< signed 16-bit interleaved PCM */
+       mlt_audio_pcm = 1, /**< \deprecated signed 16-bit interleaved PCM */
+       mlt_audio_s16 = 1, /**< signed 16-bit interleaved PCM */
+       mlt_audio_s32,     /**< signed 32-bit non-interleaved PCM */
+       mlt_audio_float    /**< 32-bit non-interleaved floating point */
 }
 mlt_audio_format;
 
index 8eee724b813df43f4c018c4301c01fc7479f7b78..e2b3aa2d911373b0e99fe77ee6a5f77bdf1c33d2 100644 (file)
@@ -72,9 +72,9 @@ unsigned char *Frame::fetch_image( mlt_image_format f, int w, int h, int writabl
        return image;
 }
 
-int16_t *Frame::get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples )
+void *Frame::get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples )
 {
-       int16_t *audio = NULL;
+       void *audio = NULL;
        mlt_frame_get_audio( get_frame( ), &audio, &format, &frequency, &channels, &samples );
        return audio;
 }
index 212d0bad42be21756da9b591d17bdddcec4bfe1a..4c2e3d76b875b9fd9896f3e00ce8da03f881638e 100644 (file)
@@ -43,7 +43,7 @@ namespace Mlt
                        mlt_properties get_properties( );
                        uint8_t *get_image( mlt_image_format &format, int &w, int &h, int writable = 0 );
                        unsigned char *fetch_image( mlt_image_format format, int w, int h, int writable = 0 );
-                       int16_t *get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples );
+                       void *get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples );
                        unsigned char *get_waveform( int w, int h );
                        Producer *get_original_producer( );
        };
index 1d46adbdae3b4f44df5e06dde07c1ae6227b2eb7..e83b6ed10987c582a6016e254808a080186c91c6 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-echo "soversion=2" > config.mak
+echo "soversion=3" > config.mak
 echo "mlt++    -I$prefix/include -I$prefix/include/mlt++ -D_REENTRANT  -L$libdir -lmlt++" >> ../../packages.dat
 
 WARNINGS="-W -Wwrite-strings -Wcast-qual -Wpointer-arith -Wcast-align -Wredundant-decls"
index 2229ff17827c1f492fe087bacfca2e6f279fc758..cf53e1246692bc110b64e2a3abcf82230702d934 100644 (file)
@@ -790,7 +790,7 @@ static void *consumer_thread( void *arg )
        int img_height = height;
 
        // Get default audio properties
-       mlt_audio_format aud_fmt = mlt_audio_pcm;
+       mlt_audio_format aud_fmt = mlt_audio_s16;
        int channels = mlt_properties_get_int( properties, "channels" );
        int frequency = mlt_properties_get_int( properties, "frequency" );
        int16_t *pcm = NULL;
@@ -1004,7 +1004,7 @@ static void *consumer_thread( void *arg )
                        if ( !terminated && audio_st )
                        {
                                samples = mlt_sample_calculator( fps, frequency, count ++ );
-                               mlt_frame_get_audio( frame, &pcm, &aud_fmt, &frequency, &channels, &samples );
+                               mlt_frame_get_audio( frame, (void**) &pcm, &aud_fmt, &frequency, &channels, &samples );
 
                                // Create the fifo if we don't have one
                                if ( fifo == NULL )
index ff8a16987e5dd620c79c731cfa9db097a850c8e5..fd765b7e4baa585fb31ff901cccd2dd4e9900a24 100644 (file)
@@ -31,7 +31,7 @@
 /** Get the audio.
 */
 
-static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        // Get the properties of the frame
        mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
@@ -60,6 +60,7 @@ static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
                output_rate = *frequency;
 
        // Get the producer's audio
+       *format = mlt_audio_s16;
        mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
 
        // Duplicate channels as necessary
@@ -74,7 +75,7 @@ static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
                {
                        for ( j = 0; j < *channels; j++ )
                        {
-                               new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
+                               new_buffer[ ( i * *channels ) + j ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + k ];
                                k = ( k + 1 ) % channels_avail;
                        }
                }
@@ -93,8 +94,8 @@ static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
                // Drop all but the first *channels
                for ( i = 0; i < *samples; i++ )
                {
-                       new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
-                       new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
+                       new_buffer[ ( i * *channels ) + 0 ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + 2 ];
+                       new_buffer[ ( i * *channels ) + 1 ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + 3 ];
                }
 
                // Update the audio buffer now - destroys the old
@@ -129,16 +130,17 @@ static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
 
                // Resample the audio
                used = audio_resample( resample, sample_buffer, *buffer, *samples );
+               int size = used * *channels * sizeof( int16_t );
 
                // Resize if necessary
                if ( used > *samples )
                {
-                       *buffer = mlt_pool_realloc( *buffer, *samples * *channels * sizeof( int16_t ) );
-                       mlt_properties_set_data( properties, "audio", *buffer, *channels * used * sizeof( int16_t ), mlt_pool_release, NULL );
+                       *buffer = mlt_pool_realloc( *buffer, size );
+                       mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
                }
 
                // Copy samples
-               memcpy( *buffer, sample_buffer, *channels * used * sizeof( int16_t ) );
+               memcpy( *buffer, sample_buffer, size );
 
                // Update output variables
                *samples = used;
index 5b2919dc82e7989db24bb4a8bf993f04abab77a1..e99d6bdcfd4a292a67732cafe48467916ba426d9 100644 (file)
@@ -1104,7 +1104,7 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame )
 /** Get the audio from a frame.
 */
 
-static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        // Get the properties from the frame
        mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
@@ -1318,8 +1318,10 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
                        av_free_packet( &pkt );
                }
 
-               *buffer = mlt_pool_alloc( *samples * *channels * sizeof( int16_t ) );
-               mlt_properties_set_data( frame_properties, "audio", *buffer, 0, ( mlt_destructor )mlt_pool_release, NULL );
+               int size = *samples * *channels * sizeof( int16_t );
+               *format = mlt_audio_s16;
+               *buffer = mlt_pool_alloc( size );
+               mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
 
                // Now handle the audio if we have enough
                if ( audio_used >= *samples )
index fbd83a59853f7454c807a00a08ed9f534fd4801c..7c371ad9938ce5f47935759a0a085df7b6861bfe 100644 (file)
@@ -13,6 +13,7 @@ OBJS = factory.o \
           producer_loader.o \
           producer_noise.o \
           producer_ppm.o \
+          filter_audioconvert.o \
           filter_brightness.o \
           filter_channelcopy.o \
           filter_crop.o \
index e6ae88965203641ffad284ccf60c50861f78c89d..b0aecb9e2a87352423d087b47740be54996281c0 100644 (file)
@@ -22,6 +22,7 @@
 #include <string.h>
 
 extern mlt_consumer consumer_null_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
+extern mlt_filter filter_audioconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_filter filter_brightness_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_filter filter_channelcopy_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
 extern mlt_filter filter_crop_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
@@ -53,6 +54,7 @@ extern mlt_transition transition_mix_init( mlt_profile profile, mlt_service_type
 MLT_REPOSITORY
 {
        MLT_REGISTER( consumer_type, "null", consumer_null_init );
+       MLT_REGISTER( filter_type, "audioconvert", filter_audioconvert_init );
        MLT_REGISTER( filter_type, "brightness", filter_brightness_init );
        MLT_REGISTER( filter_type, "channelcopy", filter_channelcopy_init );
        MLT_REGISTER( filter_type, "crop", filter_crop_init );
diff --git a/src/modules/core/filter_audioconvert.c b/src/modules/core/filter_audioconvert.c
new file mode 100644 (file)
index 0000000..0794281
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * filter_audioconvert.c -- convert from one audio format to another
+ * Copyright (C) 2009 Ushodaya Enterprises Limited
+ * Author: Dan Dennedy <dan@dennedy.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <framework/mlt_filter.h>
+#include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *format, mlt_audio_format requested_format )
+{
+       int error = 0;
+       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
+       int channels = mlt_properties_get_int( properties, "audio_channels" );
+       int samples = mlt_properties_get_int( properties, "audio_samples" );
+       int size = 0;
+
+       if ( *format != requested_format )
+       {
+               mlt_log_debug( NULL, "[filter audioconvert] %s -> %s %d channels %d samples\n",
+                       mlt_audio_format_name( *format ), mlt_audio_format_name( requested_format ),
+                       channels, samples );
+               switch ( *format )
+               {
+               case mlt_audio_s16:
+                       switch ( requested_format )
+                       {
+                       case mlt_audio_s32:
+                       {
+                               size = channels * samples * sizeof(int32_t);
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       int16_t *q = (int16_t*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               *p++ = (int32_t) *q << 16;
+                                               q += channels;
+                                       }
+                               }
+                               *audio = buffer;
+                               break;
+                       }
+                       case mlt_audio_float:
+                       {
+                               size = channels * samples * sizeof(float);
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       int16_t *q = (int16_t*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               *p++ = (float)( *q ) / 32768.0;
+                                               q += channels;
+                                       }
+                               }
+                               *audio = buffer;
+                               break;
+                       }
+                       default:
+                               error = 1;
+                       }
+                       break;
+               case mlt_audio_s32:
+                       switch ( requested_format )
+                       {
+                       case mlt_audio_s16:
+                       {
+                               size = channels * samples * sizeof(int16_t);
+                               int16_t *buffer = mlt_pool_alloc( size );
+                               int16_t *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                               *p++ = *( q + c * samples + s ) >> 16;
+                               *audio = buffer;
+                               break;
+                       }
+                       case mlt_audio_float:
+                       {
+                               size = channels * samples * sizeof(float);
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = (float)( *q++ ) / 2147483648.0;
+                               *audio = buffer;
+                               break;
+                       }
+                       default:
+                               error = 1;
+                       }
+                       break;
+               case mlt_audio_float:
+                       switch ( requested_format )
+                       {
+                       case mlt_audio_s16:
+                       {
+                               size = channels * samples * sizeof(int16_t);
+                               int16_t *buffer = mlt_pool_alloc( size );
+                               int16_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                       {
+                                               float f = *( q + c * samples + s );
+                                               f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                               *p++ = 32767 * f;
+                                       }
+                               *audio = buffer;
+                               break;
+                       }
+                       case mlt_audio_s32:
+                       {
+                               size = channels * samples * sizeof(int32_t);
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = *q++;
+                                       f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                       *p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
+                               }
+                               *audio = buffer;
+                               break;
+                       }
+                       default:
+                               error = 1;
+                       }
+                       break;
+               default:
+                       error = 1;
+               }
+       }
+       if ( !error )
+       {
+               mlt_frame_set_audio( frame, *audio, requested_format, size, mlt_pool_release );
+               *format = requested_format;
+       }
+       return error;
+}
+
+/** Filter processing.
+*/
+
+static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+{
+       frame->convert_audio = convert_audio;
+       return frame;
+}
+
+/** Constructor for the filter.
+*/
+
+mlt_filter filter_audioconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
+       if ( mlt_filter_init( this, this ) == 0 )
+               this->process = filter_process;
+       return this;
+}
index d4dd697cf67ea0e4016b886e618c781c33688eb7..6e31998fc4d6a8fc254e5f3113ecd442ac2959a6 100644 (file)
 
 #include <framework/mlt_filter.h>
 #include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
 
 #include <stdio.h>
 #include <stdlib.h>
-#define __USE_ISOC99 1
-#include <math.h>
+#include <string.h>
 
 /** 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 );
-       int i, j;
+
+       // Get the filter service
+       mlt_filter filter = mlt_frame_pop_audio( frame );
+
        int from = mlt_properties_get_int( properties, "channelcopy.from" );
        int to = mlt_properties_get_int( properties, "channelcopy.to" );
 
        // Get the producer's audio
        mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
 
-       // Duplicate channels as necessary
+       // Copy channels as necessary
+       switch ( *format )
        {
-               int size = *channels * *samples * 2;
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               
-               mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-               
-               // Duplicate the existing channels
-               for ( i = 0; i < *samples; i++ )
+               case mlt_audio_s16:
+               {
+                       int16_t *f = (int16_t*) *buffer + from;
+                       int16_t *t = (int16_t*) *buffer + to;
+                       int i;
+                       for ( i = 0; i < *samples; i++, f += *channels, t += *channels )
+                               *t = *f;
+                       break;
+               }
+               case mlt_audio_s32:
                {
-                       for ( j = 0; j < *channels; j++ )
-                       {
-                               new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * *channels ) + ( j == to ? from : j ) ];
-                       }
+                       int32_t *f = (int32_t*) *buffer + from * *samples;
+                       int32_t *t = (int32_t*) *buffer + to * *samples;
+                       memcpy( t, f, *samples * sizeof(int32_t) );
+                       break;
                }
-               *buffer = new_buffer;
+               case mlt_audio_float:
+               {
+                       float *f = (float*) *buffer + from * *samples;
+                       float *t = (float*) *buffer + to * *samples;
+                       memcpy( t, f, *samples * sizeof(float) );
+                       break;
+               }
+               default:
+                       mlt_log_error( MLT_FILTER_SERVICE( filter ), "Invalid audio format\n" );
+                       break;
        }
+
        return 0;
 }
 
@@ -73,6 +90,7 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
        mlt_properties_set_int( frame_props, "channelcopy.from", mlt_properties_get_int( properties, "from" ) );
 
        // Override the get_audio method
+       mlt_frame_push_audio( frame, this );
        mlt_frame_push_audio( frame, filter_get_audio );
 
        return frame;
index 882d6f34bc15f2a0368f8d94f6cb02a6a9c7c692..94d3549f5f9ae7518b98e75cca78786fca2f8af8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_mono.c -- mix all channels to a mono signal across n channels
- * Copyright (C) 2003-2006 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -20,6 +20,7 @@
 
 #include <framework/mlt_filter.h>
 #include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 /** 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 );
        int channels_out = mlt_properties_get_int( properties, "mono.channels" );
        int i, j, size;
-       int16_t *new_buffer;
 
        // Get the producer's audio
        mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
 
-       size = *samples * channels_out * sizeof( int16_t );
-       new_buffer = mlt_pool_alloc( size );
-       mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
+       if ( channels_out == -1 )
+               channels_out = *channels;
+       size = *samples * channels_out;
 
-       // Mix
-       for ( i = 0; i < *samples; i++ )
+       switch ( *format )
        {
-               int16_t mixdown = 0;
-               for ( j = 0; j < *channels; j++ )
-                       mixdown += (*buffer)[ ( i * *channels ) + j ] / *channels;
-               for ( j = 0; j < channels_out; j++ )
-                       new_buffer[ ( i * channels_out ) + j ] = mixdown;
+               case mlt_audio_s16:
+               {
+                       size *= sizeof( int16_t );
+                       int16_t *new_buffer = mlt_pool_alloc( size );
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               int16_t mixdown = 0;
+                               for ( j = 0; j < *channels; j++ )
+                                       mixdown += ((int16_t*) *buffer)[ ( i * *channels ) + j ] / *channels;
+                               for ( j = 0; j < channels_out; j++ )
+                                       new_buffer[ ( i * channels_out ) + j ] = mixdown;
+                       }
+                       *buffer = new_buffer;
+                       break;
+               }
+               case mlt_audio_s32:
+               {
+                       size *= sizeof( int32_t );
+                       int32_t *new_buffer = mlt_pool_alloc( size );
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               int32_t mixdown = 0;
+                               for ( j = 0; j < *channels; j++ )
+                                       mixdown += ((int32_t*) *buffer)[ ( j * *channels ) + i ] / *channels;
+                               for ( j = 0; j < channels_out; j++ )
+                                       new_buffer[ ( j * *samples ) + i ] = mixdown;
+                       }
+                       *buffer = new_buffer;
+                       break;
+               }
+               case mlt_audio_float:
+               {
+                       size *= sizeof( float );
+                       float *new_buffer = mlt_pool_alloc( size );
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               float mixdown = 0;
+                               for ( j = 0; j < *channels; j++ )
+                                       mixdown += ((float*) *buffer)[ ( j * *channels ) + i ] / *channels;
+                               for ( j = 0; j < channels_out; j++ )
+                                       new_buffer[ ( j * *samples ) + i ] = mixdown;
+                       }
+                       *buffer = new_buffer;
+                       break;
+               }
+               default:
+                       mlt_log_error( NULL, "[filter mono] Invalid audio format\n" );
+                       break;
+       }
+       if ( size > *samples * channels_out )
+       {
+               mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
+               *channels = channels_out;
        }
 
-       // Apply results
-       *buffer = new_buffer;
-       *channels = channels_out;
-       
        return 0;
 }
 
@@ -88,7 +131,7 @@ mlt_filter filter_mono_init( mlt_profile profile, mlt_service_type type, const c
                if ( arg != NULL )
                        mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", atoi( arg ) );
                else
-                       mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", 2 );
+                       mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", -1 );
        }
        return this;
 }
index cd3f4623053ecaf0eb3c6e2e850ef70a536938f4..5515d2360ad7d40921aefad0ecc1a54cda334590 100644 (file)
@@ -39,7 +39,7 @@ static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *
        NB: Not all transitions will accept a and b frames being the same...
 */
 
-static int filter_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int filter_get_audio( mlt_frame this, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        // Obtain the transition instance
        mlt_transition transition = mlt_frame_pop_audio( this );
index cf7b62ec772fe54db5a509e4da5f3a1d0e82375a..3de7ea79d6fe25786a0223426d9110e9f5a2c323 100644 (file)
@@ -14,7 +14,8 @@ resizer=resize
 imageconverter=imageconvert,avcolour_space
 
 # audio filters
-resampler=resample,soxresample,avresample
+resampler=resample,avresample
+audioconverter=audioconvert
 
 # metadata filters
 data=data_feed:attr_check
index 4baa186f39e814cb5185e025d21f58a3e4566ca4..c0c4019f83f170433b4489155c86b6d2ccc4526b 100644 (file)
@@ -63,11 +63,24 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        return result;
 }
 
-static int get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        mlt_frame nested_frame = mlt_frame_pop_audio( frame );
        int result = mlt_frame_get_audio( nested_frame, buffer, format, frequency, channels, samples );
-       int size = *channels * *samples * sizeof( int16_t );
+       int size = *channels * *samples;
+
+       switch ( *format )
+       {
+               case mlt_audio_s16:
+                       size *= sizeof( int16_t );
+                       break;
+               case mlt_audio_s32:
+                       size *= sizeof( int32_t );
+               case mlt_audio_float:
+                       size *= sizeof( float );
+               default:
+                       mlt_log_error( NULL, "[producer consumer] Invalid audio format\n" );
+       }
        int16_t *new_buffer = mlt_pool_alloc( size );
        mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "audio", new_buffer, size, mlt_pool_release, NULL );
        memcpy( new_buffer, *buffer, size );
index b2b3790a4882f72fe4735dbfb6464692ca44d4c8..756f9fb24d6518721635d09b00d2ab212e4deff9 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <math.h>
 
 
+static int mix_audio( mlt_frame this, mlt_frame that, float weight_start, float weight_end, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+       int ret = 0;
+       int16_t *src, *dest;
+       int frequency_src = *frequency, frequency_dest = *frequency;
+       int channels_src = *channels, channels_dest = *channels;
+       int samples_src = *samples, samples_dest = *samples;
+       int i, j;
+       double d = 0, s = 0;
+
+       mlt_frame_get_audio( that, (void**) &src, format, &frequency_src, &channels_src, &samples_src );
+       mlt_frame_get_audio( this, (void**) &dest, format, &frequency_dest, &channels_dest, &samples_dest );
+
+       int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
+       mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
+       if ( silent )
+               memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
+
+       silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
+       mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
+       if ( silent )
+               memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
+
+       if ( channels_src > 6 )
+               channels_src = 0;
+       if ( channels_dest > 6 )
+               channels_dest = 0;
+       if ( samples_src > 4000 )
+               samples_src = 0;
+       if ( samples_dest > 4000 )
+               samples_dest = 0;
+
+       // determine number of samples to process
+       *samples = samples_src < samples_dest ? samples_src : samples_dest;
+       *channels = channels_src < channels_dest ? channels_src : channels_dest;
+       *buffer = dest;
+       *frequency = frequency_dest;
+
+       // Compute a smooth ramp over start to end
+       float weight = weight_start;
+       float weight_step = ( weight_end - weight_start ) / *samples;
+
+       if ( src == dest )
+       {
+               *samples = samples_src;
+               *channels = channels_src;
+               *buffer = src;
+               *frequency = frequency_src;
+               return ret;
+       }
+
+       // Mixdown
+       for ( i = 0; i < *samples; i++ )
+       {
+               for ( j = 0; j < *channels; j++ )
+               {
+                       if ( j < channels_dest )
+                               d = (double) dest[ i * channels_dest + j ];
+                       if ( j < channels_src )
+                               s = (double) src[ i * channels_src + j ];
+                       dest[ i * channels_dest + j ] = s * weight + d * ( 1.0 - weight );
+               }
+               weight += weight_step;
+       }
+
+       return ret;
+}
+
+// Replacement for broken mlt_frame_audio_mix - this filter uses an inline low pass filter
+// to allow mixing without volume hacking
+static int combine_audio( mlt_frame this, mlt_frame that, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+       int ret = 0;
+       int16_t *src, *dest;
+       int frequency_src = *frequency, frequency_dest = *frequency;
+       int channels_src = *channels, channels_dest = *channels;
+       int samples_src = *samples, samples_dest = *samples;
+       int i, j;
+       double vp[ 6 ];
+       double b_weight = 1.0;
+
+       if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "meta.mixdown" ) )
+               b_weight = 1.0 - mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "meta.volume" );
+
+       mlt_frame_get_audio( that, (void**) &src, format, &frequency_src, &channels_src, &samples_src );
+       mlt_frame_get_audio( this, (void**) &dest, format, &frequency_dest, &channels_dest, &samples_dest );
+
+       int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
+       mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
+       if ( silent )
+               memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
+
+       silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
+       mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
+       if ( silent )
+               memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
+
+       if ( src == dest )
+       {
+               *samples = samples_src;
+               *channels = channels_src;
+               *buffer = src;
+               *frequency = frequency_src;
+               return ret;
+       }
+
+       // determine number of samples to process
+       *samples = samples_src < samples_dest ? samples_src : samples_dest;
+       *channels = channels_src < channels_dest ? channels_src : channels_dest;
+       *buffer = dest;
+       *frequency = frequency_dest;
+
+       for ( j = 0; j < *channels; j++ )
+               vp[ j ] = ( double )dest[ j ];
+
+       double Fc = 0.5;
+       double B = exp(-2.0 * M_PI * Fc);
+       double A = 1.0 - B;
+       double v;
+
+       for ( i = 0; i < *samples; i++ )
+       {
+               for ( j = 0; j < *channels; j++ )
+               {
+                       v = ( double )( b_weight * dest[ i * channels_dest + j ] + src[ i * channels_src + j ] );
+                       v = v < -32767 ? -32767 : v > 32768 ? 32768 : v;
+                       vp[ j ] = dest[ i * channels_dest + j ] = ( int16_t )( v * A + vp[ j ] * B );
+               }
+       }
+
+       return ret;
+}
+
 /** Get the audio.
 */
 
-static int transition_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int transition_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        // Get the b frame from the stack
        mlt_frame b_frame = mlt_frame_pop_audio( frame );
@@ -39,6 +174,9 @@ static int transition_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_fo
        // Get the properties of the b frame
        mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
 
+       // We can only mix s16
+       *format = mlt_audio_s16;
+
        if ( mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( effect ), "combine" ) == 0 )
        {
                double mix_start = 0.5, mix_end = 0.5;
@@ -52,11 +190,11 @@ static int transition_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_fo
                        mix_end = 1 - mix_end;
                }
 
-               mlt_frame_mix_audio( frame, b_frame, mix_start, mix_end, buffer, format, frequency, channels, samples );
+               mix_audio( frame, b_frame, mix_start, mix_end, buffer, format, frequency, channels, samples );
        }
        else
        {
-               mlt_frame_combine_audio( frame, b_frame, buffer, format, frequency, channels, samples );
+               combine_audio( frame, b_frame, buffer, format, frequency, channels, samples );
        }
 
        return 0;
index 2ee9b2066ce9751f918a9b2d6fef07ca6e55d16d..f9a8ba644cb510e7966a90af740ec65ffcd476be 100644 (file)
@@ -273,7 +273,7 @@ static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_fra
                int count = mlt_properties_get_int( this_properties, "count" );
 
                // Default audio args
-               mlt_audio_format fmt = mlt_audio_pcm;
+               mlt_audio_format fmt = mlt_audio_s16;
                int channels = 2;
                int frequency = mlt_properties_get_int( this_properties, "frequency" );
                int samples = mlt_sample_calculator( mlt_properties_get_double( this_properties, "fps" ), frequency, count );
@@ -293,7 +293,7 @@ static void consumer_encode_audio( mlt_consumer this, uint8_t *dv_frame, mlt_fra
                        audio_buffers[ i ] = mlt_pool_alloc( 2 * DV_AUDIO_MAX_SAMPLES );
 
                // Get the audio
-               mlt_frame_get_audio( frame, &pcm, &fmt, &frequency, &channels, &samples );
+               mlt_frame_get_audio( frame, (void**) &pcm, &fmt, &frequency, &channels, &samples );
 
                // Inform the encoder of the number of audio samples
                encoder->samples_this_frame = samples;
index 6fd012c65a997fe3efc5b04b7a8a39322b97ef7b..12501f3dbedf6ac1d78feb5507b7bdbb272d1207 100644 (file)
@@ -361,7 +361,7 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma
        return 0;
 }
 
-static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int producer_get_audio( mlt_frame this, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        int16_t *p;
        int i, j;
@@ -382,20 +382,23 @@ static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_forma
        // Check that we have audio
        if ( decoder->audio->num_channels > 0 )
        {
+               int size = *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t );
+
                // Obtain required values
                *frequency = decoder->audio->frequency;
                *samples = decoder->audio->samples_this_frame;
                *channels = decoder->audio->num_channels;
+               *format = mlt_audio_s16;
 
                // Create a temporary workspace
                for ( i = 0; i < 4; i++ )
                        audio_channels[ i ] = mlt_pool_alloc( DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
        
                // Create a workspace for the result
-               *buffer = mlt_pool_alloc( *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
+               *buffer = mlt_pool_alloc( size );
        
                // Pass the allocated audio buffer as a property
-               mlt_properties_set_data( properties, "audio", *buffer, *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ), ( mlt_destructor )mlt_pool_release, NULL );
+               mlt_frame_set_audio( this, *buffer, *format, size, mlt_pool_release );
        
                // Decode the audio
                dv_decode_full_audio( decoder, dv_data, audio_channels );
index 0c9fe9bff83e93d4b97fbb63375bddb3319b74ae..f1b472160d307c24f8eaf94fb15b3ea298bc44fb 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <framework/mlt_filter.h>
 #include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -33,7 +34,7 @@
 
 #include "jack_rack.h"
 
-#define BUFFER_LEN 204800 * 3
+#define BUFFER_LEN 204800 * 6
 
 static void initialise_jack_ports( mlt_properties properties )
 {
@@ -53,7 +54,8 @@ static void initialise_jack_ports( mlt_properties properties )
                jack_rack_t *jackrack = jack_rack_new( rack_name, mlt_properties_get_int( properties, "channels" ) );
                jack_rack_open_file( jackrack, mlt_properties_get( properties, "src" ) );               
                
-               mlt_properties_set_data( properties, "jackrack", jackrack, 0, NULL, NULL );
+               mlt_properties_set_data( properties, "jackrack", jackrack, 0,
+                       (mlt_destructor) jack_rack_destroy, NULL );
                mlt_properties_set( properties, "_rack_client_name", rack_name );
        }
                
@@ -66,12 +68,18 @@ static void initialise_jack_ports( mlt_properties properties )
        float **jack_input_buffers = mlt_pool_alloc( sizeof(float *) * jack_buffer_size );
 
        // Set properties - released inside filter_close
-       mlt_properties_set_data( properties, "output_buffers", output_buffers, sizeof( jack_ringbuffer_t *) * channels, NULL, NULL );
-       mlt_properties_set_data( properties, "input_buffers", input_buffers, sizeof( jack_ringbuffer_t *) * channels, NULL, NULL );
-       mlt_properties_set_data( properties, "jack_output_ports", jack_output_ports, sizeof( jack_port_t *) * channels, NULL, NULL );
-       mlt_properties_set_data( properties, "jack_input_ports", jack_input_ports, sizeof( jack_port_t *) * channels, NULL, NULL );
-       mlt_properties_set_data( properties, "jack_output_buffers", jack_output_buffers, sizeof( float *) * channels, NULL, NULL );
-       mlt_properties_set_data( properties, "jack_input_buffers", jack_input_buffers, sizeof( float *) * channels, NULL, NULL );
+       mlt_properties_set_data( properties, "output_buffers", output_buffers,
+               sizeof( jack_ringbuffer_t *) * channels, mlt_pool_release, NULL );
+       mlt_properties_set_data( properties, "input_buffers", input_buffers,
+               sizeof( jack_ringbuffer_t *) * channels, mlt_pool_release, NULL );
+       mlt_properties_set_data( properties, "jack_output_ports", jack_output_ports,
+               sizeof( jack_port_t *) * channels, mlt_pool_release, NULL );
+       mlt_properties_set_data( properties, "jack_input_ports", jack_input_ports,
+               sizeof( jack_port_t *) * channels, mlt_pool_release, NULL );
+       mlt_properties_set_data( properties, "jack_output_buffers", jack_output_buffers,
+               sizeof( float *) * channels, mlt_pool_release, NULL );
+       mlt_properties_set_data( properties, "jack_input_buffers", jack_input_buffers,
+               sizeof( float *) * channels, mlt_pool_release, NULL );
 
        // Start Jack processing - required before registering ports
        jack_activate( jack_client );
@@ -84,9 +92,11 @@ static void initialise_jack_ports( mlt_properties properties )
                output_buffers[i] = jack_ringbuffer_create( BUFFER_LEN * sizeof(float) );
                input_buffers[i] = jack_ringbuffer_create( BUFFER_LEN * sizeof(float) );
                snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
-               mlt_properties_set_data( properties, mlt_name, output_buffers[i], BUFFER_LEN * sizeof(float), NULL, NULL );
+               mlt_properties_set_data( properties, mlt_name, output_buffers[i],
+                       BUFFER_LEN * sizeof(float), (mlt_destructor) jack_ringbuffer_free, NULL );
                snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
-               mlt_properties_set_data( properties, mlt_name, input_buffers[i], BUFFER_LEN * sizeof(float), NULL, NULL );
+               mlt_properties_set_data( properties, mlt_name, input_buffers[i],
+                       BUFFER_LEN * sizeof(float), (mlt_destructor) jack_ringbuffer_free, NULL );
                
                for ( in = 0; in < 2; in++ )
                {
@@ -117,12 +127,12 @@ static void initialise_jack_ports( mlt_properties properties )
                        
                        if ( in )
                        {
-                               fprintf( stderr, "jack connect %s to %s\n", rack_name, mlt_name );
+                               mlt_log_verbose( NULL, "JACK connect %s to %s\n", rack_name, mlt_name );
                                jack_connect( jack_client, rack_name, mlt_name );
                        }
                        else
                        {
-                               fprintf( stderr, "jack connect %s to %s\n", mlt_name, rack_name );
+                               mlt_log_verbose( NULL, "JACK connect %s to %s\n", mlt_name, rack_name );
                                jack_connect( jack_client, mlt_name, rack_name );
                        }
                }
@@ -160,7 +170,7 @@ static int jack_process (jack_nframes_t frames, void * data)
                jack_output_buffers[i] = jack_port_get_buffer( jack_output_ports[i], frames );
                if ( ! jack_output_buffers[i] )
                {
-                       fprintf( stderr, "%s: no jack buffer for output port %d\n", __FUNCTION__, i );
+                       mlt_log_error( MLT_FILTER_SERVICE(filter), "no buffer for output port %d\n", i );
                        err = 1;
                        break;
                }
@@ -171,7 +181,7 @@ static int jack_process (jack_nframes_t frames, void * data)
                jack_input_buffers[i] = jack_port_get_buffer( jack_input_ports[i], frames );
                if ( ! jack_input_buffers[i] )
                {
-                       fprintf( stderr, "%s: no jack buffer for input port %d\n", __FUNCTION__, i );
+                       mlt_log_error( MLT_FILTER_SERVICE(filter), "no buffer for input port %d\n", i );
                        err = 1;
                        break;
                }
@@ -179,7 +189,7 @@ static int jack_process (jack_nframes_t frames, void * data)
                // Do not start returning audio until we have sent first mlt frame
                if ( sync && i == 0 && frame_size > 0 )
                        total_size += ring_size;
-               //fprintf(stderr, "sync %d frame_size %d ring_size %d jack_size %d\n", sync, frame_size, ring_size, jack_size );
+               mlt_log_debug( MLT_FILTER_SERVICE(filter), "sync %d frame_size %d ring_size %d jack_size %d\n", sync, frame_size, ring_size, jack_size );
                
                if ( ! sync || ( frame_size > 0  && total_size >= frame_size ) )
                {
@@ -206,7 +216,7 @@ static int jack_process (jack_nframes_t frames, void * data)
 /** Get the audio.
 */
 
-static int jackrack_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int jackrack_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        // Get the filter service
        mlt_filter filter = mlt_frame_pop_audio( frame );
@@ -217,11 +227,13 @@ static int jackrack_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
        int jack_frequency = mlt_properties_get_int( filter_properties, "_sample_rate" );
 
        // Get the producer's audio
+       *format = mlt_audio_float;
        mlt_frame_get_audio( frame, buffer, format, &jack_frequency, channels, samples );
        
        // TODO: Deal with sample rate differences
        if ( *frequency != jack_frequency )
-               fprintf( stderr, "mismatching frequencies in filter jackrack\n" );
+               mlt_log_error( MLT_FILTER_SERVICE( filter ), "mismatching frequencies JACK = %d actual = %d\n",
+                       jack_frequency, *frequency );
        *frequency = jack_frequency;
 
        // Initialise Jack ports and connections if needed
@@ -235,48 +247,27 @@ static int jackrack_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
 //     pthread_cond_t *output_ready = mlt_properties_get_data( filter_properties, "output_ready", NULL );
        
        // Process the audio
-       int16_t *q = *buffer;
-       float sample[ 2 ][ 10000 ];
-       int i, j;
+       float *q = (float*) *buffer;
+       size_t size = *samples * sizeof(float);
+       int j;
 //     struct timespec tm = { 0, 0 };
 
-       // Convert to floats and write into output ringbuffer
-       if ( jack_ringbuffer_write_space( output_buffers[0] ) >= ( *samples * sizeof(float) ) )
+       // Write into output ringbuffer
+       for ( j = 0; j < *channels; j++ )
        {
-               for ( i = 0; i < *samples; i++ )
-                       for ( j = 0; j < *channels; j++ )
-                               sample[ j ][ i ] = ( float )( *q ++ ) / 32768.0;
-
-               for ( j = 0; j < *channels; j++ )
-                       jack_ringbuffer_write( output_buffers[j], ( char * )sample[ j ], *samples * sizeof(float) );
+               if ( jack_ringbuffer_write_space( output_buffers[j] ) >= size )
+                       jack_ringbuffer_write( output_buffers[j], (char*)( q + j * *samples ), size );
        }
 
        // Synchronization phase - wait for signal from Jack process
-       while ( jack_ringbuffer_read_space( input_buffers[ *channels - 1 ] ) < ( *samples * sizeof(float) ) ) ;
+       while ( jack_ringbuffer_read_space( input_buffers[ *channels - 1 ] ) < size ) ;
                //pthread_cond_wait( output_ready, output_lock );
                
-       // Read from input ringbuffer and convert from floats
-       if ( jack_ringbuffer_read_space( input_buffers[0] ) >= ( *samples * sizeof(float) ) )
+       // Read from input ringbuffer
+       for ( j = 0; j < *channels; j++, q++ )
        {
-               // Initialise to silence, but repeat last frame if available in case of 
-               // buffer underrun
-               for ( j = 0; j < *channels; j++ )
-                       jack_ringbuffer_read( input_buffers[j], ( char * )sample[ j ], *samples * sizeof(float) );
-
-               q = *buffer;
-               for ( i = 0; i < *samples; i++ )
-                       for ( j = 0; j < *channels; j++ )
-                       {
-                               if ( sample[ j ][ i ] > 1.0 )
-                                       sample[ j ][ i ] = 1.0;
-                               else if ( sample[ j ][ i ] < -1.0 )
-                                       sample[ j ][ i ] = -1.0;
-                       
-                               if ( sample[ j ][ i ] > 0 )
-                                       *q ++ = 32767 * sample[ j ][ i ];
-                               else
-                                       *q ++ = 32768 * sample[ j ][ i ];
-                       }
+               if ( jack_ringbuffer_read_space( input_buffers[j] ) >= size )
+                       jack_ringbuffer_read( input_buffers[j], (char*)( q + j * *samples ), size );
        }
 
        return 0;
@@ -293,7 +284,7 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
                mlt_frame_push_audio( frame, this );
                mlt_frame_push_audio( frame, jackrack_get_audio );
                
-               if ( mlt_properties_get_int( properties, "_sync" ) )
+               if ( !mlt_properties_get_data( properties, "jackrack", NULL ) )
                        initialise_jack_ports( properties );
        }
 
@@ -303,32 +294,10 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 
 static void filter_close( mlt_filter this )
 {
-       int i;
-       char mlt_name[20];
        mlt_properties properties = MLT_FILTER_PROPERTIES( this );
        jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
-       
        jack_deactivate( jack_client );
        jack_client_close( jack_client );
-       for ( i = 0; i < mlt_properties_get_int( properties, "channels" ); i++ )
-       {
-               snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
-               jack_ringbuffer_free( mlt_properties_get_data( properties, mlt_name, NULL ) );
-               snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
-               jack_ringbuffer_free( mlt_properties_get_data( properties, mlt_name, NULL ) );
-       }
-       mlt_pool_release( mlt_properties_get_data( properties, "output_buffers", NULL ) );
-       mlt_pool_release( mlt_properties_get_data( properties, "input_buffers", NULL ) );
-       mlt_pool_release( mlt_properties_get_data( properties, "jack_output_ports", NULL ) );
-       mlt_pool_release( mlt_properties_get_data( properties, "jack_input_ports", NULL ) );
-       mlt_pool_release( mlt_properties_get_data( properties, "jack_output_buffers", NULL ) );
-       mlt_pool_release( mlt_properties_get_data( properties, "jack_input_buffers", NULL ) );
-       mlt_pool_release( mlt_properties_get_data( properties, "output_lock", NULL ) );
-       mlt_pool_release( mlt_properties_get_data( properties, "output_ready", NULL ) );
-
-       jack_rack_t *jackrack = mlt_properties_get_data( properties, "jackrack", NULL );
-       jack_rack_destroy( jackrack );
-       
        this->parent.close = NULL;
        mlt_service_close( &this->parent );
 }
@@ -362,8 +331,8 @@ mlt_filter filter_jackrack_init( mlt_profile profile, mlt_service_type type, con
                        mlt_properties_set( properties, "_client_name", name );
                        mlt_properties_set_data( properties, "jack_client", jack_client, 0, NULL, NULL );
                        mlt_properties_set_int( properties, "_sample_rate", jack_get_sample_rate( jack_client ) );
-                       mlt_properties_set_data( properties, "output_lock", output_lock, 0, NULL, NULL );
-                       mlt_properties_set_data( properties, "output_ready", output_ready, 0, NULL, NULL );
+                       mlt_properties_set_data( properties, "output_lock", output_lock, 0, mlt_pool_release, NULL );
+                       mlt_properties_set_data( properties, "output_ready", output_ready, 0, mlt_pool_release, NULL );
                        mlt_properties_set_int( properties, "_sync", 1 );
                        mlt_properties_set_int( properties, "channels", 2 );
                }
index 7eff6fab18569214bac84a51de069680c615dd51..02f427a0505a83323b0d84f40eea2ba11b3c9514 100644 (file)
 
 #define BUFFER_LEN 10000
 
-static void initialise_jack_rack( mlt_properties properties, int channels )
+static jack_rack_t* initialise_jack_rack( mlt_properties properties, int channels )
 {
-       int i;
-       char mlt_name[20];
-       
+       jack_rack_t *jackrack = NULL;
+       char *resource = mlt_properties_get( properties, "resource" );
+       if ( !resource && mlt_properties_get( properties, "src" ) )
+               resource = mlt_properties_get( properties, "src" );
+
        // Propogate these for the Jack processing callback
        mlt_properties_set_int( properties, "channels", channels );
 
        // Start JackRack
-       if ( mlt_properties_get( properties, "src" ) )
+       if ( resource )
        {
                // Create JackRack without Jack client name so that it only uses LADSPA
-               jack_rack_t *jackrack = jack_rack_new( NULL, channels );
-               mlt_properties_set_data( properties, "jackrack", jackrack, 0, NULL, NULL );
-               jack_rack_open_file( jackrack, mlt_properties_get( properties, "src" ) );
-       }
-               
-       // Allocate buffers
-       LADSPA_Data **input_buffers = mlt_pool_alloc( sizeof( LADSPA_Data ) * channels );
-       LADSPA_Data **output_buffers = mlt_pool_alloc( sizeof( LADSPA_Data ) * channels );
-
-       // Set properties - released inside filter_close
-       mlt_properties_set_data( properties, "input_buffers", input_buffers, sizeof( LADSPA_Data *) * channels, NULL, NULL );
-       mlt_properties_set_data( properties, "output_buffers", output_buffers, sizeof( LADSPA_Data *) * channels, NULL, NULL );
-
-       // Register Jack ports
-       for ( i = 0; i < channels; i++ )
-       {
-               input_buffers[i] = mlt_pool_alloc( BUFFER_LEN * sizeof( LADSPA_Data ) );
-               snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
-               mlt_properties_set_data( properties, mlt_name, input_buffers[i], BUFFER_LEN * sizeof( LADSPA_Data ), NULL, NULL );
-
-               output_buffers[i] = mlt_pool_alloc( BUFFER_LEN * sizeof( LADSPA_Data ) );
-               snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
-               mlt_properties_set_data( properties, mlt_name, output_buffers[i], BUFFER_LEN * sizeof( LADSPA_Data ), NULL, NULL );
+               jackrack = jack_rack_new( NULL, channels );
+               mlt_properties_set_data( properties, "jackrack", jackrack, 0,
+                       (mlt_destructor) jack_rack_destroy, NULL );
+               jack_rack_open_file( jackrack, resource );
        }
+       return jackrack;
 }
 
 
 /** Get the audio.
 */
 
-static int ladspa_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int ladspa_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        // Get the filter service
        mlt_filter filter = mlt_frame_pop_audio( frame );
@@ -84,51 +68,35 @@ static int ladspa_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
        mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
 
        // Get the producer's audio
+       *format = mlt_audio_float;
        mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
        
        // Initialise LADSPA if needed
        jack_rack_t *jackrack = mlt_properties_get_data( filter_properties, "jackrack", NULL );
        if ( jackrack == NULL )
        {
-               sample_rate = *frequency;
-               initialise_jack_rack( filter_properties, *channels );
-               jackrack = mlt_properties_get_data( filter_properties, "jackrack", NULL );
+               sample_rate = *frequency; // global inside jack_rack
+               jackrack = initialise_jack_rack( filter_properties, *channels );
        }
                
        // Get the filter-specific properties
-       LADSPA_Data **input_buffers = mlt_properties_get_data( filter_properties, "input_buffers", NULL );
-       LADSPA_Data **output_buffers = mlt_properties_get_data( filter_properties, "output_buffers", NULL );
-       
-       // Process the audio
-       int16_t *q = *buffer;
-       int i, j;
+       LADSPA_Data **input_buffers  = mlt_pool_alloc( sizeof( LADSPA_Data* ) * *channels );
+       LADSPA_Data **output_buffers = mlt_pool_alloc( sizeof( LADSPA_Data* ) * *channels );
 
-       // Convert to floats and write into output ringbuffer
-       for ( i = 0; i < *samples; i++ )
-               for ( j = 0; j < *channels; j++ )
-                       input_buffers[ j ][ i ] = ( float )( *q ++ ) / 32768.0;
-
-       // Do LADSPA processing
-       if ( jackrack && process_ladspa( jackrack->procinfo, *samples, input_buffers, output_buffers) == 0 )
+       int i;
+       for ( i = 0; i < *channels; i++ )
        {
-               // Read from output buffer and convert from floats
-               q = *buffer;
-               for ( i = 0; i < *samples; i++ )
-                       for ( j = 0; j < *channels; j++ )
-                       {
-                               if ( output_buffers[ j ][ i ] > 1.0 )
-                                       output_buffers[ j ][ i ] = 1.0;
-                               else if ( output_buffers[ j ][ i ] < -1.0 )
-                                       output_buffers[ j ][ i ] = -1.0;
-                       
-                               if ( output_buffers[ j ][ i ] > 0 )
-                                       *q ++ = 32767 * output_buffers[ j ][ i ];
-                               else
-                                       *q ++ = 32768 * output_buffers[ j ][ i ];
-                       }
+               input_buffers[i]  = (LADSPA_Data*) *buffer + i * *samples;
+               output_buffers[i] = (LADSPA_Data*) *buffer + i * *samples;
        }
 
-       return 0;
+       // Do LADSPA processing
+       int error = jackrack && process_ladspa( jackrack->procinfo, *samples, input_buffers, output_buffers );
+
+       mlt_pool_release( input_buffers );
+       mlt_pool_release( output_buffers );
+
+       return error;
 }
 
 
@@ -137,6 +105,7 @@ static int ladspa_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
 
 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 {
+       if ( mlt_frame_is_test_audio( frame ) == 0 )
        {
                mlt_frame_push_audio( frame, this );
                mlt_frame_push_audio( frame, ladspa_get_audio );
@@ -145,32 +114,6 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
        return frame;
 }
 
-
-static void filter_close( mlt_filter this )
-{
-       int i;
-       char mlt_name[20];
-       mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-       
-       if ( mlt_properties_get_data( properties, "jackrack", NULL ) != NULL )
-       {
-               for ( i = 0; i < mlt_properties_get_int( properties, "channels" ); i++ )
-               {
-                       snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
-                       mlt_pool_release( mlt_properties_get_data( properties, mlt_name, NULL ) );
-                       snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
-                       mlt_pool_release( mlt_properties_get_data( properties, mlt_name, NULL ) );
-               }
-               mlt_pool_release( mlt_properties_get_data( properties, "output_buffers", NULL ) );
-               mlt_pool_release( mlt_properties_get_data( properties, "input_buffers", NULL ) );
-       
-               jack_rack_t *jackrack = mlt_properties_get_data( properties, "jackrack", NULL );
-               jack_rack_destroy( jackrack );
-       }       
-       this->parent.close = NULL;
-       mlt_service_close( &this->parent );
-}
-
 /** Constructor for the filter.
 */
 
@@ -180,11 +123,8 @@ mlt_filter filter_ladspa_init( mlt_profile profile, mlt_service_type type, const
        if ( this != NULL )
        {
                mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-               
                this->process = filter_process;
-               this->close = filter_close;
-               
-               mlt_properties_set( properties, "src", arg );
+               mlt_properties_set( properties, "resource", arg );
        }
        return this;
 }
index 3bc747ced4d46b811bb23707e284d55c009bbf80..e73eef3323efef5d8f651c1a11349302719b7280 100644 (file)
@@ -163,7 +163,7 @@ 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 );
@@ -186,6 +186,7 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
                limiter_level = mlt_properties_get_double( properties, "volume.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 );
 
@@ -217,7 +218,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 );
                }
        }
        
@@ -248,7 +249,7 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
        // 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++ )
index 9ff4d9e17a64b9d90c67f1ec97b07c83751f71b5..8a4543ee40ffad7ab8839e91d40c3bb7065daccb 100644 (file)
 
 #include <framework/mlt_filter.h>
 #include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <samplerate.h>
+#include <string.h>
 
 #define BUFFER_LEN 20480
 #define RESAMPLE_TYPE SRC_SINC_FASTEST
 /** Get the audio.
 */
 
-static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
-       // Get the properties of the frame
-       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
        // Get the filter service
        mlt_filter filter = mlt_frame_pop_audio( frame );
 
@@ -44,113 +43,88 @@ static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
 
        // Get the resample information
        int output_rate = mlt_properties_get_int( filter_properties, "frequency" );
-       SRC_STATE *state = mlt_properties_get_data( filter_properties, "state", NULL );
-       float *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
-       float *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
-       int channels_avail = *channels;
-       SRC_DATA data;
-       int i;
+       int error = 0;
 
        // If no resample frequency is specified, default to requested value
        if ( output_rate == 0 )
                output_rate = *frequency;
 
        // Get the producer's audio
-       mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
-
-       // Duplicate channels as necessary
-       if ( channels_avail < *channels )
-       {
-               int size = *channels * *samples * sizeof( int16_t );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               int j, k = 0;
-               
-               // Duplicate the existing channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       for ( j = 0; j < *channels; j++ )
-                       {
-                               new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
-                               k = ( k + 1 ) % channels_avail;
-                       }
-               }
-               
-               // Update the audio buffer now - destroys the old
-               mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-               
-               *buffer = new_buffer;
-       }
-       else if ( channels_avail == 6 && *channels == 2 )
-       {
-               // Nasty hack for ac3 5.1 audio - may be a cause of failure?
-               int size = *channels * *samples * sizeof( int16_t );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               
-               // Drop all but the first *channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
-                       new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
-               }
-
-               // Update the audio buffer now - destroys the old
-               mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-               
-               *buffer = new_buffer;
-       }
+       if ( *format != mlt_audio_s16 )
+               *format = mlt_audio_float;
+       mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
 
        // Return now if no work to do
        if ( output_rate != *frequency )
        {
-               float *p = input_buffer;
-               float *end = p + *samples * *channels;
-               int16_t *q = *buffer;
-
-               // Convert to floating point
-               while( p != end )
-                       *p ++ = ( float )( *q ++ ) / 32768.0;
-
-               // Resample
+               // Do not convert to float unless we need to change the rate
+               if ( *format != mlt_audio_float )
+               {
+                       *format = mlt_audio_float;
+                       mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
+               }
+               float *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
+               float *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
+               SRC_DATA data;
                data.data_in = input_buffer;
                data.data_out = output_buffer;
                data.src_ratio = ( float ) output_rate / ( float ) *frequency;
                data.input_frames = *samples;
                data.output_frames = BUFFER_LEN / *channels;
                data.end_of_input = 0;
-               i = src_process( state, &data );
-               if ( i == 0 )
+
+               SRC_STATE *state = mlt_properties_get_data( filter_properties, "state", NULL );
+               if ( !state || mlt_properties_get_int( filter_properties, "channels" ) != *channels )
+               {
+                       // Recreate the resampler if the number of channels changed
+                       state = src_new( RESAMPLE_TYPE, *channels, &error );
+                       mlt_properties_set_data( filter_properties, "state", state, 0, (mlt_destructor) src_delete, NULL );
+                       mlt_properties_set_int( filter_properties, "channels", *channels );
+               }
+
+               // Convert to interleaved
+               float *q = (float*) *buffer;
+               float *p = input_buffer;
+               int s, c;
+               for ( s = 0; s < *samples; s++ )
+                       for ( c = 0; c < *channels; c++ )
+                               *p++ = *( q + c * *samples + s );
+
+               // Resample the audio
+               error = src_process( state, &data );
+               if ( !error )
                {
+                       int size = data.output_frames_gen * *channels * sizeof(float);
+
+                       // Resize if necessary
                        if ( data.output_frames_gen > *samples )
                        {
-                               *buffer = mlt_pool_realloc( *buffer, data.output_frames_gen * *channels * sizeof( int16_t ) );
-                               mlt_properties_set_data( properties, "audio", *buffer, *channels * data.output_frames_gen * 2, mlt_pool_release, NULL );
+                               *buffer = mlt_pool_realloc( *buffer, size );
+                               mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
                        }
 
-                       *samples = data.output_frames_gen;
-                       *frequency = output_rate;
-
-                       p = output_buffer;
-                       q = *buffer;
-                       end = p + *samples * *channels;
-                       
-                       // Convert from floating back to signed 16bit
-                       while( p != end )
+                       // Convert to non-interleaved
+                       p = (float*) *buffer;
+                       for ( c = 0; c < *channels; c++ )
                        {
-                               if ( *p > 1.0 )
-                                       *p = 1.0;
-                               if ( *p < -1.0 )
-                                       *p = -1.0;
-                               if ( *p > 0 )
-                                       *q ++ = 32767 * *p ++;
-                               else
-                                       *q ++ = 32768 * *p ++;
+                               float *q = output_buffer + c;
+                               int i = data.output_frames_gen + 1;
+                               while ( --i  )
+                               {
+                                       *p++ = *q;
+                                       q += *channels;
+                               }
                        }
+
+                       // Update output variables
+                       *samples = data.output_frames_gen;
+                       *frequency = output_rate;
                }
                else
-                       fprintf( stderr, "resample_get_audio: %s %d,%d,%d\n", src_strerror( i ), *frequency, *samples, output_rate );
+                       mlt_log_error( MLT_FILTER_SERVICE( filter ), "%s %d,%d,%d\n", src_strerror( error ), *frequency, *samples, output_rate );
        }
 
-       return 0;
+       return error;
 }
 
 /** Filter processing.
index 63ef54052d5772f7459419d4ba15433b5040547e..42582c6dd8e909ad11f3f56b0067dcd7d78bb85d 100644 (file)
@@ -342,7 +342,7 @@ static int consumer_play_audio( consumer_sdl this, mlt_frame frame, int init_aud
 {
        // Get the properties of this consumer
        mlt_properties properties = this->properties;
-       mlt_audio_format afmt = mlt_audio_pcm;
+       mlt_audio_format afmt = mlt_audio_s16;
 
        // Set the preferred params of the test card signal
        int channels = mlt_properties_get_int( properties, "channels" );
@@ -354,7 +354,7 @@ static int consumer_play_audio( consumer_sdl this, mlt_frame frame, int init_aud
        int16_t *pcm;
        int bytes;
 
-       mlt_frame_get_audio( frame, &pcm, &afmt, &frequency, &channels, &samples );
+       mlt_frame_get_audio( frame, (void**) &pcm, &afmt, &frequency, &channels, &samples );
        *duration = ( ( samples * 1000 ) / frequency );
 
        if ( mlt_properties_get_int( properties, "audio_off" ) )
index d2ef2d24f6dbbaf78e676c0b927dd0097b1d86aa..861c0d2cde9c5dd31ee0f34212c81a88804add8e 100644 (file)
@@ -179,14 +179,11 @@ static int create_effect( mlt_filter this, char *value, int count, int channel,
 /** 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 )
 {
 #if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,3,0))
        SOX_SAMPLE_LOCALS;
 #endif
-       // Get the properties of the frame
-       mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
        // Get the filter service
        mlt_filter filter = mlt_frame_pop_audio( frame );
 
@@ -194,55 +191,14 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
        mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
 
        // Get the properties
-       st_sample_t *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
+       st_sample_t *input_buffer;// = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
        st_sample_t *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
-       int channels_avail = *channels;
        int i; // channel
        int count = mlt_properties_get_int( filter_properties, "_effect_count" );
 
        // Get the producer's audio
-       mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
-
-       // Duplicate channels as necessary
-       if ( channels_avail < *channels )
-       {
-               int size = *channels * *samples * sizeof( int16_t );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               int j, k = 0;
-               
-               // Duplicate the existing channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       for ( j = 0; j < *channels; j++ )
-                       {
-                               new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
-                               k = ( k + 1 ) % channels_avail;
-                       }
-               }
-               
-               // Update the audio buffer now - destroys the old
-               mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-               
-               *buffer = new_buffer;
-       }
-       else if ( channels_avail == 6 && *channels == 2 )
-       {
-               // Nasty hack for ac3 5.1 audio - may be a cause of failure?
-               int size = *channels * *samples * sizeof( int16_t );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               
-               // Drop all but the first *channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
-                       new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
-               }
-
-               // Update the audio buffer now - destroys the old
-               mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-               
-               *buffer = new_buffer;
-       }
+       *format = mlt_audio_s32;
+       mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
 
        // Even though some effects are multi-channel aware, it is not reliable
        // We must maintain a separate effect state for each channel
@@ -296,32 +252,21 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
                }
                if ( *samples > 0 && count > 0 )
                {
+                       input_buffer = (st_sample_t*) *buffer + i * *samples;
                        st_sample_t *p = input_buffer;
-                       st_sample_t *end = p + *samples;
-                       int16_t *q = *buffer + i;
                        st_size_t isamp = *samples;
                        st_size_t osamp = *samples;
                        double rms = 0;
-                       int j;
+                       int j = *samples + 1;
                        char *normalise = mlt_properties_get( filter_properties, "normalise" );
                        double normalised_gain = 1.0;
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(13,0,0))
-                       st_sample_t dummy_clipped_count = 0;
-#endif
                        
-                       // Convert to sox encoding
-                       while( p != end )
+                       // Convert from interleaved
+                       while( --j )
                        {
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(13,0,0))
-                               *p = ST_SIGNED_WORD_TO_SAMPLE( *q, dummy_clipped_count );
-#else
-                               *p = ST_SIGNED_WORD_TO_SAMPLE( *q );
-#endif
                                // Compute rms amplitude while we are accessing each sample
                                rms += ( double )*p * ( double )*p;
-                               
                                p ++;
-                               q += *channels;
                        }
                        
                        // Compute final rms amplitude
@@ -411,20 +356,9 @@ static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format
                                        }
                                }
                        }
-                       
-                       // Convert back to signed 16bit
-                       p = input_buffer;
-                       q = *buffer + i;
-                       end = p + *samples;
-                       while ( p != end )
-                       {
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(13,0,0))
-                               *q = ST_SAMPLE_TO_SIGNED_WORD( *p ++, dummy_clipped_count );
-#else
-                               *q = ST_SAMPLE_TO_SIGNED_WORD( *p ++ );
-#endif
-                               q += *channels;
-                       }
+
+                       // Write back
+                       memcpy( output_buffer, input_buffer, *samples * sizeof(st_sample_t) );
                }
        }
 
index 1c1e7ced5d518b6ac19b830e1b31e0abed75d080..77f9216676a1cfbf656713446f052bffb05a6822 100644 (file)
@@ -206,7 +206,7 @@ static double producer_time_of_frame( mlt_producer this, mlt_position position )
 /** Get the audio from a frame.
 */
 
-static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        // Get the properties from the frame
        mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
@@ -314,11 +314,14 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
                // Now handle the audio if we have enough
                if ( audio_used >= *samples )
                {
-                       *buffer = mlt_pool_alloc( *samples * *channels * sizeof( int16_t ) );
-                       memcpy( *buffer, audio_buffer, *samples * *channels * sizeof( int16_t ) );
+                       int size = *samples * *channels * sizeof( int16_t );
+
+                       *format = mlt_audio_s16;
+                       *buffer = mlt_pool_alloc( size );
+                       memcpy( *buffer, audio_buffer, size );
                        audio_used -= *samples;
                        memmove( audio_buffer, &audio_buffer[ *samples * *channels ], audio_used * *channels * sizeof( int16_t ) );
-                       mlt_properties_set_data( frame_properties, "audio", *buffer, 0, mlt_pool_release, NULL );
+                       mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
                }
                else
                {