1 /*
2 * Bandpass filter sweep effect
3 * Copyright (c) Maarten de Boer <mdeboer@iua.upf.es>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #include <math.h>
22 #include <alsa/asoundlib.h>
23
24 struct effect_private {
25 /* filter the sweep variables */
26 float lfo,dlfo,fs,fc,BW,C,D,a0,a1,a2,b1,b2,*x[3],*y[3];
27 float lfo_depth, lfo_center;
28 unsigned int channels;
29 };
30
effect_init(struct lookback * loopback,void * private_data,snd_pcm_access_t access,unsigned int channels,unsigned int rate,snd_pcm_format_t format)31 static int effect_init(struct lookback *loopback,
32 void *private_data,
33 snd_pcm_access_t access,
34 unsigned int channels,
35 unsigned int rate,
36 snd_pcm_format_t format)
37 {
38 struct effect_private *priv = private_data;
39 int i;
40
41 #if __BYTE_ORDER == __LITTLE_ENDIAN
42 if (format != SND_PCM_FORMAT_S16_LE)
43 return -EIO;
44 #elif __BYTE_ORDER == __BIG_ENDIAN
45 if (format != SND_PCM_FORMAT_S16_BE)
46 return -EIO;
47 #else
48 return -EIO;
49 #endif
50 priv->fs = (float) rate;
51 priv->channels = channels;
52 for (i = 0; i < 3; i++) {
53 priv->x[i] = calloc(channels * sizeof(float));
54 priv->y[i] = calloc(channels * sizeof(float));
55 }
56 return 0;
57 }
58
effect_done(struct loopback * loopback,void * private_data)59 static int effect_done(struct loopback *loopback,
60 void *private_data)
61 {
62 struct effect_private *priv = private_data;
63 int i;
64
65 for (i = 0; i < 3; i++) {
66 free(priv->x[i]);
67 free(priv->y[i]);
68 }
69 return 0;
70 }
71
effect_apply(struct loopback * loopback,void * private_data,const snd_pcm_channel_area_t * areas,snd_uframes_t offset,snd_uframes_t frames)72 static int effect_apply(struct loopback *loopback,
73 void *private_data,
74 const snd_pcm_channel_area_t *areas,
75 snd_uframes_t offset,
76 snd_uframes_t frames)
77 {
78 struct effect_private *priv = private_data;
79 short *samples = (short*)areas[0].addr + offset*priv->channels;
80 snd_uframes_t i;
81
82 for (i=0; i < frames; i++) {
83 int chn;
84
85 fc = sin(priv->lfo)*priv->lfo_depth+priv->lfo_center;
86 priv->lfo += priv->dlfo;
87 if (priv->lfo>2.*M_PI) priv->lfo -= 2.*M_PI;
88 priv->C = 1./tan(M_PI*priv->BW/priv->fs);
89 priv->D = 2.*cos(2*M_PI*fc/fs);
90 priv->a0 = 1./(1.+priv->C);
91 priv->a1 = 0;
92 priv->a2 = -priv->a0;
93 priv->b1 = -priv->C*priv->D*a0;
94 priv->b2 = (priv->C-1)*priv->a0;
95
96 for (chn=0; chn < priv->channels; chn++)
97 {
98 priv->x[chn][2] = priv->x[chn][1];
99 priv->x[chn][1] = priv->x[chn][0];
100
101 priv->y[chn][2] = priv->y[chn][1];
102 priv->y[chn][1] = priv->y[chn][0];
103
104 priv->x[chn][0] = samples[i*channels+chn];
105 priv->y[chn][0] = priv->a0*priv->x[0][chn]
106 + priv->a1*priv->x[1][chn] + priv->a2*x[2][chn]
107 - priv->b1*priv->y[1][chn] - priv->b2*y[2][chn];
108 samples[i*channels+chn] = priv->y[chn][0];
109 }
110 }
111 return 0;
112 }
113
effect_init_sweep(void)114 void effect_init_sweep(void)
115 {
116 struct effect_private *priv;
117
118 priv = register_effect(effect_init,
119 effect_apply,
120 effect_done,
121 sizeof(struct effectprivate));
122 if (priv) {
123 priv->lfo_center = 2000.;
124 priv->lfo_depth = 1800.;
125 priv->lfo_freq = 0.2;
126 priv->BW = 50;
127 }
128 }
129