3 #include "../../pdbox.h"
7 #include "../src/m_pd.h"
8 #include "../src/m_fixed.h"
16 t_object x_obj
; /* header */
17 void *x_outlet
; /* a "float" outlet */
18 void *x_clock
; /* a "clock" object */
19 t_sample
*x_buf
; /* a Hanning window */
20 int x_phase
; /* number of points since last output */
21 int x_period
; /* requested period of output */
22 int x_realperiod
; /* period rounded up to vecsize multiple */
23 int x_npoints
; /* analysis window size in samples */
24 t_float x_result
; /* result to output */
25 t_sample x_sumbuf
[MAXOVERLAP
]; /* summing buffer */
29 t_class
*sigenv_class
;
30 static void sigenv_tick(t_sigenv
*x
);
32 static void *sigenv_new(t_floatarg fnpoints
, t_floatarg fperiod
)
34 int npoints
= fnpoints
;
40 if (npoints
< 1) npoints
= 1024;
41 if (period
< 1) period
= npoints
/2;
42 if (period
< npoints
/ MAXOVERLAP
+ 1)
43 period
= npoints
/ MAXOVERLAP
+ 1;
44 if (!(buf
= getbytes(sizeof(t_sample
) * (npoints
+ MAXVSTAKEN
))))
46 error("env: couldn't allocate buffer");
49 x
= (t_sigenv
*)pd_new(sigenv_class
);
51 x
->x_npoints
= npoints
;
54 for (i
= 0; i
< MAXOVERLAP
; i
++) x
->x_sumbuf
[i
] = 0;
55 for (i
= 0; i
< npoints
; i
++)
56 buf
[i
] = ftofix((1. - cos((2 * 3.14159 * i
) / npoints
))/npoints
);
57 for (; i
< npoints
+MAXVSTAKEN
; i
++) buf
[i
] = 0;
58 x
->x_clock
= clock_new(x
, (t_method
)sigenv_tick
);
59 x
->x_outlet
= outlet_new(&x
->x_obj
, gensym("float"));
64 static t_int
*sigenv_perform(t_int
*w
)
66 t_sigenv
*x
= (t_sigenv
*)(w
[1]);
67 t_sample
*in
= (t_sample
*)(w
[2]);
72 for (count
= x
->x_phase
, sump
= x
->x_sumbuf
;
73 count
< x
->x_npoints
; count
+= x
->x_realperiod
, sump
++)
75 t_sample
*hp
= x
->x_buf
+ count
;
80 for (i
= 0; i
< n
; i
++)
83 sum
+= *hp
++ * ((*fp
* *fp
)>>16)>>16;
91 x
->x_result
= x
->x_sumbuf
[0];
92 for (count
= x
->x_realperiod
, sump
= x
->x_sumbuf
;
93 count
< x
->x_npoints
; count
+= x
->x_realperiod
, sump
++)
96 x
->x_phase
= x
->x_realperiod
- n
;
97 clock_delay(x
->x_clock
, 0L);
102 static void sigenv_dsp(t_sigenv
*x
, t_signal
**sp
)
104 if (x
->x_period
% sp
[0]->s_n
) x
->x_realperiod
=
105 x
->x_period
+ sp
[0]->s_n
- (x
->x_period
% sp
[0]->s_n
);
106 else x
->x_realperiod
= x
->x_period
;
107 dsp_add(sigenv_perform
, 3, x
, sp
[0]->s_vec
, sp
[0]->s_n
);
108 if (sp
[0]->s_n
> MAXVSTAKEN
) bug("sigenv_dsp");
111 static void sigenv_tick(t_sigenv
*x
) /* callback function for the clock */
113 outlet_float(x
->x_outlet
, powtodb(x
->x_result
*3.051757e-05));
116 static void sigenv_ff(t_sigenv
*x
) /* cleanup on free */
118 clock_free(x
->x_clock
);
119 freebytes(x
->x_buf
, (x
->x_npoints
+ MAXVSTAKEN
) * sizeof(float));
123 void env_tilde_setup(void )
125 sigenv_class
= class_new(gensym("env~"), (t_newmethod
)sigenv_new
,
126 (t_method
)sigenv_ff
, sizeof(t_sigenv
), 0, A_DEFFLOAT
, A_DEFFLOAT
, 0);
127 CLASS_MAINSIGNALIN(sigenv_class
, t_sigenv
, x_f
);
128 class_addmethod(sigenv_class
, (t_method
)sigenv_dsp
, gensym("dsp"), 0);