OpenShot Audio Library | OpenShotAudio: juce_Synthesiser.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.3.0

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