1+ #include " SC_PlugIn.h"
2+
3+ // InterfaceTable contains pointers to functions in the host (server).
4+ static InterfaceTable *ft;
5+
6+ // declare struct to hold unit generator state
7+ struct MySaw : public Unit
8+ {
9+ double mPhase ; // phase of the oscillator, from -1 to 1.
10+ float mFreqMul ; // a constant for multiplying frequency
11+ };
12+
13+ // declare unit generator functions
14+ static void MySaw_next_a (MySaw *unit, int inNumSamples);
15+ static void MySaw_next_k (MySaw *unit, int inNumSamples);
16+ static void MySaw_Ctor (MySaw* unit);
17+
18+
19+ // ////////////////////////////////////////////////////////////////
20+
21+ // Ctor is called to initialize the unit generator.
22+ // It only executes once.
23+
24+ // A Ctor usually does 3 things.
25+ // 1. set the calculation function.
26+ // 2. initialize the unit generator state variables.
27+ // 3. calculate one sample of output.
28+ void MySaw_Ctor (MySaw* unit)
29+ {
30+ // 1. set the calculation function.
31+ if (INRATE (0 ) == calc_FullRate) {
32+ // if the frequency argument is audio rate
33+ SETCALC (MySaw_next_a);
34+ } else {
35+ // if the frequency argument is control rate (or a scalar).
36+ SETCALC (MySaw_next_k);
37+ }
38+
39+ // 2. initialize the unit generator state variables.
40+ // initialize a constant for multiplying the frequency
41+ unit->mFreqMul = 2.0 * SAMPLEDUR;
42+ // get initial phase of oscillator
43+ unit->mPhase = IN0 (1 );
44+
45+ // 3. calculate one sample of output.
46+ MySaw_next_k (unit, 1 );
47+ }
48+
49+
50+ // ////////////////////////////////////////////////////////////////
51+
52+ // The calculation function executes once per control period
53+ // which is typically 64 samples.
54+
55+ // calculation function for an audio rate frequency argument
56+ void MySaw_next_a (MySaw *unit, int inNumSamples)
57+ {
58+ // get the pointer to the output buffer
59+ float *out = OUT (0 );
60+
61+ // get the pointer to the input buffer
62+ float *freq = IN (0 );
63+
64+ // get phase and freqmul constant from struct and store it in a
65+ // local variable.
66+ // The optimizer will cause them to be loaded it into a register.
67+ float freqmul = unit->mFreqMul ;
68+ double phase = unit->mPhase ;
69+
70+ // perform a loop for the number of samples in the control period.
71+ // If this unit is audio rate then inNumSamples will be 64 or whatever
72+ // the block size is. If this unit is control rate then inNumSamples will
73+ // be 1.
74+ for (int i=0 ; i < inNumSamples; ++i)
75+ {
76+ // out must be written last for in place operation
77+ float z = phase;
78+ phase += freq[i] * freqmul;
79+
80+ // these if statements wrap the phase a +1 or -1.
81+ if (phase >= 1 .f ) phase -= 2 .f ;
82+ else if (phase <= -1 .f ) phase += 2 .f ;
83+
84+ // write the output
85+ out[i] = z;
86+ }
87+
88+ // store the phase back to the struct
89+ unit->mPhase = phase;
90+ }
91+
92+ // ////////////////////////////////////////////////////////////////
93+
94+ // calculation function for a control rate frequency argument
95+ void MySaw_next_k (MySaw *unit, int inNumSamples)
96+ {
97+ // get the pointer to the output buffer
98+ float *out = OUT (0 );
99+
100+ // freq is control rate, so calculate it once.
101+ float freq = IN0 (0 ) * unit->mFreqMul ;
102+
103+ // get phase from struct and store it in a local variable.
104+ // The optimizer will cause it to be loaded it into a register.
105+ double phase = unit->mPhase ;
106+
107+ // since the frequency is not changing then we can simplify the loops
108+ // by separating the cases of positive or negative frequencies.
109+ // This will make them run faster because there is less code inside the loop.
110+ if (freq >= 0 .f ) {
111+ // positive frequencies
112+ for (int i=0 ; i < inNumSamples; ++i)
113+ {
114+ out[i] = phase;
115+ phase += freq;
116+ if (phase >= 1 .f ) phase -= 2 .f ;
117+ }
118+ } else {
119+ // negative frequencies
120+ for (int i=0 ; i < inNumSamples; ++i)
121+ {
122+ out[i] = phase;
123+ phase += freq;
124+ if (phase <= -1 .f ) phase += 2 .f ;
125+ }
126+ }
127+
128+ // store the phase back to the struct
129+ unit->mPhase = phase;
130+ }
131+
132+
133+ // the entry point is called by the host when the plug-in is loaded
134+ PluginLoad (MySaw)
135+ {
136+ // InterfaceTable *inTable implicitly given as argument to the load function
137+ ft = inTable; // store pointer to InterfaceTable
138+
139+ DefineSimpleUnit (MySaw);
140+ }
0 commit comments