1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - 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 
26 //==============================================================================
27 /**
28     Represents an MPE voice that an MPESynthesiser can use to play a sound.
29 
30     A voice plays a single sound at a time, and a synthesiser holds an array of
31     voices so that it can play polyphonically.
32 
33     @see MPESynthesiser, MPENote
34 
35     @tags{Audio}
36 */
37 class JUCE_API  MPESynthesiserVoice
38 {
39 public:
40     //==============================================================================
41     /** Constructor. */
42     MPESynthesiserVoice();
43 
44     /** Destructor. */
45     virtual ~MPESynthesiserVoice();
46 
47     /** Returns the MPENote that this voice is currently playing.
48         Returns an invalid MPENote if no note is playing
49         (you can check this using MPENote::isValid() or MPEVoice::isActive()).
50     */
getCurrentlyPlayingNote()51     MPENote getCurrentlyPlayingNote() const noexcept     { return currentlyPlayingNote;  }
52 
53     /** Returns true if the voice is currently playing the given MPENote
54         (as identified by the note's initial note number and MIDI channel).
55     */
56     bool isCurrentlyPlayingNote (MPENote note) const noexcept;
57 
58     /** Returns true if this voice is currently busy playing a sound.
59         By default this just checks whether getCurrentlyPlayingNote()
60         returns a valid MPE note, but can be overridden for more advanced checking.
61     */
isActive()62     virtual bool isActive() const                       { return currentlyPlayingNote.isValid(); }
63 
64     /** Returns true if a voice is sounding in its release phase. **/
65     bool isPlayingButReleased() const noexcept;
66 
67     /** Called by the MPESynthesiser to let the voice know that a new note has started on it.
68         This will be called during the rendering callback, so must be fast and thread-safe.
69     */
70     virtual void noteStarted() = 0;
71 
72     /** Called by the MPESynthesiser to let the voice know that its currently playing note has stopped.
73         This will be called during the rendering callback, so must be fast and thread-safe.
74 
75         If allowTailOff is false or the voice doesn't want to tail-off, then it must stop all
76         sound immediately, and must call clearCurrentNote() to reset the state of this voice
77         and allow the synth to reassign it another sound.
78 
79         If allowTailOff is true and the voice decides to do a tail-off, then it's allowed to
80         begin fading out its sound, and it can stop playing until it's finished. As soon as it
81         finishes playing (during the rendering callback), it must make sure that it calls
82         clearCurrentNote().
83     */
84     virtual void noteStopped (bool allowTailOff) = 0;
85 
86     /** Called by the MPESynthesiser to let the voice know that its currently playing note
87         has changed its pressure value.
88         This will be called during the rendering callback, so must be fast and thread-safe.
89     */
90     virtual void notePressureChanged() = 0;
91 
92     /** Called by the MPESynthesiser to let the voice know that its currently playing note
93         has changed its pitchbend value.
94         This will be called during the rendering callback, so must be fast and thread-safe.
95 
96         Note: You can call currentlyPlayingNote.getFrequencyInHertz() to find out the effective frequency
97         of the note, as a sum of the initial note number, the per-note pitchbend and the master pitchbend.
98     */
99     virtual void notePitchbendChanged() = 0;
100 
101     /** Called by the MPESynthesiser to let the voice know that its currently playing note
102         has changed its timbre value.
103         This will be called during the rendering callback, so must be fast and thread-safe.
104     */
105     virtual void noteTimbreChanged() = 0;
106 
107     /** Called by the MPESynthesiser to let the voice know that its currently playing note
108         has changed its key state.
109         This typically happens when a sustain or sostenuto pedal is pressed or released (on
110         an MPE channel relevant for this note), or if the note key is lifted while the sustained
111         or sostenuto pedal is still held down.
112         This will be called during the rendering callback, so must be fast and thread-safe.
113     */
114     virtual void noteKeyStateChanged() = 0;
115 
116     /** Renders the next block of data for this voice.
117 
118         The output audio data must be added to the current contents of the buffer provided.
119         Only the region of the buffer between startSample and (startSample + numSamples)
120         should be altered by this method.
121 
122         If the voice is currently silent, it should just return without doing anything.
123 
124         If the sound that the voice is playing finishes during the course of this rendered
125         block, it must call clearCurrentNote(), to tell the synthesiser that it has finished.
126 
127         The size of the blocks that are rendered can change each time it is called, and may
128         involve rendering as little as 1 sample at a time. In between rendering callbacks,
129         the voice's methods will be called to tell it about note and controller events.
130     */
131     virtual void renderNextBlock (AudioBuffer<float>& outputBuffer,
132                                   int startSample,
133                                   int numSamples) = 0;
134 
135     /** Renders the next block of 64-bit data for this voice.
136 
137         Support for 64-bit audio is optional. You can choose to not override this method if
138         you don't need it (the default implementation simply does nothing).
139     */
renderNextBlock(AudioBuffer<double> &,int,int)140     virtual void renderNextBlock (AudioBuffer<double>& /*outputBuffer*/,
141                                   int /*startSample*/,
142                                   int /*numSamples*/) {}
143 
144     /** Changes the voice's reference sample rate.
145 
146         The rate is set so that subclasses know the output rate and can set their pitch
147         accordingly.
148 
149         This method is called by the synth, and subclasses can access the current rate with
150         the currentSampleRate member.
151     */
setCurrentSampleRate(double newRate)152     virtual void setCurrentSampleRate (double newRate)    { currentSampleRate = newRate; }
153 
154     /** Returns the current target sample rate at which rendering is being done.
155         Subclasses may need to know this so that they can pitch things correctly.
156     */
getSampleRate()157     double getSampleRate() const noexcept                 { return currentSampleRate; }
158 
159     /** This will be set to an incrementing counter value in MPESynthesiser::startVoice()
160         and can be used to determine the order in which voices started.
161     */
162     uint32 noteOnTime = 0;
163 
164 protected:
165     //==============================================================================
166     /** Resets the state of this voice after a sound has finished playing.
167 
168         The subclass must call this when it finishes playing a note and becomes available
169         to play new ones.
170 
171         It must either call it in the stopNote() method, or if the voice is tailing off,
172         then it should call it later during the renderNextBlock method, as soon as it
173         finishes its tail-off.
174 
175         It can also be called at any time during the render callback if the sound happens
176         to have finished, e.g. if it's playing a sample and the sample finishes.
177     */
178     void clearCurrentNote() noexcept;
179 
180     //==============================================================================
181     double currentSampleRate = 0.0;
182     MPENote currentlyPlayingNote;
183 
184 private:
185     //==============================================================================
186     friend class MPESynthesiser;
187 
188     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESynthesiserVoice)
189 };
190 
191 } // namespace juce
192