LMMS
Loading...
Searching...
No Matches
juce_Synthesiser.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
28
29//==============================================================================
32
33bool SynthesiserVoice::isPlayingChannel (const int midiChannel) const
34{
35 return currentPlayingMidiChannel == midiChannel;
36}
37
39{
40 currentSampleRate = newRate;
41}
42
44{
45 return getCurrentlyPlayingNote() >= 0;
46}
47
54
57
58bool SynthesiserVoice::wasStartedBefore (const SynthesiserVoice& other) const noexcept
59{
60 return noteOnTime < other.noteOnTime;
61}
62
64 int startSample, int numSamples)
65{
66 AudioBuffer<double> subBuffer (outputBuffer.getArrayOfWritePointers(),
67 outputBuffer.getNumChannels(),
68 startSample, numSamples);
69
70 tempBuffer.makeCopyOf (subBuffer, true);
71 renderNextBlock (tempBuffer, 0, numSamples);
72 subBuffer.makeCopyOf (tempBuffer, true);
73}
74
75//==============================================================================
81
85
86//==============================================================================
88{
89 const ScopedLock sl (lock);
90 return voices [index];
91}
92
94{
95 const ScopedLock sl (lock);
96 voices.clear();
97}
98
100{
101 const ScopedLock sl (lock);
103 return voices.add (newVoice);
104}
105
106void Synthesiser::removeVoice (const int index)
107{
108 const ScopedLock sl (lock);
109 voices.remove (index);
110}
111
113{
114 const ScopedLock sl (lock);
115 sounds.clear();
116}
117
119{
120 const ScopedLock sl (lock);
121 return sounds.add (newSound);
122}
123
124void Synthesiser::removeSound (const int index)
125{
126 const ScopedLock sl (lock);
127 sounds.remove (index);
128}
129
130void Synthesiser::setNoteStealingEnabled (const bool shouldSteal)
131{
132 shouldStealNotes = shouldSteal;
133}
134
135void Synthesiser::setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict) noexcept
136{
137 jassert (numSamples > 0); // it wouldn't make much sense for this to be less than 1
138 minimumSubBlockSize = numSamples;
139 subBlockSubdivisionIsStrict = shouldBeStrict;
140}
141
142//==============================================================================
144{
145 if (sampleRate != newRate)
146 {
147 const ScopedLock sl (lock);
148 allNotesOff (0, false);
149 sampleRate = newRate;
150
151 for (auto* voice : voices)
152 voice->setCurrentPlaybackSampleRate (newRate);
153 }
154}
155
156template <typename floatType>
158 const MidiBuffer& midiData,
159 int startSample,
160 int numSamples)
161{
162 // must set the sample rate before using this!
163 jassert (sampleRate != 0);
164 const int targetChannels = outputAudio.getNumChannels();
165
166 auto midiIterator = midiData.findNextSamplePosition (startSample);
167
168 bool firstEvent = true;
169
170 const ScopedLock sl (lock);
171
172 for (; numSamples > 0; ++midiIterator)
173 {
174 if (midiIterator == midiData.cend())
175 {
176 if (targetChannels > 0)
177 renderVoices (outputAudio, startSample, numSamples);
178
179 return;
180 }
181
182 const auto metadata = *midiIterator;
183 const int samplesToNextMidiMessage = metadata.samplePosition - startSample;
184
185 if (samplesToNextMidiMessage >= numSamples)
186 {
187 if (targetChannels > 0)
188 renderVoices (outputAudio, startSample, numSamples);
189
190 handleMidiEvent (metadata.getMessage());
191 break;
192 }
193
194 if (samplesToNextMidiMessage < ((firstEvent && ! subBlockSubdivisionIsStrict) ? 1 : minimumSubBlockSize))
195 {
196 handleMidiEvent (metadata.getMessage());
197 continue;
198 }
199
200 firstEvent = false;
201
202 if (targetChannels > 0)
203 renderVoices (outputAudio, startSample, samplesToNextMidiMessage);
204
205 handleMidiEvent (metadata.getMessage());
206 startSample += samplesToNextMidiMessage;
207 numSamples -= samplesToNextMidiMessage;
208 }
209
210 std::for_each (midiIterator,
211 midiData.cend(),
212 [&] (const MidiMessageMetadata& meta) { handleMidiEvent (meta.getMessage()); });
213}
214
215// explicit template instantiation
216template void Synthesiser::processNextBlock<float> (AudioBuffer<float>&, const MidiBuffer&, int, int);
217template void Synthesiser::processNextBlock<double> (AudioBuffer<double>&, const MidiBuffer&, int, int);
218
219void Synthesiser::renderNextBlock (AudioBuffer<float>& outputAudio, const MidiBuffer& inputMidi,
220 int startSample, int numSamples)
221{
222 processNextBlock (outputAudio, inputMidi, startSample, numSamples);
223}
224
226 int startSample, int numSamples)
227{
228 processNextBlock (outputAudio, inputMidi, startSample, numSamples);
229}
230
231void Synthesiser::renderVoices (AudioBuffer<float>& buffer, int startSample, int numSamples)
232{
233 for (auto* voice : voices)
234 voice->renderNextBlock (buffer, startSample, numSamples);
235}
236
237void Synthesiser::renderVoices (AudioBuffer<double>& buffer, int startSample, int numSamples)
238{
239 for (auto* voice : voices)
240 voice->renderNextBlock (buffer, startSample, numSamples);
241}
242
244{
245 const int channel = m.getChannel();
246
247 if (m.isNoteOn())
248 {
249 noteOn (channel, m.getNoteNumber(), m.getFloatVelocity());
250 }
251 else if (m.isNoteOff())
252 {
253 noteOff (channel, m.getNoteNumber(), m.getFloatVelocity(), true);
254 }
255 else if (m.isAllNotesOff() || m.isAllSoundOff())
256 {
257 allNotesOff (channel, true);
258 }
259 else if (m.isPitchWheel())
260 {
261 const int wheelPos = m.getPitchWheelValue();
262 lastPitchWheelValues [channel - 1] = wheelPos;
263 handlePitchWheel (channel, wheelPos);
264 }
265 else if (m.isAftertouch())
266 {
267 handleAftertouch (channel, m.getNoteNumber(), m.getAfterTouchValue());
268 }
269 else if (m.isChannelPressure())
270 {
271 handleChannelPressure (channel, m.getChannelPressureValue());
272 }
273 else if (m.isController())
274 {
275 handleController (channel, m.getControllerNumber(), m.getControllerValue());
276 }
277 else if (m.isProgramChange())
278 {
279 handleProgramChange (channel, m.getProgramChangeNumber());
280 }
281}
282
283//==============================================================================
284void Synthesiser::noteOn (const int midiChannel,
285 const int midiNoteNumber,
286 const float velocity)
287{
288 const ScopedLock sl (lock);
289
290 for (auto* sound : sounds)
291 {
292 if (sound->appliesToNote (midiNoteNumber) && sound->appliesToChannel (midiChannel))
293 {
294 // If hitting a note that's still ringing, stop it first (it could be
295 // still playing because of the sustain or sostenuto pedal).
296 for (auto* voice : voices)
297 if (voice->getCurrentlyPlayingNote() == midiNoteNumber && voice->isPlayingChannel (midiChannel))
298 stopVoice (voice, 1.0f, true);
299
300 startVoice (findFreeVoice (sound, midiChannel, midiNoteNumber, shouldStealNotes),
301 sound, midiChannel, midiNoteNumber, velocity);
302 }
303 }
304}
305
307 SynthesiserSound* const sound,
308 const int midiChannel,
309 const int midiNoteNumber,
310 const float velocity)
311{
312 if (voice != nullptr && sound != nullptr)
313 {
314 if (voice->currentlyPlayingSound != nullptr)
315 voice->stopNote (0.0f, false);
316
317 voice->currentlyPlayingNote = midiNoteNumber;
318 voice->currentPlayingMidiChannel = midiChannel;
319 voice->noteOnTime = ++lastNoteOnCounter;
320 voice->currentlyPlayingSound = sound;
321 voice->setKeyDown (true);
322 voice->setSostenutoPedalDown (false);
323 voice->setSustainPedalDown (sustainPedalsDown[midiChannel]);
324
325 voice->startNote (midiNoteNumber, velocity, sound,
326 lastPitchWheelValues [midiChannel - 1]);
327 }
328}
329
330void Synthesiser::stopVoice (SynthesiserVoice* voice, float velocity, const bool allowTailOff)
331{
332 jassert (voice != nullptr);
333
334 voice->stopNote (velocity, allowTailOff);
335
336 // the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()!
337 jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == nullptr));
338}
339
340void Synthesiser::noteOff (const int midiChannel,
341 const int midiNoteNumber,
342 const float velocity,
343 const bool allowTailOff)
344{
345 const ScopedLock sl (lock);
346
347 for (auto* voice : voices)
348 {
349 if (voice->getCurrentlyPlayingNote() == midiNoteNumber
350 && voice->isPlayingChannel (midiChannel))
351 {
352 if (auto sound = voice->getCurrentlyPlayingSound())
353 {
354 if (sound->appliesToNote (midiNoteNumber)
355 && sound->appliesToChannel (midiChannel))
356 {
357 jassert (! voice->keyIsDown || voice->isSustainPedalDown() == sustainPedalsDown [midiChannel]);
358
359 voice->setKeyDown (false);
360
361 if (! (voice->isSustainPedalDown() || voice->isSostenutoPedalDown()))
362 stopVoice (voice, velocity, allowTailOff);
363 }
364 }
365 }
366 }
367}
368
369void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff)
370{
371 const ScopedLock sl (lock);
372
373 for (auto* voice : voices)
374 if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
375 voice->stopNote (1.0f, allowTailOff);
376
377 sustainPedalsDown.clear();
378}
379
380void Synthesiser::handlePitchWheel (const int midiChannel, const int wheelValue)
381{
382 const ScopedLock sl (lock);
383
384 for (auto* voice : voices)
385 if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
386 voice->pitchWheelMoved (wheelValue);
387}
388
389void Synthesiser::handleController (const int midiChannel,
390 const int controllerNumber,
391 const int controllerValue)
392{
393 switch (controllerNumber)
394 {
395 case 0x40: handleSustainPedal (midiChannel, controllerValue >= 64); break;
396 case 0x42: handleSostenutoPedal (midiChannel, controllerValue >= 64); break;
397 case 0x43: handleSoftPedal (midiChannel, controllerValue >= 64); break;
398 default: break;
399 }
400
401 const ScopedLock sl (lock);
402
403 for (auto* voice : voices)
404 if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
405 voice->controllerMoved (controllerNumber, controllerValue);
406}
407
408void Synthesiser::handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue)
409{
410 const ScopedLock sl (lock);
411
412 for (auto* voice : voices)
413 if (voice->getCurrentlyPlayingNote() == midiNoteNumber
414 && (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)))
415 voice->aftertouchChanged (aftertouchValue);
416}
417
418void Synthesiser::handleChannelPressure (int midiChannel, int channelPressureValue)
419{
420 const ScopedLock sl (lock);
421
422 for (auto* voice : voices)
423 if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
424 voice->channelPressureChanged (channelPressureValue);
425}
426
427void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
428{
429 jassert (midiChannel > 0 && midiChannel <= 16);
430 const ScopedLock sl (lock);
431
432 if (isDown)
433 {
434 sustainPedalsDown.setBit (midiChannel);
435
436 for (auto* voice : voices)
437 if (voice->isPlayingChannel (midiChannel) && voice->isKeyDown())
438 voice->setSustainPedalDown (true);
439 }
440 else
441 {
442 for (auto* voice : voices)
443 {
444 if (voice->isPlayingChannel (midiChannel))
445 {
446 voice->setSustainPedalDown (false);
447
448 if (! (voice->isKeyDown() || voice->isSostenutoPedalDown()))
449 stopVoice (voice, 1.0f, true);
450 }
451 }
452
453 sustainPedalsDown.clearBit (midiChannel);
454 }
455}
456
457void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown)
458{
459 jassert (midiChannel > 0 && midiChannel <= 16);
460 const ScopedLock sl (lock);
461
462 for (auto* voice : voices)
463 {
464 if (voice->isPlayingChannel (midiChannel))
465 {
466 if (isDown)
467 voice->setSostenutoPedalDown (true);
468 else if (voice->isSostenutoPedalDown())
469 stopVoice (voice, 1.0f, true);
470 }
471 }
472}
473
474void Synthesiser::handleSoftPedal (int midiChannel, bool /*isDown*/)
475{
476 ignoreUnused (midiChannel);
477 jassert (midiChannel > 0 && midiChannel <= 16);
478}
479
480void Synthesiser::handleProgramChange (int midiChannel, int programNumber)
481{
482 ignoreUnused (midiChannel, programNumber);
483 jassert (midiChannel > 0 && midiChannel <= 16);
484}
485
486//==============================================================================
488 int midiChannel, int midiNoteNumber,
489 const bool stealIfNoneAvailable) const
490{
491 const ScopedLock sl (lock);
492
493 for (auto* voice : voices)
494 if ((! voice->isVoiceActive()) && voice->canPlaySound (soundToPlay))
495 return voice;
496
497 if (stealIfNoneAvailable)
498 return findVoiceToSteal (soundToPlay, midiChannel, midiNoteNumber);
499
500 return nullptr;
501}
502
504 int /*midiChannel*/, int midiNoteNumber) const
505{
506 // This voice-stealing algorithm applies the following heuristics:
507 // - Re-use the oldest notes first
508 // - Protect the lowest & topmost notes, even if sustained, but not if they've been released.
509
510 // apparently you are trying to render audio without having any voices...
511 jassert (! voices.isEmpty());
512
513 // These are the voices we want to protect (ie: only steal if unavoidable)
514 SynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase
515 SynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase
516
517 // this is a list of voices we can steal, sorted by how long they've been running
518 Array<SynthesiserVoice*> usableVoices;
519 usableVoices.ensureStorageAllocated (voices.size());
520
521 for (auto* voice : voices)
522 {
523 if (voice->canPlaySound (soundToPlay))
524 {
525 jassert (voice->isVoiceActive()); // We wouldn't be here otherwise
526
527 usableVoices.add (voice);
528
529 // NB: Using a functor rather than a lambda here due to scare-stories about
530 // compilers generating code containing heap allocations..
531 struct Sorter
532 {
533 bool operator() (const SynthesiserVoice* a, const SynthesiserVoice* b) const noexcept { return a->wasStartedBefore (*b); }
534 };
535
536 std::sort (usableVoices.begin(), usableVoices.end(), Sorter());
537
538 if (! voice->isPlayingButReleased()) // Don't protect released notes
539 {
540 auto note = voice->getCurrentlyPlayingNote();
541
542 if (low == nullptr || note < low->getCurrentlyPlayingNote())
543 low = voice;
544
545 if (top == nullptr || note > top->getCurrentlyPlayingNote())
546 top = voice;
547 }
548 }
549 }
550
551 // Eliminate pathological cases (ie: only 1 note playing): we always give precedence to the lowest note(s)
552 if (top == low)
553 top = nullptr;
554
555 // The oldest note that's playing with the target pitch is ideal..
556 for (auto* voice : usableVoices)
557 if (voice->getCurrentlyPlayingNote() == midiNoteNumber)
558 return voice;
559
560 // Oldest voice that has been released (no finger on it and not held by sustain pedal)
561 for (auto* voice : usableVoices)
562 if (voice != low && voice != top && voice->isPlayingButReleased())
563 return voice;
564
565 // Oldest voice that doesn't have a finger on it:
566 for (auto* voice : usableVoices)
567 if (voice != low && voice != top && ! voice->isKeyDown())
568 return voice;
569
570 // Oldest voice that isn't protected
571 for (auto* voice : usableVoices)
572 if (voice != low && voice != top)
573 return voice;
574
575 // We've only got "protected" voices now: lowest note takes priority
576 jassert (low != nullptr);
577
578 // Duophonic synth: give priority to the bass note:
579 if (top != nullptr)
580 return top;
581
582 return low;
583}
584
585} // namespace juce
uint8_t a
Definition Spc_Cpu.h:141
Definition juce_Array.h:56
void ensureStorageAllocated(int minNumElements)
Definition juce_Array.h:1065
ElementType * begin() noexcept
Definition juce_Array.h:328
ElementType * end() noexcept
Definition juce_Array.h:344
void add(const ElementType &newElement)
Definition juce_Array.h:418
Definition juce_AudioSampleBuffer.h:34
void makeCopyOf(const AudioBuffer< OtherType > &other, bool avoidReallocating=false)
Definition juce_AudioSampleBuffer.h:525
int getNumChannels() const noexcept
Definition juce_AudioSampleBuffer.h:236
Type ** getArrayOfWritePointers() noexcept
Definition juce_AudioSampleBuffer.h:342
Definition juce_MidiBuffer.h:145
MidiBufferIterator findNextSamplePosition(int samplePosition) const noexcept
Definition juce_MidiBuffer.cpp:203
MidiBufferIterator cend() const noexcept
Definition juce_MidiBuffer.h:268
Definition juce_MidiMessage.h:35
Synthesiser()
Definition juce_Synthesiser.cpp:76
virtual ~Synthesiser()
Definition juce_Synthesiser.cpp:82
virtual SynthesiserVoice * findFreeVoice(SynthesiserSound *soundToPlay, int midiChannel, int midiNoteNumber, bool stealIfNoneAvailable) const
Definition juce_Synthesiser.cpp:487
virtual void handleProgramChange(int midiChannel, int programNumber)
Definition juce_Synthesiser.cpp:480
BigInteger sustainPedalsDown
Definition juce_Synthesiser.h:629
void removeVoice(int index)
Definition juce_Synthesiser.cpp:106
void processNextBlock(AudioBuffer< floatType > &, const MidiBuffer &, int startSample, int numSamples)
Definition juce_Synthesiser.cpp:157
double sampleRate
Definition juce_Synthesiser.h:624
int minimumSubBlockSize
Definition juce_Synthesiser.h:626
void startVoice(SynthesiserVoice *voice, SynthesiserSound *sound, int midiChannel, int midiNoteNumber, float velocity)
Definition juce_Synthesiser.cpp:306
virtual void handleAftertouch(int midiChannel, int midiNoteNumber, int aftertouchValue)
Definition juce_Synthesiser.cpp:408
void renderNextBlock(AudioBuffer< float > &outputAudio, const MidiBuffer &inputMidi, int startSample, int numSamples)
Definition juce_Synthesiser.cpp:219
virtual void handleController(int midiChannel, int controllerNumber, int controllerValue)
Definition juce_Synthesiser.cpp:389
void clearSounds()
Definition juce_Synthesiser.cpp:112
virtual SynthesiserVoice * findVoiceToSteal(SynthesiserSound *soundToPlay, int midiChannel, int midiNoteNumber) const
Definition juce_Synthesiser.cpp:503
virtual void handleSoftPedal(int midiChannel, bool isDown)
Definition juce_Synthesiser.cpp:474
void removeSound(int index)
Definition juce_Synthesiser.cpp:124
virtual void allNotesOff(int midiChannel, bool allowTailOff)
Definition juce_Synthesiser.cpp:369
SynthesiserVoice * addVoice(SynthesiserVoice *newVoice)
Definition juce_Synthesiser.cpp:99
void stopVoice(SynthesiserVoice *, float velocity, bool allowTailOff)
Definition juce_Synthesiser.cpp:330
bool shouldStealNotes
Definition juce_Synthesiser.h:628
SynthesiserSound * addSound(const SynthesiserSound::Ptr &newSound)
Definition juce_Synthesiser.cpp:118
virtual void renderVoices(AudioBuffer< float > &outputAudio, int startSample, int numSamples)
Definition juce_Synthesiser.cpp:231
virtual void handleMidiEvent(const MidiMessage &)
Definition juce_Synthesiser.cpp:243
OwnedArray< SynthesiserVoice > voices
Definition juce_Synthesiser.h:565
uint32 lastNoteOnCounter
Definition juce_Synthesiser.h:625
void setNoteStealingEnabled(bool shouldStealNotes)
Definition juce_Synthesiser.cpp:130
virtual void handlePitchWheel(int midiChannel, int wheelValue)
Definition juce_Synthesiser.cpp:380
CriticalSection lock
Definition juce_Synthesiser.h:563
int lastPitchWheelValues[16]
Definition juce_Synthesiser.h:569
virtual void noteOn(int midiChannel, int midiNoteNumber, float velocity)
Definition juce_Synthesiser.cpp:284
SynthesiserVoice * getVoice(int index) const
Definition juce_Synthesiser.cpp:87
ReferenceCountedArray< SynthesiserSound > sounds
Definition juce_Synthesiser.h:566
virtual void noteOff(int midiChannel, int midiNoteNumber, float velocity, bool allowTailOff)
Definition juce_Synthesiser.cpp:340
virtual void handleChannelPressure(int midiChannel, int channelPressureValue)
Definition juce_Synthesiser.cpp:418
void clearVoices()
Definition juce_Synthesiser.cpp:93
virtual void setCurrentPlaybackSampleRate(double sampleRate)
Definition juce_Synthesiser.cpp:143
void setMinimumRenderingSubdivisionSize(int numSamples, bool shouldBeStrict=false) noexcept
Definition juce_Synthesiser.cpp:135
bool subBlockSubdivisionIsStrict
Definition juce_Synthesiser.h:627
virtual void handleSustainPedal(int midiChannel, bool isDown)
Definition juce_Synthesiser.cpp:427
virtual void handleSostenutoPedal(int midiChannel, bool isDown)
Definition juce_Synthesiser.cpp:457
Definition juce_Synthesiser.h:42
~SynthesiserSound() override
Definition juce_Synthesiser.cpp:27
SynthesiserSound()
Definition juce_Synthesiser.cpp:26
ReferenceCountedObjectPtr< SynthesiserSound > Ptr
Definition juce_Synthesiser.h:67
Definition juce_Synthesiser.h:88
virtual void stopNote(float velocity, bool allowTailOff)=0
AudioBuffer< float > tempBuffer
Definition juce_Synthesiser.h:275
void setSustainPedalDown(bool isNowDown) noexcept
Definition juce_Synthesiser.h:232
int currentlyPlayingNote
Definition juce_Synthesiser.h:270
uint32 noteOnTime
Definition juce_Synthesiser.h:271
SynthesiserVoice()
Definition juce_Synthesiser.cpp:30
virtual void channelPressureChanged(int newChannelPressureValue)
Definition juce_Synthesiser.cpp:56
void setSostenutoPedalDown(bool isNowDown) noexcept
Definition juce_Synthesiser.h:238
virtual void renderNextBlock(AudioBuffer< float > &outputBuffer, int startSample, int numSamples)=0
virtual bool isPlayingChannel(int midiChannel) const
Definition juce_Synthesiser.cpp:33
double currentSampleRate
Definition juce_Synthesiser.h:269
SynthesiserSound::Ptr currentlyPlayingSound
Definition juce_Synthesiser.h:272
bool isKeyDown() const noexcept
Definition juce_Synthesiser.h:221
void setKeyDown(bool isNowDown) noexcept
Definition juce_Synthesiser.h:226
virtual void setCurrentPlaybackSampleRate(double newRate)
Definition juce_Synthesiser.cpp:38
virtual void aftertouchChanged(int newAftertouchValue)
Definition juce_Synthesiser.cpp:55
int getCurrentlyPlayingNote() const noexcept
Definition juce_Synthesiser.h:101
virtual void startNote(int midiNoteNumber, float velocity, SynthesiserSound *sound, int currentPitchWheelPosition)=0
void clearCurrentNote()
Definition juce_Synthesiser.cpp:48
bool wasStartedBefore(const SynthesiserVoice &other) const noexcept
Definition juce_Synthesiser.cpp:58
int currentPlayingMidiChannel
Definition juce_Synthesiser.h:270
virtual ~SynthesiserVoice()
Definition juce_Synthesiser.cpp:31
bool isPlayingButReleased() const noexcept
Definition juce_Synthesiser.h:241
SynthesiserSound::Ptr getCurrentlyPlayingSound() const noexcept
Definition juce_Synthesiser.h:106
virtual bool isVoiceActive() const
Definition juce_Synthesiser.cpp:43
unsigned * m
Definition inflate.c:1559
register unsigned i
Definition inflate.c:1575
#define jassert(expression)
Definition carla_juce.cpp:31
CriticalSection::ScopedLockType ScopedLock
Definition juce_CriticalSection.h:186
void ignoreUnused(Types &&...) noexcept
Definition juce_MathsFunctions.h:333
constexpr int numElementsInArray(Type(&)[N]) noexcept
Definition juce_MathsFunctions.h:344
b
Definition crypt.c:628