Пример #1
0
static int get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
	context cx = mlt_frame_pop_audio( frame );
	mlt_frame nested_frame = mlt_frame_pop_audio( frame );
	int result = 0;

	// if not repeating last frame
	if ( mlt_frame_get_position( nested_frame ) != cx->audio_position )
	{
		double fps = mlt_profile_fps( cx->profile );
		if ( mlt_producer_get_fps( cx->self ) < fps )
			fps = mlt_producer_get_fps( cx->self );
		*samples = mlt_sample_calculator( fps, *frequency, cx->audio_counter++ );
		result = mlt_frame_get_audio( nested_frame, buffer, format, frequency, channels, samples );
		int size = mlt_audio_format_size( *format, *samples, *channels );
		int16_t *new_buffer = mlt_pool_alloc( size );

		mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
		memcpy( new_buffer, *buffer, size );
		*buffer = new_buffer;
		cx->audio_position = mlt_frame_get_position( nested_frame );
	}
	else
	{
		// otherwise return no samples
		*samples = 0;
		*buffer = NULL;
	}

	return result;
}
Пример #2
0
static int producer_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
	mlt_properties properties = MLT_FRAME_PROPERTIES( self );
	mlt_frame frame = mlt_frame_pop_audio( self );
	mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
	mlt_frame_set_audio( self, *buffer, *format, mlt_audio_format_size( *format, *samples, *channels ), 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 );
	return 0;
}
Пример #3
0
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 = 0;
			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 if ( *format == mlt_audio_s32le || *format == mlt_audio_f32le )
		{
			int32_t *p = (int32_t*) new_buffer;
			int i, j, k = 0;
			for ( i = 0; i < *samples; i++ )
			{
				for ( j = 0; j < *channels; j++ )
				{
					p[ ( i * *channels ) + j ] = ((int32_t*)(*buffer))[ ( i * channels_avail ) + k ];
					k = ( k + 1 ) % channels_avail;
				}
			}
		}
		else
		{
			// non-interleaved - s32 or float
			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;
}
Пример #4
0
static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *format, mlt_audio_format requested_format )
{
	int error = 1;
	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 = mlt_audio_format_size( requested_format, samples, channels );

	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:
			{
				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;
				error = 0;
				break;
			}
			case mlt_audio_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;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int16_t *q = (int16_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = (int32_t) *q++ << 16;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int16_t *q = (int16_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
				{
					float f = (float)( *q++ ) / 32768.0;
					f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
					*p++ = f;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_t *p = buffer;
				int16_t *q = (int16_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = ( *q++ >> 8 ) + 128;
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_s32:
			switch ( requested_format )
			{
			case mlt_audio_s16:
			{
				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;
				error = 0;
				break;
			}
			case mlt_audio_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;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_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 );
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
					{
						float f = (float)( *( q + c * samples + s ) ) / 2147483648.0;
						f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
						*p++ = f;
					}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_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] >> 24 ) + 128;
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_float:
			switch ( requested_format )
			{
			case mlt_audio_s16:
			{
				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;
				error = 0;
				break;
			}
			case mlt_audio_s32:
			{
				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;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_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++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
					}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				float *q = (float*) *audio;
				int s, c;
				for ( s = 0; s < samples; s++ )
					for ( c = 0; c < channels; c++ )
						*p++ = *( q + c * samples + s );
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_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++ = ( 127 * f ) + 128;
					}
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_s32le:
			switch ( requested_format )
			{
			case mlt_audio_s16:
			{
				int16_t *buffer = mlt_pool_alloc( size );
				int16_t *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = *q++ >> 16;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					int32_t *q = (int32_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = *q;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_float:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					int32_t *q = (int32_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = (float)( *q ) / 2147483648.0;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				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;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_t *p = buffer;
				int32_t *q = (int32_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = ( *q++ >> 24 ) + 128;
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_f32le:
			switch ( requested_format )
			{
			case mlt_audio_s16:
			{
				int16_t *buffer = mlt_pool_alloc( size );
				int16_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++ = 32767 * f;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_float:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					float *q = (float*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = *q;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					float *q = (float*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						float f = *q;
						f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
						*p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				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;
				error = 0;
				break;
			}
			case mlt_audio_u8:
			{
				uint8_t *buffer = mlt_pool_alloc( size );
				uint8_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++ = ( 127 * f ) + 128;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		case mlt_audio_u8:
			switch ( requested_format )
			{
			case mlt_audio_s32:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					uint8_t *q = (uint8_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = ( (int32_t) *q - 128 ) << 24;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_float:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				int c;
				for ( c = 0; c < channels; c++ )
				{
					uint8_t *q = (uint8_t*) *audio + c;
					int i = samples + 1;
					while ( --i )
					{
						*p++ = ( (float) *q - 128 ) / 256.0f;
						q += channels;
					}
				}
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s16:
			{
				int16_t *buffer = mlt_pool_alloc( size );
				int16_t *p = buffer;
				uint8_t *q = (uint8_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = ( (int16_t) *q++ - 128 ) << 8;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_s32le:
			{
				int32_t *buffer = mlt_pool_alloc( size );
				int32_t *p = buffer;
				uint8_t *q = (uint8_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
					*p++ = ( (int32_t) *q++ - 128 ) << 24;
				*audio = buffer;
				error = 0;
				break;
			}
			case mlt_audio_f32le:
			{
				float *buffer = mlt_pool_alloc( size );
				float *p = buffer;
				uint8_t *q = (uint8_t*) *audio;
				int i = samples * channels + 1;
				while ( --i )
				{
					float f = ( (float) *q++ - 128 ) / 256.0f;
					f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
					*p++ = f;
				}
				*audio = buffer;
				error = 0;
				break;
			}
			default:
				break;
			}
			break;
		default:
			break;
		}
	}
Пример #5
0
static void foreach_consumer_put( mlt_consumer consumer, mlt_frame frame )
{
    mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
    mlt_consumer nested = NULL;
    char key[30];
    int index = 0;

    do {
        snprintf( key, sizeof(key), "%d.consumer", index++ );
        nested = mlt_properties_get_data( properties, key, NULL );
        if ( nested )
        {
            mlt_properties nested_props = MLT_CONSUMER_PROPERTIES(nested);
            double self_fps = mlt_properties_get_double( properties, "fps" );
            double nested_fps = mlt_properties_get_double( nested_props, "fps" );
            mlt_position nested_pos = mlt_properties_get_position( nested_props, "_multi_position" );
            mlt_position self_pos = mlt_frame_get_position( frame );
            double self_time = self_pos / self_fps;
            double nested_time = nested_pos / nested_fps;

            // get the audio for the current frame
            uint8_t *buffer = NULL;
            mlt_audio_format format = mlt_audio_s16;
            int channels = mlt_properties_get_int( properties, "channels" );
            int frequency = mlt_properties_get_int( properties, "frequency" );
            int current_samples = mlt_sample_calculator( self_fps, frequency, self_pos );
            mlt_frame_get_audio( frame, (void**) &buffer, &format, &frequency, &channels, &current_samples );
            int current_size = mlt_audio_format_size( format, current_samples, channels );

            // get any leftover audio
            int prev_size = 0;
            uint8_t *prev_buffer = mlt_properties_get_data( nested_props, "_multi_audio", &prev_size );
            uint8_t *new_buffer = NULL;
            if ( prev_size > 0 )
            {
                new_buffer = mlt_pool_alloc( prev_size + current_size );
                memcpy( new_buffer, prev_buffer, prev_size );
                memcpy( new_buffer + prev_size, buffer, current_size );
                buffer = new_buffer;
            }
            current_size += prev_size;
            current_samples += mlt_properties_get_int( nested_props, "_multi_samples" );

            while ( nested_time <= self_time )
            {
                // put ideal number of samples into cloned frame
                int deeply = index > 1 ? 1 : 0;
                mlt_frame clone_frame = mlt_frame_clone( frame, deeply );
                int nested_samples = mlt_sample_calculator( nested_fps, frequency, nested_pos );
                // -10 is an optimization to avoid tiny amounts of leftover samples
                nested_samples = nested_samples > current_samples - 10 ? current_samples : nested_samples;
                int nested_size = mlt_audio_format_size( format, nested_samples, channels );
                if ( nested_size > 0 )
                {
                    prev_buffer = mlt_pool_alloc( nested_size );
                    memcpy( prev_buffer, buffer, nested_size );
                }
                else
                {
                    prev_buffer = NULL;
                    nested_size = 0;
                }
                mlt_frame_set_audio( clone_frame, prev_buffer, format, nested_size, mlt_pool_release );
                mlt_properties_set_int( MLT_FRAME_PROPERTIES(clone_frame), "audio_samples", nested_samples );
                mlt_properties_set_int( MLT_FRAME_PROPERTIES(clone_frame), "audio_frequency", frequency );
                mlt_properties_set_int( MLT_FRAME_PROPERTIES(clone_frame), "audio_channels", channels );

                // chomp the audio
                current_samples -= nested_samples;
                current_size -= nested_size;
                buffer += nested_size;

                // send frame to nested consumer
                mlt_consumer_put_frame( nested, clone_frame );
                mlt_properties_set_position( nested_props, "_multi_position", ++nested_pos );
                nested_time = nested_pos / nested_fps;
            }

            // save any remaining audio
            if ( current_size > 0 )
            {
                prev_buffer = mlt_pool_alloc( current_size );
                memcpy( prev_buffer, buffer, current_size );
            }
            else
            {
                prev_buffer = NULL;
                current_size = 0;
            }
            mlt_pool_release( new_buffer );
            mlt_properties_set_data( nested_props, "_multi_audio", prev_buffer, current_size, mlt_pool_release, NULL );
            mlt_properties_set_int( nested_props, "_multi_samples", current_samples );
        }
    } while ( nested );
}
Пример #6
0
static int ladspa_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
	int error = 0;

	// Get the filter service
	mlt_filter filter = mlt_frame_pop_audio( frame );

	// Get the filter properties
	mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );

	// Check if the channel configuration has changed
	int prev_channels = mlt_properties_get_int( filter_properties, "_prev_channels" );
	if ( prev_channels != *channels )
	{
		if( prev_channels )
		{
			mlt_log_info( MLT_FILTER_SERVICE(filter), "Channel configuration changed. Old: %d New: %d.\n", prev_channels, *channels );
			mlt_properties_set_data( filter_properties, "jackrack", NULL, 0, (mlt_destructor) NULL, NULL );
		}
		mlt_properties_set_int( filter_properties, "_prev_channels", *channels );
	}

	// Initialise LADSPA if needed
	jack_rack_t *jackrack = mlt_properties_get_data( filter_properties, "jackrack", NULL );
	if ( jackrack == NULL )
	{
		sample_rate = *frequency; // global inside jack_rack
		jackrack = initialise_jack_rack( filter_properties, *channels );
	}

	if ( jackrack && jackrack->procinfo && jackrack->procinfo->chain &&
		 mlt_properties_get_int64( filter_properties, "_pluginid" ) )
	{
		plugin_t *plugin = jackrack->procinfo->chain;
		LADSPA_Data value;
		int i, c;
		mlt_position position = mlt_filter_get_position( filter, frame );
		mlt_position length = mlt_filter_get_length2( filter, frame );

		// Get the producer's audio
		*format = mlt_audio_float;
		mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );

		// Resize the buffer if necessary.
		if ( *channels < jackrack->channels )
		{
			// Add extra channels to satisfy the plugin.
			// Extra channels in the buffer will be ignored by downstream services.
			int old_size = mlt_audio_format_size( *format, *samples, *channels );
			int new_size = mlt_audio_format_size( *format, *samples, jackrack->channels );
			uint8_t* new_buffer = mlt_pool_alloc( new_size );
			memcpy( new_buffer, *buffer, old_size );
			// Put silence in extra channels.
			memset( new_buffer + old_size, 0, new_size - old_size );
			mlt_frame_set_audio( frame, new_buffer, *format, new_size, mlt_pool_release );
			*buffer = new_buffer;
		}

		for ( i = 0; i < plugin->desc->control_port_count; i++ )
		{
			// Apply the control port values
			char key[20];
			value = plugin_desc_get_default_control_value( plugin->desc, i, sample_rate );
			snprintf( key, sizeof(key), "%d", i );
			if ( mlt_properties_get( filter_properties, key ) )
				value = mlt_properties_anim_get_double( filter_properties, key, position, length );
			for ( c = 0; c < plugin->copies; c++ )
				plugin->holders[c].control_memory[i] = value;
		}
		plugin->wet_dry_enabled = mlt_properties_get( filter_properties, "wetness" ) != NULL;
		if ( plugin->wet_dry_enabled )
		{
			value = mlt_properties_anim_get_double( filter_properties, "wetness", position, length );
			for ( c = 0; c < jackrack->channels; c++ )
				plugin->wet_dry_values[c] = value;
		}

		// Configure the buffers
		LADSPA_Data **input_buffers  = mlt_pool_alloc( sizeof( LADSPA_Data* ) * jackrack->channels );
		LADSPA_Data **output_buffers = mlt_pool_alloc( sizeof( LADSPA_Data* ) * jackrack->channels );
		
		// Some plugins crash with too many frames (samples).
		// So, feed the plugin with N samples per loop iteration.
		int samples_offset = 0;
		int sample_count = MIN(*samples, MAX_SAMPLE_COUNT);
		for (i = 0; samples_offset < *samples; i++) {
			int j = 0;
			for (; j < jackrack->channels; j++)
				output_buffers[j] = input_buffers[j] = (LADSPA_Data*) *buffer + j * (*samples) + samples_offset;
			sample_count = MIN(*samples - samples_offset, MAX_SAMPLE_COUNT);
			// Do LADSPA processing
			error = process_ladspa( jackrack->procinfo, sample_count, input_buffers, output_buffers );
			samples_offset += MAX_SAMPLE_COUNT;
		}

		mlt_pool_release( input_buffers );
		mlt_pool_release( output_buffers );

		// read the status port values
		for ( i = 0; i < plugin->desc->status_port_count; i++ )
		{
			char key[20];
			int p = plugin->desc->status_port_indicies[i];
			for ( c = 0; c < plugin->copies; c++ )
			{
				snprintf( key, sizeof(key), "%d[%d]", p, c );
				value = plugin->holders[c].status_memory[i];
				mlt_properties_set_double( filter_properties, key, value );
			}
		}
	}
	else
	{
		// Nothing to do.
		error = mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
	}

	return error;
}
Пример #7
0
mlt_frame mlt_frame_clone( mlt_frame self, int is_deep )
{
	mlt_frame new_frame = mlt_frame_init( NULL );
	mlt_properties properties = MLT_FRAME_PROPERTIES( self );
	mlt_properties new_props = MLT_FRAME_PROPERTIES( new_frame );
	void *data, *copy;
	int size;

	mlt_properties_inherit( new_props, properties );

	// Carry over some special data properties for the multi consumer.
	mlt_properties_set_data( new_props, "_producer",
		mlt_frame_get_original_producer( self ), 0, NULL, NULL );
	mlt_properties_set_data( new_props, "movit.convert",
		mlt_properties_get_data( properties, "movit.convert", NULL), 0, NULL, NULL );

	if ( is_deep )
	{
		data = mlt_properties_get_data( properties, "audio", &size );
		if ( data )
		{
			if ( !size )
				size = mlt_audio_format_size( mlt_properties_get_int( properties, "audio_format" ),
					mlt_properties_get_int( properties, "audio_samples" ),
					mlt_properties_get_int( properties, "audio_channels" ) );
			copy = mlt_pool_alloc( size );
			memcpy( copy, data, size );
			mlt_properties_set_data( new_props, "audio", copy, size, mlt_pool_release, NULL );
		}
		data = mlt_properties_get_data( properties, "image", &size );
		if ( data )
		{
			if ( ! size )
				size = mlt_image_format_size( mlt_properties_get_int( properties, "format" ),
					mlt_properties_get_int( properties, "width" ),
					mlt_properties_get_int( properties, "height" ), NULL );
			copy = mlt_pool_alloc( size );
			memcpy( copy, data, size );
			mlt_properties_set_data( new_props, "image", copy, size, mlt_pool_release, NULL );

			data = mlt_properties_get_data( properties, "alpha", &size );
			if ( data )
			{
				if ( ! size )
					size = mlt_properties_get_int( properties, "width" ) *
						mlt_properties_get_int( properties, "height" );
				copy = mlt_pool_alloc( size );
				memcpy( copy, data, size );
				mlt_properties_set_data( new_props, "alpha", copy, size, mlt_pool_release, NULL );
			};
		}
	}
	else
	{
		// This frame takes a reference on the original frame since the data is a shallow copy.
		mlt_properties_inc_ref( properties );
		mlt_properties_set_data( new_props, "_cloned_frame", self, 0,
			(mlt_destructor) mlt_frame_close, NULL );

		// Copy properties
		data = mlt_properties_get_data( properties, "audio", &size );
		mlt_properties_set_data( new_props, "audio", data, size, NULL, NULL );
		data = mlt_properties_get_data( properties, "image", &size );
		mlt_properties_set_data( new_props, "image", data, size, NULL, NULL );
		data = mlt_properties_get_data( properties, "alpha", &size );
		mlt_properties_set_data( new_props, "alpha", data, size, NULL, NULL );
	}

	return new_frame;
}
Пример #8
0
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;

	// Get the producer's audio
	mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );

	if ( channels_out == -1 )
		channels_out = *channels;
	size = mlt_audio_format_size( *format, *samples, channels_out );

	switch ( *format )
	{
		case mlt_audio_u8:
		{
			uint8_t *new_buffer = mlt_pool_alloc( size );
			for ( i = 0; i < *samples; i++ )
			{
				uint8_t mixdown = 0;
				for ( j = 0; j < *channels; j++ )
					mixdown += ((uint8_t*) *buffer)[ ( i * *channels ) + j ];
				for ( j = 0; j < channels_out; j++ )
					new_buffer[ ( i * channels_out ) + j ] = mixdown;
			}
			*buffer = new_buffer;
			break;
		}
		case mlt_audio_s16:
		{
			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 ];
				for ( j = 0; j < channels_out; j++ )
					new_buffer[ ( i * channels_out ) + j ] = mixdown;
			}
			*buffer = new_buffer;
			break;
		}
		case mlt_audio_s32le:
		{
			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)[ ( i * *channels ) + j ];
				for ( j = 0; j < channels_out; j++ )
					new_buffer[ ( i * channels_out ) + j ] = mixdown;
			}
			*buffer = new_buffer;
			break;
		}
		case mlt_audio_f32le:
		{
			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)[ ( i * *channels ) + j ];
				for ( j = 0; j < channels_out; j++ )
					new_buffer[ ( i * channels_out ) + j ] = mixdown;
			}
			*buffer = new_buffer;
			break;
		}
		case mlt_audio_s32:
		{
			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 ];
				for ( j = 0; j < channels_out; j++ )
					new_buffer[ ( j * *samples ) + i ] = mixdown;
			}
			*buffer = new_buffer;
			break;
		}
		case mlt_audio_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 ];
				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;
	}

	return 0;
}
Пример #9
0
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 );

		size = mlt_audio_format_size( *format, *samples, *channels );
		if ( size )
			*buffer = mlt_pool_alloc( size );
		else
			*buffer = NULL;
		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" ) && *buffer )
	{
		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;
}