Mercurial > audlegacy
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 ****/