OpenShot Library | OpenShotAudio  0.2.1
juce_Synthesiser.h
1 
2 /** @weakgroup juce_audio_basics-synthesisers
3  * @{
4  */
5 /*
6  ==============================================================================
7 
8  This file is part of the JUCE library.
9  Copyright (c) 2017 - ROLI Ltd.
10 
11  JUCE is an open source library subject to commercial or open-source
12  licensing.
13 
14  The code included in this file is provided under the terms of the ISC license
15  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16  To use, copy, modify, and/or distribute this software for any purpose with or
17  without fee is hereby granted provided that the above copyright notice and
18  this permission notice appear in all copies.
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 
30 //==============================================================================
31 /**
32  Describes one of the sounds that a Synthesiser can play.
33 
34  A synthesiser can contain one or more sounds, and a sound can choose which
35  midi notes and channels can trigger it.
36 
37  The SynthesiserSound is a passive class that just describes what the sound is -
38  the actual audio rendering for a sound is done by a SynthesiserVoice. This allows
39  more than one SynthesiserVoice to play the same sound at the same time.
40 
41  @see Synthesiser, SynthesiserVoice
42 
43  @tags{Audio}
44 */
46 {
47 protected:
48  //==============================================================================
50 
51 public:
52  /** Destructor. */
53  ~SynthesiserSound() override;
54 
55  //==============================================================================
56  /** Returns true if this sound should be played when a given midi note is pressed.
57 
58  The Synthesiser will use this information when deciding which sounds to trigger
59  for a given note.
60  */
61  virtual bool appliesToNote (int midiNoteNumber) = 0;
62 
63  /** Returns true if the sound should be triggered by midi events on a given channel.
64 
65  The Synthesiser will use this information when deciding which sounds to trigger
66  for a given note.
67  */
68  virtual bool appliesToChannel (int midiChannel) = 0;
69 
70  /** The class is reference-counted, so this is a handy pointer class for it. */
72 
73 
74 private:
75  //==============================================================================
76  JUCE_LEAK_DETECTOR (SynthesiserSound)
77 };
78 
79 
80 //==============================================================================
81 /**
82  Represents a voice that a Synthesiser can use to play a SynthesiserSound.
83 
84  A voice plays a single sound at a time, and a synthesiser holds an array of
85  voices so that it can play polyphonically.
86 
87  @see Synthesiser, SynthesiserSound
88 
89  @tags{Audio}
90 */
92 {
93 public:
94  //==============================================================================
95  /** Creates a voice. */
97 
98  /** Destructor. */
99  virtual ~SynthesiserVoice();
100 
101  //==============================================================================
102  /** Returns the midi note that this voice is currently playing.
103  Returns a value less than 0 if no note is playing.
104  */
105  int getCurrentlyPlayingNote() const noexcept { return currentlyPlayingNote; }
106 
107  /** Returns the sound that this voice is currently playing.
108  Returns nullptr if it's not playing.
109  */
110  SynthesiserSound::Ptr getCurrentlyPlayingSound() const noexcept { return currentlyPlayingSound; }
111 
112  /** Must return true if this voice object is capable of playing the given sound.
113 
114  If there are different classes of sound, and different classes of voice, a voice can
115  choose which ones it wants to take on.
116 
117  A typical implementation of this method may just return true if there's only one type
118  of voice and sound, or it might check the type of the sound object passed-in and
119  see if it's one that it understands.
120  */
121  virtual bool canPlaySound (SynthesiserSound*) = 0;
122 
123  /** Called to start a new note.
124  This will be called during the rendering callback, so must be fast and thread-safe.
125  */
126  virtual void startNote (int midiNoteNumber,
127  float velocity,
128  SynthesiserSound* sound,
129  int currentPitchWheelPosition) = 0;
130 
131  /** Called to stop a note.
132 
133  This will be called during the rendering callback, so must be fast and thread-safe.
134 
135  The velocity indicates how quickly the note was released - 0 is slowly, 1 is quickly.
136 
137  If allowTailOff is false or the voice doesn't want to tail-off, then it must stop all
138  sound immediately, and must call clearCurrentNote() to reset the state of this voice
139  and allow the synth to reassign it another sound.
140 
141  If allowTailOff is true and the voice decides to do a tail-off, then it's allowed to
142  begin fading out its sound, and it can stop playing until it's finished. As soon as it
143  finishes playing (during the rendering callback), it must make sure that it calls
144  clearCurrentNote().
145  */
146  virtual void stopNote (float velocity, bool allowTailOff) = 0;
147 
148  /** Returns true if this voice is currently busy playing a sound.
149  By default this just checks the getCurrentlyPlayingNote() value, but can
150  be overridden for more advanced checking.
151  */
152  virtual bool isVoiceActive() const;
153 
154  /** Called to let the voice know that the pitch wheel has been moved.
155  This will be called during the rendering callback, so must be fast and thread-safe.
156  */
157  virtual void pitchWheelMoved (int newPitchWheelValue) = 0;
158 
159  /** Called to let the voice know that a midi controller has been moved.
160  This will be called during the rendering callback, so must be fast and thread-safe.
161  */
162  virtual void controllerMoved (int controllerNumber, int newControllerValue) = 0;
163 
164  /** Called to let the voice know that the aftertouch has changed.
165  This will be called during the rendering callback, so must be fast and thread-safe.
166  */
167  virtual void aftertouchChanged (int newAftertouchValue);
168 
169  /** Called to let the voice know that the channel pressure has changed.
170  This will be called during the rendering callback, so must be fast and thread-safe.
171  */
172  virtual void channelPressureChanged (int newChannelPressureValue);
173 
174  //==============================================================================
175  /** Renders the next block of data for this voice.
176 
177  The output audio data must be added to the current contents of the buffer provided.
178  Only the region of the buffer between startSample and (startSample + numSamples)
179  should be altered by this method.
180 
181  If the voice is currently silent, it should just return without doing anything.
182 
183  If the sound that the voice is playing finishes during the course of this rendered
184  block, it must call clearCurrentNote(), to tell the synthesiser that it has finished.
185 
186  The size of the blocks that are rendered can change each time it is called, and may
187  involve rendering as little as 1 sample at a time. In between rendering callbacks,
188  the voice's methods will be called to tell it about note and controller events.
189  */
190  virtual void renderNextBlock (AudioBuffer<float>& outputBuffer,
191  int startSample,
192  int numSamples) = 0;
193 
194  /** A double-precision version of renderNextBlock() */
195  virtual void renderNextBlock (AudioBuffer<double>& outputBuffer,
196  int startSample,
197  int numSamples);
198 
199  /** Changes the voice's reference sample rate.
200 
201  The rate is set so that subclasses know the output rate and can set their pitch
202  accordingly.
203 
204  This method is called by the synth, and subclasses can access the current rate with
205  the currentSampleRate member.
206  */
207  virtual void setCurrentPlaybackSampleRate (double newRate);
208 
209  /** Returns true if the voice is currently playing a sound which is mapped to the given
210  midi channel.
211 
212  If it's not currently playing, this will return false.
213  */
214  virtual bool isPlayingChannel (int midiChannel) const;
215 
216  /** Returns the current target sample rate at which rendering is being done.
217  Subclasses may need to know this so that they can pitch things correctly.
218  */
219  double getSampleRate() const noexcept { return currentSampleRate; }
220 
221  /** Returns true if the key that triggered this voice is still held down.
222  Note that the voice may still be playing after the key was released (e.g because the
223  sostenuto pedal is down).
224  */
225  bool isKeyDown() const noexcept { return keyIsDown; }
226 
227  /** Allows you to modify the flag indicating that the key that triggered this voice is still held down.
228  @see isKeyDown
229  */
230  void setKeyDown (bool isNowDown) noexcept { keyIsDown = isNowDown; }
231 
232  /** Returns true if the sustain pedal is currently active for this voice. */
233  bool isSustainPedalDown() const noexcept { return sustainPedalDown; }
234 
235  /** Modifies the sustain pedal flag. */
236  void setSustainPedalDown (bool isNowDown) noexcept { sustainPedalDown = isNowDown; }
237 
238  /** Returns true if the sostenuto pedal is currently active for this voice. */
239  bool isSostenutoPedalDown() const noexcept { return sostenutoPedalDown; }
240 
241  /** Modifies the sostenuto pedal flag. */
242  void setSostenutoPedalDown (bool isNowDown) noexcept { sostenutoPedalDown = isNowDown; }
243 
244  /** Returns true if a voice is sounding in its release phase **/
245  bool isPlayingButReleased() const noexcept
246  {
247  return isVoiceActive() && ! (isKeyDown() || isSostenutoPedalDown() || isSustainPedalDown());
248  }
249 
250  /** Returns true if this voice started playing its current note before the other voice did. */
251  bool wasStartedBefore (const SynthesiserVoice& other) const noexcept;
252 
253 protected:
254  /** Resets the state of this voice after a sound has finished playing.
255 
256  The subclass must call this when it finishes playing a note and becomes available
257  to play new ones.
258 
259  It must either call it in the stopNote() method, or if the voice is tailing off,
260  then it should call it later during the renderNextBlock method, as soon as it
261  finishes its tail-off.
262 
263  It can also be called at any time during the render callback if the sound happens
264  to have finished, e.g. if it's playing a sample and the sample finishes.
265  */
266  void clearCurrentNote();
267 
268 
269 private:
270  //==============================================================================
271  friend class Synthesiser;
272 
273  double currentSampleRate = 44100.0;
274  int currentlyPlayingNote = -1, currentPlayingMidiChannel = 0;
275  uint32 noteOnTime = 0;
276  SynthesiserSound::Ptr currentlyPlayingSound;
277  bool keyIsDown = false, sustainPedalDown = false, sostenutoPedalDown = false;
278 
279  AudioBuffer<float> tempBuffer;
280 
281  JUCE_LEAK_DETECTOR (SynthesiserVoice)
282 };
283 
284 
285 //==============================================================================
286 /**
287  Base class for a musical device that can play sounds.
288 
289  To create a synthesiser, you'll need to create a subclass of SynthesiserSound
290  to describe each sound available to your synth, and a subclass of SynthesiserVoice
291  which can play back one of these sounds.
292 
293  Then you can use the addVoice() and addSound() methods to give the synthesiser a
294  set of sounds, and a set of voices it can use to play them. If you only give it
295  one voice it will be monophonic - the more voices it has, the more polyphony it'll
296  have available.
297 
298  Then repeatedly call the renderNextBlock() method to produce the audio. Any midi
299  events that go in will be scanned for note on/off messages, and these are used to
300  start and stop the voices playing the appropriate sounds.
301 
302  While it's playing, you can also cause notes to be triggered by calling the noteOn(),
303  noteOff() and other controller methods.
304 
305  Before rendering, be sure to call the setCurrentPlaybackSampleRate() to tell it
306  what the target playback rate is. This value is passed on to the voices so that
307  they can pitch their output correctly.
308 
309  @tags{Audio}
310 */
312 {
313 public:
314  //==============================================================================
315  /** Creates a new synthesiser.
316  You'll need to add some sounds and voices before it'll make any sound.
317  */
318  Synthesiser();
319 
320  /** Destructor. */
321  virtual ~Synthesiser();
322 
323  //==============================================================================
324  /** Deletes all voices. */
325  void clearVoices();
326 
327  /** Returns the number of voices that have been added. */
328  int getNumVoices() const noexcept { return voices.size(); }
329 
330  /** Returns one of the voices that have been added. */
331  SynthesiserVoice* getVoice (int index) const;
332 
333  /** Adds a new voice to the synth.
334 
335  All the voices should be the same class of object and are treated equally.
336 
337  The object passed in will be managed by the synthesiser, which will delete
338  it later on when no longer needed. The caller should not retain a pointer to the
339  voice.
340  */
341  SynthesiserVoice* addVoice (SynthesiserVoice* newVoice);
342 
343  /** Deletes one of the voices. */
344  void removeVoice (int index);
345 
346  //==============================================================================
347  /** Deletes all sounds. */
348  void clearSounds();
349 
350  /** Returns the number of sounds that have been added to the synth. */
351  int getNumSounds() const noexcept { return sounds.size(); }
352 
353  /** Returns one of the sounds. */
354  SynthesiserSound::Ptr getSound (int index) const noexcept { return sounds[index]; }
355 
356  /** Adds a new sound to the synthesiser.
357 
358  The object passed in is reference counted, so will be deleted when the
359  synthesiser and all voices are no longer using it.
360  */
361  SynthesiserSound* addSound (const SynthesiserSound::Ptr& newSound);
362 
363  /** Removes and deletes one of the sounds. */
364  void removeSound (int index);
365 
366  //==============================================================================
367  /** If set to true, then the synth will try to take over an existing voice if
368  it runs out and needs to play another note.
369 
370  The value of this boolean is passed into findFreeVoice(), so the result will
371  depend on the implementation of this method.
372  */
373  void setNoteStealingEnabled (bool shouldStealNotes);
374 
375  /** Returns true if note-stealing is enabled.
376  @see setNoteStealingEnabled
377  */
378  bool isNoteStealingEnabled() const noexcept { return shouldStealNotes; }
379 
380  //==============================================================================
381  /** Triggers a note-on event.
382 
383  The default method here will find all the sounds that want to be triggered by
384  this note/channel. For each sound, it'll try to find a free voice, and use the
385  voice to start playing the sound.
386 
387  Subclasses might want to override this if they need a more complex algorithm.
388 
389  This method will be called automatically according to the midi data passed into
390  renderNextBlock(), but may be called explicitly too.
391 
392  The midiChannel parameter is the channel, between 1 and 16 inclusive.
393  */
394  virtual void noteOn (int midiChannel,
395  int midiNoteNumber,
396  float velocity);
397 
398  /** Triggers a note-off event.
399 
400  This will turn off any voices that are playing a sound for the given note/channel.
401 
402  If allowTailOff is true, the voices will be allowed to fade out the notes gracefully
403  (if they can do). If this is false, the notes will all be cut off immediately.
404 
405  This method will be called automatically according to the midi data passed into
406  renderNextBlock(), but may be called explicitly too.
407 
408  The midiChannel parameter is the channel, between 1 and 16 inclusive.
409  */
410  virtual void noteOff (int midiChannel,
411  int midiNoteNumber,
412  float velocity,
413  bool allowTailOff);
414 
415  /** Turns off all notes.
416 
417  This will turn off any voices that are playing a sound on the given midi channel.
418 
419  If midiChannel is 0 or less, then all voices will be turned off, regardless of
420  which channel they're playing. Otherwise it represents a valid midi channel, from
421  1 to 16 inclusive.
422 
423  If allowTailOff is true, the voices will be allowed to fade out the notes gracefully
424  (if they can do). If this is false, the notes will all be cut off immediately.
425 
426  This method will be called automatically according to the midi data passed into
427  renderNextBlock(), but may be called explicitly too.
428  */
429  virtual void allNotesOff (int midiChannel,
430  bool allowTailOff);
431 
432  /** Sends a pitch-wheel message to any active voices.
433 
434  This will send a pitch-wheel message to any voices that are playing sounds on
435  the given midi channel.
436 
437  This method will be called automatically according to the midi data passed into
438  renderNextBlock(), but may be called explicitly too.
439 
440  @param midiChannel the midi channel, from 1 to 16 inclusive
441  @param wheelValue the wheel position, from 0 to 0x3fff, as returned by MidiMessage::getPitchWheelValue()
442  */
443  virtual void handlePitchWheel (int midiChannel,
444  int wheelValue);
445 
446  /** Sends a midi controller message to any active voices.
447 
448  This will send a midi controller message to any voices that are playing sounds on
449  the given midi channel.
450 
451  This method will be called automatically according to the midi data passed into
452  renderNextBlock(), but may be called explicitly too.
453 
454  @param midiChannel the midi channel, from 1 to 16 inclusive
455  @param controllerNumber the midi controller type, as returned by MidiMessage::getControllerNumber()
456  @param controllerValue the midi controller value, between 0 and 127, as returned by MidiMessage::getControllerValue()
457  */
458  virtual void handleController (int midiChannel,
459  int controllerNumber,
460  int controllerValue);
461 
462  /** Sends an aftertouch message.
463 
464  This will send an aftertouch message to any voices that are playing sounds on
465  the given midi channel and note number.
466 
467  This method will be called automatically according to the midi data passed into
468  renderNextBlock(), but may be called explicitly too.
469 
470  @param midiChannel the midi channel, from 1 to 16 inclusive
471  @param midiNoteNumber the midi note number, 0 to 127
472  @param aftertouchValue the aftertouch value, between 0 and 127,
473  as returned by MidiMessage::getAftertouchValue()
474  */
475  virtual void handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue);
476 
477  /** Sends a channel pressure message.
478 
479  This will send a channel pressure message to any voices that are playing sounds on
480  the given midi channel.
481 
482  This method will be called automatically according to the midi data passed into
483  renderNextBlock(), but may be called explicitly too.
484 
485  @param midiChannel the midi channel, from 1 to 16 inclusive
486  @param channelPressureValue the pressure value, between 0 and 127, as returned
487  by MidiMessage::getChannelPressureValue()
488  */
489  virtual void handleChannelPressure (int midiChannel, int channelPressureValue);
490 
491  /** Handles a sustain pedal event. */
492  virtual void handleSustainPedal (int midiChannel, bool isDown);
493 
494  /** Handles a sostenuto pedal event. */
495  virtual void handleSostenutoPedal (int midiChannel, bool isDown);
496 
497  /** Can be overridden to handle soft pedal events. */
498  virtual void handleSoftPedal (int midiChannel, bool isDown);
499 
500  /** Can be overridden to handle an incoming program change message.
501  The base class implementation of this has no effect, but you may want to make your
502  own synth react to program changes.
503  */
504  virtual void handleProgramChange (int midiChannel,
505  int programNumber);
506 
507  //==============================================================================
508  /** Tells the synthesiser what the sample rate is for the audio it's being used to render.
509 
510  This value is propagated to the voices so that they can use it to render the correct
511  pitches.
512  */
513  virtual void setCurrentPlaybackSampleRate (double sampleRate);
514 
515  /** Creates the next block of audio output.
516 
517  This will process the next numSamples of data from all the voices, and add that output
518  to the audio block supplied, starting from the offset specified. Note that the
519  data will be added to the current contents of the buffer, so you should clear it
520  before calling this method if necessary.
521 
522  The midi events in the inputMidi buffer are parsed for note and controller events,
523  and these are used to trigger the voices. Note that the startSample offset applies
524  both to the audio output buffer and the midi input buffer, so any midi events
525  with timestamps outside the specified region will be ignored.
526  */
527  void renderNextBlock (AudioBuffer<float>& outputAudio,
528  const MidiBuffer& inputMidi,
529  int startSample,
530  int numSamples);
531 
532  void renderNextBlock (AudioBuffer<double>& outputAudio,
533  const MidiBuffer& inputMidi,
534  int startSample,
535  int numSamples);
536 
537  /** Returns the current target sample rate at which rendering is being done.
538  Subclasses may need to know this so that they can pitch things correctly.
539  */
540  double getSampleRate() const noexcept { return sampleRate; }
541 
542  /** Sets a minimum limit on the size to which audio sub-blocks will be divided when rendering.
543 
544  When rendering, the audio blocks that are passed into renderNextBlock() will be split up
545  into smaller blocks that lie between all the incoming midi messages, and it is these smaller
546  sub-blocks that are rendered with multiple calls to renderVoices().
547 
548  Obviously in a pathological case where there are midi messages on every sample, then
549  renderVoices() could be called once per sample and lead to poor performance, so this
550  setting allows you to set a lower limit on the block size.
551 
552  The default setting is 32, which means that midi messages are accurate to about < 1ms
553  accuracy, which is probably fine for most purposes, but you may want to increase or
554  decrease this value for your synth.
555 
556  If shouldBeStrict is true, the audio sub-blocks will strictly never be smaller than numSamples.
557 
558  If shouldBeStrict is false (default), the first audio sub-block in the buffer is allowed
559  to be smaller, to make sure that the first MIDI event in a buffer will always be sample-accurate
560  (this can sometimes help to avoid quantisation or phasing issues).
561  */
562  void setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict = false) noexcept;
563 
564 protected:
565  //==============================================================================
566  /** This is used to control access to the rendering callback and the note trigger methods. */
568 
571 
572  /** The last pitch-wheel values for each midi channel. */
573  int lastPitchWheelValues [16];
574 
575  /** Renders the voices for the given range.
576  By default this just calls renderNextBlock() on each voice, but you may need
577  to override it to handle custom cases.
578  */
579  virtual void renderVoices (AudioBuffer<float>& outputAudio,
580  int startSample, int numSamples);
581  virtual void renderVoices (AudioBuffer<double>& outputAudio,
582  int startSample, int numSamples);
583 
584  /** Searches through the voices to find one that's not currently playing, and
585  which can play the given sound.
586 
587  Returns nullptr if all voices are busy and stealing isn't enabled.
588 
589  To implement a custom note-stealing algorithm, you can either override this
590  method, or (preferably) override findVoiceToSteal().
591  */
592  virtual SynthesiserVoice* findFreeVoice (SynthesiserSound* soundToPlay,
593  int midiChannel,
594  int midiNoteNumber,
595  bool stealIfNoneAvailable) const;
596 
597  /** Chooses a voice that is most suitable for being re-used.
598  The default method will attempt to find the oldest voice that isn't the
599  bottom or top note being played. If that's not suitable for your synth,
600  you can override this method and do something more cunning instead.
601  */
602  virtual SynthesiserVoice* findVoiceToSteal (SynthesiserSound* soundToPlay,
603  int midiChannel,
604  int midiNoteNumber) const;
605 
606  /** Starts a specified voice playing a particular sound.
607  You'll probably never need to call this, it's used internally by noteOn(), but
608  may be needed by subclasses for custom behaviours.
609  */
610  void startVoice (SynthesiserVoice* voice,
611  SynthesiserSound* sound,
612  int midiChannel,
613  int midiNoteNumber,
614  float velocity);
615 
616  /** Stops a given voice.
617  You should never need to call this, it's used internally by noteOff, but is protected
618  in case it's useful for some custom subclasses. It basically just calls through to
619  SynthesiserVoice::stopNote(), and has some assertions to sanity-check a few things.
620  */
621  void stopVoice (SynthesiserVoice*, float velocity, bool allowTailOff);
622 
623  /** Can be overridden to do custom handling of incoming midi events. */
624  virtual void handleMidiEvent (const MidiMessage&);
625 
626 private:
627  //==============================================================================
628  double sampleRate = 0;
629  uint32 lastNoteOnCounter = 0;
630  int minimumSubBlockSize = 32;
631  bool subBlockSubdivisionIsStrict = false;
632  bool shouldStealNotes = true;
633  BigInteger sustainPedalsDown;
634 
635  template <typename floatType>
636  void processNextBlock (AudioBuffer<floatType>&, const MidiBuffer&, int startSample, int numSamples);
637 
638  #if JUCE_CATCH_DEPRECATED_CODE_MISUSE
639  // Note the new parameters for these methods.
640  virtual int findFreeVoice (const bool) const { return 0; }
641  virtual int noteOff (int, int, int) { return 0; }
642  virtual int findFreeVoice (SynthesiserSound*, const bool) { return 0; }
643  virtual int findVoiceToSteal (SynthesiserSound*) const { return 0; }
644  #endif
645 
646  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser)
647 };
648 
649 } // namespace juce
650 
651 /** @}*/
#define JUCE_API
This macro is added to all JUCE public class declarations.
bool isSustainPedalDown() const noexcept
Returns true if the sustain pedal is currently active for this voice.
Encapsulates a MIDI message.
bool isNoteStealingEnabled() const noexcept
Returns true if note-stealing is enabled.
int getNumVoices() const noexcept
Returns the number of voices that have been added.
void setSostenutoPedalDown(bool isNowDown) noexcept
Modifies the sostenuto pedal flag.
SynthesiserSound::Ptr getCurrentlyPlayingSound() const noexcept
Returns the sound that this voice is currently playing.
Describes one of the sounds that a Synthesiser can play.
An arbitrarily large integer class.
void setSustainPedalDown(bool isNowDown) noexcept
Modifies the sustain pedal flag.
SynthesiserSound::Ptr getSound(int index) const noexcept
Returns one of the sounds.
Base class for a musical device that can play sounds.
bool isKeyDown() const noexcept
Returns true if the key that triggered this voice is still held down.
Represents a voice that a Synthesiser can use to play a SynthesiserSound.
Holds a sequence of time-stamped midi events.
int getNumSounds() const noexcept
Returns the number of sounds that have been added to the synth.
bool isPlayingButReleased() const noexcept
Returns true if a voice is sounding in its release phase.
int getCurrentlyPlayingNote() const noexcept
Returns the midi note that this voice is currently playing.
CriticalSection lock
This is used to control access to the rendering callback and the note trigger methods.
A re-entrant mutex.
double getSampleRate() const noexcept
Returns the current target sample rate at which rendering is being done.
An array designed for holding objects.
A base class which provides methods for reference-counting.
double getSampleRate() const noexcept
Returns the current target sample rate at which rendering is being done.
bool isSostenutoPedalDown() const noexcept
Returns true if the sostenuto pedal is currently active for this voice.
Holds a list of objects derived from ReferenceCountedObject, or which implement basic reference-count...
void setKeyDown(bool isNowDown) noexcept
Allows you to modify the flag indicating that the key that triggered this voice is still held down...