Skip to content

Commit 7f884d4

Browse files
committed
Finished breaking classes into cpp/h
1 parent 9e5cb82 commit 7f884d4

7 files changed

Lines changed: 767 additions & 741 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Builds/
22
JuceLibraryCode/
33
Releases/
4+
Unused/
45
.DS_Store

Source/Freeverb.cpp

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,209 @@
99
*/
1010

1111
#include "Freeverb.h"
12+
13+
//==============================================================================
14+
Freeverb::Freeverb() {}
15+
16+
//==============================================================================
17+
void Freeverb::prepareToPlay(double sampleRate, int samplesPerBlock)
18+
{
19+
juce::dsp::ProcessSpec spec;
20+
spec.sampleRate = sampleRate;
21+
spec.maximumBlockSize = samplesPerBlock;
22+
spec.numChannels = getMainBusNumInputChannels();
23+
24+
earlyReflections.prepareToPlay(sampleRate, samplesPerBlock);
25+
26+
comb0.prepare(spec);
27+
comb1.prepare(spec);
28+
comb2.prepare(spec);
29+
comb3.prepare(spec);
30+
comb4.prepare(spec);
31+
comb5.prepare(spec);
32+
comb6.prepare(spec);
33+
comb7.prepare(spec);
34+
35+
dampingFilter0.prepare(spec);
36+
dampingFilter0.setType(juce::dsp::FirstOrderTPTFilterType::lowpass);
37+
dampingFilter1.prepare(spec);
38+
dampingFilter1.setType(juce::dsp::FirstOrderTPTFilterType::lowpass);
39+
dampingFilter2.prepare(spec);
40+
dampingFilter2.setType(juce::dsp::FirstOrderTPTFilterType::lowpass);
41+
dampingFilter3.prepare(spec);
42+
dampingFilter3.setType(juce::dsp::FirstOrderTPTFilterType::lowpass);
43+
dampingFilter4.prepare(spec);
44+
dampingFilter4.setType(juce::dsp::FirstOrderTPTFilterType::lowpass);
45+
dampingFilter5.prepare(spec);
46+
dampingFilter5.setType(juce::dsp::FirstOrderTPTFilterType::lowpass);
47+
dampingFilter6.prepare(spec);
48+
dampingFilter6.setType(juce::dsp::FirstOrderTPTFilterType::lowpass);
49+
dampingFilter7.prepare(spec);
50+
dampingFilter7.setType(juce::dsp::FirstOrderTPTFilterType::lowpass);
51+
52+
allpass0.prepare(spec);
53+
allpass1.prepare(spec);
54+
allpass2.prepare(spec);
55+
allpass3.prepare(spec);
56+
57+
mixer.prepare(spec);
58+
}
59+
60+
//==============================================================================
61+
void Freeverb::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
62+
{
63+
juce::ScopedNoDenormals noDenormals;
64+
65+
juce::dsp::AudioBlock<float> block { buffer };
66+
mixer.setWetMixProportion(mDryWetMix);
67+
mixer.pushDrySamples(block);
68+
69+
juce::AudioBuffer<float> earlyReflectionsBuffer(buffer.getNumChannels(), buffer.getNumSamples());
70+
earlyReflectionsBuffer.clear();
71+
earlyReflectionsBuffer.makeCopyOf(buffer, false);
72+
73+
// mix between
74+
float earlyGain = cos(mEarlyLateMix * M_PI * 0.5);
75+
float lateGain = cos((mEarlyLateMix * M_PI * 0.5) + M_PI * 1.5);
76+
earlyReflectionsBuffer.applyGain(earlyGain);
77+
buffer.applyGain(lateGain);
78+
79+
// get early reflection parameters
80+
earlyReflections.setSize(mSize);
81+
earlyReflections.setDecay(mDecay);
82+
83+
earlyReflections.processBlock(earlyReflectionsBuffer, midiMessages);
84+
85+
dampingFilter0.setCutoffFrequency(mDampingCutoff);
86+
dampingFilter1.setCutoffFrequency(mDampingCutoff);
87+
dampingFilter2.setCutoffFrequency(mDampingCutoff);
88+
dampingFilter3.setCutoffFrequency(mDampingCutoff);
89+
dampingFilter4.setCutoffFrequency(mDampingCutoff);
90+
dampingFilter5.setCutoffFrequency(mDampingCutoff);
91+
dampingFilter6.setCutoffFrequency(mDampingCutoff);
92+
dampingFilter7.setCutoffFrequency(mDampingCutoff);
93+
94+
for (int channel = 0; channel < buffer.getNumChannels(); ++channel)
95+
{
96+
auto* channelData = buffer.getWritePointer (channel);
97+
98+
comb0.setDelay(1557 * mSize + (channel * mWidth));
99+
comb1.setDelay(1617 * mSize + (channel * mWidth));
100+
comb2.setDelay(1491 * mSize + (channel * mWidth));
101+
comb3.setDelay(1422 * mSize + (channel * mWidth));
102+
comb4.setDelay(1277 * mSize + (channel * mWidth));
103+
comb5.setDelay(1356 * mSize + (channel * mWidth));
104+
comb6.setDelay(1188 * mSize + (channel * mWidth));
105+
comb7.setDelay(1116 * mSize + (channel * mWidth));
106+
107+
allpass0.setDelay(225 + (channel * mWidth));
108+
allpass1.setDelay(556 + (channel * mWidth));
109+
allpass2.setDelay(441 + (channel * mWidth));
110+
allpass3.setDelay(341 + (channel * mWidth));
111+
112+
// comb processing in parallel
113+
for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
114+
{
115+
auto currentSample = channelData[sample]/8;
116+
117+
comb0Output = comb0.popSample(channel);
118+
comb0.pushSample(channel, dampingFilter0.processSample(channel, currentSample + comb0Output * (mDecay)));
119+
120+
comb1Output = comb1.popSample(channel);
121+
comb1.pushSample(channel, dampingFilter1.processSample(channel, currentSample + comb1Output * (mDecay)));
122+
123+
comb2Output = comb2.popSample(channel);
124+
comb2.pushSample(channel, dampingFilter2.processSample(channel, currentSample + comb2Output * (mDecay)));
125+
126+
comb3Output = comb3.popSample(channel);
127+
comb3.pushSample(channel, dampingFilter3.processSample(channel, currentSample + comb3Output * (mDecay)));
128+
129+
comb4Output = comb4.popSample(channel);
130+
comb4.pushSample(channel, dampingFilter4.processSample(channel, currentSample + comb4Output * (mDecay)));
131+
132+
comb5Output = comb5.popSample(channel);
133+
comb5.pushSample(channel, dampingFilter5.processSample(channel, currentSample + comb5Output * (mDecay)));
134+
135+
comb6Output = comb6.popSample(channel);
136+
comb6.pushSample(channel, dampingFilter6.processSample(channel, currentSample + comb6Output * (mDecay)));
137+
138+
comb7Output = comb7.popSample(channel);
139+
comb7.pushSample(channel, dampingFilter7.processSample(channel, currentSample + comb7Output * (mDecay)));
140+
141+
channelData[sample] = comb0Output + comb1Output + comb2Output + comb3Output + comb4Output + comb5Output + comb6Output + comb7Output;
142+
}
143+
144+
// allpass processing in series
145+
float allpassFeedbackCoefficient = 0.5;
146+
147+
for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
148+
{
149+
allpass0Output = allpass0.popSample(channel);
150+
feedback = allpass0Output * allpassFeedbackCoefficient;
151+
feedforward = -channelData[sample] - allpass0Output * allpassFeedbackCoefficient;
152+
allpass0.pushSample(channel, channelData[sample] + feedback);
153+
channelData[sample] = allpass0Output + feedforward;
154+
155+
allpass1Output = allpass1.popSample(channel);
156+
feedback = allpass1Output * allpassFeedbackCoefficient;
157+
feedforward = -channelData[sample] - allpass1Output * allpassFeedbackCoefficient;
158+
allpass1.pushSample(channel, channelData[sample] + feedback);
159+
channelData[sample] = allpass1Output + feedforward;
160+
161+
allpass2Output = allpass2.popSample(channel);
162+
feedback = allpass2Output * allpassFeedbackCoefficient;
163+
feedforward = -channelData[sample] - allpass2Output * allpassFeedbackCoefficient;
164+
allpass2.pushSample(channel, channelData[sample] + feedback);
165+
channelData[sample] = allpass2Output + feedforward;
166+
167+
allpass3Output = allpass3.popSample(channel);
168+
feedback = allpass3Output * allpassFeedbackCoefficient;
169+
feedforward = -channelData[sample] - allpass2Output * allpassFeedbackCoefficient;
170+
allpass3.pushSample(channel, channelData[sample] + feedback);
171+
channelData[sample] = allpass3Output + feedforward;
172+
}
173+
}
174+
175+
// mix early/late reflection buffers; add wet samples
176+
for (int channel = 0; channel < buffer.getNumChannels(); ++channel)
177+
buffer.addFrom(channel, 0, earlyReflectionsBuffer, channel, 0, buffer.getNumSamples());
178+
juce::dsp::AudioBlock<float> wetBlock { buffer };
179+
mixer.mixWetSamples(wetBlock);
180+
}
181+
182+
//==============================================================================
183+
void Freeverb::reset()
184+
{
185+
comb0.reset();
186+
comb1.reset();
187+
comb2.reset();
188+
comb3.reset();
189+
comb4.reset();
190+
comb5.reset();
191+
comb6.reset();
192+
comb7.reset();
193+
194+
dampingFilter0.reset();
195+
dampingFilter1.reset();
196+
dampingFilter2.reset();
197+
dampingFilter3.reset();
198+
dampingFilter4.reset();
199+
dampingFilter5.reset();
200+
dampingFilter6.reset();
201+
dampingFilter7.reset();
202+
203+
allpass0.reset();
204+
allpass1.reset();
205+
allpass2.reset();
206+
allpass3.reset();
207+
208+
mixer.reset();
209+
}
210+
211+
//==============================================================================
212+
void Freeverb::setSize(float newSize) { mSize = newSize; }
213+
void Freeverb::setDecay(float newDecay) { mDecay = newDecay; }
214+
void Freeverb::setDampingCutoff(float newCutoff) { mDampingCutoff = newCutoff; }
215+
void Freeverb::setPreDelay(float newPreDelay) { mPreDelayTime = newPreDelay; }
216+
void Freeverb::setEarlyLateMix(float newMix) { mEarlyLateMix = newMix; }
217+
void Freeverb::setDryWetMix(float newMix) { mDryWetMix = newMix; }

0 commit comments

Comments
 (0)