示例#1
0
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;
}
示例#2
0
文件: mlt_frame.c 项目: agpanarin/mlt
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;
}