summaryrefslogtreecommitdiffstats
path: root/core/Resample.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/Resample.c')
-rw-r--r--core/Resample.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/core/Resample.c b/core/Resample.c
new file mode 100644
index 000000000..f3632b371
--- /dev/null
+++ b/core/Resample.c
@@ -0,0 +1,159 @@
+/* $Id: Resample.c,v 1.4 2004/05/02 16:25:00 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "HBInternal.h"
+
+#include "samplerate.h"
+
+struct HBWork
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBAudio * audio;
+
+ float * samples;
+ SRC_STATE * state;
+ SRC_DATA data;
+
+ uint64_t in;
+ uint64_t out;
+};
+
+/* Local prototypes */
+static int ResampleWork( HBWork * );
+
+HBWork * HBResampleInit( HBHandle * handle, HBAudio * audio )
+{
+ HBWork * w;
+ if( !( w = calloc( sizeof( HBWork ), 1 ) ) )
+ {
+ HBLog( "HBResampleInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ w->name = strdup( "Resample" );
+ w->work = ResampleWork;
+
+ w->handle = handle;
+ w->audio = audio;
+
+ return w;
+}
+
+void HBResampleClose( HBWork ** _w )
+{
+ HBWork * w = *_w;
+
+ if( w->samples ) free( w->samples );
+ if( w->state ) src_delete( w->state );
+
+ free( w->name );
+ free( w );
+ *_w = NULL;
+}
+
+static int ResampleWork( HBWork * w )
+{
+ HBAudio * audio = w->audio;
+
+ HBBuffer * resampleBuffer;
+ float position;
+
+ if( HBFifoIsHalfFull( audio->resampleFifo ) )
+ {
+ return 0;
+ }
+
+ /* Initialization */
+ if( !w->samples )
+ {
+ int error;
+
+ /* Until a first packet comes, audio->inSampleRate is
+ undefined */
+ if( !HBFifoSize( audio->rawFifo ) )
+ {
+ return 0;
+ }
+
+ /* No, the user can't choose. 44100 Hz, take it or leave it */
+ audio->outSampleRate = 44100;
+ HBLog( "HBResample: in = %d Hz, out = %d Hz",
+ audio->inSampleRate, audio->outSampleRate );
+
+ /* Buffer in which we'll pop the samples from the decoder */
+ w->samples = malloc( audio->inSampleRate * 2 *
+ sizeof( float ) / 10 );
+
+ /* Init libsamplerate */
+ w->state = src_new( SRC_SINC_FASTEST, 2, &error );
+
+ /* Prepare the SRC_DATA structure */
+ w->data.data_in = w->samples;
+ w->data.input_frames = audio->inSampleRate / 10;
+ w->data.output_frames = audio->outSampleRate / 10;
+ w->data.src_ratio = (double) audio->outSampleRate /
+ (double) audio->inSampleRate;
+ w->data.end_of_input = 0;
+ }
+
+ /* Fix A/V synchro in case the audio track starts later than the
+ video */
+ if( audio->delay > 0 )
+ {
+ HBLog( "HBResample: adding %d ms of silence", audio->delay );
+
+ resampleBuffer = HBBufferInit( audio->delay *
+ audio->outSampleRate * 2 * sizeof( float ) / 1000 );
+ memset( resampleBuffer->data, 0, resampleBuffer->size );
+ if( !HBFifoPush( audio->resampleFifo, &resampleBuffer ) )
+ {
+ HBLog( "HBResample: HBFifoPush failed" );
+ }
+
+ audio->delay = 0;
+ return 1;
+ }
+
+ /* Get samples from the decoder */
+ if( !HBFifoGetBytes( audio->rawFifo, (uint8_t *) w->samples,
+ audio->inSampleRate * 2 * sizeof( float ) / 10,
+ &position ) )
+ {
+ return 0;
+ }
+
+ /* Init resampled buffer */
+ resampleBuffer = HBBufferInit( audio->outSampleRate * 2 *
+ sizeof( float ) / 10 );
+ resampleBuffer->position = position;
+
+ /* Resample */
+ w->data.data_out = resampleBuffer->dataf;
+ if( src_process( w->state, &w->data ) )
+ {
+ HBLog( "HBResample: src_process failed" );
+ }
+ resampleBuffer->size = w->data.output_frames_gen * 2 *
+ sizeof( float );
+
+ if( w->data.input_frames_used != w->data.input_frames )
+ {
+ /* Here we're basically f*cked */
+ HBLog( "HBResample: ohoh, %d/%d used",
+ w->data.input_frames_used, w->data.input_frames );
+ }
+
+ /* Send resampled data to the encoder */
+ if( !HBFifoPush( audio->resampleFifo, &resampleBuffer ) )
+ {
+ HBLog( "HBResample: HBFifoPush failed" );
+ }
+
+ return 1;
+}
+