]> git.sesse.net Git - mlt/commitdiff
Add audiochannels normalization filter.
authorDan Dennedy <dan@dennedy.org>
Sat, 7 May 2011 03:52:25 +0000 (20:52 -0700)
committerDan Dennedy <dan@dennedy.org>
Sat, 7 May 2011 03:52:25 +0000 (20:52 -0700)
Refactors code from the resamplers into a new filter to be more
manageable. Eventually, we can add options on what to do when
adding/removing channels.

src/modules/avformat/filter_avresample.c
src/modules/core/Makefile
src/modules/core/factory.c
src/modules/core/filter_audiochannels.c [new file with mode: 0644]
src/modules/core/loader.ini
src/modules/resample/filter_resample.c

index 5c19cf8b9e2ad8884d4294160bf5fbfdb5842fd2..d6260ce3104bb4dde7188f36feb4aec3a4104108 100644 (file)
@@ -48,57 +48,13 @@ static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
        // Obtain the resample context if it exists
        ReSampleContext *resample = mlt_properties_get_data( filter_properties, "audio_resample", NULL );
 
-       // Used to return number of channels in the source
-       int channels_avail = *channels;
-
        // If no resample frequency is specified, default to requested value
        if ( output_rate == 0 )
                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
-       if ( channels_avail < *channels )
-       {
-               int size = mlt_audio_format_size( *format, *samples, *channels );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               int i, j, k;
-               
-               // Duplicate the existing channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       for ( j = 0; j < *channels; j++ )
-                       {
-                               new_buffer[ ( i * *channels ) + j ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + k ];
-                               k = ( k + 1 ) % channels_avail;
-                       }
-               }
-               
-               // Update the audio buffer now - destroys the old
-               mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
-
-               *buffer = new_buffer;
-       }
-       else if ( channels_avail > *channels )
-       {
-               int size = mlt_audio_format_size( *format, *samples, *channels );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               int i, j;
-               
-               // Drop all but the first *channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       for ( j = 0; j < *channels; j++ )
-                               new_buffer[ ( i * *channels ) + j ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + j ];
-               }
-
-               // Update the audio buffer now - destroys the old
-               mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
-
-               *buffer = new_buffer;
-       }
+       int error = mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
+       if ( error ) return error;
 
        // Return now if no work to do
        if ( output_rate != *frequency )
@@ -106,6 +62,13 @@ static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
                // Will store number of samples created
                int used = 0;
 
+               // Do not convert to s16 unless we need to change the rate
+               if ( *format != mlt_audio_s16 )
+               {
+                       *format = mlt_audio_s16;
+                       mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
+               }
+
                // Create a resampler if nececessary
                if ( resample == NULL || *frequency != mlt_properties_get_int( filter_properties, "last_frequency" ) )
                {
@@ -149,7 +112,7 @@ static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
                mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
        }
 
-       return 0;
+       return error;
 }
 
 /** Filter processing.
index 788319c9f622ade2232ddf5af98d59dd50f7217b..b0a653c237a2c819079c1280fd91f02f1427f9b2 100644 (file)
@@ -13,6 +13,7 @@ OBJS = factory.o \
           producer_loader.o \
           producer_noise.o \
           producer_ppm.o \
+          filter_audiochannels.o \
           filter_audioconvert.o \
           filter_audiowave.o \
           filter_brightness.o \
index 51fe96357db3c0133b36ccaa5f25a6eeaaa7fb27..9f207faab46289361dd5cdf096a53db450928d42 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_audiochannels_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_audiowave_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 );
@@ -56,6 +57,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, "audiochannels", filter_audiochannels_init );
        MLT_REGISTER( filter_type, "audioconvert", filter_audioconvert_init );
        MLT_REGISTER( filter_type, "audiowave", filter_audiowave_init );
        MLT_REGISTER( filter_type, "brightness", filter_brightness_init );
diff --git a/src/modules/core/filter_audiochannels.c b/src/modules/core/filter_audiochannels.c
new file mode 100644 (file)
index 0000000..dc2b00f
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * filter_audiochannels.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 <string.h>
+
+static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+       // Used to return number of channels in the source
+       int channels_avail = *channels;
+
+       // Get the producer's audio
+       int error = mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
+       if ( error ) return error;
+
+       if ( channels_avail < *channels )
+       {
+               int size = mlt_audio_format_size( *format, *samples, *channels );
+               int16_t *new_buffer = mlt_pool_alloc( size );
+
+               // Duplicate the existing channels
+               if ( *format == mlt_audio_s16 )
+               {
+                       int i, j, k;
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               for ( j = 0; j < *channels; j++ )
+                               {
+                                       new_buffer[ ( i * *channels ) + j ]     = ((int16_t*)(*buffer))[ ( i * channels_avail ) + k ];
+                                       k = ( k + 1 ) % channels_avail;
+                               }
+                       }
+               }
+               else
+               {
+                       // non-interleaved
+                       int size_avail = mlt_audio_format_size( *format, *samples, channels_avail );
+                       int32_t *p = (int32_t*) new_buffer;
+                       int i = *channels / channels_avail;
+                       while ( i-- )
+                       {
+                               memcpy( p, *buffer, size_avail );
+                               p += size_avail / sizeof(*p);
+                       }
+                       i = *channels % channels_avail;
+                       if ( i )
+                       {
+                               size_avail = mlt_audio_format_size( *format, *samples, i );
+                               memcpy( p, *buffer, size_avail );
+                       }
+               }
+               // Update the audio buffer now - destroys the old
+               mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
+               *buffer = new_buffer;
+       }
+       else if ( channels_avail > *channels )
+       {
+               int size = mlt_audio_format_size( *format, *samples, *channels );
+               int16_t *new_buffer = mlt_pool_alloc( size );
+
+               // Drop all but the first *channels
+               if ( *format == mlt_audio_s16 )
+               {
+                       int i, j;
+                       for ( i = 0; i < *samples; i++ )
+                               for ( j = 0; j < *channels; j++ )
+                                       new_buffer[ ( i * *channels ) + j ]     = ((int16_t*)(*buffer))[ ( i * channels_avail ) + j ];
+               }
+               else
+               {
+                       // non-interleaved
+                       memcpy( new_buffer, *buffer, size );
+               }
+               // Update the audio buffer now - destroys the old
+               mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
+               *buffer = new_buffer;
+       }
+       return error;
+}
+
+/** Filter processing.
+*/
+
+static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
+{
+       mlt_frame_push_audio( frame, filter_get_audio );
+       return frame;
+}
+
+/** Constructor for the filter.
+*/
+
+mlt_filter filter_audiochannels_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+       mlt_filter filter = mlt_filter_new();
+       if ( filter )
+               filter->process = filter_process;
+       return filter;
+}
index 09dbd5114b3e0360bbb89d6a117b73a9e074529c..3138581e01cf83e37d0a6bf4e28e12f5dd6eeba1 100644 (file)
@@ -13,7 +13,8 @@ rescaler=swscale,gtkrescale,rescale
 resizer=resize
 
 # audio filters
-resampler=resample,avresample
+channels=audiochannels
+resampler=avresample,resample
 
 # metadata filters
 data=data_feed:attr_check
index c536be74234717ece41e2d984e7a5d3d8020fa0a..274fbd6714c6d2d02f0f1cd205964a9a38f2cc75 100644 (file)
@@ -45,66 +45,19 @@ static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format
 
        // Get the resample information
        int output_rate = mlt_properties_get_int( filter_properties, "frequency" );
-       int error = 0;
-
-       // Used to return number of channels in the source
-       int channels_avail = *channels;
 
        // 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 );
-
-       if ( channels_avail < *channels )
-       {
-               int size = mlt_audio_format_size( *format, *samples, *channels );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               int sample_size_factor = mlt_audio_format_size( *format, 1, 1 ) / sizeof( *new_buffer );
-               int i, j, k;
-
-               // Duplicate the existing channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       for ( j = 0; j < *channels; j++ )
-                       {
-                               new_buffer[ ( ( i * *channels ) + j ) * sample_size_factor ]
-                                       = ((int16_t*)(*buffer))[ ( ( i * channels_avail ) + k ) * sample_size_factor ];
-                               k = ( k + 1 ) % channels_avail;
-                       }
-               }
-
-               // Update the audio buffer now - destroys the old
-               mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
-
-               *buffer = new_buffer;
-       }
-       else if ( channels_avail > *channels )
-       {
-               int size = mlt_audio_format_size( *format, *samples, *channels );
-               int16_t *new_buffer = mlt_pool_alloc( size );
-               int sample_size_factor = mlt_audio_format_size( *format, 1, 1 ) / sizeof( *new_buffer );
-               int i, j;
-
-               // Drop all but the first *channels
-               for ( i = 0; i < *samples; i++ )
-               {
-                       for ( j = 0; j < *channels; j++ )
-                               new_buffer[ ( ( i * *channels ) + j ) * sample_size_factor ]
-                                       = ((int16_t*)(*buffer))[ ( ( i * channels_avail ) + j ) * sample_size_factor ];
-               }
-
-               // Update the audio buffer now - destroys the old
-               mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
-
-               *buffer = new_buffer;
-       }
+       int error = mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
+       if ( error ) return error;
 
        // Return now if no work to do
        if ( output_rate != *frequency )
        {
-               mlt_log_verbose( MLT_FILTER_SERVICE(filter), "channels %d samples %d frequency %d -> %d\n",
+               mlt_log_debug( MLT_FILTER_SERVICE(filter), "channels %d samples %d frequency %d -> %d\n",
                        *channels, *samples, *frequency, output_rate );
 
                // Do not convert to float unless we need to change the rate