changeset 3545:7a2b667bab4b trunk

Add volumecontrol flow implementation.
author William Pitcock <nenolod@atheme.org>
date Tue, 18 Sep 2007 10:41:40 -0500
parents e235357029ba
children fd4cd1945b91
files src/audacious/Makefile src/audacious/volumecontrol.c src/audacious/volumecontrol.h
diffstat 3 files changed, 194 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/audacious/Makefile	Tue Sep 18 10:23:27 2007 -0500
+++ b/src/audacious/Makefile	Tue Sep 18 10:41:40 2007 -0500
@@ -117,6 +117,7 @@
 	vfs_buffered_file.c \
 	vfs_common.c \
 	visualization.c \
+	volumecontrol.c \
 	sync-menu.c \
 	xconvert.c
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audacious/volumecontrol.c	Tue Sep 18 10:41:40 2007 -0500
@@ -0,0 +1,162 @@
+/*
+ * Audacious
+ * Copyright (c) 2007 William Pitcock
+ *
+ * volumecontrol.c: High quality volume PCM padding flow.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses>.
+ *
+ * The Audacious team does not consider modular code linking to
+ * Audacious or using our public API to be a derived work.
+ */
+
+#include "output.h"
+#include "iir.h"
+#include "main.h"
+#include "input.h"
+#include "playback.h"
+
+#include "playlist.h"
+#include "configdb.h"
+
+#include "effect.h"
+#include "xconvert.h"
+
+#include "volumecontrol.h"
+
+#include <math.h>
+
+typedef struct {
+    gint left;
+    gint right;
+} volumecontrol_req_t;
+
+static volumecontrol_req_t vc_state_ = { 100, 100 };
+
+#define STEREO_ADJUST(type, type2, endian)                                      \
+do {                                                                            \
+        type *ptr = data;                                                       \
+        for (i = 0; i < length; i += 4)                                         \
+        {                                                                       \
+                *ptr = type2##_TO_##endian(type2##_FROM_## endian(*ptr) *       \
+                                           lvol / 256);                         \
+                ptr++;                                                          \
+                *ptr = type2##_TO_##endian(type2##_FROM_##endian(*ptr) *        \
+                                           rvol / 256);                         \
+                ptr++;                                                          \
+        }                                                                       \
+} while (0)
+
+#define MONO_ADJUST(type, type2, endian)                                        \
+do {                                                                            \
+        type *ptr = data;                                                       \
+        for (i = 0; i < length; i += 2)                                         \
+        {                                                                       \
+                *ptr = type2##_TO_##endian(type2##_FROM_## endian(*ptr) *       \
+                                           vol / 256);                          \
+                ptr++;                                                          \
+        }                                                                       \
+} while (0)
+
+#define VOLUME_ADJUST(type, type2, endian)              \
+do {                                                    \
+        if (channels == 2)                              \
+                STEREO_ADJUST(type, type2, endian);     \
+        else                                            \
+                MONO_ADJUST(type, type2, endian);       \
+} while (0)
+
+#define STEREO_ADJUST8(type)                            \
+do {                                                    \
+        type *ptr = data;                               \
+        for (i = 0; i < length; i += 2)                 \
+        {                                               \
+                *ptr = *ptr * lvol / 256;               \
+                ptr++;                                  \
+                *ptr = *ptr * rvol / 256;               \
+                ptr++;                                  \
+        }                                               \
+} while (0)
+
+#define MONO_ADJUST8(type)                      \
+do {                                            \
+        type *ptr = data;                       \
+        for (i = 0; i < length; i++)            \
+        {                                       \
+                *ptr = *ptr * vol / 256;        \
+                ptr++;                          \
+        }                                       \
+} while (0)
+
+#define VOLUME_ADJUST8(type)                    \
+do {                                            \
+        if (channels == 2)                      \
+                STEREO_ADJUST8(type);           \
+        else                                    \
+                MONO_ADJUST8(type);             \
+} while (0)
+
+void volumecontrol_pad_audio(gpointer data, gint length, AFormat fmt,
+    gint channels)
+{
+    gint i, vol, lvol, rvol;
+
+    if (vc_state_.left == 100 && vc_state_.right == 100)
+        return;
+
+    if (channels == 1 && (vc_state_.left == 100 || vc_state_.right == 100))
+        return;
+
+    lvol = pow(10, (vc_state_.left - 100) / 40.0) * 256;
+    rvol = pow(10, (vc_state_.right - 100) / 40.0) * 256;
+    vol = MAX(lvol, rvol);
+
+    switch (fmt)
+    {
+        case FMT_S16_LE:
+            VOLUME_ADJUST(gint16, GINT16, LE);
+            break;
+        case FMT_U16_LE:
+            VOLUME_ADJUST(guint16, GUINT16, LE);
+            break;
+        case FMT_S16_BE:
+            VOLUME_ADJUST(gint16, GINT16, LE);
+            break;
+        case FMT_U16_BE:
+            VOLUME_ADJUST(guint16, GUINT16, LE);
+            break;
+        case FMT_S8:
+            VOLUME_ADJUST8(gint8);
+            break;
+        case FMT_U8:
+            VOLUME_ADJUST8(guint8);
+            break;
+        default:
+            g_warning("unhandled format %d.", fmt);
+            break;
+    }
+}
+
+void
+volumecontrol_get_volume_state(gint *l, gint *r)
+{
+    *l = vc_state_.left;
+    *r = vc_state_.right;
+}
+
+void
+volumecontrol_set_volume_state(gint l, gint r)
+{
+    vc_state_.left = l;
+    vc_state_.right = r;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audacious/volumecontrol.h	Tue Sep 18 10:41:40 2007 -0500
@@ -0,0 +1,31 @@
+/*
+ * Audacious
+ * Copyright (c) 2007 William Pitcock
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses>.
+ *
+ * The Audacious team does not consider modular code linking to
+ * Audacious or using our public API to be a derived work.
+ */
+
+#include <glib.h>
+
+#ifndef __VOLUMECONTROL_H__
+#define __VOLUMECONTROL_H__
+
+void volumecontrol_pad_audio(gpointer data, gint length, AFormat fmt, 
+    gint channels);
+void volumecontrol_get_volume_state(gint *l, gint *r);
+void volumecontrol_set_volume_state(gint l, gint r);
+
+#endif