OpenShot Audio Library | OpenShotAudio 0.4.0

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