1 /* Copyright (c) 1997-1999 Miller Puckette and others.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
7 /* ------------------------ fft~ and ifft~ -------------------------------- */
8 static t_class
*sigfft_class
, *sigifft_class
;
16 static void *sigfft_new(void)
18 t_sigfft
*x
= (t_sigfft
*)pd_new(sigfft_class
);
19 outlet_new(&x
->x_obj
, gensym("signal"));
20 outlet_new(&x
->x_obj
, gensym("signal"));
21 inlet_new(&x
->x_obj
, &x
->x_obj
.ob_pd
, &s_signal
, &s_signal
);
26 static void *sigifft_new(void)
28 t_sigfft
*x
= (t_sigfft
*)pd_new(sigifft_class
);
29 outlet_new(&x
->x_obj
, gensym("signal"));
30 outlet_new(&x
->x_obj
, gensym("signal"));
31 inlet_new(&x
->x_obj
, &x
->x_obj
.ob_pd
, &s_signal
, &s_signal
);
36 static t_int
*sigfft_swap(t_int
*w
)
38 t_sample
*in1
= (t_sample
*)(w
[1]);
39 t_sample
*in2
= (t_sample
*)(w
[2]);
41 for (;n
--; in1
++, in2
++)
50 static t_int
*sigfft_perform(t_int
*w
)
52 t_sample
*in1
= (t_sample
*)(w
[1]);
53 t_sample
*in2
= (t_sample
*)(w
[2]);
55 mayer_fft(n
, in1
, in2
);
59 static t_int
*sigifft_perform(t_int
*w
)
61 t_sample
*in1
= (t_sample
*)(w
[1]);
62 t_sample
*in2
= (t_sample
*)(w
[2]);
64 mayer_ifft(n
, in1
, in2
);
68 static void sigfft_dspx(t_sigfft
*x
, t_signal
**sp
, t_int
*(*f
)(t_int
*w
))
74 t_sample
*in1
= sp
[0]->s_vec
;
75 t_sample
*in2
= sp
[1]->s_vec
;
76 t_sample
*out1
= sp
[2]->s_vec
;
77 t_sample
*out2
= sp
[3]->s_vec
;
78 if (out1
== in2
&& out2
== in1
)
79 dsp_add(sigfft_swap
, 3, out1
, out2
, n
);
82 dsp_add(copy_perform
, 3, in2
, out2
, n
);
83 dsp_add(copy_perform
, 3, in1
, out1
, n
);
87 if (out1
!= in1
) dsp_add(copy_perform
, 3, in1
, out1
, n
);
88 if (out2
!= in2
) dsp_add(copy_perform
, 3, in2
, out2
, n
);
90 dsp_add(f
, 3, sp
[2]->s_vec
, sp
[3]->s_vec
, n
);
93 static void sigfft_dsp(t_sigfft
*x
, t_signal
**sp
)
95 sigfft_dspx(x
, sp
, sigfft_perform
);
98 static void sigifft_dsp(t_sigfft
*x
, t_signal
**sp
)
100 sigfft_dspx(x
, sp
, sigifft_perform
);
103 static void sigfft_setup(void)
105 sigfft_class
= class_new(gensym("fft~"), sigfft_new
, 0,
106 sizeof(t_sigfft
), 0, 0);
107 CLASS_MAINSIGNALIN(sigfft_class
, t_sigfft
, x_f
);
108 class_addmethod(sigfft_class
, (t_method
)sigfft_dsp
, gensym("dsp"), 0);
110 sigifft_class
= class_new(gensym("ifft~"), sigifft_new
, 0,
111 sizeof(t_sigfft
), 0, 0);
112 CLASS_MAINSIGNALIN(sigifft_class
, t_sigfft
, x_f
);
113 class_addmethod(sigifft_class
, (t_method
)sigifft_dsp
, gensym("dsp"), 0);
114 class_sethelpsymbol(sigifft_class
, gensym("fft~"));
117 /* ----------------------- rfft~ -------------------------------- */
119 static t_class
*sigrfft_class
;
127 static void *sigrfft_new(void)
129 t_sigrfft
*x
= (t_sigrfft
*)pd_new(sigrfft_class
);
130 outlet_new(&x
->x_obj
, gensym("signal"));
131 outlet_new(&x
->x_obj
, gensym("signal"));
136 static t_int
*sigrfft_flip(t_int
*w
)
138 t_sample
*in
= (t_sample
*)(w
[1]);
139 t_sample
*out
= (t_sample
*)(w
[2]);
141 while (n
--) *(--out
) = *in
++;
142 *(--out
) = 0; /* to hell with it */
146 static t_int
*sigrfft_perform(t_int
*w
)
148 t_sample
*in
= (t_sample
*)(w
[1]);
150 mayer_realfft(n
, in
);
154 static void sigrfft_dsp(t_sigrfft
*x
, t_signal
**sp
)
159 int n
= sp
[0]->s_n
, n2
= (n
>>1);
160 t_sample
*in1
= sp
[0]->s_vec
;
161 t_sample
*out1
= sp
[1]->s_vec
;
162 t_sample
*out2
= sp
[2]->s_vec
;
165 error("fft: minimum 4 points");
168 if (in1
== out2
) /* this probably never happens */
170 dsp_add(sigrfft_perform
, 2, out2
, n
);
171 dsp_add(copy_perform
, 3, out2
, out1
, n2
);
172 dsp_add(sigrfft_flip
, 3, out2
+ (n2
+1), out2
+ n2
, n2
-1);
176 if (in1
!= out1
) dsp_add(copy_perform
, 3, in1
, out1
, n
);
177 dsp_add(sigrfft_perform
, 2, out1
, n
);
178 dsp_add(sigrfft_flip
, 3, out1
+ (n2
+1), out2
+ n2
, n2
-1);
180 dsp_add_zero(out1
+ n2
, n2
);
181 dsp_add_zero(out2
+ n2
, n2
);
184 static void sigrfft_setup(void)
186 sigrfft_class
= class_new(gensym("rfft~"), sigrfft_new
, 0,
187 sizeof(t_sigrfft
), 0, 0);
188 CLASS_MAINSIGNALIN(sigrfft_class
, t_sigrfft
, x_f
);
189 class_addmethod(sigrfft_class
, (t_method
)sigrfft_dsp
, gensym("dsp"), 0);
190 class_sethelpsymbol(sigrfft_class
, gensym("fft~"));
193 /* ----------------------- rifft~ -------------------------------- */
195 static t_class
*sigrifft_class
;
203 static void *sigrifft_new(void)
205 t_sigrifft
*x
= (t_sigrifft
*)pd_new(sigrifft_class
);
206 inlet_new(&x
->x_obj
, &x
->x_obj
.ob_pd
, &s_signal
, &s_signal
);
207 outlet_new(&x
->x_obj
, gensym("signal"));
212 static t_int
*sigrifft_perform(t_int
*w
)
214 t_sample
*in
= (t_sample
*)(w
[1]);
216 mayer_realifft(n
, in
);
220 static void sigrifft_dsp(t_sigrifft
*x
, t_signal
**sp
)
225 int n
= sp
[0]->s_n
, n2
= (n
>>1);
226 t_sample
*in1
= sp
[0]->s_vec
;
227 t_sample
*in2
= sp
[1]->s_vec
;
228 t_sample
*out1
= sp
[2]->s_vec
;
231 error("fft: minimum 4 points");
236 dsp_add(sigrfft_flip
, 3, out1
+1, out1
+ n
, (n2
-1));
237 dsp_add(copy_perform
, 3, in1
, out1
, n2
);
241 if (in1
!= out1
) dsp_add(copy_perform
, 3, in1
, out1
, n2
);
242 dsp_add(sigrfft_flip
, 3, in2
+1, out1
+ n
, n2
-1);
244 dsp_add(sigrifft_perform
, 2, out1
, n
);
247 static void sigrifft_setup(void)
249 sigrifft_class
= class_new(gensym("rifft~"), sigrifft_new
, 0,
250 sizeof(t_sigrifft
), 0, 0);
251 CLASS_MAINSIGNALIN(sigrifft_class
, t_sigrifft
, x_f
);
252 class_addmethod(sigrifft_class
, (t_method
)sigrifft_dsp
, gensym("dsp"), 0);
253 class_sethelpsymbol(sigrifft_class
, gensym("fft~"));
256 /* ----------------------- framp~ -------------------------------- */
259 static t_class
*sigframp_class
;
267 static void *sigframp_new(void)
269 t_sigframp
*x
= (t_sigframp
*)pd_new(sigframp_class
);
270 inlet_new(&x
->x_obj
, &x
->x_obj
.ob_pd
, &s_signal
, &s_signal
);
271 outlet_new(&x
->x_obj
, gensym("signal"));
272 outlet_new(&x
->x_obj
, gensym("signal"));
277 static t_int
*sigframp_perform(t_int
*w
)
279 float *inreal
= (t_float
*)(w
[1]);
280 float *inimag
= (t_float
*)(w
[2]);
281 float *outfreq
= (t_float
*)(w
[3]);
282 float *outamp
= (t_float
*)(w
[4]);
283 float lastreal
= 0, currentreal
= inreal
[0], nextreal
= inreal
[1];
284 float lastimag
= 0, currentimag
= inimag
[0], nextimag
= inimag
[1];
287 float fbin
= 1, oneovern2
= 1.f
/((float)n
* (float)n
);
291 *outamp
++ = *outfreq
++ = 0;
295 float re
, im
, pow
, freq
;
296 lastreal
= currentreal
;
297 currentreal
= nextreal
;
298 nextreal
= *inreal
++;
299 lastimag
= currentimag
;
300 currentimag
= nextimag
;
301 nextimag
= *inimag
++;
302 re
= currentreal
- 0.5f
* (lastreal
+ nextreal
);
303 im
= currentimag
- 0.5f
* (lastimag
+ nextimag
);
304 pow
= re
* re
+ im
* im
;
307 float detune
= ((lastreal
- nextreal
) * re
+
308 (lastimag
- nextimag
) * im
) / (2.0f
* pow
);
309 if (detune
> 2 || detune
< -2) freq
= pow
= 0;
310 else freq
= fbin
+ detune
;
314 *outamp
++ = oneovern2
* pow
;
317 while (m
--) *outamp
++ = *outfreq
++ = 0;
321 t_int
*sigsqrt_perform(t_int
*w
);
323 static void sigframp_dsp(t_sigframp
*x
, t_signal
**sp
)
325 int n
= sp
[0]->s_n
, n2
= (n
>>1);
328 error("framp: minimum 4 points");
331 dsp_add(sigframp_perform
, 5, sp
[0]->s_vec
, sp
[1]->s_vec
,
332 sp
[2]->s_vec
, sp
[3]->s_vec
, n2
);
333 dsp_add(sigsqrt_perform
, 3, sp
[3]->s_vec
, sp
[3]->s_vec
, n2
);
336 static void sigframp_setup(void)
338 sigframp_class
= class_new(gensym("framp~"), sigframp_new
, 0,
339 sizeof(t_sigframp
), 0, 0);
340 CLASS_MAINSIGNALIN(sigframp_class
, t_sigframp
, x_f
);
341 class_addmethod(sigframp_class
, (t_method
)sigframp_dsp
, gensym("dsp"), 0);
345 /* ------------------------ global setup routine ------------------------- */
347 void d_fft_setup(void)