Mercurial > audlegacy
changeset 2538:719e0898ff3c trunk
[svn] - Patch to use libsamplerate for high-quality interpolated upsampling,
similar to what foobar2000 can do. Patch by Teru KAMOGASHIRA.
author | nenolod |
---|---|
date | Sat, 17 Feb 2007 02:19:35 -0800 |
parents | 7aac1b5ef85d |
children | 76724f3da0e1 |
files | ChangeLog configure.ac mk/rules.mk.in src/audacious/Makefile src/audacious/build_stamp.c src/audacious/glade/prefswin.glade src/audacious/output.c src/audacious/ui_preferences.c |
diffstat | 8 files changed, 501 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Sat Feb 17 01:54:30 2007 -0800 +++ b/ChangeLog Sat Feb 17 02:19:35 2007 -0800 @@ -1,3 +1,14 @@ +2007-02-17 09:54:30 +0000 William Pitcock <nenolod@sacredspiral.co.uk> + revision [4084] + - reinstate rcfile class for now + + trunk/src/audacious/Makefile | 2 + trunk/src/audacious/rcfile.c | 565 +++++++++++++++++++++++++++++++++++++ + trunk/src/audacious/rcfile.h | 94 ++++++ + trunk/src/audacious/ui_equalizer.c | 2 + 4 files changed, 662 insertions(+), 1 deletion(-) + + 2007-02-17 09:02:11 +0000 William Pitcock <nenolod@sacredspiral.co.uk> revision [4082] - relocate configdb to audacious core
--- a/configure.ac Sat Feb 17 01:54:30 2007 -0800 +++ b/configure.ac Sat Feb 17 02:19:35 2007 -0800 @@ -204,6 +204,20 @@ AC_SUBST(CHARDET_LIBS) AC_SUBST(SUBDIR_GUESS) +dnl libsamplerate support +dnl ======================== +AC_ARG_ENABLE(samplerate, + [ --enable-samplerate enable libsamplerate support (default=no)], + [cv_samplerate="$enable_samplerate"], [cv_samplerate="no"]) +if test "x$cv_samplerate" = "xyes"; then + AC_DEFINE(USE_SRC, 1, [Define if libsamplerate enabled] ) + PKG_CHECK_MODULES(samplerate, samplerate) + AC_SUBST(USE_SRC) + AC_SUBST(samplerate_CFLAGS) + AC_SUBST(samplerate_LIBS) + AC_CHECK_LIB(samplerate, src_process,,AC_MSG_ERROR([*** Unable to find libsamplerate library!])) +fi + dnl regex support (gnu/oniguruma/pcre) dnl ======================== REGEX_LIBS=
--- a/mk/rules.mk.in Sat Feb 17 01:54:30 2007 -0800 +++ b/mk/rules.mk.in Sat Feb 17 02:19:35 2007 -0800 @@ -316,6 +316,8 @@ CURL_LIBS ?= @CURL_LIBS@ MUSICBRAINZ_LIBS ?= @MUSICBRAINZ_LIBS@ CHARDET_LIBS ?= @CHARDET_LIBS@ +samplerate_CFLAGS ?= @samplerate_CFLAGS@ +samplerate_LIBS ?= @samplerate_LIBS@ SUBDIR_GUESS ?= @SUBDIR_GUESS@ LIBNOTIFY_CFLAGS ?= @LIBNOTIFY_CFLAGS@ LIBNOTIFY_LIBS ?= @LIBNOTIFY_LIBS@
--- a/src/audacious/Makefile Sat Feb 17 01:54:30 2007 -0800 +++ b/src/audacious/Makefile Sat Feb 17 02:19:35 2007 -0800 @@ -11,6 +11,7 @@ LDADD = \ -L.. $(LTLIBINTL) \ -L../libaudacious -laudacious \ + $(samplerate_LIBS) \ $(CHARDET_LIBS) \ $(GTK_LIBS) \ $(LIBGLADE_LIBS) \ @@ -22,6 +23,7 @@ $(LIBGLADE_CFLAGS) \ $(BEEP_DEFINES) \ $(ARCH_DEFINES) \ + $(samplerate_CFLAGS) \ $(REGEX_CFLAGS) \ -D_AUDACIOUS_CORE \ -I.. -I../.. \
--- a/src/audacious/build_stamp.c Sat Feb 17 01:54:30 2007 -0800 +++ b/src/audacious/build_stamp.c Sat Feb 17 02:19:35 2007 -0800 @@ -1,2 +1,2 @@ #include <glib.h> -const gchar *svn_stamp = "20070217-4082"; +const gchar *svn_stamp = "20070217-4084";
--- a/src/audacious/glade/prefswin.glade Sat Feb 17 01:54:30 2007 -0800 +++ b/src/audacious/glade/prefswin.glade Sat Feb 17 02:19:35 2007 -0800 @@ -4156,6 +4156,274 @@ <property name="fill">False</property> </packing> </child> + + <child> + <widget class="GtkAlignment" id="alignment90"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">12</property> + <property name="bottom_padding">12</property> + <property name="left_padding">0</property> + <property name="right_padding">0</property> + + <child> + <widget class="GtkLabel" id="label93"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Sampling Rate Converter</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment92"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">0</property> + <property name="bottom_padding">0</property> + <property name="left_padding">12</property> + <property name="right_padding">0</property> + + <child> + <widget class="GtkCheckButton" id="enable_src"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Enable Sampling Rate Converter</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">True</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="realize" handler="on_enable_src_realize" last_modification_time="Fri, 16 Feb 2007 11:10:57 GMT"/> + <signal name="toggled" handler="on_enable_src_toggled" last_modification_time="Fri, 16 Feb 2007 11:11:02 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment91"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">0</property> + <property name="bottom_padding">6</property> + <property name="left_padding">12</property> + <property name="right_padding">0</property> + + <child> + <widget class="GtkVBox" id="vbox36"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkTable" id="table13"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + + <child> + <widget class="GtkLabel" id="label91"> + <property name="visible">True</property> + <property name="label" translatable="yes">Sampling Rate [Hz]:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkSpinButton" id="src_rate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">False</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">96000 1000 768000 1000 1000 1000</property> + <signal name="realize" handler="on_src_rate_realize" last_modification_time="Fri, 16 Feb 2007 11:11:10 GMT"/> + <signal name="value_changed" handler="on_src_rate_value_changed" last_modification_time="Fri, 16 Feb 2007 11:11:15 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkImage" id="image9"> + <property name="visible">True</property> + <property name="stock">gtk-info</property> + <property name="icon_size">4</property> + <property name="xalign">1</property> + <property name="yalign">0</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label92"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span size="small">All stream will be converted to this sampling rate. +This should be the max supported sampling rate of +the sound card or output plugin.</span></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label94"> + <property name="visible">True</property> + <property name="label" translatable="yes">Converter Type:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="src_converter_type"> + <property name="visible">True</property> + <property name="items" translatable="yes">SRC_SINC_BEST_QUALITY +SRC_SINC_MEDIUM_QUALITY +SRC_SINC_FASTEST +SRC_ZERO_ORDER_HOLD +SRC_LINEAR</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + <signal name="realize" handler="on_src_converter_type_realize" after="yes" last_modification_time="Fri, 16 Feb 2007 13:16:11 GMT"/> + <signal name="changed" handler="on_src_converter_type_changed" last_modification_time="Fri, 16 Feb 2007 13:16:37 GMT"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> </widget> <packing> <property name="tab_expand">False</property>
--- a/src/audacious/output.c Sat Feb 17 01:54:30 2007 -0800 +++ b/src/audacious/output.c Sat Feb 17 02:19:35 2007 -0800 @@ -32,6 +32,10 @@ #include "playback.h" #include "playlist.h" +#include "libaudacious/configdb.h" +#ifdef USE_SRC +#include <samplerate.h> +#endif OutputPluginData op_data = { NULL, @@ -217,12 +221,63 @@ return op->output_time(); } +#ifdef USE_SRC +static SRC_STATE *src_state; +static SRC_DATA src_data; +static int overSamplingFs = 96000; +static int converter_type = SRC_SINC_BEST_QUALITY; +static int srcError = 0; +static void freeSRC() +{ + if(src_state != NULL) + src_state = src_delete(src_state); +} +#endif + gint output_open_audio(AFormat fmt, gint rate, gint nch) { gint ret; OutputPlugin *op; +#ifdef USE_SRC + ConfigDb *db; + gboolean src_enabled; + gint src_rate, src_type; + db = bmp_cfg_db_open(); + + if (bmp_cfg_db_get_bool(db, NULL, "enable_src", &src_enabled) == FALSE) + src_enabled = FALSE; + + if (bmp_cfg_db_get_int(db, NULL, "src_rate", &src_rate) == FALSE) + overSamplingFs = 48000; + else + overSamplingFs = src_rate; + + if (bmp_cfg_db_get_int(db, NULL, "src_type", &src_type) == FALSE) + converter_type = SRC_SINC_BEST_QUALITY; + else + converter_type = src_type; + + bmp_cfg_db_close(db); + + freeSRC(); + + if(src_enabled&& + (fmt == FMT_S16_NE||(fmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN)|| + (fmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN))) + { + src_state = src_new(converter_type, nch, &srcError); + if (src_state != NULL) + { + src_data.src_ratio = (float)overSamplingFs/(float)rate; + rate = overSamplingFs; + } + else + fprintf(stderr, "src_new(): %s\n\n", src_strerror(srcError)); + } +#endif + op = get_current_output_plugin(); if (op == NULL) @@ -268,6 +323,10 @@ { OutputPlugin *op = get_current_output_plugin(); +#ifdef USE_SRC + freeSRC(); +#endif + /* Do not close if there are still songs to play and the user has * not requested a stop. --nenolod */ @@ -329,6 +388,12 @@ return op->buffer_playing(); } +#ifdef USE_SRC +static float *srcIn = NULL, *srcOut = NULL; +static short int *wOut = NULL; +static gboolean isSrcAlloc = FALSE; +#endif + /* called by input plugin when data is ready */ void produce_audio(gint time, /* position */ @@ -346,6 +411,42 @@ OutputPlugin *op = get_current_output_plugin(); int writeoffs; +#ifdef USE_SRC + if(isSrcAlloc == TRUE) + { + free(srcIn); + free(srcOut); + free(wOut); + isSrcAlloc = FALSE; + } + + if(src_state != NULL&&length > 0) + { + int lrLength = length/2; + int overLrLength = (int)floor(lrLength*(src_data.src_ratio+1)); + srcIn = (float*)malloc(sizeof(float)*lrLength); + srcOut = (float*)malloc(sizeof(float)*overLrLength); + wOut = (short int*)malloc(sizeof(short int)*overLrLength); + src_short_to_float_array((short int*)ptr, srcIn, lrLength); + isSrcAlloc = TRUE; + src_data.data_in = srcIn; + src_data.data_out = srcOut; + src_data.end_of_input = 0; + src_data.input_frames = lrLength/2; + src_data.output_frames = overLrLength/2; + if (srcError = src_process(src_state, &src_data)) + { + fprintf(stderr, "src_process(): %s\n", src_strerror(srcError)); + } + else + { + src_float_to_short_array(srcOut, wOut, src_data.output_frames_gen*2); + ptr = wOut; + length = src_data.output_frames_gen*4; + } + } +#endif + if (!caneq && cfg.equalizer_active) { /* wrong byte order */ byteswap(length, ptr); /* so convert */ ++swapped;
--- a/src/audacious/ui_preferences.c Sat Feb 17 01:54:30 2007 -0800 +++ b/src/audacious/ui_preferences.c Sat Feb 17 02:19:35 2007 -0800 @@ -1510,6 +1510,102 @@ } static void +on_enable_src_realize(GtkToggleButton * button, + gpointer data) +{ +#ifdef USE_SRC + ConfigDb *db; + gboolean ret; + + db = bmp_cfg_db_open(); + + if (bmp_cfg_db_get_bool(db, NULL, "enable_src", &ret) != FALSE) + gtk_toggle_button_set_active(button, ret); + + bmp_cfg_db_close(db); +#else + gtk_toggle_button_set_active(button, FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); +#endif +} + +static void +on_enable_src_toggled(GtkToggleButton * button, + gpointer data) +{ + ConfigDb *db; + gboolean ret = gtk_toggle_button_get_active(button); + + db = bmp_cfg_db_open(); + bmp_cfg_db_set_bool(db, NULL, "enable_src", ret); + bmp_cfg_db_close(db); +} + +static void +on_src_rate_realize(GtkSpinButton * button, + gpointer data) +{ +#ifdef USE_SRC + ConfigDb *db; + gint value; + + db = bmp_cfg_db_open(); + + if (bmp_cfg_db_get_int(db, NULL, "src_rate", &value) != FALSE) + gtk_spin_button_set_value(button, (gdouble)value); + + bmp_cfg_db_close(db); +#else + gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE); +#endif +} + +static void +on_src_rate_value_changed(GtkSpinButton * button, + gpointer data) +{ + ConfigDb *db; + gint value = gtk_spin_button_get_value_as_int(button); + + db = bmp_cfg_db_open(); + bmp_cfg_db_set_int(db, NULL, "src_rate", value); + bmp_cfg_db_close(db); +} + +static void +on_src_converter_type_realize(GtkComboBox * box, + gpointer data) +{ +#ifdef USE_SRC + ConfigDb *db; + gint value; + + db = bmp_cfg_db_open(); + + if (bmp_cfg_db_get_int(db, NULL, "src_type", &value) != FALSE) + gtk_combo_box_set_active(box, value); + else + gtk_combo_box_set_active(box, 0); + + bmp_cfg_db_close(db); +#else + gtk_widget_set_sensitive(GTK_WIDGET(box), FALSE); +#endif +} + +static void +on_src_converter_type_changed(GtkComboBox * box, + gpointer data) +{ + ConfigDb *db; + gint value = gtk_combo_box_get_active(box); + + db = bmp_cfg_db_open(); + bmp_cfg_db_set_int(db, NULL, "src_type", value); + bmp_cfg_db_close(db); +} + +static void on_mouse_wheel_scroll_pl_realize(GtkSpinButton * button, gpointer data) { @@ -2253,6 +2349,12 @@ FUNC_MAP_ENTRY(on_mouse_wheel_scroll_pl_changed) FUNC_MAP_ENTRY(on_pause_between_songs_time_realize) FUNC_MAP_ENTRY(on_pause_between_songs_time_changed) + FUNC_MAP_ENTRY(on_enable_src_realize) + FUNC_MAP_ENTRY(on_enable_src_toggled) + FUNC_MAP_ENTRY(on_src_rate_realize) + FUNC_MAP_ENTRY(on_src_rate_value_changed) + FUNC_MAP_ENTRY(on_src_converter_type_realize) + FUNC_MAP_ENTRY(on_src_converter_type_changed) FUNC_MAP_ENTRY(on_pl_metadata_on_load_realize) FUNC_MAP_ENTRY(on_pl_metadata_on_load_toggled) FUNC_MAP_ENTRY(on_pl_metadata_on_display_realize)