X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Fresample%2Ffilter_resample.c;h=72df0119a18664f923d0600a059069e8f2fc87f8;hb=6ad443b3ffd53b2e8be119df6fb7d3f2da1c4cec;hp=c8fbf5fd924b591d5fc4e817dd03d572559322d7;hpb=3a63c2147254f4382a91f007c86680259b41f1be;p=melted diff --git a/src/modules/resample/filter_resample.c b/src/modules/resample/filter_resample.c index c8fbf5f..72df011 100644 --- a/src/modules/resample/filter_resample.c +++ b/src/modules/resample/filter_resample.c @@ -36,63 +36,123 @@ static int resample_get_audio( mlt_frame frame, int16_t **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 output_rate = mlt_properties_get_int( properties, "resample.frequency" ); - SRC_STATE *state = mlt_properties_get_data( properties, "resample.state", NULL ); + // 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 filter properties + mlt_properties filter_properties = MLT_FILTER_PROPERTIES( filter ); + + // 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; - float *input_buffer = mlt_properties_get_data( properties, "resample.input_buffer", NULL ); - float *output_buffer = mlt_properties_get_data( properties, "resample.output_buffer", NULL ); int i; + // If no resample frequency is specified, default to requested value if ( output_rate == 0 ) output_rate = *frequency; - // Restore the original get_audio - frame->get_audio = mlt_properties_get_data( properties, "resample.get_audio", NULL ); - // Get the producer's audio - mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples ); - - // Convert to floating point - for ( i = 0; i < *samples * *channels; ++i ) - input_buffer[ i ] = ( float )( (*buffer)[ i ] ) / 32768; - - // Resample - 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 ) + mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples ); + + // Duplicate channels as necessary + if ( channels_avail < *channels ) { - if ( data.output_frames_gen > *samples ) + 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++ ) { - *buffer = (int16_t*) malloc( data.output_frames_gen * *channels * 2 ); - mlt_properties_set_data( properties, "audio", *buffer, *channels * data.output_frames_gen * 2, free, NULL ); + for ( j = 0; j < *channels; j++ ) + { + new_buffer[ ( i * *channels ) + j ] = (*buffer)[ ( i * channels_avail ) + k ]; + k = ( k + 1 ) % channels_avail; + } } - *samples = data.output_frames_gen; - *frequency = output_rate; - // Convert from floating back to signed 16bit - for ( i = 0; i < *samples * *channels; ++i ) + // 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++ ) { - float sample = output_buffer[ i ]; - if ( sample > 1.0 ) - sample = 1.0; - if ( sample < -1.0 ) - sample = -1.0; - if ( sample >= 0 ) - (*buffer)[ i ] = lrint( 32767.0 * sample ); - else - (*buffer)[ i ] = lrint( 32768.0 * sample ); + 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; } - else - fprintf( stderr, "resample_get_audio: %s %d,%d,%d\n", src_strerror( i ), *frequency, *samples, output_rate ); - + + // 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 + 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 ) + { + 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 ); + } + + *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 ) + { + if ( *p > 1.0 ) + *p = 1.0; + if ( *p < -1.0 ) + *p = -1.0; + if ( *p > 0 ) + *q ++ = 32767 * *p ++; + else + *q ++ = 32768 * *p ++; + } + } + else + fprintf( stderr, "resample_get_audio: %s %d,%d,%d\n", src_strerror( i ), *frequency, *samples, output_rate ); + } + return 0; } @@ -101,24 +161,11 @@ static int resample_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) { - mlt_properties properties = mlt_filter_properties( this ); - mlt_properties frame_props = mlt_frame_properties( frame ); - - // Propogate the frequency property if supplied - if ( mlt_properties_get( properties, "frequency" ) != NULL ) - mlt_properties_set_int( frame_props, "resample.frequency", mlt_properties_get_int( properties, "frequency" ) ); - - // Propogate the other properties - mlt_properties_set_int( frame_props, "resample.channels", mlt_properties_get_int( properties, "channels" ) ); - mlt_properties_set_data( frame_props, "resample.state", mlt_properties_get_data( properties, "state", NULL ), 0, NULL, NULL ); - mlt_properties_set_data( frame_props, "resample.input_buffer", mlt_properties_get_data( properties, "input_buffer", NULL ), 0, NULL, NULL ); - mlt_properties_set_data( frame_props, "resample.output_buffer", mlt_properties_get_data( properties, "output_buffer", NULL ), 0, NULL, NULL ); - - // Backup the original get_audio (it's still needed) - mlt_properties_set_data( frame_props, "resample.get_audio", frame->get_audio, 0, NULL, NULL ); - - // Override the get_audio method - frame->get_audio = resample_get_audio; + if ( mlt_frame_is_test_audio( frame ) != 0 ) + { + mlt_frame_push_audio( frame, this ); + mlt_frame_push_audio( frame, resample_get_audio ); + } return frame; } @@ -128,22 +175,22 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) mlt_filter filter_resample_init( char *arg ) { - mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 ); - if ( this != NULL && mlt_filter_init( this, NULL ) == 0 ) + mlt_filter this = mlt_filter_new( ); + if ( this != NULL ) { int error; SRC_STATE *state = src_new( RESAMPLE_TYPE, 2 /* channels */, &error ); if ( error == 0 ) { + void *input_buffer = mlt_pool_alloc( BUFFER_LEN ); + void *output_buffer = mlt_pool_alloc( BUFFER_LEN ); this->process = filter_process; if ( arg != NULL ) - mlt_properties_set_int( mlt_filter_properties( this ), "frequency", atoi( arg ) ); - mlt_properties_set_int( mlt_filter_properties( this ), "channels", 2 ); - mlt_properties_set_data( mlt_filter_properties( this ), "state", state, 0, (mlt_destructor)src_delete, NULL ); - mlt_properties_set_data( mlt_filter_properties( this ), "input_buffer", - malloc( BUFFER_LEN ), BUFFER_LEN, free, NULL ); - mlt_properties_set_data( mlt_filter_properties( this ), "output_buffer", - malloc( BUFFER_LEN ), BUFFER_LEN, free, NULL ); + mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "frequency", atoi( arg ) ); + mlt_properties_set_int( MLT_FILTER_PROPERTIES( this ), "channels", 2 ); + mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "state", state, 0, (mlt_destructor)src_delete, NULL ); + mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "input_buffer", input_buffer, BUFFER_LEN, mlt_pool_release, NULL ); + mlt_properties_set_data( MLT_FILTER_PROPERTIES( this ), "output_buffer", output_buffer, BUFFER_LEN, mlt_pool_release, NULL ); } else { @@ -152,4 +199,3 @@ mlt_filter filter_resample_init( char *arg ) } return this; } -