1 /*
2 * madplay - MPEG audio decoder and player
3 * Copyright (C) 2000-2004 Robert Leslie
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * $Id: filter.c,v 1.13 2004/02/17 02:26:43 rob Exp $
20 */
21
22 # ifdef HAVE_CONFIG_H
23 # include "config.h"
24 # endif
25
26 # include "global.h"
27
28 # include <stdlib.h>
29 # include <stdio.h>
30 # include <mad.h>
31
32 # include "filter.h"
33 # include "player.h"
34
35 /*
36 * NAME: filter->init()
37 * DESCRIPTION: initialize a new filter
38 */
filter_init(struct filter * filter,filter_func_t * func,void * data,struct filter * chain)39 void filter_init(struct filter *filter,
40 filter_func_t *func, void *data, struct filter *chain)
41 {
42 filter->flags = 0;
43 filter->func = func;
44 filter->data = data;
45 filter->chain = chain;
46 }
47
48 /*
49 * NAME: filter->new()
50 * DESCRIPTION: allocate a new filter object and chain it to another
51 */
filter_new(filter_func_t * func,void * data,struct filter * chain)52 struct filter *filter_new(filter_func_t *func, void *data,
53 struct filter *chain)
54 {
55 struct filter *filter;
56
57 filter = malloc(sizeof(*filter));
58 if (filter) {
59 filter_init(filter, func, data, chain);
60 filter->flags |= FILTER_FLAG_DMEM;
61 }
62
63 return filter;
64 }
65
66 /*
67 * NAME: filter->free()
68 * DESCRIPTION: deallocate a filter object chain
69 */
filter_free(struct filter * filter)70 void filter_free(struct filter *filter)
71 {
72 while (filter) {
73 struct filter *chain;
74
75 chain = filter->chain;
76
77 if (filter->flags & FILTER_FLAG_DMEM)
78 free(filter);
79 else
80 filter->chain = 0;
81
82 filter = chain;
83 }
84 }
85
86 /*
87 * NAME: filter->run()
88 * DESCRIPTION: execute a filter chain
89 */
filter_run(struct filter * filter,struct mad_frame * frame)90 enum mad_flow filter_run(struct filter *filter, struct mad_frame *frame)
91 {
92 while (filter) {
93 enum mad_flow result;
94
95 result = filter->func(filter->data, frame);
96 if (result != MAD_FLOW_CONTINUE)
97 return result;
98
99 filter = filter->chain;
100 }
101
102 return MAD_FLOW_CONTINUE;
103 }
104
105 /* --- Filters ------------------------------------------------------------- */
106
107 /*
108 * NAME: gain_filter()
109 * DESCRIPTION: perform attenuation or amplification
110 */
gain_filter(void * data,struct mad_frame * frame)111 enum mad_flow gain_filter(void *data, struct mad_frame *frame)
112 {
113 register mad_fixed_t gain = *(mad_fixed_t *) data;
114
115 if (gain != MAD_F_ONE) {
116 unsigned int nch, ch, ns, s, sb;
117
118 nch = MAD_NCHANNELS(&frame->header);
119 ns = MAD_NSBSAMPLES(&frame->header);
120
121 for (ch = 0; ch < nch; ++ch) {
122 for (s = 0; s < ns; ++s) {
123 for (sb = 0; sb < 32; ++sb) {
124 frame->sbsample[ch][s][sb] =
125 mad_f_mul(frame->sbsample[ch][s][sb], gain);
126 }
127 }
128 }
129 }
130
131 return MAD_FLOW_CONTINUE;
132 }
133
134 # if 0
135 /*
136 * NAME: limit_filter()
137 * DESCRIPTION: limiting filter
138 */
139 enum mad_flow limit_filter(void *data, struct mad_frame *frame)
140 {
141 struct player *player = data;
142 unsigned int nch, ch, ns, s, sb;
143
144 nch = MAD_NCHANNELS(&frame->header);
145 ns = MAD_NSBSAMPLES(&frame->header);
146
147 for (ch = 0; ch < nch; ++ch) {
148 for (s = 0; s < ns; ++s) {
149 for (sb = 0; sb < 32; ++sb) {
150 frame->sbsample[ch][s][sb];
151 }
152 }
153 }
154
155 return MAD_FLOW_CONTINUE;
156 }
157 # endif
158
159 /*
160 * NAME: mono_filter()
161 * DESCRIPTION: transform stereo frame to mono
162 */
mono_filter(void * data,struct mad_frame * frame)163 enum mad_flow mono_filter(void *data, struct mad_frame *frame)
164 {
165 if (frame->header.mode != MAD_MODE_SINGLE_CHANNEL) {
166 unsigned int ns, s, sb;
167 mad_fixed_t left, right;
168
169 ns = MAD_NSBSAMPLES(&frame->header);
170
171 for (s = 0; s < ns; ++s) {
172 for (sb = 0; sb < 32; ++sb) {
173 left = frame->sbsample[0][s][sb];
174 right = frame->sbsample[1][s][sb];
175
176 frame->sbsample[0][s][sb] = (left + right) / 2;
177 /* frame->sbsample[1][s][sb] = 0; */
178 }
179 }
180
181 frame->header.mode = MAD_MODE_SINGLE_CHANNEL;
182 }
183
184 return MAD_FLOW_CONTINUE;
185 }
186
187 /*
188 * NAME: fadein_filter()
189 * DESCRIPTION: fade-in filter
190 */
fadein_filter(void * data,struct mad_frame * frame)191 enum mad_flow fadein_filter(void *data, struct mad_frame *frame)
192 {
193 struct player *player = data;
194
195 if (mad_timer_compare(player->stats.play_timer, player->fade_in) < 0) {
196 mad_timer_t frame_start, frame_end, ratio;
197 unsigned int nch, nsamples, s;
198 mad_fixed_t step, scalefactor;
199
200 /*
201 * Fade-in processing may occur over the entire frame, or it may end
202 * somewhere within the frame. Find out where processing should end.
203 */
204
205 nsamples = MAD_NSBSAMPLES(&frame->header);
206
207 /* this frame has not yet been added to play_timer */
208
209 frame_start = frame_end = player->stats.play_timer;
210 mad_timer_add(&frame_end, frame->header.duration);
211
212 if (mad_timer_compare(player->fade_in, frame_end) < 0) {
213 mad_timer_t length;
214
215 length = frame_start;
216
217 mad_timer_negate(&length);
218 mad_timer_add(&length, player->fade_in);
219
220 mad_timer_set(&ratio, 0,
221 mad_timer_count(length, frame->header.samplerate),
222 mad_timer_count(frame->header.duration,
223 frame->header.samplerate));
224
225 nsamples = mad_timer_fraction(ratio, nsamples);
226 }
227
228 /* determine starting scalefactor and step size */
229
230 mad_timer_set(&ratio, 0,
231 mad_timer_count(frame_start, frame->header.samplerate),
232 mad_timer_count(player->fade_in, frame->header.samplerate));
233
234 scalefactor = mad_timer_fraction(ratio, MAD_F_ONE);
235 step = MAD_F_ONE / (mad_timer_count(player->fade_in,
236 frame->header.samplerate) / 32);
237
238 /* scale subband samples */
239
240 nch = MAD_NCHANNELS(&frame->header);
241
242 for (s = 0; s < nsamples; ++s) {
243 unsigned int ch, sb;
244
245 for (ch = 0; ch < nch; ++ch) {
246 for (sb = 0; sb < 32; ++sb) {
247 frame->sbsample[ch][s][sb] =
248 mad_f_mul(frame->sbsample[ch][s][sb], scalefactor);
249 }
250 }
251
252 scalefactor += step;
253 }
254 }
255
256 return MAD_FLOW_CONTINUE;
257 }
258
259 # if defined(EXPERIMENTAL)
260 /*
261 * NAME: mixer_filter()
262 * DESCRIPTION: pre-empt decoding by dumping frame to independent mixer
263 */
mixer_filter(void * data,struct mad_frame * frame)264 enum mad_flow mixer_filter(void *data, struct mad_frame *frame)
265 {
266 FILE *dest = data;
267
268 if (fwrite(frame, sizeof(*frame), 1, dest) != 1)
269 return MAD_FLOW_BREAK;
270
271 return MAD_FLOW_IGNORE;
272 }
273
274 /*
275 * NAME: experimental_filter()
276 * DESCRIPTION: experimental filter
277 */
experimental_filter(void * data,struct mad_frame * frame)278 enum mad_flow experimental_filter(void *data, struct mad_frame *frame)
279 {
280 if (frame->header.mode == MAD_MODE_STEREO ||
281 frame->header.mode == MAD_MODE_JOINT_STEREO) {
282 unsigned int ns, s, sb;
283
284 ns = MAD_NSBSAMPLES(&frame->header);
285
286 /* enhance stereo separation */
287
288 for (s = 0; s < ns; ++s) {
289 for (sb = 0; sb < 32; ++sb) {
290 mad_fixed_t left, right;
291
292 left = frame->sbsample[0][s][sb];
293 right = frame->sbsample[1][s][sb];
294
295 frame->sbsample[0][s][sb] -= right / 4;
296 frame->sbsample[1][s][sb] -= left / 4;
297 }
298 }
299 }
300
301 return MAD_FLOW_CONTINUE;
302 }
303 # endif
304