LMMS
Loading...
Searching...
No Matches
Synthesiser.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2016 ROLI Ltd.
6 Copyright (C) 2018 Filipe Coelho <falktx@falktx.com>
7
8 Permission is granted to use this software under the terms of the ISC license
9 http://www.isc.org/downloads/software-support-policy/isc-license/
10
11 Permission to use, copy, modify, and/or distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
14
15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 OF THIS SOFTWARE.
22
23 ==============================================================================
24*/
25
26#include "Synthesiser.h"
27
29#include "../containers/Array.h"
30#include "../midi/MidiBuffer.h"
31#include "../midi/MidiMessage.h"
32
33namespace water {
34
37
38//==============================================================================
49
53
54bool SynthesiserVoice::isPlayingChannel (const int midiChannel) const
55{
56 return currentPlayingMidiChannel == midiChannel;
57}
58
60{
61 currentSampleRate = newRate;
62}
63
65{
66 return getCurrentlyPlayingNote() >= 0;
67}
68
75
78
79bool SynthesiserVoice::wasStartedBefore (const SynthesiserVoice& other) const noexcept
80{
81 return noteOnTime < other.noteOnTime;
82}
83
84
85//==============================================================================
98
102
103//==============================================================================
105{
106 return voices [index];
107}
108
110{
111 voices.clear();
112}
113
115{
117 return voices.add (newVoice);
118}
119
120void Synthesiser::removeVoice (const int index)
121{
122 voices.remove (index);
123}
124
126{
127 sounds.clear();
128}
129
131{
132 return sounds.add (newSound);
133}
134
135void Synthesiser::removeSound (const int index)
136{
137 sounds.remove (index);
138}
139
140void Synthesiser::setNoteStealingEnabled (const bool shouldSteal)
141{
142 shouldStealNotes = shouldSteal;
143}
144
145void Synthesiser::setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict) noexcept
146{
147 wassert (numSamples > 0); // it wouldn't make much sense for this to be less than 1
148 minimumSubBlockSize = numSamples;
149 subBlockSubdivisionIsStrict = shouldBeStrict;
150}
151
152//==============================================================================
154{
155 if (sampleRate != newRate)
156 {
157 allNotesOff (0, false);
158
159 sampleRate = newRate;
160
161 for (int i = voices.size(); --i >= 0;)
162 voices.getUnchecked (i)->setCurrentPlaybackSampleRate (newRate);
163 }
164}
165
167 const MidiBuffer& midiData,
168 int startSample,
169 int numSamples)
170{
171 // must set the sample rate before using this!
172 wassert (sampleRate != 0);
173 const int targetChannels = outputAudio.getNumChannels();
174
175 MidiBuffer::Iterator midiIterator (midiData);
176 midiIterator.setNextSamplePosition (startSample);
177
178 bool firstEvent = true;
179 int midiEventPos;
181
182
183 while (numSamples > 0)
184 {
185 if (! midiIterator.getNextEvent (m, midiEventPos))
186 {
187 if (targetChannels > 0)
188 renderVoices (outputAudio, startSample, numSamples);
189
190 return;
191 }
192
193 const int samplesToNextMidiMessage = midiEventPos - startSample;
194
195 if (samplesToNextMidiMessage >= numSamples)
196 {
197 if (targetChannels > 0)
198 renderVoices (outputAudio, startSample, numSamples);
199
201 break;
202 }
203
204 if (samplesToNextMidiMessage < ((firstEvent && ! subBlockSubdivisionIsStrict) ? 1 : minimumSubBlockSize))
205 {
207 continue;
208 }
209
210 firstEvent = false;
211
212 if (targetChannels > 0)
213 renderVoices (outputAudio, startSample, samplesToNextMidiMessage);
214
216 startSample += samplesToNextMidiMessage;
217 numSamples -= samplesToNextMidiMessage;
218 }
219
220 while (midiIterator.getNextEvent (m, midiEventPos))
222}
223
224void Synthesiser::renderVoices (AudioSampleBuffer& buffer, int startSample, int numSamples)
225{
226 for (int i = voices.size(); --i >= 0;)
227 voices.getUnchecked (i)->renderNextBlock (buffer, startSample, numSamples);
228}
229
231{
232 const int channel = m.getChannel();
233
234 if (m.isNoteOn())
235 {
236 noteOn (channel, m.getNoteNumber(), m.getFloatVelocity());
237 }
238 else if (m.isNoteOff())
239 {
240 noteOff (channel, m.getNoteNumber(), m.getFloatVelocity(), true);
241 }
242 else if (m.isAllNotesOff() || m.isAllSoundOff())
243 {
244 allNotesOff (channel, true);
245 }
246 else if (m.isPitchWheel())
247 {
248 const int wheelPos = m.getPitchWheelValue();
249 lastPitchWheelValues [channel - 1] = wheelPos;
250 handlePitchWheel (channel, wheelPos);
251 }
252 else if (m.isAftertouch())
253 {
254 handleAftertouch (channel, m.getNoteNumber(), m.getAfterTouchValue());
255 }
256 else if (m.isChannelPressure())
257 {
258 handleChannelPressure (channel, m.getChannelPressureValue());
259 }
260 else if (m.isController())
261 {
262 handleController (channel, m.getControllerNumber(), m.getControllerValue());
263 }
264 else if (m.isProgramChange())
265 {
266 handleProgramChange (channel, m.getProgramChangeNumber());
267 }
268}
269
270//==============================================================================
271void Synthesiser::noteOn (const int midiChannel,
272 const int midiNoteNumber,
273 const float velocity)
274{
275
276 for (int i = sounds.size(); --i >= 0;)
277 {
278 SynthesiserSound* const sound = sounds.getUnchecked(i);
279
280 if (sound->appliesToNote (midiNoteNumber)
281 && sound->appliesToChannel (midiChannel))
282 {
283 // If hitting a note that's still ringing, stop it first (it could be
284 // still playing because of the sustain or sostenuto pedal).
285 for (int j = voices.size(); --j >= 0;)
286 {
287 SynthesiserVoice* const voice = voices.getUnchecked (j);
288
289 if (voice->getCurrentlyPlayingNote() == midiNoteNumber
290 && voice->isPlayingChannel (midiChannel))
291 stopVoice (voice, 1.0f, true);
292 }
293
294 startVoice (findFreeVoice (sound, midiChannel, midiNoteNumber, shouldStealNotes),
295 sound, midiChannel, midiNoteNumber, velocity);
296 }
297 }
298}
299
301 SynthesiserSound* const sound,
302 const int midiChannel,
303 const int midiNoteNumber,
304 const float velocity)
305{
306 if (voice != nullptr && sound != nullptr)
307 {
308 CARLA_SAFE_ASSERT_RETURN(midiChannel > 0 && midiChannel <= 16,);
309
310 if (voice->currentlyPlayingSound != nullptr)
311 voice->stopNote (0.0f, false);
312
313 voice->currentlyPlayingNote = midiNoteNumber;
314 voice->currentPlayingMidiChannel = midiChannel;
315 voice->noteOnTime = ++lastNoteOnCounter;
316 voice->currentlyPlayingSound = sound;
317 voice->keyIsDown = true;
318 voice->sostenutoPedalDown = false;
319 voice->sustainPedalDown = sustainPedalsDown[midiChannel];
320
321 voice->startNote (midiNoteNumber, velocity, sound,
322 lastPitchWheelValues [midiChannel - 1]);
323 }
324}
325
326void Synthesiser::stopVoice (SynthesiserVoice* voice, float velocity, const bool allowTailOff)
327{
328 wassert (voice != nullptr);
329
330 voice->stopNote (velocity, allowTailOff);
331
332 // the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()!
333 wassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == 0));
334}
335
336void Synthesiser::noteOff (const int midiChannel,
337 const int midiNoteNumber,
338 const float velocity,
339 const bool allowTailOff)
340{
341 CARLA_SAFE_ASSERT_RETURN(midiChannel > 0 && midiChannel <= 16,);
342
343 for (int i = voices.size(); --i >= 0;)
344 {
345 SynthesiserVoice* const voice = voices.getUnchecked (i);
346
347 if (voice->getCurrentlyPlayingNote() == midiNoteNumber
348 && voice->isPlayingChannel (midiChannel))
349 {
350 if (SynthesiserSound* const sound = voice->getCurrentlyPlayingSound())
351 {
352 if (sound->appliesToNote (midiNoteNumber)
353 && sound->appliesToChannel (midiChannel))
354 {
355 CARLA_SAFE_ASSERT_RETURN (! voice->keyIsDown || voice->sustainPedalDown == sustainPedalsDown [midiChannel],);
356
357 voice->keyIsDown = false;
358
359 if (! (voice->sustainPedalDown || voice->sostenutoPedalDown))
360 stopVoice (voice, velocity, allowTailOff);
361 }
362 }
363 }
364 }
365}
366
367void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff)
368{
369 for (int i = voices.size(); --i >= 0;)
370 {
371 SynthesiserVoice* const voice = voices.getUnchecked (i);
372
373 if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
374 voice->stopNote (1.0f, allowTailOff);
375 }
376
378}
379
380void Synthesiser::handlePitchWheel (const int midiChannel, const int wheelValue)
381{
382 for (int i = voices.size(); --i >= 0;)
383 {
384 SynthesiserVoice* const voice = voices.getUnchecked (i);
385
386 if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
387 voice->pitchWheelMoved (wheelValue);
388 }
389}
390
391void Synthesiser::handleController (const int midiChannel,
392 const int controllerNumber,
393 const int controllerValue)
394{
395 switch (controllerNumber)
396 {
397 case 0x40: handleSustainPedal (midiChannel, controllerValue >= 64); break;
398 case 0x42: handleSostenutoPedal (midiChannel, controllerValue >= 64); break;
399 case 0x43: handleSoftPedal (midiChannel, controllerValue >= 64); break;
400 default: break;
401 }
402
403
404 for (int i = voices.size(); --i >= 0;)
405 {
406 SynthesiserVoice* const voice = voices.getUnchecked (i);
407
408 if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
409 voice->controllerMoved (controllerNumber, controllerValue);
410 }
411}
412
413void Synthesiser::handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue)
414{
415
416 for (int i = voices.size(); --i >= 0;)
417 {
418 SynthesiserVoice* const voice = voices.getUnchecked (i);
419
420 if (voice->getCurrentlyPlayingNote() == midiNoteNumber
421 && (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)))
422 voice->aftertouchChanged (aftertouchValue);
423 }
424}
425
426void Synthesiser::handleChannelPressure (int midiChannel, int channelPressureValue)
427{
428
429 for (int i = voices.size(); --i >= 0;)
430 {
431 SynthesiserVoice* const voice = voices.getUnchecked (i);
432
433 if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
434 voice->channelPressureChanged (channelPressureValue);
435 }
436}
437
438void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
439{
440 CARLA_SAFE_ASSERT_RETURN(midiChannel > 0 && midiChannel <= 16,);
441
442 if (isDown)
443 {
444 sustainPedalsDown[midiChannel] = true;
445
446 for (int i = voices.size(); --i >= 0;)
447 {
448 SynthesiserVoice* const voice = voices.getUnchecked (i);
449
450 if (voice->isPlayingChannel (midiChannel) && voice->isKeyDown())
451 voice->sustainPedalDown = true;
452 }
453 }
454 else
455 {
456 for (int i = voices.size(); --i >= 0;)
457 {
458 SynthesiserVoice* const voice = voices.getUnchecked (i);
459
460 if (voice->isPlayingChannel (midiChannel))
461 {
462 voice->sustainPedalDown = false;
463
464 if (! voice->isKeyDown())
465 stopVoice (voice, 1.0f, true);
466 }
467 }
468
469 sustainPedalsDown[midiChannel] = false;
470 }
471}
472
473void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown)
474{
475 wassert (midiChannel > 0 && midiChannel <= 16);
476
477 for (int i = voices.size(); --i >= 0;)
478 {
479 SynthesiserVoice* const voice = voices.getUnchecked (i);
480
481 if (voice->isPlayingChannel (midiChannel))
482 {
483 if (isDown)
484 voice->sostenutoPedalDown = true;
485 else if (voice->sostenutoPedalDown)
486 stopVoice (voice, 1.0f, true);
487 }
488 }
489}
490
491void Synthesiser::handleSoftPedal (int midiChannel, bool /*isDown*/)
492{
493 ignoreUnused (midiChannel);
494 wassert (midiChannel > 0 && midiChannel <= 16);
495}
496
497void Synthesiser::handleProgramChange (int midiChannel, int programNumber)
498{
499 ignoreUnused (midiChannel, programNumber);
500 wassert (midiChannel > 0 && midiChannel <= 16);
501}
502
503//==============================================================================
505 int midiChannel, int midiNoteNumber,
506 const bool stealIfNoneAvailable) const
507{
508
509 for (size_t i = 0; i < voices.size(); ++i)
510 {
511 SynthesiserVoice* const voice = voices.getUnchecked (i);
512
513 if ((! voice->isVoiceActive()) && voice->canPlaySound (soundToPlay))
514 return voice;
515 }
516
517 if (stealIfNoneAvailable)
518 return findVoiceToSteal (soundToPlay, midiChannel, midiNoteNumber);
519
520 return nullptr;
521}
522
524{
526 {
527 return v1->wasStartedBefore (*v2) ? -1 : (v2->wasStartedBefore (*v1) ? 1 : 0);
528 }
529};
530
532 int /*midiChannel*/, int midiNoteNumber) const
533{
534 // This voice-stealing algorithm applies the following heuristics:
535 // - Re-use the oldest notes first
536 // - Protect the lowest & topmost notes, even if sustained, but not if they've been released.
537
538 // apparently you are trying to render audio without having any voices...
539 wassert (voices.size() > 0);
540
541 // These are the voices we want to protect (ie: only steal if unavoidable)
542 SynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase
543 SynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase
544
545 // this is a list of voices we can steal, sorted by how long they've been running
546 Array<SynthesiserVoice*> usableVoices;
547 usableVoices.ensureStorageAllocated (voices.size());
548
549 for (size_t i = 0; i < voices.size(); ++i)
550 {
551 SynthesiserVoice* const voice = voices.getUnchecked (i);
552
553 if (voice->canPlaySound (soundToPlay))
554 {
555 wassert (voice->isVoiceActive()); // We wouldn't be here otherwise
556
557 VoiceAgeSorter sorter;
558 usableVoices.addSorted (sorter, voice);
559
560 if (! voice->isPlayingButReleased()) // Don't protect released notes
561 {
562 const int note = voice->getCurrentlyPlayingNote();
563
564 if (low == nullptr || note < low->getCurrentlyPlayingNote())
565 low = voice;
566
567 if (top == nullptr || note > top->getCurrentlyPlayingNote())
568 top = voice;
569 }
570 }
571 }
572
573 // Eliminate pathological cases (ie: only 1 note playing): we always give precedence to the lowest note(s)
574 if (top == low)
575 top = nullptr;
576
577 const int numUsableVoices = usableVoices.size();
578
579 // The oldest note that's playing with the target pitch is ideal..
580 for (int i = 0; i < numUsableVoices; ++i)
581 {
582 SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
583
584 if (voice->getCurrentlyPlayingNote() == midiNoteNumber)
585 return voice;
586 }
587
588 // Oldest voice that has been released (no finger on it and not held by sustain pedal)
589 for (int i = 0; i < numUsableVoices; ++i)
590 {
591 SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
592
593 if (voice != low && voice != top && voice->isPlayingButReleased())
594 return voice;
595 }
596
597 // Oldest voice that doesn't have a finger on it:
598 for (int i = 0; i < numUsableVoices; ++i)
599 {
600 SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
601
602 if (voice != low && voice != top && ! voice->isKeyDown())
603 return voice;
604 }
605
606 // Oldest voice that isn't protected
607 for (int i = 0; i < numUsableVoices; ++i)
608 {
609 SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
610
611 if (voice != low && voice != top)
612 return voice;
613 }
614
615 // We've only got "protected" voices now: lowest note takes priority
616 wassert (low != nullptr);
617
618 // Duophonic synth: give priority to the bass note:
619 if (top != nullptr)
620 return top;
621
622 return low;
623}
624
625}
#define CARLA_SAFE_ASSERT_RETURN(cond, ret)
Definition CarlaDefines.h:190
Definition Array.h:57
bool ensureStorageAllocated(const int minNumElements) noexcept
Definition Array.h:1004
int size() const noexcept
Definition Array.h:187
ElementType getUnchecked(const int index) const
Definition Array.h:228
int addSorted(ElementComparator &comparator, ParameterType newElement)
Definition Array.h:655
Definition AudioSampleBuffer.h:42
uint32_t getNumChannels() const noexcept
Definition AudioSampleBuffer.h:212
Definition MidiBuffer.h:176
void setNextSamplePosition(int samplePosition) noexcept
Definition MidiBuffer.cpp:203
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
Definition MidiBuffer.cpp:226
Definition MidiBuffer.h:48
Definition MidiMessage.h:40
double sampleRate
Definition Synthesiser.h:610
bool sustainPedalsDown[17]
Definition Synthesiser.h:615
virtual void handleSoftPedal(int midiChannel, bool isDown)
Definition Synthesiser.cpp:491
virtual void handleSostenutoPedal(int midiChannel, bool isDown)
Definition Synthesiser.cpp:473
int lastPitchWheelValues[16]
Definition Synthesiser.h:562
virtual void renderVoices(AudioSampleBuffer &outputAudio, int startSample, int numSamples)
Definition Synthesiser.cpp:224
virtual void allNotesOff(int midiChannel, bool allowTailOff)
Definition Synthesiser.cpp:367
virtual ~Synthesiser()
Definition Synthesiser.cpp:99
virtual SynthesiserVoice * findVoiceToSteal(SynthesiserSound *soundToPlay, int midiChannel, int midiNoteNumber) const
Definition Synthesiser.cpp:531
void removeSound(int index)
Definition Synthesiser.cpp:135
virtual void handleSustainPedal(int midiChannel, bool isDown)
Definition Synthesiser.cpp:438
int minimumSubBlockSize
Definition Synthesiser.h:612
void setMinimumRenderingSubdivisionSize(int numSamples, bool shouldBeStrict=false) noexcept
Definition Synthesiser.cpp:145
Synthesiser()
Definition Synthesiser.cpp:86
void removeVoice(int index)
Definition Synthesiser.cpp:120
void clearVoices()
Definition Synthesiser.cpp:109
virtual void handleChannelPressure(int midiChannel, int channelPressureValue)
Definition Synthesiser.cpp:426
virtual void handlePitchWheel(int midiChannel, int wheelValue)
Definition Synthesiser.cpp:380
void stopVoice(SynthesiserVoice *, float velocity, bool allowTailOff)
Definition Synthesiser.cpp:326
void processNextBlock(AudioSampleBuffer &outputAudio, const MidiBuffer &inputMidi, int startSample, int numSamples)
Definition Synthesiser.cpp:166
void setNoteStealingEnabled(bool shouldStealNotes)
Definition Synthesiser.cpp:140
uint32 lastNoteOnCounter
Definition Synthesiser.h:611
virtual void setCurrentPlaybackSampleRate(double sampleRate)
Definition Synthesiser.cpp:153
virtual void handleMidiEvent(const MidiMessage &)
Definition Synthesiser.cpp:230
bool shouldStealNotes
Definition Synthesiser.h:614
SynthesiserVoice * getVoice(int index) const
Definition Synthesiser.cpp:104
bool subBlockSubdivisionIsStrict
Definition Synthesiser.h:613
virtual void handleController(int midiChannel, int controllerNumber, int controllerValue)
Definition Synthesiser.cpp:391
virtual SynthesiserVoice * findFreeVoice(SynthesiserSound *soundToPlay, int midiChannel, int midiNoteNumber, bool stealIfNoneAvailable) const
Definition Synthesiser.cpp:504
virtual void noteOn(int midiChannel, int midiNoteNumber, float velocity)
Definition Synthesiser.cpp:271
void startVoice(SynthesiserVoice *voice, SynthesiserSound *sound, int midiChannel, int midiNoteNumber, float velocity)
Definition Synthesiser.cpp:300
virtual void handleProgramChange(int midiChannel, int programNumber)
Definition Synthesiser.cpp:497
void clearSounds()
Definition Synthesiser.cpp:125
SynthesiserSound * addSound(const SynthesiserSound::Ptr &newSound)
Definition Synthesiser.cpp:130
virtual void noteOff(int midiChannel, int midiNoteNumber, float velocity, bool allowTailOff)
Definition Synthesiser.cpp:336
OwnedArray< SynthesiserVoice > voices
Definition Synthesiser.h:558
SynthesiserVoice * addVoice(SynthesiserVoice *newVoice)
Definition Synthesiser.cpp:114
ReferenceCountedArray< SynthesiserSound > sounds
Definition Synthesiser.h:559
virtual void handleAftertouch(int midiChannel, int midiNoteNumber, int aftertouchValue)
Definition Synthesiser.cpp:413
Definition Synthesiser.h:52
virtual ~SynthesiserSound()
Definition Synthesiser.cpp:36
virtual bool appliesToChannel(int midiChannel)=0
virtual bool appliesToNote(int midiNoteNumber)=0
SynthesiserSound()
Definition Synthesiser.cpp:35
ReferenceCountedObjectPtr< SynthesiserSound > Ptr
Definition Synthesiser.h:77
Definition Synthesiser.h:96
bool keyIsDown
Definition Synthesiser.h:265
SynthesiserSound::Ptr currentlyPlayingSound
Definition Synthesiser.h:264
bool isKeyDown() const noexcept
Definition Synthesiser.h:224
virtual void aftertouchChanged(int newAftertouchValue)
Definition Synthesiser.cpp:76
bool sustainPedalDown
Definition Synthesiser.h:265
int currentlyPlayingNote
Definition Synthesiser.h:262
int currentPlayingMidiChannel
Definition Synthesiser.h:262
virtual ~SynthesiserVoice()
Definition Synthesiser.cpp:50
virtual void channelPressureChanged(int newChannelPressureValue)
Definition Synthesiser.cpp:77
void clearCurrentNote()
Definition Synthesiser.cpp:69
virtual void stopNote(float velocity, bool allowTailOff)=0
SynthesiserSound::Ptr getCurrentlyPlayingSound() const noexcept
Definition Synthesiser.h:114
virtual void controllerMoved(int controllerNumber, int newControllerValue)=0
bool isPlayingButReleased() const noexcept
Definition Synthesiser.h:233
double currentSampleRate
Definition Synthesiser.h:261
int getCurrentlyPlayingNote() const noexcept
Definition Synthesiser.h:109
virtual void setCurrentPlaybackSampleRate(double newRate)
Definition Synthesiser.cpp:59
bool wasStartedBefore(const SynthesiserVoice &other) const noexcept
Definition Synthesiser.cpp:79
SynthesiserVoice()
Definition Synthesiser.cpp:39
virtual bool isPlayingChannel(int midiChannel) const
Definition Synthesiser.cpp:54
virtual void startNote(int midiNoteNumber, float velocity, SynthesiserSound *sound, int currentPitchWheelPosition)=0
virtual void pitchWheelMoved(int newPitchWheelValue)=0
virtual bool canPlaySound(SynthesiserSound *)=0
uint32 noteOnTime
Definition Synthesiser.h:263
bool sostenutoPedalDown
Definition Synthesiser.h:265
virtual bool isVoiceActive() const
Definition Synthesiser.cpp:64
unsigned * m
Definition inflate.c:1559
register unsigned j
Definition inflate.c:1576
register unsigned i
Definition inflate.c:1575
static void v2(register WDL_FFT_REAL *a)
Definition fft.c:1099
#define wassert(expression)
Definition AudioSampleBuffer.h:33
void ignoreUnused(const Type1 &) noexcept
Definition MathsFunctions.h:237
void zerostruct(Type &structure) noexcept
Definition Memory.h:41
size_t numElementsInArray(Type(&array)[N])
Definition MathsFunctions.h:257
#define true
Definition ordinals.h:82
#define false
Definition ordinals.h:83
Definition Synthesiser.cpp:524
static int compareElements(SynthesiserVoice *v1, SynthesiserVoice *v2) noexcept
Definition Synthesiser.cpp:525