2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
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.
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
20 ==============================================================================
26 //==============================================================================
28 Describes one of the sounds that a Synthesiser can play.
30 A synthesiser can contain one or more sounds, and a sound can choose which
31 midi notes and channels can trigger it.
33 The SynthesiserSound is a passive class that just describes what the sound is -
34 the actual audio rendering for a sound is done by a SynthesiserVoice. This allows
35 more than one SynthesiserVoice to play the same sound at the same time.
37 @see Synthesiser, SynthesiserVoice
41 class JUCE_API SynthesiserSound
: public ReferenceCountedObject
44 //==============================================================================
49 ~SynthesiserSound() override
;
51 //==============================================================================
52 /** Returns true if this sound should be played when a given midi note is pressed.
54 The Synthesiser will use this information when deciding which sounds to trigger
57 virtual bool appliesToNote (int midiNoteNumber
) = 0;
59 /** Returns true if the sound should be triggered by midi events on a given channel.
61 The Synthesiser will use this information when deciding which sounds to trigger
64 virtual bool appliesToChannel (int midiChannel
) = 0;
66 /** The class is reference-counted, so this is a handy pointer class for it. */
67 using Ptr
= ReferenceCountedObjectPtr
<SynthesiserSound
>;
71 //==============================================================================
72 JUCE_LEAK_DETECTOR (SynthesiserSound
)
76 //==============================================================================
78 Represents a voice that a Synthesiser can use to play a SynthesiserSound.
80 A voice plays a single sound at a time, and a synthesiser holds an array of
81 voices so that it can play polyphonically.
83 @see Synthesiser, SynthesiserSound
87 class JUCE_API SynthesiserVoice
90 //==============================================================================
91 /** Creates a voice. */
95 virtual ~SynthesiserVoice();
97 //==============================================================================
98 /** Returns the midi note that this voice is currently playing.
99 Returns a value less than 0 if no note is playing.
101 int getCurrentlyPlayingNote() const noexcept
{ return currentlyPlayingNote
; }
103 /** Returns the sound that this voice is currently playing.
104 Returns nullptr if it's not playing.
106 SynthesiserSound::Ptr
getCurrentlyPlayingSound() const noexcept
{ return currentlyPlayingSound
; }
108 /** Must return true if this voice object is capable of playing the given sound.
110 If there are different classes of sound, and different classes of voice, a voice can
111 choose which ones it wants to take on.
113 A typical implementation of this method may just return true if there's only one type
114 of voice and sound, or it might check the type of the sound object passed-in and
115 see if it's one that it understands.
117 virtual bool canPlaySound (SynthesiserSound
*) = 0;
119 /** Called to start a new note.
120 This will be called during the rendering callback, so must be fast and thread-safe.
122 virtual void startNote (int midiNoteNumber
,
124 SynthesiserSound
* sound
,
125 int currentPitchWheelPosition
) = 0;
127 /** Called to stop a note.
129 This will be called during the rendering callback, so must be fast and thread-safe.
131 The velocity indicates how quickly the note was released - 0 is slowly, 1 is quickly.
133 If allowTailOff is false or the voice doesn't want to tail-off, then it must stop all
134 sound immediately, and must call clearCurrentNote() to reset the state of this voice
135 and allow the synth to reassign it another sound.
137 If allowTailOff is true and the voice decides to do a tail-off, then it's allowed to
138 begin fading out its sound, and it can stop playing until it's finished. As soon as it
139 finishes playing (during the rendering callback), it must make sure that it calls
142 virtual void stopNote (float velocity
, bool allowTailOff
) = 0;
144 /** Returns true if this voice is currently busy playing a sound.
145 By default this just checks the getCurrentlyPlayingNote() value, but can
146 be overridden for more advanced checking.
148 virtual bool isVoiceActive() const;
150 /** Called to let the voice know that the pitch wheel has been moved.
151 This will be called during the rendering callback, so must be fast and thread-safe.
153 virtual void pitchWheelMoved (int newPitchWheelValue
) = 0;
155 /** Called to let the voice know that a midi controller has been moved.
156 This will be called during the rendering callback, so must be fast and thread-safe.
158 virtual void controllerMoved (int controllerNumber
, int newControllerValue
) = 0;
160 /** Called to let the voice know that the aftertouch has changed.
161 This will be called during the rendering callback, so must be fast and thread-safe.
163 virtual void aftertouchChanged (int newAftertouchValue
);
165 /** Called to let the voice know that the channel pressure has changed.
166 This will be called during the rendering callback, so must be fast and thread-safe.
168 virtual void channelPressureChanged (int newChannelPressureValue
);
170 //==============================================================================
171 /** Renders the next block of data for this voice.
173 The output audio data must be added to the current contents of the buffer provided.
174 Only the region of the buffer between startSample and (startSample + numSamples)
175 should be altered by this method.
177 If the voice is currently silent, it should just return without doing anything.
179 If the sound that the voice is playing finishes during the course of this rendered
180 block, it must call clearCurrentNote(), to tell the synthesiser that it has finished.
182 The size of the blocks that are rendered can change each time it is called, and may
183 involve rendering as little as 1 sample at a time. In between rendering callbacks,
184 the voice's methods will be called to tell it about note and controller events.
186 virtual void renderNextBlock (AudioBuffer
<float>& outputBuffer
,
190 /** A double-precision version of renderNextBlock() */
191 virtual void renderNextBlock (AudioBuffer
<double>& outputBuffer
,
195 /** Changes the voice's reference sample rate.
197 The rate is set so that subclasses know the output rate and can set their pitch
200 This method is called by the synth, and subclasses can access the current rate with
201 the currentSampleRate member.
203 virtual void setCurrentPlaybackSampleRate (double newRate
);
205 /** Returns true if the voice is currently playing a sound which is mapped to the given
208 If it's not currently playing, this will return false.
210 virtual bool isPlayingChannel (int midiChannel
) const;
212 /** Returns the current target sample rate at which rendering is being done.
213 Subclasses may need to know this so that they can pitch things correctly.
215 double getSampleRate() const noexcept
{ return currentSampleRate
; }
217 /** Returns true if the key that triggered this voice is still held down.
218 Note that the voice may still be playing after the key was released (e.g because the
219 sostenuto pedal is down).
221 bool isKeyDown() const noexcept
{ return keyIsDown
; }
223 /** Allows you to modify the flag indicating that the key that triggered this voice is still held down.
226 void setKeyDown (bool isNowDown
) noexcept
{ keyIsDown
= isNowDown
; }
228 /** Returns true if the sustain pedal is currently active for this voice. */
229 bool isSustainPedalDown() const noexcept
{ return sustainPedalDown
; }
231 /** Modifies the sustain pedal flag. */
232 void setSustainPedalDown (bool isNowDown
) noexcept
{ sustainPedalDown
= isNowDown
; }
234 /** Returns true if the sostenuto pedal is currently active for this voice. */
235 bool isSostenutoPedalDown() const noexcept
{ return sostenutoPedalDown
; }
237 /** Modifies the sostenuto pedal flag. */
238 void setSostenutoPedalDown (bool isNowDown
) noexcept
{ sostenutoPedalDown
= isNowDown
; }
240 /** Returns true if a voice is sounding in its release phase **/
241 bool isPlayingButReleased() const noexcept
243 return isVoiceActive() && ! (isKeyDown() || isSostenutoPedalDown() || isSustainPedalDown());
246 /** Returns true if this voice started playing its current note before the other voice did. */
247 bool wasStartedBefore (const SynthesiserVoice
& other
) const noexcept
;
250 /** Resets the state of this voice after a sound has finished playing.
252 The subclass must call this when it finishes playing a note and becomes available
255 It must either call it in the stopNote() method, or if the voice is tailing off,
256 then it should call it later during the renderNextBlock method, as soon as it
257 finishes its tail-off.
259 It can also be called at any time during the render callback if the sound happens
260 to have finished, e.g. if it's playing a sample and the sample finishes.
262 void clearCurrentNote();
266 //==============================================================================
267 friend class Synthesiser
;
269 double currentSampleRate
= 44100.0;
270 int currentlyPlayingNote
= -1, currentPlayingMidiChannel
= 0;
271 uint32 noteOnTime
= 0;
272 SynthesiserSound::Ptr currentlyPlayingSound
;
273 bool keyIsDown
= false, sustainPedalDown
= false, sostenutoPedalDown
= false;
275 AudioBuffer
<float> tempBuffer
;
277 JUCE_LEAK_DETECTOR (SynthesiserVoice
)
281 //==============================================================================
283 Base class for a musical device that can play sounds.
285 To create a synthesiser, you'll need to create a subclass of SynthesiserSound
286 to describe each sound available to your synth, and a subclass of SynthesiserVoice
287 which can play back one of these sounds.
289 Then you can use the addVoice() and addSound() methods to give the synthesiser a
290 set of sounds, and a set of voices it can use to play them. If you only give it
291 one voice it will be monophonic - the more voices it has, the more polyphony it'll
294 Then repeatedly call the renderNextBlock() method to produce the audio. Any midi
295 events that go in will be scanned for note on/off messages, and these are used to
296 start and stop the voices playing the appropriate sounds.
298 While it's playing, you can also cause notes to be triggered by calling the noteOn(),
299 noteOff() and other controller methods.
301 Before rendering, be sure to call the setCurrentPlaybackSampleRate() to tell it
302 what the target playback rate is. This value is passed on to the voices so that
303 they can pitch their output correctly.
307 class JUCE_API Synthesiser
310 //==============================================================================
311 /** Creates a new synthesiser.
312 You'll need to add some sounds and voices before it'll make any sound.
317 virtual ~Synthesiser();
319 //==============================================================================
320 /** Deletes all voices. */
323 /** Returns the number of voices that have been added. */
324 int getNumVoices() const noexcept
{ return voices
.size(); }
326 /** Returns one of the voices that have been added. */
327 SynthesiserVoice
* getVoice (int index
) const;
329 /** Adds a new voice to the synth.
331 All the voices should be the same class of object and are treated equally.
333 The object passed in will be managed by the synthesiser, which will delete
334 it later on when no longer needed. The caller should not retain a pointer to the
337 SynthesiserVoice
* addVoice (SynthesiserVoice
* newVoice
);
339 /** Deletes one of the voices. */
340 void removeVoice (int index
);
342 //==============================================================================
343 /** Deletes all sounds. */
346 /** Returns the number of sounds that have been added to the synth. */
347 int getNumSounds() const noexcept
{ return sounds
.size(); }
349 /** Returns one of the sounds. */
350 SynthesiserSound::Ptr
getSound (int index
) const noexcept
{ return sounds
[index
]; }
352 /** Adds a new sound to the synthesiser.
354 The object passed in is reference counted, so will be deleted when the
355 synthesiser and all voices are no longer using it.
357 SynthesiserSound
* addSound (const SynthesiserSound::Ptr
& newSound
);
359 /** Removes and deletes one of the sounds. */
360 void removeSound (int index
);
362 //==============================================================================
363 /** If set to true, then the synth will try to take over an existing voice if
364 it runs out and needs to play another note.
366 The value of this boolean is passed into findFreeVoice(), so the result will
367 depend on the implementation of this method.
369 void setNoteStealingEnabled (bool shouldStealNotes
);
371 /** Returns true if note-stealing is enabled.
372 @see setNoteStealingEnabled
374 bool isNoteStealingEnabled() const noexcept
{ return shouldStealNotes
; }
376 //==============================================================================
377 /** Triggers a note-on event.
379 The default method here will find all the sounds that want to be triggered by
380 this note/channel. For each sound, it'll try to find a free voice, and use the
381 voice to start playing the sound.
383 Subclasses might want to override this if they need a more complex algorithm.
385 This method will be called automatically according to the midi data passed into
386 renderNextBlock(), but may be called explicitly too.
388 The midiChannel parameter is the channel, between 1 and 16 inclusive.
390 virtual void noteOn (int midiChannel
,
394 /** Triggers a note-off event.
396 This will turn off any voices that are playing a sound for the given note/channel.
398 If allowTailOff is true, the voices will be allowed to fade out the notes gracefully
399 (if they can do). If this is false, the notes will all be cut off immediately.
401 This method will be called automatically according to the midi data passed into
402 renderNextBlock(), but may be called explicitly too.
404 The midiChannel parameter is the channel, between 1 and 16 inclusive.
406 virtual void noteOff (int midiChannel
,
411 /** Turns off all notes.
413 This will turn off any voices that are playing a sound on the given midi channel.
415 If midiChannel is 0 or less, then all voices will be turned off, regardless of
416 which channel they're playing. Otherwise it represents a valid midi channel, from
419 If allowTailOff is true, the voices will be allowed to fade out the notes gracefully
420 (if they can do). If this is false, the notes will all be cut off immediately.
422 This method will be called automatically according to the midi data passed into
423 renderNextBlock(), but may be called explicitly too.
425 virtual void allNotesOff (int midiChannel
,
428 /** Sends a pitch-wheel message to any active voices.
430 This will send a pitch-wheel message to any voices that are playing sounds on
431 the given midi channel.
433 This method will be called automatically according to the midi data passed into
434 renderNextBlock(), but may be called explicitly too.
436 @param midiChannel the midi channel, from 1 to 16 inclusive
437 @param wheelValue the wheel position, from 0 to 0x3fff, as returned by MidiMessage::getPitchWheelValue()
439 virtual void handlePitchWheel (int midiChannel
,
442 /** Sends a midi controller message to any active voices.
444 This will send a midi controller message to any voices that are playing sounds on
445 the given midi channel.
447 This method will be called automatically according to the midi data passed into
448 renderNextBlock(), but may be called explicitly too.
450 @param midiChannel the midi channel, from 1 to 16 inclusive
451 @param controllerNumber the midi controller type, as returned by MidiMessage::getControllerNumber()
452 @param controllerValue the midi controller value, between 0 and 127, as returned by MidiMessage::getControllerValue()
454 virtual void handleController (int midiChannel
,
455 int controllerNumber
,
456 int controllerValue
);
458 /** Sends an aftertouch message.
460 This will send an aftertouch message to any voices that are playing sounds on
461 the given midi channel and note number.
463 This method will be called automatically according to the midi data passed into
464 renderNextBlock(), but may be called explicitly too.
466 @param midiChannel the midi channel, from 1 to 16 inclusive
467 @param midiNoteNumber the midi note number, 0 to 127
468 @param aftertouchValue the aftertouch value, between 0 and 127,
469 as returned by MidiMessage::getAftertouchValue()
471 virtual void handleAftertouch (int midiChannel
, int midiNoteNumber
, int aftertouchValue
);
473 /** Sends a channel pressure message.
475 This will send a channel pressure message to any voices that are playing sounds on
476 the given midi channel.
478 This method will be called automatically according to the midi data passed into
479 renderNextBlock(), but may be called explicitly too.
481 @param midiChannel the midi channel, from 1 to 16 inclusive
482 @param channelPressureValue the pressure value, between 0 and 127, as returned
483 by MidiMessage::getChannelPressureValue()
485 virtual void handleChannelPressure (int midiChannel
, int channelPressureValue
);
487 /** Handles a sustain pedal event. */
488 virtual void handleSustainPedal (int midiChannel
, bool isDown
);
490 /** Handles a sostenuto pedal event. */
491 virtual void handleSostenutoPedal (int midiChannel
, bool isDown
);
493 /** Can be overridden to handle soft pedal events. */
494 virtual void handleSoftPedal (int midiChannel
, bool isDown
);
496 /** Can be overridden to handle an incoming program change message.
497 The base class implementation of this has no effect, but you may want to make your
498 own synth react to program changes.
500 virtual void handleProgramChange (int midiChannel
,
503 //==============================================================================
504 /** Tells the synthesiser what the sample rate is for the audio it's being used to render.
506 This value is propagated to the voices so that they can use it to render the correct
509 virtual void setCurrentPlaybackSampleRate (double sampleRate
);
511 /** Creates the next block of audio output.
513 This will process the next numSamples of data from all the voices, and add that output
514 to the audio block supplied, starting from the offset specified. Note that the
515 data will be added to the current contents of the buffer, so you should clear it
516 before calling this method if necessary.
518 The midi events in the inputMidi buffer are parsed for note and controller events,
519 and these are used to trigger the voices. Note that the startSample offset applies
520 both to the audio output buffer and the midi input buffer, so any midi events
521 with timestamps outside the specified region will be ignored.
523 void renderNextBlock (AudioBuffer
<float>& outputAudio
,
524 const MidiBuffer
& inputMidi
,
528 void renderNextBlock (AudioBuffer
<double>& outputAudio
,
529 const MidiBuffer
& inputMidi
,
533 /** Returns the current target sample rate at which rendering is being done.
534 Subclasses may need to know this so that they can pitch things correctly.
536 double getSampleRate() const noexcept
{ return sampleRate
; }
538 /** Sets a minimum limit on the size to which audio sub-blocks will be divided when rendering.
540 When rendering, the audio blocks that are passed into renderNextBlock() will be split up
541 into smaller blocks that lie between all the incoming midi messages, and it is these smaller
542 sub-blocks that are rendered with multiple calls to renderVoices().
544 Obviously in a pathological case where there are midi messages on every sample, then
545 renderVoices() could be called once per sample and lead to poor performance, so this
546 setting allows you to set a lower limit on the block size.
548 The default setting is 32, which means that midi messages are accurate to about < 1ms
549 accuracy, which is probably fine for most purposes, but you may want to increase or
550 decrease this value for your synth.
552 If shouldBeStrict is true, the audio sub-blocks will strictly never be smaller than numSamples.
554 If shouldBeStrict is false (default), the first audio sub-block in the buffer is allowed
555 to be smaller, to make sure that the first MIDI event in a buffer will always be sample-accurate
556 (this can sometimes help to avoid quantisation or phasing issues).
558 void setMinimumRenderingSubdivisionSize (int numSamples
, bool shouldBeStrict
= false) noexcept
;
561 //==============================================================================
562 /** This is used to control access to the rendering callback and the note trigger methods. */
563 CriticalSection lock
;
565 OwnedArray
<SynthesiserVoice
> voices
;
566 ReferenceCountedArray
<SynthesiserSound
> sounds
;
568 /** The last pitch-wheel values for each midi channel. */
569 int lastPitchWheelValues
[16];
571 /** Renders the voices for the given range.
572 By default this just calls renderNextBlock() on each voice, but you may need
573 to override it to handle custom cases.
575 virtual void renderVoices (AudioBuffer
<float>& outputAudio
,
576 int startSample
, int numSamples
);
577 virtual void renderVoices (AudioBuffer
<double>& outputAudio
,
578 int startSample
, int numSamples
);
580 /** Searches through the voices to find one that's not currently playing, and
581 which can play the given sound.
583 Returns nullptr if all voices are busy and stealing isn't enabled.
585 To implement a custom note-stealing algorithm, you can either override this
586 method, or (preferably) override findVoiceToSteal().
588 virtual SynthesiserVoice
* findFreeVoice (SynthesiserSound
* soundToPlay
,
591 bool stealIfNoneAvailable
) const;
593 /** Chooses a voice that is most suitable for being re-used.
594 The default method will attempt to find the oldest voice that isn't the
595 bottom or top note being played. If that's not suitable for your synth,
596 you can override this method and do something more cunning instead.
598 virtual SynthesiserVoice
* findVoiceToSteal (SynthesiserSound
* soundToPlay
,
600 int midiNoteNumber
) const;
602 /** Starts a specified voice playing a particular sound.
603 You'll probably never need to call this, it's used internally by noteOn(), but
604 may be needed by subclasses for custom behaviours.
606 void startVoice (SynthesiserVoice
* voice
,
607 SynthesiserSound
* sound
,
612 /** Stops a given voice.
613 You should never need to call this, it's used internally by noteOff, but is protected
614 in case it's useful for some custom subclasses. It basically just calls through to
615 SynthesiserVoice::stopNote(), and has some assertions to sanity-check a few things.
617 void stopVoice (SynthesiserVoice
*, float velocity
, bool allowTailOff
);
619 /** Can be overridden to do custom handling of incoming midi events. */
620 virtual void handleMidiEvent (const MidiMessage
&);
623 //==============================================================================
624 double sampleRate
= 0;
625 uint32 lastNoteOnCounter
= 0;
626 int minimumSubBlockSize
= 32;
627 bool subBlockSubdivisionIsStrict
= false;
628 bool shouldStealNotes
= true;
629 BigInteger sustainPedalsDown
;
631 template <typename floatType
>
632 void processNextBlock (AudioBuffer
<floatType
>&, const MidiBuffer
&, int startSample
, int numSamples
);
634 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser
)