# HG changeset patch # User nenolod # Date 1171707575 28800 # Node ID 719e0898ff3c17d301082ee982213ed20c2c5d9e # Parent 7aac1b5ef85df2e4c2210220bdb2110da48617d2 [svn] - Patch to use libsamplerate for high-quality interpolated upsampling, similar to what foobar2000 can do. Patch by Teru KAMOGASHIRA. diff -r 7aac1b5ef85d -r 719e0898ff3c ChangeLog --- 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 + 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 revision [4082] - relocate configdb to audacious core diff -r 7aac1b5ef85d -r 719e0898ff3c configure.ac --- 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= diff -r 7aac1b5ef85d -r 719e0898ff3c mk/rules.mk.in --- 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@ diff -r 7aac1b5ef85d -r 719e0898ff3c src/audacious/Makefile --- 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../.. \ diff -r 7aac1b5ef85d -r 719e0898ff3c src/audacious/build_stamp.c --- 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 -const gchar *svn_stamp = "20070217-4082"; +const gchar *svn_stamp = "20070217-4084"; diff -r 7aac1b5ef85d -r 719e0898ff3c src/audacious/glade/prefswin.glade --- 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 @@ False + + + + True + 0.5 + 0.5 + 1 + 1 + 12 + 12 + 0 + 0 + + + + True + <b>Sampling Rate Converter</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + False + False + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + True + Enable Sampling Rate Converter + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + + + + 0 + False + False + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 6 + 12 + 0 + + + + True + False + 0 + + + + True + 3 + 2 + False + 6 + 6 + + + + True + Sampling Rate [Hz]: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 96000 1000 768000 1000 1000 1000 + + + + + 1 + 2 + 0 + 1 + + + + + + + True + gtk-info + 4 + 1 + 0 + 0 + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + True + <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> + False + True + GTK_JUSTIFY_LEFT + True + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + Converter Type: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + SRC_SINC_BEST_QUALITY +SRC_SINC_MEDIUM_QUALITY +SRC_SINC_FASTEST +SRC_ZERO_ORDER_HOLD +SRC_LINEAR + False + True + + + + + 1 + 2 + 1 + 2 + fill + fill + + + + + 0 + False + False + + + + + + + 0 + False + False + + False diff -r 7aac1b5ef85d -r 719e0898ff3c src/audacious/output.c --- 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 +#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; diff -r 7aac1b5ef85d -r 719e0898ff3c src/audacious/ui_preferences.c --- 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)