barjac

Untitled

Jan 3rd, 2011
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.20 KB | None | 0 0
  1. /*
  2.  * filter_sox.c -- apply any number of SOX effects using libst
  3.  * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
  4.  * Author: Dan Dennedy <dan@dennedy.org>
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2.1 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include <framework/mlt_filter.h>
  22. #include <framework/mlt_frame.h>
  23. #include <framework/mlt_tokeniser.h>
  24. #include <framework/mlt_log.h>
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <math.h>
  30.  
  31. // TODO: does not support multiple effects with SoX v14.1.0+
  32.  
  33. #ifdef SOX14
  34. #   include <sox.h>
  35. #   define ST_EOF SOX_EOF
  36. #   define ST_SUCCESS SOX_SUCCESS
  37. #   define st_sample_t sox_sample_t
  38. #   define eff_t sox_effect_t*
  39. #   define ST_LIB_VERSION_CODE SOX_LIB_VERSION_CODE
  40. #   define ST_LIB_VERSION SOX_LIB_VERSION
  41. #   if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,2,0))
  42. #       define st_size_t size_t
  43. #   else
  44. #       define st_size_t sox_size_t
  45. #   endif
  46. #   define ST_SIGNED_WORD_TO_SAMPLE(d,clips) SOX_SIGNED_16BIT_TO_SAMPLE(d,clips)
  47. #   if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
  48. #       define ST_SSIZE_MIN SOX_SAMPLE_MIN
  49. #   else
  50. #       define ST_SSIZE_MIN SOX_SSIZE_MIN
  51. #   endif
  52. #       define ST_SAMPLE_TO_SIGNED_WORD(d,clips) SOX_SAMPLE_TO_SIGNED_16BIT(d,clips)
  53. #else
  54. #   include <st.h>
  55. #endif
  56.  
  57. #define BUFFER_LEN 8192
  58. #define AMPLITUDE_NORM 0.2511886431509580 /* -12dBFS */
  59. #define AMPLITUDE_MIN 0.00001
  60.  
  61. /** Compute the mean of a set of doubles skipping unset values flagged as -1
  62. */
  63. static inline double mean( double *buf, int count )
  64. {
  65.     double mean = 0;
  66.     int i;
  67.     int j = 0;
  68.    
  69.     for ( i = 0; i < count; i++ )
  70.     {
  71.         if ( buf[ i ] != -1.0 )
  72.         {
  73.             mean += buf[ i ];
  74.             j ++;
  75.         }
  76.     }
  77.     if ( j > 0 )
  78.         mean /= j;
  79.    
  80.     return mean;
  81. }
  82.  
  83. #if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
  84. static void delete_effect( eff_t effp )
  85. {
  86.     free( effp->priv );
  87.     free( (void*)effp->in_encoding );
  88.     free( effp );
  89. }
  90. #endif
  91.  
  92. /** Create an effect state instance for a channels
  93. */
  94. static int create_effect( mlt_filter this, char *value, int count, int channel, int frequency )
  95. {
  96.     mlt_tokeniser tokeniser = mlt_tokeniser_init();
  97.     char id[ 256 ];
  98.     int error = 1;
  99.  
  100.     // Tokenise the effect specification
  101.     mlt_tokeniser_parse_new( tokeniser, value, " " );
  102.     if ( tokeniser->count < 1 )
  103.         return error;
  104.  
  105.     // Locate the effect
  106.     mlt_destructor effect_destructor = mlt_pool_release;
  107. #ifdef SOX14
  108.     //fprintf(stderr, "%s: effect %s count %d\n", __FUNCTION__, tokeniser->tokens[0], tokeniser->count );
  109. #if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
  110.     sox_effect_handler_t const *eff_handle = sox_find_effect( tokeniser->tokens[0] );
  111.     if (eff_handle == NULL ) return error;
  112.     eff_t eff = sox_create_effect( eff_handle );
  113.     effect_destructor = ( mlt_destructor ) delete_effect;
  114.     sox_encodinginfo_t *enc = calloc( 1, sizeof( sox_encodinginfo_t ) );
  115.     enc->encoding = SOX_ENCODING_SIGN2;
  116.     enc->bits_per_sample = 16;
  117.     eff->in_encoding = eff->out_encoding = enc;
  118. #else
  119.     eff_t eff = mlt_pool_alloc( sizeof( sox_effect_t ) );
  120.     sox_create_effect( eff, sox_find_effect( tokeniser->tokens[0] ) );
  121. #endif
  122.     int opt_count = tokeniser->count - 1;
  123. #else
  124.     eff_t eff = mlt_pool_alloc( sizeof( struct st_effect ) );
  125.     int opt_count = st_geteffect_opt( eff, tokeniser->count, tokeniser->tokens );
  126. #endif
  127.    
  128.     // If valid effect
  129.     if ( opt_count != ST_EOF )
  130.     {
  131.         // Supply the effect parameters
  132. #ifdef SOX14
  133. #if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,2,0))
  134.         if ( sox_effect_options( eff, opt_count, &tokeniser->tokens[ tokeniser->count > 1 ? 1 : 0  ] ) == ST_SUCCESS )
  135. #else
  136.         if ( ( * eff->handler.getopts )( eff, opt_count, &tokeniser->tokens[ tokeniser->count > 1 ? 1 : 0  ] ) == ST_SUCCESS )
  137. #endif
  138. #else
  139.         if ( ( * eff->h->getopts )( eff, opt_count, &tokeniser->tokens[ tokeniser->count - opt_count ] ) == ST_SUCCESS )
  140. #endif
  141.         {
  142.             // Set the sox signal parameters
  143. #if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
  144.             eff->in_signal.rate = frequency;
  145.             eff->out_signal.rate = frequency;
  146.             eff->in_signal.channels = 1;
  147.             eff->out_signal.channels = 1;
  148.             eff->in_signal.precision = 16;
  149.             eff->out_signal.precision = 16;
  150.             eff->in_signal.length = 0;
  151.             eff->out_signal.length = 0;
  152. #else
  153.             eff->ininfo.rate = frequency;
  154.             eff->outinfo.rate = frequency;
  155.             eff->ininfo.channels = 1;
  156.             eff->outinfo.channels = 1;
  157. #endif
  158.            
  159.             // Start the effect
  160. #ifdef SOX14
  161.             if ( ( * eff->handler.start )( eff ) == ST_SUCCESS )
  162. #else
  163.             if ( ( * eff->h->start )( eff ) == ST_SUCCESS )
  164. #endif
  165.             {
  166.                 // Construct id
  167.                 sprintf( id, "_effect_%d_%d", count, channel );
  168.  
  169.                 // Save the effect state
  170.                 mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), id, eff, 0, effect_destructor, NULL );
  171.                 error = 0;
  172.             }
  173.         }
  174.     }
  175.     // Some error occurred so delete the temp effect state
  176.     if ( error == 1 )
  177.         effect_destructor( eff );
  178.    
  179.     mlt_tokeniser_close( tokeniser );
  180.    
  181.     return error;
  182. }
  183.  
  184. /** Get the audio.
  185. */
  186.  
  187. static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
  188. {
  189. #if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,3,0))
  190.     SOX_SAMPLE_LOCALS;
  191. #endif
  192.     // Get the filter service
  193.     mlt_filter filter = mlt_frame_pop_audio( frame );
  194.  
  195.     // Get the filter properties
  196.     mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
  197.  
  198.     // Get the properties
  199.     st_sample_t *input_buffer;// = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
  200.     st_sample_t *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
  201.     int i; // channel
  202.     int count = mlt_properties_get_int( filter_properties, "_effect_count" );
  203.  
  204.     // Get the producer's audio
  205.     *format = mlt_audio_s32;
  206.     mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
  207.  
  208.     // Even though some effects are multi-channel aware, it is not reliable
  209.     // We must maintain a separate effect state for each channel
  210.     for ( i = 0; i < *channels; i++ )
  211.     {
  212.         char id[ 256 ];
  213.         sprintf( id, "_effect_0_%d", i );
  214.        
  215.         // Get an existing effect state
  216.         eff_t e = mlt_properties_get_data( filter_properties, id, NULL );
  217.        
  218.         // Validate the existing effect state
  219. #if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,1,0))
  220.         if ( e != NULL && ( e->in_signal.rate != *frequency ||
  221.                             e->out_signal.rate != *frequency ) )
  222. #else
  223.         if ( e != NULL && ( e->ininfo.rate != *frequency ||
  224.                             e->outinfo.rate != *frequency ) )
  225. #endif
  226.             e = NULL;
  227.        
  228.         // (Re)Create the effect state
  229.         if ( e == NULL )
  230.         {
  231.             int j = 0;
  232.            
  233.             // Reset the count
  234.             count = 0;
  235.    
  236.             // Loop over all properties
  237.             for ( j = 0; j < mlt_properties_count( filter_properties ); j ++ )
  238.             {
  239.                 // Get the name of this property
  240.                 char *name = mlt_properties_get_name( filter_properties, j );
  241.    
  242.                 // If the name does not contain a . and matches effect
  243.                 if ( !strncmp( name, "effect", 6 ) )
  244.                 {
  245.                     // Get the effect specification
  246.                     char *value = mlt_properties_get( filter_properties, name );
  247.    
  248.                     // Create an instance
  249.                     if ( create_effect( filter, value, count, i, *frequency ) == 0 )
  250.                         count ++;
  251.                 }
  252.             }
  253.            
  254.             // Save the number of filters
  255.             mlt_properties_set_int( filter_properties, "_effect_count", count );
  256.            
  257.         }
  258.         if ( *samples > 0 && count > 0 )
  259.         {
  260.             input_buffer = (st_sample_t*) *buffer + i * *samples;
  261.             st_sample_t *p = input_buffer;
  262.             st_size_t isamp = *samples;
  263.             st_size_t osamp = *samples;
  264.             double rms = 0;
  265.             int j = *samples + 1;
  266.             char *normalise = mlt_properties_get( filter_properties, "normalise" );
  267.             double normalised_gain = 1.0;
  268.            
  269.             // Convert from interleaved
  270.             while( --j )
  271.             {
  272.                 // Compute rms amplitude while we are accessing each sample
  273.                 rms += ( double )*p * ( double )*p;
  274.                 p ++;
  275.             }
  276.            
  277.             // Compute final rms amplitude
  278.             rms = sqrt( rms / *samples / ST_SSIZE_MIN / ST_SSIZE_MIN );
  279.            
  280.             if ( normalise )
  281.             {
  282.                 int window = mlt_properties_get_int( filter_properties, "window" );
  283.                 double *smooth_buffer = mlt_properties_get_data( filter_properties, "smooth_buffer", NULL );
  284.                 double max_gain = mlt_properties_get_double( filter_properties, "max_gain" );
  285.                
  286.                 // Default the maximum gain factor to 20dBFS
  287.                 if ( max_gain == 0 )
  288.                     max_gain = 10.0;
  289.                
  290.                 // The smoothing buffer prevents radical shifts in the gain level
  291.                 if ( window > 0 && smooth_buffer != NULL )
  292.                 {
  293.                     int smooth_index = mlt_properties_get_int( filter_properties, "_smooth_index" );
  294.                     smooth_buffer[ smooth_index ] = rms;
  295.                    
  296.                     // Ignore very small values that adversely affect the mean
  297.                     if ( rms > AMPLITUDE_MIN )
  298.                         mlt_properties_set_int( filter_properties, "_smooth_index", ( smooth_index + 1 ) % window );
  299.                    
  300.                     // Smoothing is really just a mean over the past N values
  301.                     normalised_gain = AMPLITUDE_NORM / mean( smooth_buffer, window );
  302.                 }
  303.                 else if ( rms > 0 )
  304.                 {
  305.                     // Determine gain to apply as current amplitude
  306.                     normalised_gain = AMPLITUDE_NORM / rms;
  307.                 }
  308.                    
  309.                 //printf("filter_sox: rms %.3f gain %.3f\n", rms, normalised_gain );
  310.                
  311.                 // Govern the maximum gain
  312.                 if ( normalised_gain > max_gain )
  313.                     normalised_gain = max_gain;
  314.             }
  315.            
  316.             // For each effect
  317.             for ( j = 0; j < count; j++ )
  318.             {
  319.                 sprintf( id, "_effect_%d_%d", j, i );
  320.                 e = mlt_properties_get_data( filter_properties, id, NULL );
  321.                
  322.                 // We better have this guy
  323.                 if ( e != NULL )
  324.                 {
  325.                     float saved_gain = 1.0;
  326.                    
  327.                     // XXX: hack to apply the normalised gain level to the vol effect
  328. #ifdef SOX14
  329.                     if ( normalise && strcmp( e->handler.name, "vol" ) == 0 )
  330. #else
  331.                     if ( normalise && strcmp( e->name, "vol" ) == 0 )
  332. #endif
  333.                     {
  334.                         float *f = ( float * )( e->priv );
  335.                         saved_gain = *f;
  336.                         *f = saved_gain * normalised_gain;
  337.                     }
  338.                    
  339.                     // Apply the effect
  340. #ifdef SOX14
  341.                     if ( ( * e->handler.flow )( e, input_buffer, output_buffer, &isamp, &osamp ) != ST_SUCCESS )
  342. #else
  343.                     if ( ( * e->h->flow )( e, input_buffer, output_buffer, &isamp, &osamp ) != ST_SUCCESS )
  344. #endif
  345.                     {
  346.                         mlt_log_warning( MLT_FILTER_SERVICE(filter), "effect processing failed\n" );
  347.                     }
  348.                    
  349.                     // XXX: hack to restore the original vol gain to prevent accumulation
  350. #ifdef SOX14
  351.                     if ( normalise && strcmp( e->handler.name, "vol" ) == 0 )
  352. #else
  353.                     if ( normalise && strcmp( e->name, "vol" ) == 0 )
  354. #endif
  355.                     {
  356.                         float *f = ( float * )( e->priv );
  357.                         *f = saved_gain;
  358.                     }
  359.                 }
  360.             }
  361.  
  362.             // Write back
  363.             memcpy( input_buffer, output_buffer, *samples * sizeof(st_sample_t) );
  364.         }
  365.     }
  366.  
  367.     return 0;
  368. }
  369.  
  370. /** Filter processing.
  371. */
  372.  
  373. static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
  374. {
  375.     if ( mlt_frame_is_test_audio( frame ) == 0 )
  376.     {
  377.         // Add the filter to the frame
  378.         mlt_frame_push_audio( frame, this );
  379.         mlt_frame_push_audio( frame, filter_get_audio );
  380.        
  381.         // Parse the window property and allocate smoothing buffer if needed
  382.         mlt_properties properties = MLT_FILTER_PROPERTIES( this );
  383.         int window = mlt_properties_get_int( properties, "window" );
  384.         if ( mlt_properties_get( properties, "smooth_buffer" ) == NULL && window > 1 )
  385.         {
  386.             // Create a smoothing buffer for the calculated "max power" of frame of audio used in normalisation
  387.             double *smooth_buffer = (double*) calloc( window, sizeof( double ) );
  388.             int i;
  389.             for ( i = 0; i < window; i++ )
  390.                 smooth_buffer[ i ] = -1.0;
  391.             mlt_properties_set_data( properties, "smooth_buffer", smooth_buffer, 0, free, NULL );
  392.         }
  393.     }
  394.  
  395.     return frame;
  396. }
  397.  
  398. /** Constructor for the filter.
  399. */
  400.  
  401. mlt_filter filter_sox_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
  402. {
  403.     mlt_filter this = mlt_filter_new( );
  404.     if ( this != NULL )
  405.     {
  406.         void *input_buffer = mlt_pool_alloc( BUFFER_LEN );
  407.         void *output_buffer = mlt_pool_alloc( BUFFER_LEN );
  408.         mlt_properties properties = MLT_FILTER_PROPERTIES( this );
  409.        
  410.         this->process = filter_process;
  411.        
  412.         if ( arg != NULL )
  413.             mlt_properties_set( properties, "effect", arg );
  414.         mlt_properties_set_data( properties, "input_buffer", input_buffer, BUFFER_LEN, mlt_pool_release, NULL );
  415.         mlt_properties_set_data( properties, "output_buffer", output_buffer, BUFFER_LEN, mlt_pool_release, NULL );
  416.         mlt_properties_set_int( properties, "window", 75 );
  417.     }
  418.     return this;
  419. }
  420.  
  421. // What to do when a libst internal failure occurs
  422. void cleanup(void){}
  423.  
  424. // Is there a build problem with my sox-devel package?
  425. #ifndef gsm_create
  426. void gsm_create(void){}
  427. #endif
  428. #ifndef gsm_decode
  429. void gsm_decode(void){}
  430. #endif
  431. #ifndef gdm_encode
  432. void gsm_encode(void){}
  433. #endif
  434. #ifndef gsm_destroy
  435. void gsm_destroy(void){}
  436. #endif
  437. #ifndef gsm_option
  438. void gsm_option(void){}
  439. #endif
Add Comment
Please, Sign In to add comment