Krotos Modules 3
Loading...
Searching...
No Matches
ReformerOscillator.cpp
Go to the documentation of this file.
1/*
2==============================================================================
3
4 ReformerOscillator.cpp
5 Sample based oscillator / reformer engine
6 Author: Sandy
7 Date: 19/08/2020
8
9==============================================================================
10*/
11
12namespace krotos
13{
15
16 void ReformerOscillator::setGranularParameter(size_t paramIndex, const float* newValue)
17 {
18 jassert(paramIndex >= 0 && paramIndex < GranularParam::NUM_PARAMS);
19 m_parameters[paramIndex] = newValue;
20 }
21
22 inline void ReformerOscillator::setGranularParameters(std::vector<const float*>& newParams)
23 {
24 jassert(newParams.size() == m_parameters.size());
25 m_parameters = newParams;
26 }
27
28 inline void ReformerOscillator::setSampleRate(double sampleRate)
29 {
30 m_samplerate = sampleRate;
31 m_voicePhase.setSampleRate(static_cast<float>(m_samplerate));
33 m_popcornTimer.setSampleRate(static_cast<float>(m_samplerate));
35 m_channelCrossfade.setMaxSlewRate(2.f / static_cast<float>(sampleRate));
36 }
37
38 void ReformerOscillator::setSampleData(SampleEngine* sampleEngine) { m_sampleEngine = sampleEngine; }
39
40 // Remove all playing grains from the active grains list
42 {
43 for (auto& grain : m_activeGrains)
44 {
45 m_sampleEngine->freeGrain(grain); // Stop playing the grain
46 }
47 m_activeGrains.clear();
48 }
49
50 /*
51 How the frequency calculation works
52 setFrequency( frequency ) is called with the desired output frequency of
53 the sample
54
55 Things we need to calculate:
56
57 1) An increment to be added to the playhead every sample
58 2) A resample ratio to compensate for any difference between the
59 sample's sample rate and the DAW's sample rate 3) A ratio to adjust for the
60 frequency of the sampled note (working with C3 at present, pending some
61 analysis or meta-data)
62
63 1 is simply m_playbackHz * m_resampleRatio
64 2 & 3 are combined into m_resampleRatio
65 */
66
67 inline void ReformerOscillator::setFrequency(float frequency)
68 {
69 // Clamp within reasonable limits ie frequency >= epsilon, frequency <=
70 // nyquist (m_samplerate / 2)
71 m_playbackHz = std::max(std::min(float(m_samplerate * 0.5f), frequency), std::numeric_limits<float>::epsilon());
72 }
73
74 inline float ReformerOscillator::cube(float val) { return val * val * val; }
75
76 void ReformerOscillator::startNote(int midiNote, float velocity, int voiceIndex)
77 {
78 m_voiceIndex = voiceIndex; // Used finally merely to indicate on the UX the
79 // voice index of each playhead
80
82 m_isDrone = (midiNote & MIDI_NOTE_FLAG_DRONE) != 0;
83
84 m_stopped = false;
85 m_keyDown = true;
86 m_velocity = velocity;
87
88 setFrequency(static_cast<float>(MidiMessage::getMidiNoteInHertz(midiNote & MIDI_NOTE_MASK)));
89 m_voicePhase.triggerNewGrain(); // Trigger a new grain
90 }
91
93
95
97 {
98 m_keyDown = false;
99 if (!m_stopped)
100 {
101 m_stopped = true;
103 }
104 }
105
106 inline void ReformerOscillator::setTaggingType(bool isOn) { m_taggingType = isOn; }
107
109
111
113 {
114 if (std::isnan(sample.left))
115 {
116 jassertfalse; // Shouldn't get here
117 sample.left = 0.0f;
118 }
119 if (std::isnan(sample.right))
120 {
121 jassertfalse; // Shouldn't get here
122 sample.right = 0.0f;
123 }
124#ifdef USE_BRICK_WALL_CLIPPING
125 const float clippingVal = 3.0f;
126 if (sample.left > clippingVal)
127 {
128 sample.left = clippingVal;
129 }
130 if (sample.right > clippingVal)
131 {
132 sample.right = clippingVal;
133 }
134#endif
135 }
136
137 double ReformerOscillator::calculatePlayheadPosition(double startPosition, float halfSpray,
138 float /*referenceGrainsize*/)
139 {
140 // Calculate start and spray
141 // If the combination of start and spray take the spray range off the edge of
142 // the sample ...
143 // .. then the spray range is shifted forwards or backwards to keep it inside
144 // the sample while preserving the spray range size eg if spray is set to 1,
145 // start will have no effect whatsoever, as the spray range already covers the
146 // entire sample Conversely if spray is set to 0, start will be effective
147 // throughout its entire range
148
149 //--------------------- Scale spray range to grain size
150 halfSpray *= 10.0f * m_closestDescriptor.grainSize / float(m_length); // += 10 grains max spray range
151
152 Range<double> sprayRange(startPosition - static_cast<double>(halfSpray),
153 startPosition + static_cast<double>(halfSpray));
154 Range<double> constraintRange(0.f, 1.f);
155 Range<double> useableRange = constraintRange.constrainRange(sprayRange);
156
157 // Randomly place playhead somewhere within useable range
158 return (useableRange.getStart() + m_rand.nextDouble() * useableRange.getLength()) *
159 static_cast<double>(m_length);
160 }
161
162 Grain* ReformerOscillator::launchGrain(float paramSize, float paramStart, float paramSpray, Grain::Flavour flavour,
163 float gain)
164 {
165 const float minimumGrainLength{0.1f};
166
167 bool checkGrain = false;
168 if (m_isDrone)
169 {
171 {
172 checkGrain = true;
173 }
174 }
175 else
176 {
177 checkGrain = true;
178 }
179
180 if (checkGrain)
181 {
182 // Ask the sample engine for a free grain slot, returns non-null if
183 // successful
184 Grain* newGrain = m_sampleEngine->allocateGrain();
185 if (newGrain) // If non-null, means a free grain slot was found and newGrain
186 // is pointing to it
187 {
188 // Each voice instance (this is a voice instance) keeps its own personal
189 // record of every grain it is playing
190 m_activeGrains.push_back(newGrain);
191
192 int grainLength =
193 static_cast<int>(jmax<float>(minimumGrainLength, m_closestDescriptor.grainSize * paramSize));
194
195 double playHead = calculatePlayheadPosition(paramStart, paramSpray, m_closestDescriptor.grainSize);
197 static_cast<int>(playHead) -
198 grainLength / 2); // Center the playing grain about the start position
199
200 // Calculate jitter - this implementation is an amplitude variation factor
201 // of +-1 centered around 1
202 if (gain < 0.f) // If supplied gain < 0, we generate it here
203 {
204 gain = 1.0f +
205 2.f * m_parameters[GranularParam::LevelRand][m_sampleIndex] * (m_rand.nextFloat() - 0.5f);
206 }
207
208 // Calculate drift
209 float pitchRand =
210 1.0f + m_parameters[GranularParam::DetuneRand][m_sampleIndex] * (m_rand.nextFloat() - 0.5f);
211
212 // Now we populate all the properties of the grain ...
213 newGrain->playHead =
214 static_cast<double>(quantisedGrain.grainIndexByTime); // phase cycle index with phase angle 0
215 newGrain->playHeadStart = quantisedGrain.audioIndex; // Keep a record of the start point - used
216 // in displaying grain in UI
217 newGrain->windowDelta = 1.f / float(grainLength); // Calculate the increment needed to go from
218 // 0->1 during lifetime of grain
219 newGrain->grainWindow = 0.f; // Reset the window value
220 newGrain->length = grainLength; // Set the grainLength in samples
221 newGrain->gainRand = gain * gain;
222 newGrain->pitchRand = pitchRand;
223 newGrain->flavour = flavour;
224 }
225
226 return newGrain;
227 }
228
229 return nullptr;
230 }
231
233 {
234 if (m_sampleEngine == nullptr)
235 {
236 return StereoSample{}; // Return silence if no sample data
237 }
238
239 if (!m_sampleEngine->analysisResultsAreValid()) // If analysis isn't valid
240 {
241 return StereoSample{}; // Return silence
242 }
243
244 if (m_stopped)
245 {
246 return StereoSample{}; // Return silence if engine stopped
247 }
248
250 {
251 return StereoSample{}; // Return silence if sample engine is loading
252 }
253
255
256 m_sampleIndex = sampleIndex;
257 m_length = m_sampleEngine->getNumSamples();
258
260 }
261
262 inline int clamp(int val, int min, int max) { return jmin<int>(jmax<int>(val, min), max); }
263
265 {
266 // A new m_rateRandFactor value is generated every new grain time
267 float rand = m_rand.nextFloat() - 0.5f; // rand varies between +- 0.5
268 // scaled by Rate parameter, skewed for more action lower down
270 if (rand > 0.0f)
271 return 1.0f + rand * 6.0f;
272 else
273 return 1.0f + rand * 1.5f;
274 }
275
277
279 {
280 StereoSample sampleAccumulator;
281
282 int segmentIndex = 0;
283
284 bool popcornMode = false;
286 popcornMode = static_cast<bool>(m_parameters[GranularParam::Popcorn][0]);
287
289 {
291 }
292
294
296
297 // Calculate Pitch playBack
299
301 float playbackHzDetunedMod;
302 if (m_detuneModVal == 0)
303 {
304 playbackHzDetunedMod = m_playbackHz;
305 }
306 else
307 {
308 playbackHzDetunedMod =
309 (m_playbackHz * powf(2.0, m_detuneModVal / static_cast<float>(SEMITONES_PER_OCTAVE)));
310 }
311
312 if (detuneVal == 0)
313 {
314 m_playbackHzDetuned = playbackHzDetunedMod;
315 }
316 else
317 {
319 playbackHzDetunedMod * powf(2.0, detuneVal / static_cast<float>(SEMITONES_PER_OCTAVE));
320 }
321
322 // Tick the grain timer
324
325 Grain* newGrain = nullptr;
326 // It is time to launch a new grain if m_grainTimer has wrapped and we can obtain a granular slot
327 if (m_voicePhase.hasWrapped()) // Time for new grain
328 {
330 {
331 // If key is up, quench mode disables new grain generation
333 {
334 bool inhibitGrainGeneration = false;
335
336 if (popcornMode)
337 {
338 auto nearestGrainIndex =
340 if (m_nearestGrainIndex == nearestGrainIndex)
341 {
342 inhibitGrainGeneration = true;
343 }
344 m_nearestGrainIndex = nearestGrainIndex;
345 }
346 else if (m_proximityMode)
347 {
348 const float radius = m_parameters[GranularParam::Radius][m_sampleIndex];
349 const auto nearestIndexes =
351 if ((!nearestIndexes.empty()) && (!m_proximityTrigger))
352 {
353 m_nearestGrainIndex = nearestIndexes[rand() % nearestIndexes.size()];
354 }
355 else
356 {
357 inhibitGrainGeneration = true;
358 }
359 m_proximityTrigger = !nearestIndexes.empty();
360 }
361 else
362 {
363 // return this many nearest grains
364 size_t n = static_cast<size_t>(m_parameters[GranularParam::Nearest][m_sampleIndex]);
365 auto nearestIndexes =
367 m_nearestGrainIndex = nearestIndexes[rand() % nearestIndexes.size()];
368 }
369
370 if (!inhibitGrainGeneration)
371 {
374 // Ask the sample engine for a free grain slot
375 newGrain = m_sampleEngine->allocateGrain();
376 }
377 }
378 }
379 }
380
381 // Detect the case where looping and popcorn are enabled and
382 // grains have stop playing because the crossfade has played out
383 // and the puck is static
384 if (m_loopingEnable && popcornMode && !m_activeGrains.size())
385 {
386 // Tick the popcorn timer
388 // This is done on a timer - otherwise it would happen at sample rate
390 {
391 // Triggering a new grain here gives the popcorn mechanism
392 // an opportunity to test for a new nearest neighbour
393 // without that, we are stuck with no sound forever
395 }
396 }
397
398 // The grain launch timer is updated when GranularParam::Rate value changes or isNewGrainTime
399 float newGrainRate = m_parameters[GranularParam::Rate][m_sampleIndex];
400 bool grainRateChanged = m_grainRate != newGrainRate;
401 m_grainRate = newGrainRate;
402 if (newGrain || grainRateChanged)
403 {
404 if (m_loopingEnable)
405 {
406 m_grainRate = 0.f;
408 }
409 else
410 {
411 float grainRate = m_grainRate * getRateRandFactor();
412 m_voicePhase.setFrequency(grainRate);
413 m_popcornTimer.setFrequency(grainRate);
414 }
415 }
416
417 // Time to launch a grain ?
418 if (newGrain) // If non-null, means a free grain slot was found and returned
419 {
420 m_activeGrains.push_back(newGrain); // We keep a local reference to the grains we are playing
421
422 // Populate all the properties of the grain ...
423
424 // Set the pan randomisation per grain - ranges from -1 to +1
425 newGrain->panRand = (m_rand.nextFloat() * 2.f - 1.f) * m_parameters[GranularParam::PanRand][m_sampleIndex];
426
427 // Set the width randomisation per grain - ranges from 0 to 1 when full up, to 1 when turned to 0
428 newGrain->widthRand = 1.f - m_rand.nextFloat() * m_parameters[GranularParam::WidthRand][m_sampleIndex];
429
430 // Calculate start and spray
431 // If the combination of start and spray take the spray range off the edge of the sample ...
432 // .. then the spray range is shifted forwards or backwards to keep it inside the sample while preserving
433 // the spray range size eg if spray is set to 1, start will have no effect whatsoever, as the spray range
434 // already covers the entire sample Conversely if spray is set to 0, start will be effective throughout its
435 // entire range
436
437 int startPositionInSamples = m_sampleEngine->getGrainDescriptionByTime()[m_nearestGrainIndex].audioIndex;
443
444 int halfSpray = static_cast<int>(0.5f * m_parameters[GranularParam::StartRand][m_sampleIndex] * m_length);
445 Range<int> sprayRange(static_cast<int>(startPositionInSamples - halfSpray),
446 static_cast<int>(startPositionInSamples + halfSpray));
447 Range<int> constraintRange(0, m_length);
448 Range<int> useableRange = constraintRange.constrainRange(sprayRange);
449 newGrain->playHead = (useableRange.getStart() + m_rand.nextFloat() * useableRange.getLength());
450
451 newGrain->playHeadStart = static_cast<int>(newGrain->playHead); // For display
452
453 int segmentSampleRate = static_cast<int>(m_samplerate);
454 segmentSampleRate = m_sampleEngine->getAudioSegmentSampleRate(segmentIndex);
455
456 float gainNormalisationFactor = m_sampleEngine->getAudioSegmentNormalisationFactor(segmentIndex);
457
458 gainNormalisationFactor =
459 jmap<float>(m_parameters[GranularParam::Normalise][m_sampleIndex], 1.f, gainNormalisationFactor);
460
461 // Calculate the ratio between the DAW sample rate and the source sample rate
462 float resampleRatio = static_cast<float>(segmentSampleRate) / m_sampleEngine->getSampleRate();
463
464 // Compensate by the frequency of the sampled note
465 newGrain->resampleRatio = resampleRatio / m_sampleEngine->getNativeNoteFrequency();
466
467 // Calculate variations in grain size - sizeRandomiser will fluctuate between 0 and 1
468 float sizeRandomiser = 1.0f - m_parameters[GranularParam::SizeRand][m_sampleIndex] * m_rand.nextFloat();
469 float grainSizeInSamples = m_parameters[GranularParam::Size][m_sampleIndex] * 0.01f * newGrain->grainSize;
470 newGrain->setLifetime(clamp(static_cast<int>(sizeRandomiser * grainSizeInSamples), 1, m_length));
471
472 // Calculate drift (pitch randomisation)
473 newGrain->pitchRand =
474 1.0f + m_parameters[GranularParam::DetuneRand][m_sampleIndex] * (m_rand.nextFloat() - 0.5f);
475
476 // Calculate jitter - this implementation is an amplitude variation factor of +-1 centered around 1
477 float gain =
478 1.0f + 2.f * m_parameters[GranularParam::LevelRand][m_sampleIndex] * (m_rand.nextFloat() - 0.5f);
479 newGrain->gainRand = gain * gain * gainNormalisationFactor;
480
481 m_isDrone ? newGrain->flavour = Grain::Flavour::background : newGrain->flavour = Grain::Flavour::foreground;
482
483 newGrain->voiceIndex = m_voiceIndex;
484 }
485
486 generateGrains(sampleAccumulator);
487
488 killNANs(sampleAccumulator);
489
490 return sampleAccumulator;
491 }
492
494 {
496 float masterGain = gainMod * Decibels::decibelsToGain(m_parameters[GranularParam::Level][m_sampleIndex]);
497 masterGain *= Decibels::decibelsToGain(m_parameters[GranularParam::GranularLevel][m_sampleIndex]);
500 float fadePoint = jmax(m_parameters[GranularParam::Shape][m_sampleIndex] * 0.5f, FADE_POINT_MIN);
501 int grainIndex = static_cast<int>(m_activeGrains.size()) - 1;
502
503 // This is the loop which generates the grains.
504 // Everything inside will be called per grain, so we have pre-calculated as
505 // much as possible before entry (& a bit more can be done in this respect)
506 while (grainIndex >= 0)
507 {
508 Grain* playingGrain = m_activeGrains[size_t(grainIndex)];
509 float increment = m_playbackHzDetuned * playingGrain->resampleRatio;
510 float randomisedPan = 0.5f * (1.f + jlimit<float>(-1.f, 1.f, pan + playingGrain->panRand));
511 playingGrain->envelope = 1.f; // Full amplitude most of the time, only set < 1 when ramping up or
512 // down. Expensive sinf() called only during ramp
513
514 if (playingGrain->grainWindow < fadePoint) // Are we ramping up ?
515 {
516 // Sine law here provides for equal power crossfading when looping
517 playingGrain->envelope = sinf(jmap<float>(playingGrain->grainWindow, 0.f, fadePoint, 0.f, 1.f) *
518 MathConstants<float>::halfPi);
519 }
520 else if (playingGrain->grainWindow >= 1.f - fadePoint) // Are we ramping down ?
521 {
522 playingGrain->envelope = sinf(jmap<float>(playingGrain->grainWindow, 1.f - fadePoint, 1.f, 1.f, 0.f) *
523 MathConstants<float>::halfPi);
524 if ((m_activeGrains.size() < 2) && m_loopingEnable) // We acheive cross-dissolved looping by triggering
525 // a second grain wwhen we start ramping down
526 {
527 m_voicePhase.triggerNewGrain(); // Trigger a new grain
528 }
529 }
530
531 if (m_proximityMode)
532 {
533 // use a rectangular window for one-shot grains
534 playingGrain->envelope = 1.0f;
535 }
536
537 // Accumulate audio from all the playing grains
538 StereoSample newSample = m_sampleEngine->getInterpolatedSample(playingGrain->playHead);
539 sampleAccumulator += newSample.panSine(randomisedPan).width(width * playingGrain->widthRand) * masterGain *
540 playingGrain->gainRand * playingGrain->envelope;
541
542 if (playingGrain->grainWindow >= 1.f) // Has the grain come to the end of its life ?
543 {
544 m_sampleEngine->freeGrain(playingGrain); // If so, release the grain to the sample engine's
545 // central pool of grains
546 m_activeGrains.erase(m_activeGrains.begin() + grainIndex); // then remove its entry from our local
547 // list of playing grains
548 }
549 else // If the grain is still playing, we increment the playhead and grain
550 // window
551 {
552 float playheadIncrement = increment * playingGrain->pitchRand;
553 playingGrain->playHead += playheadIncrement; // Advance the playhead
554 playingGrain->grainWindow += playheadIncrement / playingGrain->length; // Keep the grain window in sync
555 }
556 playingGrain->gainMod = gainMod;
557 playingGrain->pitchMod = m_detuneModVal / static_cast<float>(SEMITONES_PER_OCTAVE);
558 grainIndex--;
559 }
560 }
561
563
565
566 inline int ReformerOscillator::getNumActiveGrains() { return static_cast<int>(m_activeGrains.size()); }
567} // namespace krotos
Definition OscillatorUtils.h:39
float resampleRatio
Definition OscillatorUtils.h:67
int length
Definition OscillatorUtils.h:61
float principalZ
Definition OscillatorUtils.h:81
float gainRand
Definition OscillatorUtils.h:69
float principalX
Definition OscillatorUtils.h:79
float panRand
Definition OscillatorUtils.h:70
double playHead
Definition OscillatorUtils.h:65
float envelope
Definition OscillatorUtils.h:63
float windowDelta
Definition OscillatorUtils.h:74
float gainMod
Definition OscillatorUtils.h:76
float principalY
Definition OscillatorUtils.h:80
float widthRand
Definition OscillatorUtils.h:71
float pitchMod
Definition OscillatorUtils.h:77
float pitchRand
Definition OscillatorUtils.h:68
void setLifetime(int grainPlaybackLength)
Set the approriate variables to control the lifetime of the grain.
Definition OscillatorUtils.cpp:12
float grainSize
Definition OscillatorUtils.h:60
int voiceIndex
Definition OscillatorUtils.h:75
float principalQ
Definition OscillatorUtils.h:82
Flavour
Definition OscillatorUtils.h:49
@ foreground
Definition OscillatorUtils.h:52
@ background
Definition OscillatorUtils.h:53
int playHeadStart
Definition OscillatorUtils.h:58
float grainWindow
Definition OscillatorUtils.h:62
ProgressTracker & getProgressTracker()
Get a reference to this buffer's ProgressTracker.
Definition KrotosAudioBufferDSP.cpp:24
std::size_t getNearestNeighbour2D(float x, float y)
Definition KrotosAudioBufferDSP.h:456
bool analysisResultsAreValid()
Definition KrotosAudioBufferDSP.h:422
AudioDescriptor & audioIndexToDescriptor(int audioIndex)
Definition KrotosAudioBufferDSP.cpp:895
std::vector< AudioDescriptor > & getGrainDescriptionByTime()
Definition KrotosAudioBufferDSP.h:452
float getSampleRate(void)
Definition KrotosAudioBuffer.cpp:506
StereoSample getInterpolatedSample(double index)
Get a stereo sample from the audio buffer.
Definition KrotosAudioBuffer.cpp:318
float getNativeNoteFrequency(void)
Definition KrotosAudioBuffer.cpp:512
void setSampleRate(float val)
Definition OscillatorUtils.cpp:105
void triggerNewGrain()
Definition OscillatorUtils.cpp:92
void setFrequency(float val)
Definition OscillatorUtils.cpp:78
bool hasWrapped()
Definition OscillatorUtils.cpp:99
void nextPhase()
Definition OscillatorUtils.cpp:24
bool isLoading()
Definition KrotosAudioBufferDSP.h:98
bool m_loopingEnable
Definition ReformerOscillator.h:221
double m_samplerate
Definition ReformerOscillator.h:201
juce::Random m_rand
Definition ReformerOscillator.h:190
float getRateRandFactor()
Definition ReformerOscillator.cpp:264
bool m_proximityMode
Definition ReformerOscillator.h:241
SlewLimiter m_channelCrossfade
Definition ReformerOscillator.h:218
const float FADE_POINT_MIN
Definition ReformerOscillator.h:229
void stopNote()
Signals the oscillator to begin key up behaviour, usually called by key up event The oscillator may c...
Definition ReformerOscillator.cpp:92
bool m_trackingEnable
Definition ReformerOscillator.h:220
void setHardLoopEnable(bool isOn)
Definition ReformerOscillator.cpp:110
StereoSample getNextStereoSample(size_t sampleIndex) override
Updates the granular engine and returns the next audio value.
Definition ReformerOscillator.cpp:232
void startNote(int midiNote, float velocity, int voiceIndex)
Starts the oscillator playing, usually called by key down event.
Definition ReformerOscillator.cpp:76
int m_length
Definition ReformerOscillator.h:208
float m_detuneModVal
Definition ReformerOscillator.h:227
void setTaggingType(bool isOn)
Definition ReformerOscillator.cpp:106
float m_velocity
Definition ReformerOscillator.h:224
std::vector< const float * > m_parameters
Definition ReformerOscillator.h:209
float getFrequency() override
Gets the target frequency which you set with the setFrequency method.
Definition ReformerOscillator.cpp:562
void setSampleData(SampleEngine *sampleEngine)
Sets the oscillator's internal reference to the SampleEngine structure it is to use.
Definition ReformerOscillator.cpp:38
void setGranularParameter(size_t paramIndex, const float *newValue)
Updates the granular engine and returns the next audio value.
Definition ReformerOscillator.cpp:16
int getNumActiveGrains() override
Returns the number of grains currently active for this instance of the oscillator.
Definition ReformerOscillator.cpp:566
PhaseGenerator m_popcornTimer
Definition ReformerOscillator.h:196
float cube(float val)
Definition ReformerOscillator.cpp:74
float m_playbackHz
Definition ReformerOscillator.h:198
void setGranularParameters(std::vector< const float * > &newParams)
Sets multiple internal parameter to new values.
Definition ReformerOscillator.cpp:22
void flushGranular()
Definition ReformerOscillator.cpp:41
SampleEngine * m_sampleEngine
Definition ReformerOscillator.h:206
bool m_autoplayEnabled
Definition ReformerOscillator.h:231
Point< float > m_puckPosition
Definition ReformerOscillator.h:213
void setFrequency(float frequency) override
Sets the target frequency which you want the oscillator to output.
Definition ReformerOscillator.cpp:67
float m_grainRate
Definition ReformerOscillator.h:203
void setSampleRate(double sampleRate) override
Sets the sample rate which the granular oscillator uses to calculate its output.
Definition ReformerOscillator.cpp:28
void generateGrains(StereoSample &sampleAccumulator)
Definition ReformerOscillator.cpp:493
size_t m_sampleIndex
Definition ReformerOscillator.h:223
StereoSample getNextStereoGranularSample()
Definition ReformerOscillator.cpp:278
double calculatePlayheadPosition(double startPosition, float halfSpray, float referenceGrainsize)
Definition ReformerOscillator.cpp:137
double getSampleRate() override
Returns the sample rate which which you set with the setSampleRate method.
Definition ReformerOscillator.cpp:564
void killNANs(StereoSample &sample)
Definition ReformerOscillator.cpp:112
std::vector< Grain * > m_activeGrains
Definition ReformerOscillator.h:207
const float getVelocity()
Returns the value of the velocity as a float in [0...1].
Definition ReformerOscillator.cpp:94
bool m_taggingType
Definition ReformerOscillator.h:219
bool m_proximityTrigger
Definition ReformerOscillator.h:242
size_t m_nearestGrainIndex
Definition ReformerOscillator.h:233
float m_playbackHzDetuned
Definition ReformerOscillator.h:199
int m_voiceIndex
Definition ReformerOscillator.h:216
bool m_keyDown
Definition ReformerOscillator.h:211
void setTrackingEnable(bool isOn)
Definition ReformerOscillator.cpp:108
bool m_isDrone
Definition ReformerOscillator.h:230
AudioDescriptor m_closestDescriptor
Definition ReformerOscillator.h:205
Grain * launchGrain(float paramSize, float paramStart, float paramSpray, Grain::Flavour flavour, float gain=-1.f)
Definition ReformerOscillator.cpp:162
ReformerOscillator()
Definition ReformerOscillator.cpp:14
void clearNote()
Signals the oscillator to stop immediately, and return any grains to pool.
Definition ReformerOscillator.cpp:96
bool m_stopped
Definition ReformerOscillator.h:210
@ Shape
Definition ReformerOscillator.h:152
@ Proximity
Definition ReformerOscillator.h:158
@ WidthRand
Definition ReformerOscillator.h:137
@ Width
Definition ReformerOscillator.h:136
@ GranularLevel
Definition ReformerOscillator.h:144
@ Rate
Definition ReformerOscillator.h:134
@ LevelRand
Definition ReformerOscillator.h:146
@ Pan
Definition ReformerOscillator.h:138
@ PanRand
Definition ReformerOscillator.h:139
@ SALoop
Definition ReformerOscillator.h:150
@ DetuneMod
Definition ReformerOscillator.h:141
@ NUM_PARAMS
Definition ReformerOscillator.h:160
@ SizeRand
Definition ReformerOscillator.h:133
@ Level
Definition ReformerOscillator.h:143
@ Popcorn
Definition ReformerOscillator.h:147
@ RateRand
Definition ReformerOscillator.h:135
@ StartRand
Definition ReformerOscillator.h:131
@ LevelMod
Definition ReformerOscillator.h:145
@ GrainLim
Definition ReformerOscillator.h:153
@ Autoplay
Definition ReformerOscillator.h:151
@ PuckX
Definition ReformerOscillator.h:128
@ Normalise
Definition ReformerOscillator.h:155
@ Quench
Definition ReformerOscillator.h:148
@ Nearest
Definition ReformerOscillator.h:130
@ DetuneRand
Definition ReformerOscillator.h:142
@ Size
Definition ReformerOscillator.h:132
@ Detune
Definition ReformerOscillator.h:140
@ Radius
Definition ReformerOscillator.h:159
@ PuckY
Definition ReformerOscillator.h:129
PhaseGenerator m_voicePhase
Definition ReformerOscillator.h:193
Definition SampleEngine.h:84
void setGrainLimit(int newLimit)
Definition SampleEngine.cpp:64
float getAudioSegmentNormalisationFactor(int segmentIndex)
Definition SampleEngine.h:259
void freeGrain(Grain *grain)
Definition SampleEngine.cpp:66
Grain * allocateGrain()
Definition SampleEngine.cpp:31
int getAudioSegmentSampleRate(int segmentIndex)
Definition SampleEngine.h:246
void setMaxSlewRate(float val)
Definition OscillatorUtils.cpp:238
Definition KrotosAudioBuffer.h:16
float left
Definition KrotosAudioBuffer.h:107
float right
Definition KrotosAudioBuffer.h:107
StereoSample width(float width)
Definition KrotosAudioBuffer.h:98
StereoSample panSine(float pan)
Definition KrotosAudioBuffer.h:90
Definition AirAbsorptionFilter.cpp:2
static const int MIDI_NOTE_MASK
Definition OscillatorUtils.h:21
int clamp(int val, int min, int max)
Definition ReformerOscillator.cpp:262
static const int MIDI_NOTE_FLAG_DRONE
Definition OscillatorUtils.h:22
static const int SEMITONES_PER_OCTAVE
Definition OscillatorUtils.h:36
int debugCounter
Definition ReformerOscillator.cpp:276
A class to contains any attributes we want to store for the described audio.
Definition KrotosAudioBufferDSP.h:177
int grainIndexByTime
Definition KrotosAudioBufferDSP.h:182
int audioIndex
Definition KrotosAudioBufferDSP.h:180
float grainSize
Definition KrotosAudioBufferDSP.h:181