aboutsummaryrefslogtreecommitdiff
path: root/experimental/fasor~.c
blob: ac9b4d3a2599e39f432544f720c28665a4d2dbcc (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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* (C) Guenter Geiger <geiger@epy.co.at> */


#include <m_pd.h>
#include "math.h"

#define UNITBIT32 1572864.  /* 3*2^19; bit 32 has place value 1 */

    /* machine-dependent definitions.  These ifdefs really
    should have been by CPU type and not by operating system! */
#ifdef IRIX
    /* big-endian.  Most significant byte is at low address in memory */
#define HIOFFSET 0    /* word offset to find MSB */
#define LOWOFFSET 1    /* word offset to find LSB */
#define int32 long  /* a data type that has 32 bits */
#else
#ifdef NT
    /* little-endian; most significant byte is at highest address */
#define HIOFFSET 1
#define LOWOFFSET 0
#define int32 long
#else
#ifdef  __linux__

#include <endian.h>

#if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN)                         
#error No byte order defined                                                    
#endif                                                                          
                                                                                
#if __BYTE_ORDER == __LITTLE_ENDIAN                                             
#define HIOFFSET 1                                                              
#define LOWOFFSET 0                                                             
#else                                                                           
#define HIOFFSET 0    /* word offset to find MSB */                             
#define LOWOFFSET 1    /* word offset to find LSB */                            
#endif /* __BYTE_ORDER */                                                       

#include <sys/types.h>
#define int32 int32_t

#endif /* __linux__ */
#endif /* NT */
#endif /* SGI */

union tabfudge
{
    double tf_d;
    int32 tf_i[2];
};

typedef struct fasor
{
     t_object x_obj;
     double x_phase;
     float x_conv;
     float x_f;	    /* used for scalar only */
     float x_fnew;	    /* used for scalar only */
     double x_flast;	    /* used for scalar only */
} t_fasor;

static t_class *fasor_class;

static void *fasor_new(t_symbol *s, int argc, t_atom *argv)
{
    t_fasor *x;
    x = (t_fasor *)pd_new(fasor_class);

    if (argc)
	 x->x_f =  atom_getfloatarg(0, argc, argv);
    else
	 x->x_f = 0;


    x->x_flast = 1.0;
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
    x->x_phase = 0;
    x->x_conv = 0;
    outlet_new(&x->x_obj, gensym("signal"));
    return (x);
}

static t_int *fasor_perform(t_int *w)
{
    t_fasor *x = (t_fasor *)(w[1]);
    t_float *out = (t_float *)(w[2]);
    int n = (int)(w[3]);

    double dphase = x->x_phase + UNITBIT32;
    union tabfudge tf;
    int normhipart;
    float conv = x->x_conv;
    double freq = x->x_f;
    double flast = x->x_flast;
    double fout;

    tf.tf_d = UNITBIT32;
    normhipart = tf.tf_i[HIOFFSET];
    tf.tf_d = dphase;
    fout = tf.tf_d;

    while (n--)
    {
    	tf.tf_i[HIOFFSET] = normhipart;
    	dphase += freq * conv;
	*out++ = (t_float) (fout = tf.tf_d - UNITBIT32);
	tf.tf_d = dphase;

	if (fout <= flast) {
	     freq = x->x_f = x->x_fnew; /*!! performance if freq = 0 ?? */ 
	}

	flast = fout;
    }

    x->x_flast = flast;
    tf.tf_i[HIOFFSET] = normhipart;
    x->x_phase = tf.tf_d - UNITBIT32;
    return (w+4);
}

static void fasor_dsp(t_fasor *x, t_signal **sp)
{
     
    x->x_conv = 1.f/sp[0]->s_sr;
    dsp_add(fasor_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
}

static void fasor_ft1(t_fasor *x, t_float f)
{
    x->x_phase = f;
}

static void fasor_float(t_fasor *x, t_float f)
{
    x->x_fnew = (float) fabs(f);
}


void fasor_tilde_setup(void)
{
    fasor_class = class_new(gensym("fasor~"), (t_newmethod)fasor_new, 0,
    	sizeof(t_fasor), 0, A_GIMME, 0);
    class_addmethod(fasor_class, nullfn, gensym("signal"), 0);
    class_addmethod(fasor_class, (t_method)fasor_dsp, gensym("dsp"), 0);
    class_addmethod(fasor_class, (t_method)fasor_ft1,
    	gensym("ft1"), A_FLOAT, 0);
    class_addfloat(fasor_class,fasor_float);
}