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