# HG changeset patch # User Eugene Zagidullin # Date 1203115650 -10800 # Node ID af324ff0a9830a0b264694663291af9a7c3b8257 # Parent 314c972f2060f25fd6115a55bc50f77d4a8a16ce added passthrough mode. tested with ape and flac diff -r 314c972f2060 -r af324ff0a983 src/audacious/main.c --- a/src/audacious/main.c Fri Feb 15 15:34:46 2008 +0100 +++ b/src/audacious/main.c Sat Feb 16 01:47:30 2008 +0300 @@ -248,6 +248,7 @@ 48000, /* samplerate */ SRC_SINC_BEST_QUALITY, /* default interpolation method */ #endif + FALSE, /* bypass dsp */ }; typedef struct bmp_cfg_boolent_t { @@ -367,6 +368,7 @@ #ifdef USE_SRC {"enable_src", &cfg.enable_src, TRUE}, #endif + {"bypass_dsp", &cfg.bypass_dsp, TRUE}, }; static gint ncfgbent = G_N_ELEMENTS(bmp_boolents); diff -r 314c972f2060 -r af324ff0a983 src/audacious/main.h --- a/src/audacious/main.h Fri Feb 15 15:34:46 2008 +0100 +++ b/src/audacious/main.h Sat Feb 16 01:47:30 2008 +0300 @@ -155,6 +155,7 @@ gint src_rate; gint src_type; #endif + gboolean bypass_dsp; }; typedef struct _BmpConfig BmpConfig; diff -r 314c972f2060 -r af324ff0a983 src/audacious/output.c --- 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 ****/ diff -r 314c972f2060 -r af324ff0a983 src/audacious/ui_preferences.c --- a/src/audacious/ui_preferences.c Fri Feb 15 15:34:46 2008 +0100 +++ b/src/audacious/ui_preferences.c Sat Feb 16 01:47:30 2008 +0300 @@ -225,7 +225,19 @@ {WIDGET_LABEL, N_("Bit Depth"), NULL, NULL, NULL, FALSE}, {WIDGET_CUSTOM, NULL, NULL, NULL, NULL, FALSE, ui_preferences_bit_depth}, }; - + +static PreferencesWidget audio_page_widgets2[] = { + {WIDGET_LABEL, N_("Volume Control"), NULL, NULL, NULL, FALSE}, + {WIDGET_CHK_BTN, N_("Use software volume control"), &cfg.software_volume_control, NULL, + N_("Use software volume control. This may be useful for situations where your audio system does not support" + "controlling the playback volume."), FALSE}, + {WIDGET_LABEL, N_("Advanced"), NULL, NULL, NULL, FALSE}, + {WIDGET_CHK_BTN, N_("Bypass all of signal processing if possible"), &cfg.bypass_dsp, NULL, + N_("Try to pass input plugin's output directly to output plugin, if the latter supports " + "format produced by input plugin. If it's true, all signal processing will be disabled " + "(i.e. DSP plugins, equalizer, Replay Gain and software volume control)."), FALSE}, +}; + static PreferencesWidget replay_gain_page_widgets[] = { {WIDGET_LABEL, N_("Replay Gain configuration"), NULL, NULL, NULL, FALSE}, {WIDGET_CHK_BTN, N_("Enable Replay Gain"), &cfg.enable_replay_gain, NULL, NULL, FALSE}, @@ -927,18 +939,6 @@ } static void -on_software_volume_control_toggled(GtkToggleButton * button, gpointer data) -{ - cfg.software_volume_control = gtk_toggle_button_get_active(button); -} - -static void -on_software_volume_control_realize(GtkToggleButton * button, gpointer data) -{ - gtk_toggle_button_set_active(button, cfg.software_volume_control); -} - -static void on_skin_refresh_button_clicked(GtkButton * button, gpointer data) { @@ -2278,10 +2278,6 @@ GtkWidget *src_rate; GtkWidget *label91; GtkWidget *alignment4; - GtkWidget *label2; - GtkWidget *alignment7; - GtkWidget *software_volume_control; - audio_page_vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (category_notebook), audio_page_vbox); @@ -2463,20 +2459,8 @@ alignment4 = gtk_alignment_new (0.5, 0.5, 1, 1); gtk_box_pack_start (GTK_BOX (audio_page_vbox), alignment4, FALSE, FALSE, 0); gtk_alignment_set_padding (GTK_ALIGNMENT (alignment4), 12, 12, 0, 0); - - label2 = gtk_label_new (_("Volume Control")); - gtk_container_add (GTK_CONTAINER (alignment4), label2); - gtk_label_set_use_markup (GTK_LABEL (label2), TRUE); - gtk_misc_set_alignment (GTK_MISC (label2), 0, 0.5); - - alignment7 = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_box_pack_start (GTK_BOX (audio_page_vbox), alignment7, FALSE, FALSE, 0); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment7), 0, 0, 12, 0); - - software_volume_control = gtk_check_button_new_with_mnemonic (_("Use software volume control")); - gtk_container_add (GTK_CONTAINER (alignment7), software_volume_control); - gtk_tooltips_set_tip (tooltips, software_volume_control, _("Use software volume control. This may be useful for situations where your audio system does not support controlling the playback volume."), NULL); - + + create_widgets(GTK_BOX(audio_page_vbox), audio_page_widgets2, G_N_ELEMENTS(audio_page_widgets2)); g_signal_connect(G_OBJECT(output_plugin_bufsize), "value_changed", G_CALLBACK(on_output_plugin_bufsize_value_changed), @@ -2505,12 +2489,6 @@ g_signal_connect(G_OBJECT(src_rate), "realize", G_CALLBACK(on_src_rate_realize), NULL); - g_signal_connect(G_OBJECT(software_volume_control), "toggled", - G_CALLBACK(on_software_volume_control_toggled), - NULL); - g_signal_connect(G_OBJECT(software_volume_control), "realize", - G_CALLBACK(on_software_volume_control_realize), - NULL); /* plugin->output page */