CFLAGS += $(RDYNAMIC) -DPREFIX="\"$(prefix)\"" -DLIBDIR="\"$(libdir)\""
-LDFLAGS += -lm $(LIBDL) -lpthread
+LDFLAGS += $(LIBDL) -lpthread
all: $(TARGET)
int preview_format = mlt_properties_get_int( properties, "preview_format" );
// Get the audio settings
- mlt_audio_format afmt = mlt_audio_pcm;
+ mlt_audio_format afmt = mlt_audio_s16;
int counter = 0;
double fps = mlt_properties_get_double( properties, "fps" );
int channels = mlt_properties_get_int( properties, "channels" );
int frequency = mlt_properties_get_int( properties, "frequency" );
int samples = 0;
- int16_t *pcm = NULL;
+ void *audio = NULL;
// See if audio is turned off
int audio_off = mlt_properties_get_int( properties, "audio_off" );
if ( !audio_off )
{
samples = mlt_sample_calculator( fps, frequency, counter++ );
- mlt_frame_get_audio( frame, &pcm, &afmt, &frequency, &channels, &samples );
+ mlt_frame_get_audio( frame, &audio, &afmt, &frequency, &channels, &samples );
}
// Unlock the lock object
if ( !audio_off )
{
samples = mlt_sample_calculator( fps, frequency, counter++ );
- mlt_frame_get_audio( frame, &pcm, &afmt, &frequency, &channels, &samples );
+ mlt_frame_get_audio( frame, &audio, &afmt, &frequency, &channels, &samples );
}
// Increment the time take for this frame
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
/** Constructor for a frame.
*/
return alpha;
}
-int mlt_frame_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+const char * mlt_audio_format_name( mlt_audio_format format )
+{
+ switch ( format )
+ {
+ case mlt_audio_none: return "none";
+ case mlt_audio_s16: return "s16";
+ case mlt_audio_s32: return "s32";
+ case mlt_audio_float: return "float";
+ }
+ return "invalid";
+}
+
+int mlt_frame_get_audio( mlt_frame this, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
mlt_get_audio get_audio = mlt_frame_pop_audio( this );
mlt_properties properties = MLT_FRAME_PROPERTIES( this );
int hide = mlt_properties_get_int( properties, "test_audio" );
+ mlt_audio_format requested_format = *format;
if ( hide == 0 && get_audio != NULL )
{
mlt_position position = mlt_frame_get_position( this );
get_audio( this, buffer, format, frequency, channels, samples );
mlt_frame_set_position( this, position );
+ 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 ( this->convert_audio )
+ this->convert_audio( this, 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 ( this->convert_audio )
+ this->convert_audio( this, buffer, format, requested_format );
}
else
{
*samples = *samples <= 0 ? 1920 : *samples;
*channels = *channels <= 0 ? 2 : *channels;
*frequency = *frequency <= 0 ? 48000 : *frequency;
- size = *samples * *channels * sizeof( int16_t );
- *buffer = mlt_pool_alloc( size );
- if ( *buffer != 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 );
+ 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;
+ }
+ 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 );
}
- mlt_properties_set_int( properties, "audio_frequency", *frequency );
- mlt_properties_set_int( properties, "audio_channels", *channels );
- mlt_properties_set_int( properties, "audio_samples", *samples );
-
- if ( mlt_properties_get( properties, "meta.volume" ) )
+ // 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" );
return 0;
}
+int mlt_frame_set_audio( mlt_frame this, void *buffer, mlt_audio_format format, int size, mlt_destructor destructor )
+{
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "audio_format", format );
+ return mlt_properties_set_data( MLT_FRAME_PROPERTIES( this ), "audio", buffer, size, destructor, NULL );
+}
+
unsigned char *mlt_frame_get_waveform( mlt_frame this, int w, int h )
{
int16_t *pcm = NULL;
mlt_properties properties = MLT_FRAME_PROPERTIES( this );
- mlt_audio_format format = mlt_audio_pcm;
+ mlt_audio_format format = mlt_audio_s16;
int frequency = 32000; // lower frequency available?
int channels = 2;
double fps = mlt_profile_fps( NULL );
int samples = mlt_sample_calculator( fps, frequency, mlt_frame_get_position( this ) );
// Get the pcm data
- mlt_frame_get_audio( this, &pcm, &format, &frequency, &channels, &samples );
+ mlt_frame_get_audio( this, (void**)&pcm, &format, &frequency, &channels, &samples );
// Make an 8-bit buffer large enough to hold rendering
int size = w * h;
/***** convenience functions *****/
-int mlt_frame_mix_audio( mlt_frame this, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- int ret = 0;
- int16_t *src, *dest;
- int frequency_src = *frequency, frequency_dest = *frequency;
- int channels_src = *channels, channels_dest = *channels;
- int samples_src = *samples, samples_dest = *samples;
- int i, j;
- double d = 0, s = 0;
-
- mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
- mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
-
- int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
- if ( silent )
- memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
-
- silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
- if ( silent )
- memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
-
- if ( channels_src > 6 )
- channels_src = 0;
- if ( channels_dest > 6 )
- channels_dest = 0;
- if ( samples_src > 4000 )
- samples_src = 0;
- if ( samples_dest > 4000 )
- samples_dest = 0;
-
- // determine number of samples to process
- *samples = samples_src < samples_dest ? samples_src : samples_dest;
- *channels = channels_src < channels_dest ? channels_src : channels_dest;
- *buffer = dest;
- *frequency = frequency_dest;
-
- // Compute a smooth ramp over start to end
- float weight = weight_start;
- float weight_step = ( weight_end - weight_start ) / *samples;
-
- if ( src == dest )
- {
- *samples = samples_src;
- *channels = channels_src;
- *buffer = src;
- *frequency = frequency_src;
- return ret;
- }
-
- // Mixdown
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- if ( j < channels_dest )
- d = (double) dest[ i * channels_dest + j ];
- if ( j < channels_src )
- s = (double) src[ i * channels_src + j ];
- dest[ i * channels_dest + j ] = s * weight + d * ( 1.0 - weight );
- }
- weight += weight_step;
- }
-
- return ret;
-}
-
-// Replacement for broken mlt_frame_audio_mix - this filter uses an inline low pass filter
-// to allow mixing without volume hacking
-int mlt_frame_combine_audio( mlt_frame this, mlt_frame that, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
-{
- int ret = 0;
- int16_t *src, *dest;
- int frequency_src = *frequency, frequency_dest = *frequency;
- int channels_src = *channels, channels_dest = *channels;
- int samples_src = *samples, samples_dest = *samples;
- int i, j;
- double vp[ 6 ];
- double b_weight = 1.0;
-
- if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "meta.mixdown" ) )
- b_weight = 1.0 - mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "meta.volume" );
-
- mlt_frame_get_audio( that, &src, format, &frequency_src, &channels_src, &samples_src );
- mlt_frame_get_audio( this, &dest, format, &frequency_dest, &channels_dest, &samples_dest );
-
- int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
- if ( silent )
- memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
-
- silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
- mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
- if ( silent )
- memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
-
- if ( src == dest )
- {
- *samples = samples_src;
- *channels = channels_src;
- *buffer = src;
- *frequency = frequency_src;
- return ret;
- }
-
- // determine number of samples to process
- *samples = samples_src < samples_dest ? samples_src : samples_dest;
- *channels = channels_src < channels_dest ? channels_src : channels_dest;
- *buffer = dest;
- *frequency = frequency_dest;
-
- for ( j = 0; j < *channels; j++ )
- vp[ j ] = ( double )dest[ j ];
-
- double Fc = 0.5;
- double B = exp(-2.0 * M_PI * Fc);
- double A = 1.0 - B;
- double v;
-
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- v = ( double )( b_weight * dest[ i * channels_dest + j ] + src[ i * channels_src + j ] );
- v = v < -32767 ? -32767 : v > 32768 ? 32768 : v;
- vp[ j ] = dest[ i * channels_dest + j ] = ( int16_t )( v * A + vp[ j ] * B );
- }
- }
-
- return ret;
-}
-
/* Will this break when mlt_position is converted to double? -Zach */
int mlt_sample_calculator( float fps, int frequency, int64_t position )
{
*
*/
-typedef int ( *mlt_get_audio )( mlt_frame self, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
+typedef int ( *mlt_get_audio )( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
/** \brief Frame class
*
/* Virtual methods */
uint8_t * ( *get_alpha_mask )( mlt_frame self );
int ( *convert_image )( mlt_frame self, uint8_t **image, mlt_image_format *input, mlt_image_format output );
+ int ( *convert_audio )( mlt_frame self, void **audio, mlt_audio_format *input, mlt_audio_format output );
/* Private properties */
mlt_deque stack_image;
extern void mlt_frame_replace_image( mlt_frame self, uint8_t *image, mlt_image_format format, int width, int height );
extern int mlt_frame_get_image( mlt_frame self, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable );
extern uint8_t *mlt_frame_get_alpha_mask( mlt_frame self );
-extern int mlt_frame_get_audio( mlt_frame self, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
+extern int mlt_frame_get_audio( mlt_frame self, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
+extern int mlt_frame_set_audio( mlt_frame self, void *buffer, mlt_audio_format, int size, mlt_destructor );
extern unsigned char *mlt_frame_get_waveform( mlt_frame self, int w, int h );
extern int mlt_frame_push_get_image( mlt_frame self, mlt_get_image get_image );
extern mlt_get_image mlt_frame_pop_get_image( mlt_frame self );
extern void mlt_frame_close( mlt_frame self );
/* convenience functions */
-extern int mlt_frame_mix_audio( mlt_frame self, mlt_frame that, float weight_start, float weight_end, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
-extern int mlt_frame_combine_audio( mlt_frame self, mlt_frame that, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples );
extern int mlt_sample_calculator( float fps, int frequency, int64_t position );
extern int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t position );
extern const char * mlt_image_format_name( mlt_image_format format );
+extern const char * mlt_audio_format_name( mlt_audio_format format );
/** This macro scales rgb into the yuv gamut - y is scaled by 219/255 and uv by 224/255. */
#define RGB2YUV(r, g, b, y, u, v)\
return 0;
}
-static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int producer_get_audio( mlt_frame this, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
mlt_properties properties = MLT_FRAME_PROPERTIES( this );
mlt_frame frame = mlt_frame_pop_audio( this );
typedef enum
{
mlt_audio_none = 0,/**< audio not available */
- mlt_audio_pcm /**< signed 16-bit interleaved PCM */
+ mlt_audio_pcm = 1, /**< \deprecated signed 16-bit interleaved PCM */
+ mlt_audio_s16 = 1, /**< signed 16-bit interleaved PCM */
+ mlt_audio_s32, /**< signed 32-bit non-interleaved PCM */
+ mlt_audio_float /**< 32-bit non-interleaved floating point */
}
mlt_audio_format;
return image;
}
-int16_t *Frame::get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples )
+void *Frame::get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples )
{
- int16_t *audio = NULL;
+ void *audio = NULL;
mlt_frame_get_audio( get_frame( ), &audio, &format, &frequency, &channels, &samples );
return audio;
}
mlt_properties get_properties( );
uint8_t *get_image( mlt_image_format &format, int &w, int &h, int writable = 0 );
unsigned char *fetch_image( mlt_image_format format, int w, int h, int writable = 0 );
- int16_t *get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples );
+ void *get_audio( mlt_audio_format &format, int &frequency, int &channels, int &samples );
unsigned char *get_waveform( int w, int h );
Producer *get_original_producer( );
};
#!/bin/sh
-echo "soversion=2" > config.mak
+echo "soversion=3" > config.mak
echo "mlt++ -I$prefix/include -I$prefix/include/mlt++ -D_REENTRANT -L$libdir -lmlt++" >> ../../packages.dat
WARNINGS="-W -Wwrite-strings -Wcast-qual -Wpointer-arith -Wcast-align -Wredundant-decls"
int img_height = height;
// Get default audio properties
- mlt_audio_format aud_fmt = mlt_audio_pcm;
+ mlt_audio_format aud_fmt = mlt_audio_s16;
int channels = mlt_properties_get_int( properties, "channels" );
int frequency = mlt_properties_get_int( properties, "frequency" );
int16_t *pcm = NULL;
if ( !terminated && audio_st )
{
samples = mlt_sample_calculator( fps, frequency, count ++ );
- mlt_frame_get_audio( frame, &pcm, &aud_fmt, &frequency, &channels, &samples );
+ mlt_frame_get_audio( frame, (void**) &pcm, &aud_fmt, &frequency, &channels, &samples );
// Create the fifo if we don't have one
if ( fifo == NULL )
/** Get the audio.
*/
-static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
// Get the properties of the frame
mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
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
{
for ( j = 0; j < *channels; j++ )
{
- new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
+ new_buffer[ ( i * *channels ) + j ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + k ];
k = ( k + 1 ) % channels_avail;
}
}
// Drop all but the first *channels
for ( i = 0; i < *samples; i++ )
{
- new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
- new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
+ new_buffer[ ( i * *channels ) + 0 ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + 2 ];
+ new_buffer[ ( i * *channels ) + 1 ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + 3 ];
}
// Update the audio buffer now - destroys the old
// Resample the audio
used = audio_resample( resample, sample_buffer, *buffer, *samples );
+ int size = used * *channels * sizeof( int16_t );
// Resize if necessary
if ( used > *samples )
{
- *buffer = mlt_pool_realloc( *buffer, *samples * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( properties, "audio", *buffer, *channels * used * sizeof( int16_t ), mlt_pool_release, NULL );
+ *buffer = mlt_pool_realloc( *buffer, size );
+ mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
}
// Copy samples
- memcpy( *buffer, sample_buffer, *channels * used * sizeof( int16_t ) );
+ memcpy( *buffer, sample_buffer, size );
// Update output variables
*samples = used;
/** Get the audio from a frame.
*/
-static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
// Get the properties from the frame
mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
av_free_packet( &pkt );
}
- *buffer = mlt_pool_alloc( *samples * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( frame_properties, "audio", *buffer, 0, ( mlt_destructor )mlt_pool_release, NULL );
+ int size = *samples * *channels * sizeof( int16_t );
+ *format = mlt_audio_s16;
+ *buffer = mlt_pool_alloc( size );
+ mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
// Now handle the audio if we have enough
if ( audio_used >= *samples )
producer_loader.o \
producer_noise.o \
producer_ppm.o \
+ filter_audioconvert.o \
filter_brightness.o \
filter_channelcopy.o \
filter_crop.o \
#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_audioconvert_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 );
extern mlt_filter filter_channelcopy_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
extern mlt_filter filter_crop_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
MLT_REPOSITORY
{
MLT_REGISTER( consumer_type, "null", consumer_null_init );
+ MLT_REGISTER( filter_type, "audioconvert", filter_audioconvert_init );
MLT_REGISTER( filter_type, "brightness", filter_brightness_init );
MLT_REGISTER( filter_type, "channelcopy", filter_channelcopy_init );
MLT_REGISTER( filter_type, "crop", filter_crop_init );
--- /dev/null
+/*
+ * filter_audioconvert.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 <stdio.h>
+#include <stdlib.h>
+
+static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *format, mlt_audio_format requested_format )
+{
+ int error = 0;
+ 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 = 0;
+
+ 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:
+ {
+ size = channels * samples * sizeof(int32_t);
+ 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;
+ break;
+ }
+ case mlt_audio_float:
+ {
+ size = channels * samples * sizeof(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;
+ break;
+ }
+ default:
+ error = 1;
+ }
+ break;
+ case mlt_audio_s32:
+ switch ( requested_format )
+ {
+ case mlt_audio_s16:
+ {
+ size = channels * samples * sizeof(int16_t);
+ 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;
+ break;
+ }
+ case mlt_audio_float:
+ {
+ size = channels * samples * sizeof(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;
+ break;
+ }
+ default:
+ error = 1;
+ }
+ break;
+ case mlt_audio_float:
+ switch ( requested_format )
+ {
+ case mlt_audio_s16:
+ {
+ size = channels * samples * sizeof(int16_t);
+ 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;
+ break;
+ }
+ case mlt_audio_s32:
+ {
+ size = channels * samples * sizeof(int32_t);
+ 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;
+ break;
+ }
+ default:
+ error = 1;
+ }
+ break;
+ default:
+ error = 1;
+ }
+ }
+ if ( !error )
+ {
+ mlt_frame_set_audio( frame, *audio, requested_format, size, mlt_pool_release );
+ *format = requested_format;
+ }
+ return error;
+}
+
+/** Filter processing.
+*/
+
+static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+{
+ frame->convert_audio = convert_audio;
+ return frame;
+}
+
+/** Constructor for the filter.
+*/
+
+mlt_filter filter_audioconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
+{
+ mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
+ if ( mlt_filter_init( this, this ) == 0 )
+ this->process = filter_process;
+ return this;
+}
#include <framework/mlt_filter.h>
#include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
#include <stdio.h>
#include <stdlib.h>
-#define __USE_ISOC99 1
-#include <math.h>
+#include <string.h>
/** Get the audio.
*/
-static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+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 i, j;
+
+ // Get the filter service
+ mlt_filter filter = mlt_frame_pop_audio( frame );
+
int from = mlt_properties_get_int( properties, "channelcopy.from" );
int to = mlt_properties_get_int( properties, "channelcopy.to" );
// Get the producer's audio
mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
- // Duplicate channels as necessary
+ // Copy channels as necessary
+ switch ( *format )
{
- int size = *channels * *samples * 2;
- int16_t *new_buffer = mlt_pool_alloc( size );
-
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- // Duplicate the existing channels
- for ( i = 0; i < *samples; i++ )
+ case mlt_audio_s16:
+ {
+ int16_t *f = (int16_t*) *buffer + from;
+ int16_t *t = (int16_t*) *buffer + to;
+ int i;
+ for ( i = 0; i < *samples; i++, f += *channels, t += *channels )
+ *t = *f;
+ break;
+ }
+ case mlt_audio_s32:
{
- for ( j = 0; j < *channels; j++ )
- {
- new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * *channels ) + ( j == to ? from : j ) ];
- }
+ int32_t *f = (int32_t*) *buffer + from * *samples;
+ int32_t *t = (int32_t*) *buffer + to * *samples;
+ memcpy( t, f, *samples * sizeof(int32_t) );
+ break;
}
- *buffer = new_buffer;
+ case mlt_audio_float:
+ {
+ float *f = (float*) *buffer + from * *samples;
+ float *t = (float*) *buffer + to * *samples;
+ memcpy( t, f, *samples * sizeof(float) );
+ break;
+ }
+ default:
+ mlt_log_error( MLT_FILTER_SERVICE( filter ), "Invalid audio format\n" );
+ break;
}
+
return 0;
}
mlt_properties_set_int( frame_props, "channelcopy.from", mlt_properties_get_int( properties, "from" ) );
// Override the get_audio method
+ mlt_frame_push_audio( frame, this );
mlt_frame_push_audio( frame, filter_get_audio );
return frame;
/*
* filter_mono.c -- mix all channels to a mono signal across n channels
- * Copyright (C) 2003-2006 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
* Author: Dan Dennedy <dan@dennedy.org>
*
* This library is free software; you can redistribute it and/or
#include <framework/mlt_filter.h>
#include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
#include <stdio.h>
#include <stdlib.h>
/** Get the audio.
*/
-static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+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;
- int16_t *new_buffer;
// Get the producer's audio
mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
- size = *samples * channels_out * sizeof( int16_t );
- new_buffer = mlt_pool_alloc( size );
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
+ if ( channels_out == -1 )
+ channels_out = *channels;
+ size = *samples * channels_out;
- // Mix
- for ( i = 0; i < *samples; i++ )
+ switch ( *format )
{
- int16_t mixdown = 0;
- for ( j = 0; j < *channels; j++ )
- mixdown += (*buffer)[ ( i * *channels ) + j ] / *channels;
- for ( j = 0; j < channels_out; j++ )
- new_buffer[ ( i * channels_out ) + j ] = mixdown;
+ case mlt_audio_s16:
+ {
+ size *= sizeof( int16_t );
+ 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 ] / *channels;
+ for ( j = 0; j < channels_out; j++ )
+ new_buffer[ ( i * channels_out ) + j ] = mixdown;
+ }
+ *buffer = new_buffer;
+ break;
+ }
+ case mlt_audio_s32:
+ {
+ size *= sizeof( int32_t );
+ 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 ] / *channels;
+ for ( j = 0; j < channels_out; j++ )
+ new_buffer[ ( j * *samples ) + i ] = mixdown;
+ }
+ *buffer = new_buffer;
+ break;
+ }
+ case mlt_audio_float:
+ {
+ size *= sizeof( 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 ] / *channels;
+ 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;
}
- // Apply results
- *buffer = new_buffer;
- *channels = channels_out;
-
return 0;
}
if ( arg != NULL )
mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", atoi( arg ) );
else
- mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", 2 );
+ mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", -1 );
}
return this;
}
NB: Not all transitions will accept a and b frames being the same...
*/
-static int filter_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int filter_get_audio( mlt_frame this, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
// Obtain the transition instance
mlt_transition transition = mlt_frame_pop_audio( this );
imageconverter=imageconvert,avcolour_space
# audio filters
-resampler=resample,soxresample,avresample
+resampler=resample,avresample
+audioconverter=audioconvert
# metadata filters
data=data_feed:attr_check
return result;
}
-static int get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
mlt_frame nested_frame = mlt_frame_pop_audio( frame );
int result = mlt_frame_get_audio( nested_frame, buffer, format, frequency, channels, samples );
- int size = *channels * *samples * sizeof( int16_t );
+ int size = *channels * *samples;
+
+ switch ( *format )
+ {
+ case mlt_audio_s16:
+ size *= sizeof( int16_t );
+ break;
+ case mlt_audio_s32:
+ size *= sizeof( int32_t );
+ case mlt_audio_float:
+ size *= sizeof( float );
+ default:
+ mlt_log_error( NULL, "[producer consumer] Invalid audio format\n" );
+ }
int16_t *new_buffer = mlt_pool_alloc( size );
mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "audio", new_buffer, size, mlt_pool_release, NULL );
memcpy( new_buffer, *buffer, size );
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+static int mix_audio( mlt_frame this, mlt_frame that, float weight_start, float weight_end, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+ int ret = 0;
+ int16_t *src, *dest;
+ int frequency_src = *frequency, frequency_dest = *frequency;
+ int channels_src = *channels, channels_dest = *channels;
+ int samples_src = *samples, samples_dest = *samples;
+ int i, j;
+ double d = 0, s = 0;
+
+ mlt_frame_get_audio( that, (void**) &src, format, &frequency_src, &channels_src, &samples_src );
+ mlt_frame_get_audio( this, (void**) &dest, format, &frequency_dest, &channels_dest, &samples_dest );
+
+ int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
+ if ( silent )
+ memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
+
+ silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
+ if ( silent )
+ memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
+
+ if ( channels_src > 6 )
+ channels_src = 0;
+ if ( channels_dest > 6 )
+ channels_dest = 0;
+ if ( samples_src > 4000 )
+ samples_src = 0;
+ if ( samples_dest > 4000 )
+ samples_dest = 0;
+
+ // determine number of samples to process
+ *samples = samples_src < samples_dest ? samples_src : samples_dest;
+ *channels = channels_src < channels_dest ? channels_src : channels_dest;
+ *buffer = dest;
+ *frequency = frequency_dest;
+
+ // Compute a smooth ramp over start to end
+ float weight = weight_start;
+ float weight_step = ( weight_end - weight_start ) / *samples;
+
+ if ( src == dest )
+ {
+ *samples = samples_src;
+ *channels = channels_src;
+ *buffer = src;
+ *frequency = frequency_src;
+ return ret;
+ }
+
+ // Mixdown
+ for ( i = 0; i < *samples; i++ )
+ {
+ for ( j = 0; j < *channels; j++ )
+ {
+ if ( j < channels_dest )
+ d = (double) dest[ i * channels_dest + j ];
+ if ( j < channels_src )
+ s = (double) src[ i * channels_src + j ];
+ dest[ i * channels_dest + j ] = s * weight + d * ( 1.0 - weight );
+ }
+ weight += weight_step;
+ }
+
+ return ret;
+}
+
+// Replacement for broken mlt_frame_audio_mix - this filter uses an inline low pass filter
+// to allow mixing without volume hacking
+static int combine_audio( mlt_frame this, mlt_frame that, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+ int ret = 0;
+ int16_t *src, *dest;
+ int frequency_src = *frequency, frequency_dest = *frequency;
+ int channels_src = *channels, channels_dest = *channels;
+ int samples_src = *samples, samples_dest = *samples;
+ int i, j;
+ double vp[ 6 ];
+ double b_weight = 1.0;
+
+ if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "meta.mixdown" ) )
+ b_weight = 1.0 - mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "meta.volume" );
+
+ mlt_frame_get_audio( that, (void**) &src, format, &frequency_src, &channels_src, &samples_src );
+ mlt_frame_get_audio( this, (void**) &dest, format, &frequency_dest, &channels_dest, &samples_dest );
+
+ int silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "silent_audio" );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( this ), "silent_audio", 0 );
+ if ( silent )
+ memset( dest, 0, samples_dest * channels_dest * sizeof( int16_t ) );
+
+ silent = mlt_properties_get_int( MLT_FRAME_PROPERTIES( that ), "silent_audio" );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( that ), "silent_audio", 0 );
+ if ( silent )
+ memset( src, 0, samples_src * channels_src * sizeof( int16_t ) );
+
+ if ( src == dest )
+ {
+ *samples = samples_src;
+ *channels = channels_src;
+ *buffer = src;
+ *frequency = frequency_src;
+ return ret;
+ }
+
+ // determine number of samples to process
+ *samples = samples_src < samples_dest ? samples_src : samples_dest;
+ *channels = channels_src < channels_dest ? channels_src : channels_dest;
+ *buffer = dest;
+ *frequency = frequency_dest;
+
+ for ( j = 0; j < *channels; j++ )
+ vp[ j ] = ( double )dest[ j ];
+
+ double Fc = 0.5;
+ double B = exp(-2.0 * M_PI * Fc);
+ double A = 1.0 - B;
+ double v;
+
+ for ( i = 0; i < *samples; i++ )
+ {
+ for ( j = 0; j < *channels; j++ )
+ {
+ v = ( double )( b_weight * dest[ i * channels_dest + j ] + src[ i * channels_src + j ] );
+ v = v < -32767 ? -32767 : v > 32768 ? 32768 : v;
+ vp[ j ] = dest[ i * channels_dest + j ] = ( int16_t )( v * A + vp[ j ] * B );
+ }
+ }
+
+ return ret;
+}
+
/** Get the audio.
*/
-static int transition_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int transition_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
// Get the b frame from the stack
mlt_frame b_frame = mlt_frame_pop_audio( frame );
// Get the properties of the b frame
mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame );
+ // We can only mix s16
+ *format = mlt_audio_s16;
+
if ( mlt_properties_get_int( MLT_TRANSITION_PROPERTIES( effect ), "combine" ) == 0 )
{
double mix_start = 0.5, mix_end = 0.5;
mix_end = 1 - mix_end;
}
- mlt_frame_mix_audio( frame, b_frame, mix_start, mix_end, buffer, format, frequency, channels, samples );
+ mix_audio( frame, b_frame, mix_start, mix_end, buffer, format, frequency, channels, samples );
}
else
{
- mlt_frame_combine_audio( frame, b_frame, buffer, format, frequency, channels, samples );
+ combine_audio( frame, b_frame, buffer, format, frequency, channels, samples );
}
return 0;
int count = mlt_properties_get_int( this_properties, "count" );
// Default audio args
- mlt_audio_format fmt = mlt_audio_pcm;
+ mlt_audio_format fmt = mlt_audio_s16;
int channels = 2;
int frequency = mlt_properties_get_int( this_properties, "frequency" );
int samples = mlt_sample_calculator( mlt_properties_get_double( this_properties, "fps" ), frequency, count );
audio_buffers[ i ] = mlt_pool_alloc( 2 * DV_AUDIO_MAX_SAMPLES );
// Get the audio
- mlt_frame_get_audio( frame, &pcm, &fmt, &frequency, &channels, &samples );
+ mlt_frame_get_audio( frame, (void**) &pcm, &fmt, &frequency, &channels, &samples );
// Inform the encoder of the number of audio samples
encoder->samples_this_frame = samples;
return 0;
}
-static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int producer_get_audio( mlt_frame this, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
int16_t *p;
int i, j;
// Check that we have audio
if ( decoder->audio->num_channels > 0 )
{
+ int size = *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t );
+
// Obtain required values
*frequency = decoder->audio->frequency;
*samples = decoder->audio->samples_this_frame;
*channels = decoder->audio->num_channels;
+ *format = mlt_audio_s16;
// Create a temporary workspace
for ( i = 0; i < 4; i++ )
audio_channels[ i ] = mlt_pool_alloc( DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
// Create a workspace for the result
- *buffer = mlt_pool_alloc( *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
+ *buffer = mlt_pool_alloc( size );
// Pass the allocated audio buffer as a property
- mlt_properties_set_data( properties, "audio", *buffer, *channels * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ), ( mlt_destructor )mlt_pool_release, NULL );
+ mlt_frame_set_audio( this, *buffer, *format, size, mlt_pool_release );
// Decode the audio
dv_decode_full_audio( decoder, dv_data, audio_channels );
#include <framework/mlt_filter.h>
#include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
#include <stdio.h>
#include <stdlib.h>
#include "jack_rack.h"
-#define BUFFER_LEN 204800 * 3
+#define BUFFER_LEN 204800 * 6
static void initialise_jack_ports( mlt_properties properties )
{
jack_rack_t *jackrack = jack_rack_new( rack_name, mlt_properties_get_int( properties, "channels" ) );
jack_rack_open_file( jackrack, mlt_properties_get( properties, "src" ) );
- mlt_properties_set_data( properties, "jackrack", jackrack, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "jackrack", jackrack, 0,
+ (mlt_destructor) jack_rack_destroy, NULL );
mlt_properties_set( properties, "_rack_client_name", rack_name );
}
float **jack_input_buffers = mlt_pool_alloc( sizeof(float *) * jack_buffer_size );
// Set properties - released inside filter_close
- mlt_properties_set_data( properties, "output_buffers", output_buffers, sizeof( jack_ringbuffer_t *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "input_buffers", input_buffers, sizeof( jack_ringbuffer_t *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "jack_output_ports", jack_output_ports, sizeof( jack_port_t *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "jack_input_ports", jack_input_ports, sizeof( jack_port_t *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "jack_output_buffers", jack_output_buffers, sizeof( float *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "jack_input_buffers", jack_input_buffers, sizeof( float *) * channels, NULL, NULL );
+ mlt_properties_set_data( properties, "output_buffers", output_buffers,
+ sizeof( jack_ringbuffer_t *) * channels, mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "input_buffers", input_buffers,
+ sizeof( jack_ringbuffer_t *) * channels, mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "jack_output_ports", jack_output_ports,
+ sizeof( jack_port_t *) * channels, mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "jack_input_ports", jack_input_ports,
+ sizeof( jack_port_t *) * channels, mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "jack_output_buffers", jack_output_buffers,
+ sizeof( float *) * channels, mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "jack_input_buffers", jack_input_buffers,
+ sizeof( float *) * channels, mlt_pool_release, NULL );
// Start Jack processing - required before registering ports
jack_activate( jack_client );
output_buffers[i] = jack_ringbuffer_create( BUFFER_LEN * sizeof(float) );
input_buffers[i] = jack_ringbuffer_create( BUFFER_LEN * sizeof(float) );
snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
- mlt_properties_set_data( properties, mlt_name, output_buffers[i], BUFFER_LEN * sizeof(float), NULL, NULL );
+ mlt_properties_set_data( properties, mlt_name, output_buffers[i],
+ BUFFER_LEN * sizeof(float), (mlt_destructor) jack_ringbuffer_free, NULL );
snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
- mlt_properties_set_data( properties, mlt_name, input_buffers[i], BUFFER_LEN * sizeof(float), NULL, NULL );
+ mlt_properties_set_data( properties, mlt_name, input_buffers[i],
+ BUFFER_LEN * sizeof(float), (mlt_destructor) jack_ringbuffer_free, NULL );
for ( in = 0; in < 2; in++ )
{
if ( in )
{
- fprintf( stderr, "jack connect %s to %s\n", rack_name, mlt_name );
+ mlt_log_verbose( NULL, "JACK connect %s to %s\n", rack_name, mlt_name );
jack_connect( jack_client, rack_name, mlt_name );
}
else
{
- fprintf( stderr, "jack connect %s to %s\n", mlt_name, rack_name );
+ mlt_log_verbose( NULL, "JACK connect %s to %s\n", mlt_name, rack_name );
jack_connect( jack_client, mlt_name, rack_name );
}
}
jack_output_buffers[i] = jack_port_get_buffer( jack_output_ports[i], frames );
if ( ! jack_output_buffers[i] )
{
- fprintf( stderr, "%s: no jack buffer for output port %d\n", __FUNCTION__, i );
+ mlt_log_error( MLT_FILTER_SERVICE(filter), "no buffer for output port %d\n", i );
err = 1;
break;
}
jack_input_buffers[i] = jack_port_get_buffer( jack_input_ports[i], frames );
if ( ! jack_input_buffers[i] )
{
- fprintf( stderr, "%s: no jack buffer for input port %d\n", __FUNCTION__, i );
+ mlt_log_error( MLT_FILTER_SERVICE(filter), "no buffer for input port %d\n", i );
err = 1;
break;
}
// Do not start returning audio until we have sent first mlt frame
if ( sync && i == 0 && frame_size > 0 )
total_size += ring_size;
- //fprintf(stderr, "sync %d frame_size %d ring_size %d jack_size %d\n", sync, frame_size, ring_size, jack_size );
+ mlt_log_debug( MLT_FILTER_SERVICE(filter), "sync %d frame_size %d ring_size %d jack_size %d\n", sync, frame_size, ring_size, jack_size );
if ( ! sync || ( frame_size > 0 && total_size >= frame_size ) )
{
/** Get the audio.
*/
-static int jackrack_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int jackrack_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 );
int jack_frequency = mlt_properties_get_int( filter_properties, "_sample_rate" );
// Get the producer's audio
+ *format = mlt_audio_float;
mlt_frame_get_audio( frame, buffer, format, &jack_frequency, channels, samples );
// TODO: Deal with sample rate differences
if ( *frequency != jack_frequency )
- fprintf( stderr, "mismatching frequencies in filter jackrack\n" );
+ mlt_log_error( MLT_FILTER_SERVICE( filter ), "mismatching frequencies JACK = %d actual = %d\n",
+ jack_frequency, *frequency );
*frequency = jack_frequency;
// Initialise Jack ports and connections if needed
// pthread_cond_t *output_ready = mlt_properties_get_data( filter_properties, "output_ready", NULL );
// Process the audio
- int16_t *q = *buffer;
- float sample[ 2 ][ 10000 ];
- int i, j;
+ float *q = (float*) *buffer;
+ size_t size = *samples * sizeof(float);
+ int j;
// struct timespec tm = { 0, 0 };
- // Convert to floats and write into output ringbuffer
- if ( jack_ringbuffer_write_space( output_buffers[0] ) >= ( *samples * sizeof(float) ) )
+ // Write into output ringbuffer
+ for ( j = 0; j < *channels; j++ )
{
- for ( i = 0; i < *samples; i++ )
- for ( j = 0; j < *channels; j++ )
- sample[ j ][ i ] = ( float )( *q ++ ) / 32768.0;
-
- for ( j = 0; j < *channels; j++ )
- jack_ringbuffer_write( output_buffers[j], ( char * )sample[ j ], *samples * sizeof(float) );
+ if ( jack_ringbuffer_write_space( output_buffers[j] ) >= size )
+ jack_ringbuffer_write( output_buffers[j], (char*)( q + j * *samples ), size );
}
// Synchronization phase - wait for signal from Jack process
- while ( jack_ringbuffer_read_space( input_buffers[ *channels - 1 ] ) < ( *samples * sizeof(float) ) ) ;
+ while ( jack_ringbuffer_read_space( input_buffers[ *channels - 1 ] ) < size ) ;
//pthread_cond_wait( output_ready, output_lock );
- // Read from input ringbuffer and convert from floats
- if ( jack_ringbuffer_read_space( input_buffers[0] ) >= ( *samples * sizeof(float) ) )
+ // Read from input ringbuffer
+ for ( j = 0; j < *channels; j++, q++ )
{
- // Initialise to silence, but repeat last frame if available in case of
- // buffer underrun
- for ( j = 0; j < *channels; j++ )
- jack_ringbuffer_read( input_buffers[j], ( char * )sample[ j ], *samples * sizeof(float) );
-
- q = *buffer;
- for ( i = 0; i < *samples; i++ )
- for ( j = 0; j < *channels; j++ )
- {
- if ( sample[ j ][ i ] > 1.0 )
- sample[ j ][ i ] = 1.0;
- else if ( sample[ j ][ i ] < -1.0 )
- sample[ j ][ i ] = -1.0;
-
- if ( sample[ j ][ i ] > 0 )
- *q ++ = 32767 * sample[ j ][ i ];
- else
- *q ++ = 32768 * sample[ j ][ i ];
- }
+ if ( jack_ringbuffer_read_space( input_buffers[j] ) >= size )
+ jack_ringbuffer_read( input_buffers[j], (char*)( q + j * *samples ), size );
}
return 0;
mlt_frame_push_audio( frame, this );
mlt_frame_push_audio( frame, jackrack_get_audio );
- if ( mlt_properties_get_int( properties, "_sync" ) )
+ if ( !mlt_properties_get_data( properties, "jackrack", NULL ) )
initialise_jack_ports( properties );
}
static void filter_close( mlt_filter this )
{
- int i;
- char mlt_name[20];
mlt_properties properties = MLT_FILTER_PROPERTIES( this );
jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
-
jack_deactivate( jack_client );
jack_client_close( jack_client );
- for ( i = 0; i < mlt_properties_get_int( properties, "channels" ); i++ )
- {
- snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
- jack_ringbuffer_free( mlt_properties_get_data( properties, mlt_name, NULL ) );
- snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
- jack_ringbuffer_free( mlt_properties_get_data( properties, mlt_name, NULL ) );
- }
- mlt_pool_release( mlt_properties_get_data( properties, "output_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "input_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "jack_output_ports", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "jack_input_ports", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "jack_output_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "jack_input_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "output_lock", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "output_ready", NULL ) );
-
- jack_rack_t *jackrack = mlt_properties_get_data( properties, "jackrack", NULL );
- jack_rack_destroy( jackrack );
-
this->parent.close = NULL;
mlt_service_close( &this->parent );
}
mlt_properties_set( properties, "_client_name", name );
mlt_properties_set_data( properties, "jack_client", jack_client, 0, NULL, NULL );
mlt_properties_set_int( properties, "_sample_rate", jack_get_sample_rate( jack_client ) );
- mlt_properties_set_data( properties, "output_lock", output_lock, 0, NULL, NULL );
- mlt_properties_set_data( properties, "output_ready", output_ready, 0, NULL, NULL );
+ mlt_properties_set_data( properties, "output_lock", output_lock, 0, mlt_pool_release, NULL );
+ mlt_properties_set_data( properties, "output_ready", output_ready, 0, mlt_pool_release, NULL );
mlt_properties_set_int( properties, "_sync", 1 );
mlt_properties_set_int( properties, "channels", 2 );
}
#define BUFFER_LEN 10000
-static void initialise_jack_rack( mlt_properties properties, int channels )
+static jack_rack_t* initialise_jack_rack( mlt_properties properties, int channels )
{
- int i;
- char mlt_name[20];
-
+ jack_rack_t *jackrack = NULL;
+ char *resource = mlt_properties_get( properties, "resource" );
+ if ( !resource && mlt_properties_get( properties, "src" ) )
+ resource = mlt_properties_get( properties, "src" );
+
// Propogate these for the Jack processing callback
mlt_properties_set_int( properties, "channels", channels );
// Start JackRack
- if ( mlt_properties_get( properties, "src" ) )
+ if ( resource )
{
// Create JackRack without Jack client name so that it only uses LADSPA
- jack_rack_t *jackrack = jack_rack_new( NULL, channels );
- mlt_properties_set_data( properties, "jackrack", jackrack, 0, NULL, NULL );
- jack_rack_open_file( jackrack, mlt_properties_get( properties, "src" ) );
- }
-
- // Allocate buffers
- LADSPA_Data **input_buffers = mlt_pool_alloc( sizeof( LADSPA_Data ) * channels );
- LADSPA_Data **output_buffers = mlt_pool_alloc( sizeof( LADSPA_Data ) * channels );
-
- // Set properties - released inside filter_close
- mlt_properties_set_data( properties, "input_buffers", input_buffers, sizeof( LADSPA_Data *) * channels, NULL, NULL );
- mlt_properties_set_data( properties, "output_buffers", output_buffers, sizeof( LADSPA_Data *) * channels, NULL, NULL );
-
- // Register Jack ports
- for ( i = 0; i < channels; i++ )
- {
- input_buffers[i] = mlt_pool_alloc( BUFFER_LEN * sizeof( LADSPA_Data ) );
- snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
- mlt_properties_set_data( properties, mlt_name, input_buffers[i], BUFFER_LEN * sizeof( LADSPA_Data ), NULL, NULL );
-
- output_buffers[i] = mlt_pool_alloc( BUFFER_LEN * sizeof( LADSPA_Data ) );
- snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
- mlt_properties_set_data( properties, mlt_name, output_buffers[i], BUFFER_LEN * sizeof( LADSPA_Data ), NULL, NULL );
+ jackrack = jack_rack_new( NULL, channels );
+ mlt_properties_set_data( properties, "jackrack", jackrack, 0,
+ (mlt_destructor) jack_rack_destroy, NULL );
+ jack_rack_open_file( jackrack, resource );
}
+ return jackrack;
}
/** Get the audio.
*/
-static int ladspa_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int ladspa_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 );
mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
// Get the producer's audio
+ *format = mlt_audio_float;
mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
// Initialise LADSPA if needed
jack_rack_t *jackrack = mlt_properties_get_data( filter_properties, "jackrack", NULL );
if ( jackrack == NULL )
{
- sample_rate = *frequency;
- initialise_jack_rack( filter_properties, *channels );
- jackrack = mlt_properties_get_data( filter_properties, "jackrack", NULL );
+ sample_rate = *frequency; // global inside jack_rack
+ jackrack = initialise_jack_rack( filter_properties, *channels );
}
// Get the filter-specific properties
- LADSPA_Data **input_buffers = mlt_properties_get_data( filter_properties, "input_buffers", NULL );
- LADSPA_Data **output_buffers = mlt_properties_get_data( filter_properties, "output_buffers", NULL );
-
- // Process the audio
- int16_t *q = *buffer;
- int i, j;
+ LADSPA_Data **input_buffers = mlt_pool_alloc( sizeof( LADSPA_Data* ) * *channels );
+ LADSPA_Data **output_buffers = mlt_pool_alloc( sizeof( LADSPA_Data* ) * *channels );
- // Convert to floats and write into output ringbuffer
- for ( i = 0; i < *samples; i++ )
- for ( j = 0; j < *channels; j++ )
- input_buffers[ j ][ i ] = ( float )( *q ++ ) / 32768.0;
-
- // Do LADSPA processing
- if ( jackrack && process_ladspa( jackrack->procinfo, *samples, input_buffers, output_buffers) == 0 )
+ int i;
+ for ( i = 0; i < *channels; i++ )
{
- // Read from output buffer and convert from floats
- q = *buffer;
- for ( i = 0; i < *samples; i++ )
- for ( j = 0; j < *channels; j++ )
- {
- if ( output_buffers[ j ][ i ] > 1.0 )
- output_buffers[ j ][ i ] = 1.0;
- else if ( output_buffers[ j ][ i ] < -1.0 )
- output_buffers[ j ][ i ] = -1.0;
-
- if ( output_buffers[ j ][ i ] > 0 )
- *q ++ = 32767 * output_buffers[ j ][ i ];
- else
- *q ++ = 32768 * output_buffers[ j ][ i ];
- }
+ input_buffers[i] = (LADSPA_Data*) *buffer + i * *samples;
+ output_buffers[i] = (LADSPA_Data*) *buffer + i * *samples;
}
- return 0;
+ // Do LADSPA processing
+ int error = jackrack && process_ladspa( jackrack->procinfo, *samples, input_buffers, output_buffers );
+
+ mlt_pool_release( input_buffers );
+ mlt_pool_release( output_buffers );
+
+ return error;
}
static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
{
+ if ( mlt_frame_is_test_audio( frame ) == 0 )
{
mlt_frame_push_audio( frame, this );
mlt_frame_push_audio( frame, ladspa_get_audio );
return frame;
}
-
-static void filter_close( mlt_filter this )
-{
- int i;
- char mlt_name[20];
- mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
- if ( mlt_properties_get_data( properties, "jackrack", NULL ) != NULL )
- {
- for ( i = 0; i < mlt_properties_get_int( properties, "channels" ); i++ )
- {
- snprintf( mlt_name, sizeof( mlt_name ), "obuf%d", i );
- mlt_pool_release( mlt_properties_get_data( properties, mlt_name, NULL ) );
- snprintf( mlt_name, sizeof( mlt_name ), "ibuf%d", i );
- mlt_pool_release( mlt_properties_get_data( properties, mlt_name, NULL ) );
- }
- mlt_pool_release( mlt_properties_get_data( properties, "output_buffers", NULL ) );
- mlt_pool_release( mlt_properties_get_data( properties, "input_buffers", NULL ) );
-
- jack_rack_t *jackrack = mlt_properties_get_data( properties, "jackrack", NULL );
- jack_rack_destroy( jackrack );
- }
- this->parent.close = NULL;
- mlt_service_close( &this->parent );
-}
-
/** Constructor for the filter.
*/
if ( this != NULL )
{
mlt_properties properties = MLT_FILTER_PROPERTIES( this );
-
this->process = filter_process;
- this->close = filter_close;
-
- mlt_properties_set( properties, "src", arg );
+ mlt_properties_set( properties, "resource", arg );
}
return this;
}
/** Get the audio.
*/
-static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+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 );
limiter_level = mlt_properties_get_double( properties, "volume.limiter" );
// Get the producer's audio
+ *format = mlt_audio_s16;
mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
// fprintf( stderr, "filter_volume: frequency %d\n", *frequency );
}
else
{
- gain *= amplitude / signal_max_power( *buffer, *channels, *samples, &peak );
+ gain *= amplitude / signal_max_power( (int16_t*) *buffer, *channels, *samples, &peak );
}
}
// Ramp from the previous gain to the current
gain = previous_gain;
- int16_t *p = *buffer;
+ int16_t *p = (int16_t*) *buffer;
// Apply the gain
for ( i = 0; i < *samples; i++ )
#include <framework/mlt_filter.h>
#include <framework/mlt_frame.h>
+#include <framework/mlt_log.h>
#include <stdio.h>
#include <stdlib.h>
#include <samplerate.h>
+#include <string.h>
#define BUFFER_LEN 20480
#define RESAMPLE_TYPE SRC_SINC_FASTEST
/** Get the audio.
*/
-static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int resample_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
- // Get the properties of the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
// Get the filter service
mlt_filter filter = mlt_frame_pop_audio( frame );
// Get the resample information
int output_rate = mlt_properties_get_int( filter_properties, "frequency" );
- SRC_STATE *state = mlt_properties_get_data( filter_properties, "state", NULL );
- float *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
- float *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
- int channels_avail = *channels;
- SRC_DATA data;
- int i;
+ int error = 0;
// 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 );
-
- // Duplicate channels as necessary
- if ( channels_avail < *channels )
- {
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
- int j, k = 0;
-
- // Duplicate the existing channels
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
- k = ( k + 1 ) % channels_avail;
- }
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
- else if ( channels_avail == 6 && *channels == 2 )
- {
- // Nasty hack for ac3 5.1 audio - may be a cause of failure?
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
-
- // Drop all but the first *channels
- for ( i = 0; i < *samples; i++ )
- {
- new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
- new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
+ if ( *format != mlt_audio_s16 )
+ *format = mlt_audio_float;
+ mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
// Return now if no work to do
if ( output_rate != *frequency )
{
- float *p = input_buffer;
- float *end = p + *samples * *channels;
- int16_t *q = *buffer;
-
- // Convert to floating point
- while( p != end )
- *p ++ = ( float )( *q ++ ) / 32768.0;
-
- // Resample
+ // Do not convert to float unless we need to change the rate
+ if ( *format != mlt_audio_float )
+ {
+ *format = mlt_audio_float;
+ mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
+ }
+ float *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
+ float *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
+ SRC_DATA data;
data.data_in = input_buffer;
data.data_out = output_buffer;
data.src_ratio = ( float ) output_rate / ( float ) *frequency;
data.input_frames = *samples;
data.output_frames = BUFFER_LEN / *channels;
data.end_of_input = 0;
- i = src_process( state, &data );
- if ( i == 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 );
+ }
+
+ // Convert to interleaved
+ float *q = (float*) *buffer;
+ float *p = input_buffer;
+ int s, c;
+ for ( s = 0; s < *samples; s++ )
+ for ( c = 0; c < *channels; c++ )
+ *p++ = *( q + c * *samples + s );
+
+ // Resample the audio
+ error = src_process( state, &data );
+ if ( !error )
{
+ int size = data.output_frames_gen * *channels * sizeof(float);
+
+ // Resize if necessary
if ( data.output_frames_gen > *samples )
{
- *buffer = mlt_pool_realloc( *buffer, data.output_frames_gen * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( properties, "audio", *buffer, *channels * data.output_frames_gen * 2, mlt_pool_release, NULL );
+ *buffer = mlt_pool_realloc( *buffer, size );
+ mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
}
- *samples = data.output_frames_gen;
- *frequency = output_rate;
-
- p = output_buffer;
- q = *buffer;
- end = p + *samples * *channels;
-
- // Convert from floating back to signed 16bit
- while( p != end )
+ // Convert to non-interleaved
+ p = (float*) *buffer;
+ for ( c = 0; c < *channels; c++ )
{
- if ( *p > 1.0 )
- *p = 1.0;
- if ( *p < -1.0 )
- *p = -1.0;
- if ( *p > 0 )
- *q ++ = 32767 * *p ++;
- else
- *q ++ = 32768 * *p ++;
+ float *q = output_buffer + c;
+ int i = data.output_frames_gen + 1;
+ while ( --i )
+ {
+ *p++ = *q;
+ q += *channels;
+ }
}
+
+ // Update output variables
+ *samples = data.output_frames_gen;
+ *frequency = output_rate;
}
else
- fprintf( stderr, "resample_get_audio: %s %d,%d,%d\n", src_strerror( i ), *frequency, *samples, output_rate );
+ mlt_log_error( MLT_FILTER_SERVICE( filter ), "%s %d,%d,%d\n", src_strerror( error ), *frequency, *samples, output_rate );
}
- return 0;
+ return error;
}
/** Filter processing.
{
// Get the properties of this consumer
mlt_properties properties = this->properties;
- mlt_audio_format afmt = mlt_audio_pcm;
+ mlt_audio_format afmt = mlt_audio_s16;
// Set the preferred params of the test card signal
int channels = mlt_properties_get_int( properties, "channels" );
int16_t *pcm;
int bytes;
- mlt_frame_get_audio( frame, &pcm, &afmt, &frequency, &channels, &samples );
+ mlt_frame_get_audio( frame, (void**) &pcm, &afmt, &frequency, &channels, &samples );
*duration = ( ( samples * 1000 ) / frequency );
if ( mlt_properties_get_int( properties, "audio_off" ) )
/** Get the audio.
*/
-static int filter_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(14,3,0))
SOX_SAMPLE_LOCALS;
#endif
- // Get the properties of the frame
- mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
-
// Get the filter service
mlt_filter filter = mlt_frame_pop_audio( frame );
mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter );
// Get the properties
- st_sample_t *input_buffer = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
+ st_sample_t *input_buffer;// = mlt_properties_get_data( filter_properties, "input_buffer", NULL );
st_sample_t *output_buffer = mlt_properties_get_data( filter_properties, "output_buffer", NULL );
- int channels_avail = *channels;
int i; // channel
int count = mlt_properties_get_int( filter_properties, "_effect_count" );
// Get the producer's audio
- mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
-
- // Duplicate channels as necessary
- if ( channels_avail < *channels )
- {
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
- int j, k = 0;
-
- // Duplicate the existing channels
- for ( i = 0; i < *samples; i++ )
- {
- for ( j = 0; j < *channels; j++ )
- {
- new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ];
- k = ( k + 1 ) % channels_avail;
- }
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
- else if ( channels_avail == 6 && *channels == 2 )
- {
- // Nasty hack for ac3 5.1 audio - may be a cause of failure?
- int size = *channels * *samples * sizeof( int16_t );
- int16_t *new_buffer = mlt_pool_alloc( size );
-
- // Drop all but the first *channels
- for ( i = 0; i < *samples; i++ )
- {
- new_buffer[ ( i * *channels ) + 0 ] = (*buffer)[ ( i * channels_avail ) + 2 ];
- new_buffer[ ( i * *channels ) + 1 ] = (*buffer)[ ( i * channels_avail ) + 3 ];
- }
-
- // Update the audio buffer now - destroys the old
- mlt_properties_set_data( properties, "audio", new_buffer, size, ( mlt_destructor )mlt_pool_release, NULL );
-
- *buffer = new_buffer;
- }
+ *format = mlt_audio_s32;
+ mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
// Even though some effects are multi-channel aware, it is not reliable
// We must maintain a separate effect state for each channel
}
if ( *samples > 0 && count > 0 )
{
+ input_buffer = (st_sample_t*) *buffer + i * *samples;
st_sample_t *p = input_buffer;
- st_sample_t *end = p + *samples;
- int16_t *q = *buffer + i;
st_size_t isamp = *samples;
st_size_t osamp = *samples;
double rms = 0;
- int j;
+ int j = *samples + 1;
char *normalise = mlt_properties_get( filter_properties, "normalise" );
double normalised_gain = 1.0;
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(13,0,0))
- st_sample_t dummy_clipped_count = 0;
-#endif
- // Convert to sox encoding
- while( p != end )
+ // Convert from interleaved
+ while( --j )
{
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(13,0,0))
- *p = ST_SIGNED_WORD_TO_SAMPLE( *q, dummy_clipped_count );
-#else
- *p = ST_SIGNED_WORD_TO_SAMPLE( *q );
-#endif
// Compute rms amplitude while we are accessing each sample
rms += ( double )*p * ( double )*p;
-
p ++;
- q += *channels;
}
// Compute final rms amplitude
}
}
}
-
- // Convert back to signed 16bit
- p = input_buffer;
- q = *buffer + i;
- end = p + *samples;
- while ( p != end )
- {
-#if (ST_LIB_VERSION_CODE >= ST_LIB_VERSION(13,0,0))
- *q = ST_SAMPLE_TO_SIGNED_WORD( *p ++, dummy_clipped_count );
-#else
- *q = ST_SAMPLE_TO_SIGNED_WORD( *p ++ );
-#endif
- q += *channels;
- }
+
+ // Write back
+ memcpy( output_buffer, input_buffer, *samples * sizeof(st_sample_t) );
}
}
/** Get the audio from a frame.
*/
-static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int producer_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
{
// Get the properties from the frame
mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
// Now handle the audio if we have enough
if ( audio_used >= *samples )
{
- *buffer = mlt_pool_alloc( *samples * *channels * sizeof( int16_t ) );
- memcpy( *buffer, audio_buffer, *samples * *channels * sizeof( int16_t ) );
+ int size = *samples * *channels * sizeof( int16_t );
+
+ *format = mlt_audio_s16;
+ *buffer = mlt_pool_alloc( size );
+ memcpy( *buffer, audio_buffer, size );
audio_used -= *samples;
memmove( audio_buffer, &audio_buffer[ *samples * *channels ], audio_used * *channels * sizeof( int16_t ) );
- mlt_properties_set_data( frame_properties, "audio", *buffer, 0, mlt_pool_release, NULL );
+ mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
}
else
{