Skip to content

Commit 13f5dd3

Browse files
author
Nathan Ho
committed
actually -- let's use the MySaw example from the help
1 parent b495280 commit 13f5dd3

File tree

6 files changed

+152
-49
lines changed

6 files changed

+152
-49
lines changed

BoringMixer.cpp

Lines changed: 0 additions & 33 deletions
This file was deleted.

BoringMixer.sc

Lines changed: 0 additions & 13 deletions
This file was deleted.

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
cmake_minimum_required (VERSION 2.8)
2-
set(PROJECT "BoringMixer")
2+
set(PROJECT "MySaw")
33
project (${PROJECT})
44

55
include_directories(${SC_PATH}/include/plugin_interface)
@@ -18,4 +18,4 @@ if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG)
1818
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
1919
endif()
2020

21-
add_library(${PROJECT} MODULE BoringMixer.cpp)
21+
add_library(${PROJECT} MODULE MySaw.cpp)

MySaw.cpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
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+
}

MySaw.sc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// without mul and add.
2+
MySaw : UGen {
3+
*ar { arg freq = 440.0, iphase = 0.0;
4+
^this.multiNew('audio', freq, iphase)
5+
}
6+
*kr { arg freq = 440.0, iphase = 0.0;
7+
^this.multiNew('control', freq, iphase)
8+
}
9+
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
This is a minimal example of a SuperCollider server plugin. It compiles a "BoringMixer" ugen that takes the average of its two audio-rate inputs.
1+
This is a minimal example of a SuperCollider server plugin. It compiles a "MySaw" ugen, which is a simple saw oscillator with controllable frequency and initial phase.
22

33
## Compiling
44

0 commit comments

Comments
 (0)