diff src/audacious/output.c @ 4286:af324ff0a983

added passthrough mode. tested with ape and flac
author Eugene Zagidullin <e.asphyx@gmail.com>
date Sat, 16 Feb 2008 01:47:30 +0300
parents 0a9e1d9eae7b
children 19c4a20d11a1
line wrap: on
line diff
--- a/src/audacious/output.c	Fri Feb 15 15:34:46 2008 +0100
+++ b/src/audacious/output.c	Sat Feb 16 01:47:30 2008 +0300
@@ -23,7 +23,7 @@
  *  Audacious or using our public API to be a derived work.
  */
 
-/*#define AUD_DEBUG*/
+/* #define AUD_DEBUG */
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
@@ -69,6 +69,7 @@
 };
 
 static gint decoder_srate = 0;
+static gboolean bypass_dsp = FALSE;
 
 OutputPlugin psuedo_output_plugin = {
     .description = "XMMS reverse compatibility output plugin",
@@ -271,11 +272,51 @@
     if (sad_state_to_float != NULL)   {SAD_dither_free(sad_state_to_float);   sad_state_to_float = NULL;}
 }
 
+static gboolean
+reopen_audio(AFormat fmt, gint rate, gint nch)
+{
+    OutputPlugin *op = get_current_output_plugin();
+
+    if (op == NULL)
+        return FALSE;
+
+    /* Is our output port already open? */
+    if ((op_state.rate != 0 && op_state.nch != 0) &&
+        (op_state.rate == rate && op_state.nch == nch && op_state.fmt == fmt))
+    {
+        /* Yes, and it's the correct sampling rate. Reset the counter and go. */
+	AUDDBG("flushing output instead of reopening\n");
+	plugin_set_current((Plugin *)op);
+        op->flush(0);
+        return TRUE;
+    }
+    else if (op_state.rate != 0 && op_state.nch != 0)
+    {
+        plugin_set_current((Plugin *)op);
+        op->close_audio();
+    }
+
+    plugin_set_current((Plugin *)op);
+    gint ret = op->open_audio(fmt, rate, nch);
+
+    if (ret == 1)            /* Success? */
+    {
+        AUDDBG("opened audio: fmt=%d, rate=%d, nch=%d\n", fmt, rate, nch);
+        op_state.fmt = fmt;
+        op_state.rate = rate;
+        op_state.nch = nch;
+
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
 gint
 output_open_audio(AFormat fmt, gint rate, gint nch)
 {
     gint ret;
-    OutputPlugin *op;
+    /*OutputPlugin *op;*/
     AUDDBG("requested: fmt=%d, rate=%d, nch=%d\n", fmt, rate, nch);
 
     AFormat output_fmt;
@@ -284,71 +325,85 @@
     SAD_buffer_format output_sad_fmt;
 
     decoder_srate = rate;
+    bypass_dsp = cfg.bypass_dsp;
 
+    if (bypass_dsp) {
+        AUDDBG("trying to open audio in native format\n");
+        bypass_dsp = reopen_audio(fmt, rate, nch);
+        AUDDBG("opening in native fmt %s\n", bypass_dsp ? "succeeded" : "failed");
+    }
+
+    if (bypass_dsp) {
+        return TRUE;
+    } else {
 #ifdef USE_SRC
-    if(cfg.enable_src) rate = cfg.src_rate;
+        if(cfg.enable_src) rate = cfg.src_rate;
 #endif
     
-    bit_depth = cfg.output_bit_depth;
-
-    AUDDBG("bit depth: %d\n", bit_depth);
-    output_fmt = (bit_depth == 24) ? FMT_S24_NE : FMT_S16_NE;
+        bit_depth = cfg.output_bit_depth;
     
-    freeSAD();
-
-    AUDDBG("initializing dithering engine for 2 stage conversion: fmt%d --> float -->fmt%d\n", fmt, output_fmt);
-    input_sad_fmt.sample_format = sadfmt_from_afmt(fmt);
-    if (input_sad_fmt.sample_format < 0) return FALSE;
-    input_sad_fmt.fracbits = FMT_FRACBITS(fmt);
-    input_sad_fmt.channels = nch;
-    input_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
-    input_sad_fmt.samplerate = 0;
-    
-    output_sad_fmt.sample_format = SAD_SAMPLE_FLOAT;
-    output_sad_fmt.fracbits = 0;
-    output_sad_fmt.channels = nch;
-    output_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
-    output_sad_fmt.samplerate = 0;
-    
-    sad_state_to_float = SAD_dither_init(&input_sad_fmt, &output_sad_fmt, &ret);
-    if (sad_state_to_float == NULL) {
-        AUDDBG("ditherer init failed (decoder's native --> float)\n");
-        return FALSE;
-    }
-    SAD_dither_set_dither (sad_state_to_float, FALSE);
+        AUDDBG("bit depth: %d\n", bit_depth);
+        output_fmt = (bit_depth == 24) ? FMT_S24_NE : FMT_S16_NE;
+        
+        freeSAD();
     
-    input_sad_fmt.sample_format = SAD_SAMPLE_FLOAT;
-    input_sad_fmt.fracbits = 0;
-    input_sad_fmt.channels = nch;
-    input_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
-    input_sad_fmt.samplerate = 0;
-    
-    output_sad_fmt.sample_format = sadfmt_from_afmt(output_fmt);
-    if (output_sad_fmt.sample_format < 0) return FALSE;
-    output_sad_fmt.fracbits = FMT_FRACBITS(output_fmt);
-    output_sad_fmt.channels = nch;
-    output_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
-    output_sad_fmt.samplerate = 0;
+        AUDDBG("initializing dithering engine for 2 stage conversion: fmt%d --> float -->fmt%d\n", fmt, output_fmt);
+        input_sad_fmt.sample_format = sadfmt_from_afmt(fmt);
+        if (input_sad_fmt.sample_format < 0) return FALSE;
+        input_sad_fmt.fracbits = FMT_FRACBITS(fmt);
+        input_sad_fmt.channels = nch;
+        input_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
+        input_sad_fmt.samplerate = 0;
+        
+        output_sad_fmt.sample_format = SAD_SAMPLE_FLOAT;
+        output_sad_fmt.fracbits = 0;
+        output_sad_fmt.channels = nch;
+        output_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
+        output_sad_fmt.samplerate = 0;
+        
+        sad_state_to_float = SAD_dither_init(&input_sad_fmt, &output_sad_fmt, &ret);
+        if (sad_state_to_float == NULL) {
+            AUDDBG("ditherer init failed (decoder's native --> float)\n");
+            return FALSE;
+        }
+        SAD_dither_set_dither (sad_state_to_float, FALSE);
+        
+        input_sad_fmt.sample_format = SAD_SAMPLE_FLOAT;
+        input_sad_fmt.fracbits = 0;
+        input_sad_fmt.channels = nch;
+        input_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
+        input_sad_fmt.samplerate = 0;
+        
+        output_sad_fmt.sample_format = sadfmt_from_afmt(output_fmt);
+        if (output_sad_fmt.sample_format < 0) return FALSE;
+        output_sad_fmt.fracbits = FMT_FRACBITS(output_fmt);
+        output_sad_fmt.channels = nch;
+        output_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
+        output_sad_fmt.samplerate = 0;
+        
+        sad_state_from_float = SAD_dither_init(&input_sad_fmt, &output_sad_fmt, &ret);
+        if (sad_state_from_float == NULL) {
+            SAD_dither_free(sad_state_to_float);
+            AUDDBG("ditherer init failed (float --> output)\n");
+            return FALSE;
+        }
+        SAD_dither_set_dither (sad_state_from_float, TRUE);
+        
+        fmt = output_fmt;
     
-    sad_state_from_float = SAD_dither_init(&input_sad_fmt, &output_sad_fmt, &ret);
-    if (sad_state_from_float == NULL) {
-        SAD_dither_free(sad_state_to_float);
-        AUDDBG("ditherer init failed (float --> output)\n");
-        return FALSE;
-    }
-    SAD_dither_set_dither (sad_state_from_float, TRUE);
+        if(replay_gain_info.album_peak == 0.0 && replay_gain_info.track_peak == 0.0) {
+            AUDDBG("RG info isn't set yet. Filling replay_gain_info with default values.\n");
+            replay_gain_info.track_gain = cfg.default_gain;
+            replay_gain_info.track_peak = 0.01;
+            replay_gain_info.album_gain = cfg.default_gain;
+            replay_gain_info.album_peak = 0.01;
+        }
+        apply_replaygain_info(&replay_gain_info);
     
-    fmt = output_fmt;
-
-    if(replay_gain_info.album_peak == 0.0 && replay_gain_info.track_peak == 0.0) {
-        AUDDBG("RG info isn't set yet. Filling replay_gain_info with default values.\n");
-        replay_gain_info.track_gain = cfg.default_gain;
-        replay_gain_info.track_peak = 0.01;
-        replay_gain_info.album_gain = cfg.default_gain;
-        replay_gain_info.album_peak = 0.01;
-    }
-    apply_replaygain_info(&replay_gain_info);
+        return reopen_audio(fmt, rate, nch);
+    } /* bypass_dsp */
     
+#if 0
     op = get_current_output_plugin();
 
     if (op == NULL)
@@ -382,6 +437,7 @@
     }
 
     return ret;
+#endif
 }
 
 void
@@ -499,64 +555,67 @@
     gint writeoffs;
     gpointer float_ptr;
 
-    if(length <= 0 || sad_state_from_float == NULL || sad_state_to_float == NULL) return;
-    
-    plugin_set_current((Plugin *)(playback->output));
-    gint time = playback->output->written_time();
+    if (!bypass_dsp) {
 
-    if (legacy_flow == NULL)
-    {
-        legacy_flow = flow_new();
-        flow_link_element(legacy_flow, iir_flow);
-        flow_link_element(legacy_flow, effect_flow);
-    }
-    
-    if (postproc_flow == NULL)
-    {
-        postproc_flow = flow_new();
-        flow_link_element(postproc_flow, vis_flow);
-#ifdef USE_SRC
-        flow_link_element(postproc_flow, src_flow);
-#endif
-        flow_link_element(postproc_flow, volumecontrol_flow);
-    }
-
-    int frames = length / nch / FMT_SIZEOF(fmt);
-    int len = frames * nch * sizeof(float);
-    if(sad_float_buf == NULL || sad_float_buf_length < len) {
-        sad_float_buf_length = len;
-        sad_float_buf = smart_realloc(sad_float_buf, &sad_float_buf_length);
-    }
+        if(length <= 0 || sad_state_from_float == NULL || sad_state_to_float == NULL) return;
+        
+        plugin_set_current((Plugin *)(playback->output));
+        gint time = playback->output->written_time();
 
-    SAD_dither_process_buffer(sad_state_to_float, ptr, sad_float_buf, frames);
-    float_ptr = sad_float_buf;
+        if (legacy_flow == NULL)
+        {
+            legacy_flow = flow_new();
+            flow_link_element(legacy_flow, iir_flow);
+            flow_link_element(legacy_flow, effect_flow);
+        }
+        
+        if (postproc_flow == NULL)
+        {
+            postproc_flow = flow_new();
+            flow_link_element(postproc_flow, vis_flow);
+#ifdef USE_SRC
+            flow_link_element(postproc_flow, src_flow);
+#endif
+            flow_link_element(postproc_flow, volumecontrol_flow);
+        }
     
-    length = flow_execute(postproc_flow,
-                          time,
-                          &float_ptr,
-                          len,
-                          FMT_FLOAT,
-                          decoder_srate,
-                          nch);
+        int frames = length / nch / FMT_SIZEOF(fmt);
+        int len = frames * nch * sizeof(float);
+        if(sad_float_buf == NULL || sad_float_buf_length < len) {
+            sad_float_buf_length = len;
+            sad_float_buf = smart_realloc(sad_float_buf, &sad_float_buf_length);
+        }
     
-    frames = length / nch / sizeof(float);
-    len = frames * nch * FMT_SIZEOF(op_state.fmt);
-    if(sad_out_buf == NULL || sad_out_buf_length < len) {
-        sad_out_buf_length = len;
-        sad_out_buf = smart_realloc(sad_out_buf, &sad_out_buf_length);
-    }
-
-    SAD_dither_process_buffer(sad_state_from_float, float_ptr, sad_out_buf, frames);
-
-    length = len;
-    ptr = sad_out_buf;
+        SAD_dither_process_buffer(sad_state_to_float, ptr, sad_float_buf, frames);
+        float_ptr = sad_float_buf;
+        
+        length = flow_execute(postproc_flow,
+                              time,
+                              &float_ptr,
+                              len,
+                              FMT_FLOAT,
+                              decoder_srate,
+                              nch);
+        
+        frames = length / nch / sizeof(float);
+        len = frames * nch * FMT_SIZEOF(op_state.fmt);
+        if(sad_out_buf == NULL || sad_out_buf_length < len) {
+            sad_out_buf_length = len;
+            sad_out_buf = smart_realloc(sad_out_buf, &sad_out_buf_length);
+        }
     
-    if (op_state.fmt == FMT_S16_NE || (op_state.fmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN) ||
-                                      (op_state.fmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN)) {
-        length = flow_execute(legacy_flow, time, &ptr, length, op_state.fmt, op_state.rate, op_state.nch);
-    } else {
-        AUDDBG("legacy_flow can deal only with S16_NE streams\n"); /*FIXME*/
-    }
+        SAD_dither_process_buffer(sad_state_from_float, float_ptr, sad_out_buf, frames);
+    
+        length = len;
+        ptr = sad_out_buf;
+    
+        if (op_state.fmt == FMT_S16_NE || (op_state.fmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN) ||
+                                          (op_state.fmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN)) {
+            length = flow_execute(legacy_flow, time, &ptr, length, op_state.fmt, op_state.rate, op_state.nch);
+        } else {
+            AUDDBG("legacy_flow can deal only with S16_NE streams\n"); /*FIXME*/
+        }
+    } /* !bypass_dsp */
 
     /**** write it out ****/