aboutsummaryrefslogtreecommitdiff
path: root/src/iemlib1/biquad_freq_resp.c
blob: 3ebe25dc2e3164cffd7caee855d3bcf153dd3fe2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.

iemlib1 written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2003 */

#ifdef NT
#pragma warning( disable : 4244 )
#pragma warning( disable : 4305 )
#endif


#include "m_pd.h"
#include "iemlib.h"
#include <math.h>
#include <stdio.h>
#include <string.h>

/* --------------------------- biquad_freq_resp ----------------------------- */

typedef struct _biquad_freq_resp
{
	t_object	x_obj;
	float			a0;
	float			a1;
	float			a2;
	float			b1;
	float			b2;
	t_outlet	*x_out_re;
	t_outlet	*x_out_im;
} t_biquad_freq_resp;

static t_class *biquad_freq_resp_class;

static void biquad_freq_resp_float(t_biquad_freq_resp *x, t_float f)
{
	float re1, im1, re2, im2;
	float c, s, a;

	if(f < 0.0f)
		f = 0.0f;
	else if(f > 180.0f)
		f = 180.0;
	f *= 3.14159265f;
	f /= 180.0f;

	c = cos(f);
	s = sin(f);

	re1 = x->a0 + x->a1*c + x->a2*(c*c - s*s);
	im1 = x->a1*s + x->a2*2.0f*(s*c);
	re2 = 1.0f - x->b1*c - x->b2*(c*c - s*s);
	im2 = -x->b1*s - x->b2*2.0f*(s*c);
	a = re2*re2 + im2*im2;
	outlet_float(x->x_out_im, (re1*im2 - re2*im1)/a);/* because z^-1 = e^-jwt, negative sign */
	outlet_float(x->x_out_re, (re1*re2 + im1*im2)/a);
	
}
/* y/x = (a0 + a1*z-1 + a2*z-2)/(1 - b1*z-1 - b2*z-2);*/

static void biquad_freq_resp_list(t_biquad_freq_resp *x, t_symbol *s, int argc, t_atom *argv)
{
	if((argc == 5)&&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,3)&&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,1)&&IS_A_FLOAT(argv,0))
	{
		x->b1 = (float)atom_getfloatarg(0, argc, argv);
		x->b2 = (float)atom_getfloatarg(1, argc, argv);
		x->a0 = (float)atom_getfloatarg(2, argc, argv);
		x->a1 = (float)atom_getfloatarg(3, argc, argv);
		x->a2 = (float)atom_getfloatarg(4, argc, argv);
	}
}

static void *biquad_freq_resp_new(void)
{
	t_biquad_freq_resp *x = (t_biquad_freq_resp *)pd_new(biquad_freq_resp_class);
	x->x_out_re = outlet_new(&x->x_obj, &s_float);
	x->x_out_im = outlet_new(&x->x_obj, &s_float);
	x->b1 = 0.0f;
	x->b2 = 0.0f;
	x->a0 = 0.0f;
	x->a1 = 0.0f;
	x->a2 = 0.0f;
	return (x);
}

void biquad_freq_resp_setup(void)
{
    biquad_freq_resp_class = class_new(gensym("biquad_freq_resp"), (t_newmethod)biquad_freq_resp_new, 0,
    	sizeof(t_biquad_freq_resp), 0, 0);
    class_addfloat(biquad_freq_resp_class, biquad_freq_resp_float);
		class_addlist(biquad_freq_resp_class, (t_method)biquad_freq_resp_list);
    class_sethelpsymbol(biquad_freq_resp_class, gensym("iemhelp/help-biquad_freq_resp"));
}