Skip to content

Commit cba61ed

Browse files
committed
fix/update C++ code
1 parent 3fb3a22 commit cba61ed

File tree

4 files changed

+88
-105
lines changed

4 files changed

+88
-105
lines changed

Ch 29 Writing Unit Generator Plug-ins/Figure_29-10_Flanger_2.cpp

Lines changed: 41 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ static InterfaceTable *ft;
88
struct Flanger : public Unit {
99
// it is a convention to use some kind of prefix (or postfix)
1010
// to distinguish member variables from local variables
11-
float mRate;
11+
float mModRate;
1212
float mDelaysize;
1313
float mAdvance;
1414
float mReadpos;
1515
int mWritepos;
16-
// a pointer to the memory we'll use for our internal delay
16+
// a pointer to the memory we'll use for our internal delay
1717
float *mDelayline;
1818
};
1919

@@ -27,90 +27,81 @@ void Flanger_Ctor(Flanger *unit) {
2727
// Rather than using rate directly, we're going to calculate the size of
2828
// jumps we must make each time to scan through the delayline at "rate"
2929
unit->mAdvance = ((unit->mDelaysize * rate) / SAMPLERATE) + 1.0f;
30-
unit->mRate = rate;
30+
unit->mModRate = rate;
3131
unit->mWritepos = 0;
3232
unit->mReadpos = 0;
33-
34-
// Allocate the delay line
33+
34+
// Allocate the delay line
3535
unit->mDelayline = (float*)RTAlloc(unit->mWorld, (int)unit->mDelaysize * sizeof(float));
3636
// Check the result of RTAlloc because it can fail if the RT pool is too small!
37-
if (!unit->mDelayline)
38-
{
39-
Print("RTAlloc failed!");
40-
// clear outputs, set calc function and set done
41-
ClearUnitOutputs(unit, 1);
42-
SETCALC(ClearUnitOutputs);
43-
unit->mDone = true;
44-
return;
45-
}
37+
ClearUnitIfMemFailed(unit->mDelayline);
4638
// Set the delay line to zeros.
4739
memset(unit->mDelayline, 0, unit->mDelaysize * sizeof(float));
48-
49-
// IMPORTANT: This tells scsynth the name of the calculation function for this UGen.
50-
SETCALC(Flanger_next);
51-
52-
// Should also calc 1 sample's worth of output - ensures each ugen's "pipes" are "primed"
53-
Flanger_next(unit, 1);
40+
41+
// IMPORTANT: This tells scsynth the name of the calculation function for this UGen.
42+
SETCALC(Flanger_next);
43+
44+
// Should also calc 1 sample's worth of output - ensures each ugen's "pipes" are "primed"
45+
Flanger_next(unit, 1);
5446
}
5547

5648
void Flanger_next(Flanger *unit, int inNumSamples) {
57-
float *in = IN(0);
49+
float *in = IN(0);
5850
float *out = OUT(0);
5951

6052
// "rate" and "depth" can be modulated at control rate
6153
float currate = IN0(1);
62-
float depth = IN0(2);
63-
54+
float depth = IN0(2);
55+
6456
// The compiler doesn't know that "out" can't possibly point
6557
// to one of our members, so it would have to reload them from
6658
// memory on every loop iteration. To prevent this from happening,
6759
// we temporarily store them in local variables.
68-
float rate = unit->mRate;
60+
float rate = unit->mModRate;
6961
float advance = unit->mAdvance;
7062
float readpos = unit->mReadpos;
7163
int writepos = unit->mWritepos;
7264
const float delaysize = unit->mDelaysize; // this one is fixed
7365
float *delayline = unit->mDelayline;
74-
66+
7567
if (rate != currate) {
76-
// rate input needs updating
77-
rate = currate;
78-
advance = ((delaysize * rate * 2) / SAMPLERATE) + 1.0f;
79-
}
80-
68+
// rate input needs updating
69+
rate = currate;
70+
advance = ((delaysize * rate) / SAMPLERATE) + 1.0f;
71+
}
72+
8173
for (int i = 0; i < inNumSamples; ++i) {
8274
float val = in[i];
83-
84-
// Write to the delay line
85-
delayline[writepos++] = val;
75+
76+
// Write to the delay line
77+
delayline[writepos++] = val;
8678
if(writepos == delaysize)
87-
writepos = 0;
88-
89-
// Read from the delay line
79+
writepos = 0;
80+
81+
// Read from the delay line
9082
float delayed = delayline[(int)readpos];
9183
readpos += advance;
92-
// Update position, NB we may be moving forwards or backwards (depending on input)
84+
// Update position, NB we may be moving forwards or backwards (depending on input)
9385
while(readpos >= delaysize)
94-
readpos -= delaysize;
86+
readpos -= delaysize;
9587
while(readpos < 0)
96-
readpos += delaysize;
97-
98-
// Mix dry and wet together, and output them
99-
out[i] = val + (delayed * depth);
100-
}
101-
88+
readpos += delaysize;
89+
90+
// Mix dry and wet together, and output them
91+
out[i] = val + (delayed * depth);
92+
}
93+
10294
// store them back
103-
unit->mRate = rate;
95+
unit->mModRate = rate;
10496
unit->mAdvance = advance;
10597
unit->mWritepos = writepos;
10698
unit->mReadpos = readpos;
107-
}
99+
}
108100

109101
void Flanger_Dtor(Flanger *unit) {
110-
// check in case RTFree failed in the Ctor
111-
if (unit->mDelayline)
112-
RTFree(unit->mWorld, unit->mDelayline);
113-
}
102+
// NB: it's ok to pass NULL to RTFree()
103+
RTFree(unit->mWorld, unit->mDelayline);
104+
}
114105

115106
PluginLoad(InterfaceTable *inTable) {
116107
ft = inTable;

Ch 29 Writing Unit Generator Plug-ins/Figure_29-10b_Flanger_2 C++ interface.cpp

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Flanger : public SCUnit {
1313
private:
1414
// it is a convention to use some kind of prefix (or postfix)
1515
// to distinguish member variables from local variables
16-
float mRate;
16+
float mModRate;
1717
float mDelaysize;
1818
float mAdvance;
1919
float mReadpos;
@@ -25,42 +25,34 @@ class Flanger : public SCUnit {
2525
Flanger::Flanger() {
2626
// Here we must initialise *all* state variables in our Flanger struct.
2727
mDelaysize = sampleRate() * 0.02f; // Fixed 20ms max delay
28-
float rate = IN0(1); // initial rate
28+
float rate = in0(1); // initial rate
2929
// Rather than using rate directly, we're going to calculate the size of
3030
// jumps we must make each time to scan through the delayline at "rate"
3131
mAdvance = ((mDelaysize * rate) / sampleRate()) + 1.0f;
32-
mRate = rate;
32+
mModRate = rate;
3333
mWritepos = 0;
3434
mReadpos = 0;
3535

3636
// Allocate the delay line
3737
mDelayline = (float*)RTAlloc(mWorld, (int)mDelaysize * sizeof(float));
3838
// Check the result of RTAlloc because it can fail if the RT pool is too small!
39-
if (!mDelayline)
40-
{
41-
Print("RTAlloc failed!");
42-
// clear outputs, set calc function and set done
43-
ClearUnitOutputs(unit, 1);
44-
SETCALC(ClearUnitOutputs);
45-
mDone = true;
46-
return;
47-
}
39+
auto unit = this;
40+
ClearUnitIfMemFailed(mDelayline);
4841
// Set the delay line to zeros.
4942
memset(mDelayline, 0, mDelaysize * sizeof(float));
5043

5144
// sets the calc function and automatically computes 1 sample.
52-
set_calc_function<&Flanger::next>();
45+
set_calc_function<Flanger, &Flanger::next>();
5346
}
5447

5548
Flanger::~Flanger() {
56-
// check in case RTFree failed in the Ctor
57-
if (mDelayline)
58-
RTFree(mWorld, mDelayline);
49+
// NB: it's ok to pass NULL to RTFree()
50+
RTFree(mWorld, mDelayline);
5951
}
6052

61-
void Flanger::next(int inNumSamples ) {
62-
float *in = in(0);
63-
float *out = out(0);
53+
void Flanger::next(int inNumSamples) {
54+
const float *input = in(0);
55+
float *output = out(0);
6456

6557
// "rate" and "depth" can be modulated at control rate
6658
float currate = in0(1);
@@ -70,7 +62,7 @@ void Flanger::next(int inNumSamples ) {
7062
// to one of our members, so it would have to reload them from
7163
// memory on every loop iteration. To prevent this from happening,
7264
// we temporarily store them in local variables.
73-
float rate = mRate;
65+
float rate = mModRate;
7466
float advance = mAdvance;
7567
float readpos = mReadpos;
7668
int writepos = mWritepos;
@@ -80,11 +72,11 @@ void Flanger::next(int inNumSamples ) {
8072
if (rate != currate) {
8173
// rate input needs updating
8274
rate = currate;
83-
advance = ((delaysize * rate * 2) / SAMPLERATE) + 1.0f;
75+
advance = ((delaysize * rate) / sampleRate()) + 1.0f;
8476
}
8577

8678
for (int i = 0; i < inNumSamples; ++i) {
87-
float val = in[i];
79+
float val = input[i];
8880

8981
// Write to the delay line
9082
delayline[writepos++] = val;
@@ -101,11 +93,11 @@ void Flanger::next(int inNumSamples ) {
10193
readpos += delaysize;
10294

10395
// Mix dry and wet together, and output them
104-
out[i] = val + (delayed * depth);
96+
output[i] = val + (delayed * depth);
10597
}
10698

10799
// store them back
108-
mRate = rate;
100+
mModRate = rate;
109101
mAdvance = advance;
110102
mWritepos = writepos;
111103
mReadpos = readpos;

Ch 29 Writing Unit Generator Plug-ins/Figure_29-8_Flanger_1.cpp

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ static InterfaceTable *ft;
88
struct Flanger : public Unit {
99
// it is a convention to use some kind of prefix (or postfix)
1010
// to distinguish member variables from local variables
11-
float mRate;
11+
float mModRate;
1212
float mDelaysize;
1313
float mAdvance;
1414
float mReadpos;
@@ -22,54 +22,54 @@ void Flanger_Ctor(Flanger *unit) {
2222
// Here we must initialise *all* state variables in our Flanger struct.
2323
unit->mDelaysize = SAMPLERATE * 0.02f; // Fixed 20ms max delay
2424
float rate = IN0(1); // initial rate
25-
// Rather than using rate directly, we're going to calculate the size of
26-
// jumps we must make each time to scan through the delayline at "rate"
25+
// Rather than using rate directly, we're going to calculate the size of
26+
// jumps we must make each time to scan through the delayline at "rate"
2727
float delta = (unit->mDelaysize * rate) / SAMPLERATE;
2828
unit->mAdvance = delta + 1.0f;
29-
unit->mRate = rate;
29+
unit->mModRate = rate;
3030
unit->mWritepos = 0;
3131
unit->mReadpos = 0;
32-
33-
// IMPORTANT: This tells scsynth the name of the calculation function for this UGen.
34-
SETCALC(Flanger_next);
35-
36-
// Should also calc 1 sample's worth of output - ensures each ugen's "pipes" are "primed"
37-
Flanger_next(unit, 1);
3832

39-
// store them back
40-
unit->mRate = rate;
41-
unit->mAdvance = advance;
42-
unit->mWritepos = writepos;
43-
unit->mReadpos = readpos;
33+
// IMPORTANT: This tells scsynth the name of the calculation function for this UGen.
34+
SETCALC(Flanger_next);
35+
36+
// Should also calc 1 sample's worth of output - ensures each ugen's "pipes" are "primed"
37+
Flanger_next(unit, 1);
4438
}
4539

4640
void Flanger_next(Flanger *unit, int inNumSamples) {
47-
float *in = IN(0);
48-
float *out = OUT(0);
41+
float *in = IN(0);
42+
float *out = OUT(0);
4943

5044
// "rate" and "depth" can be modulated at control rate
5145
float currate = IN0(1);
5246
float depth = IN0(2);
53-
54-
float rate = unit->mRate;
47+
48+
float rate = unit->mModRate;
5549
float delaysize = unit->mDelaysize;
56-
float advancce = unit->mAdvance;
50+
float advance = unit->mAdvance;
5751
float readpos = unit->mReadpos;
5852
int writepos = unit->mWritepos;
59-
53+
6054
for (int i = 0; i < inNumSamples; ++i) {
6155
float val = in[i];
62-
63-
// Do something to the signal before outputting
64-
// (not yet done)
65-
66-
out[i] = val;
56+
57+
// Do something to the signal before outputting
58+
// (not yet done)
59+
60+
out[i] = val;
6761
}
68-
}
62+
63+
// store them back
64+
unit->mModRate = rate;
65+
unit->mAdvance = advance;
66+
unit->mWritepos = writepos;
67+
unit->mReadpos = readpos;
68+
}
6969

7070

7171
PluginLoad(InterfaceTable *inTable) {
72-
ft = inTable;
73-
74-
DefineSimpleUnit(Flanger);
72+
ft = inTable;
73+
74+
DefineSimpleUnit(Flanger);
7575
}

Ch 29 Writing Unit Generator Plug-ins/Figure_29_16_Optimization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include <SC_Unit.h>
1+
#include "SC_Unit.h"
22

33
struct Test : Unit {
44
float mMul;

0 commit comments

Comments
 (0)