static int resample_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 ); // Get the filter properties mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter ); // Get the resample information int output_rate = mlt_properties_get_int( filter_properties, "frequency" ); // If no resample frequency is specified, default to requested value if ( output_rate == 0 ) output_rate = *frequency; // Get the producer's audio 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 && *frequency > 0 && *channels > 0 ) { 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 if ( *format != mlt_audio_f32le ) frame->convert_audio( frame, buffer, format, mlt_audio_f32le ); mlt_service_lock( MLT_FILTER_SERVICE(filter) ); SRC_DATA data; data.data_in = *buffer; data.data_out = mlt_properties_get_data( filter_properties, "output_buffer", NULL ); data.src_ratio = ( float ) output_rate / ( float ) *frequency; data.input_frames = *samples; data.output_frames = BUFFER_LEN / *channels; data.end_of_input = 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 ); } // Resample the audio error = src_process( state, &data ); if ( !error ) { // Update output variables *samples = data.output_frames_gen; *frequency = output_rate; *buffer = data.data_out; } else { mlt_log_error( MLT_FILTER_SERVICE( filter ), "%s %d,%d,%d\n", src_strerror( error ), *frequency, *samples, output_rate ); } mlt_service_unlock( MLT_FILTER_SERVICE(filter) ); } return error; }
int mlt_frame_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples ) { mlt_get_audio get_audio = mlt_frame_pop_audio( self ); mlt_properties properties = MLT_FRAME_PROPERTIES( self ); int hide = mlt_properties_get_int( properties, "test_audio" ); mlt_audio_format requested_format = *format; if ( hide == 0 && get_audio != NULL ) { get_audio( self, buffer, format, frequency, channels, samples ); 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 ( self->convert_audio && *buffer && requested_format != mlt_audio_none ) self->convert_audio( self, 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 ( self->convert_audio && *buffer && requested_format != mlt_audio_none ) self->convert_audio( self, buffer, format, requested_format ); } else { int size = 0; *samples = *samples <= 0 ? 1920 : *samples; *channels = *channels <= 0 ? 2 : *channels; *frequency = *frequency <= 0 ? 48000 : *frequency; 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; default: 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 ); } // 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" ); if ( value == 0.0 ) { memset( *buffer, 0, *samples * *channels * 2 ); } else if ( value != 1.0 ) { int total = *samples * *channels; int16_t *p = *buffer; while ( total -- ) { *p = *p * value; p ++; } } mlt_properties_set( properties, "meta.volume", NULL ); } return 0; }