comparison src/audacious/volumecontrol.c @ 3545:7a2b667bab4b trunk

Add volumecontrol flow implementation.
author William Pitcock <nenolod@atheme.org>
date Tue, 18 Sep 2007 10:41:40 -0500
parents
children a140fadd741d
comparison
equal deleted inserted replaced
3544:e235357029ba 3545:7a2b667bab4b
1 /*
2 * Audacious
3 * Copyright (c) 2007 William Pitcock
4 *
5 * volumecontrol.c: High quality volume PCM padding flow.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; under version 3 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses>.
18 *
19 * The Audacious team does not consider modular code linking to
20 * Audacious or using our public API to be a derived work.
21 */
22
23 #include "output.h"
24 #include "iir.h"
25 #include "main.h"
26 #include "input.h"
27 #include "playback.h"
28
29 #include "playlist.h"
30 #include "configdb.h"
31
32 #include "effect.h"
33 #include "xconvert.h"
34
35 #include "volumecontrol.h"
36
37 #include <math.h>
38
39 typedef struct {
40 gint left;
41 gint right;
42 } volumecontrol_req_t;
43
44 static volumecontrol_req_t vc_state_ = { 100, 100 };
45
46 #define STEREO_ADJUST(type, type2, endian) \
47 do { \
48 type *ptr = data; \
49 for (i = 0; i < length; i += 4) \
50 { \
51 *ptr = type2##_TO_##endian(type2##_FROM_## endian(*ptr) * \
52 lvol / 256); \
53 ptr++; \
54 *ptr = type2##_TO_##endian(type2##_FROM_##endian(*ptr) * \
55 rvol / 256); \
56 ptr++; \
57 } \
58 } while (0)
59
60 #define MONO_ADJUST(type, type2, endian) \
61 do { \
62 type *ptr = data; \
63 for (i = 0; i < length; i += 2) \
64 { \
65 *ptr = type2##_TO_##endian(type2##_FROM_## endian(*ptr) * \
66 vol / 256); \
67 ptr++; \
68 } \
69 } while (0)
70
71 #define VOLUME_ADJUST(type, type2, endian) \
72 do { \
73 if (channels == 2) \
74 STEREO_ADJUST(type, type2, endian); \
75 else \
76 MONO_ADJUST(type, type2, endian); \
77 } while (0)
78
79 #define STEREO_ADJUST8(type) \
80 do { \
81 type *ptr = data; \
82 for (i = 0; i < length; i += 2) \
83 { \
84 *ptr = *ptr * lvol / 256; \
85 ptr++; \
86 *ptr = *ptr * rvol / 256; \
87 ptr++; \
88 } \
89 } while (0)
90
91 #define MONO_ADJUST8(type) \
92 do { \
93 type *ptr = data; \
94 for (i = 0; i < length; i++) \
95 { \
96 *ptr = *ptr * vol / 256; \
97 ptr++; \
98 } \
99 } while (0)
100
101 #define VOLUME_ADJUST8(type) \
102 do { \
103 if (channels == 2) \
104 STEREO_ADJUST8(type); \
105 else \
106 MONO_ADJUST8(type); \
107 } while (0)
108
109 void volumecontrol_pad_audio(gpointer data, gint length, AFormat fmt,
110 gint channels)
111 {
112 gint i, vol, lvol, rvol;
113
114 if (vc_state_.left == 100 && vc_state_.right == 100)
115 return;
116
117 if (channels == 1 && (vc_state_.left == 100 || vc_state_.right == 100))
118 return;
119
120 lvol = pow(10, (vc_state_.left - 100) / 40.0) * 256;
121 rvol = pow(10, (vc_state_.right - 100) / 40.0) * 256;
122 vol = MAX(lvol, rvol);
123
124 switch (fmt)
125 {
126 case FMT_S16_LE:
127 VOLUME_ADJUST(gint16, GINT16, LE);
128 break;
129 case FMT_U16_LE:
130 VOLUME_ADJUST(guint16, GUINT16, LE);
131 break;
132 case FMT_S16_BE:
133 VOLUME_ADJUST(gint16, GINT16, LE);
134 break;
135 case FMT_U16_BE:
136 VOLUME_ADJUST(guint16, GUINT16, LE);
137 break;
138 case FMT_S8:
139 VOLUME_ADJUST8(gint8);
140 break;
141 case FMT_U8:
142 VOLUME_ADJUST8(guint8);
143 break;
144 default:
145 g_warning("unhandled format %d.", fmt);
146 break;
147 }
148 }
149
150 void
151 volumecontrol_get_volume_state(gint *l, gint *r)
152 {
153 *l = vc_state_.left;
154 *r = vc_state_.right;
155 }
156
157 void
158 volumecontrol_set_volume_state(gint l, gint r)
159 {
160 vc_state_.left = l;
161 vc_state_.right = r;
162 }