OpenShot Library | libopenshot-audio 0.2.0
juce_MPESynthesiserBase.h
1
2/** @weakgroup juce_audio_basics-mpe
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
27namespace juce
28{
29
30//==============================================================================
31/**
32 Derive from this class to create a basic audio generator capable of MPE.
33 Implement the callbacks of MPEInstrument::Listener (noteAdded, notePressureChanged
34 etc.) to let your audio generator know that MPE notes were triggered, modulated,
35 or released. What to do inside them, and how that influences your audio generator,
36 is up to you!
37
38 This class uses an instance of MPEInstrument internally to handle the MPE
39 note state logic.
40
41 This class is a very low-level base class for an MPE instrument. If you need
42 something more sophisticated, have a look at MPESynthesiser. This class extends
43 MPESynthesiserBase by adding the concept of voices that can play notes,
44 a voice stealing algorithm, and much more.
45
46 @see MPESynthesiser, MPEInstrument
47
48 @tags{Audio}
49*/
51{
52public:
53 //==============================================================================
54 /** Constructor. */
56
57 /** Constructor.
58
59 If you use this constructor, the synthesiser will take ownership of the
60 provided instrument object, and will use it internally to handle the
61 MPE note state logic.
62 This is useful if you want to use an instance of your own class derived
63 from MPEInstrument for the MPE logic.
64 */
66
67 //==============================================================================
68 /** Returns the synthesiser's internal MPE zone layout.
69 This happens by value, to enforce thread-safety and class invariants.
70 */
71 MPEZoneLayout getZoneLayout() const noexcept;
72
73 /** Re-sets the synthesiser's internal MPE zone layout to the one passed in.
74 As a side effect, this will discard all currently playing notes,
75 call noteReleased for all of them, and disable legacy mode (if previously enabled).
76 */
77 void setZoneLayout (MPEZoneLayout newLayout);
78
79 //==============================================================================
80 /** Tells the synthesiser what the sample rate is for the audio it's being
81 used to render.
82 */
83 virtual void setCurrentPlaybackSampleRate (double sampleRate);
84
85 /** Returns the current target sample rate at which rendering is being done.
86 Subclasses may need to know this so that they can pitch things correctly.
87 */
88 double getSampleRate() const noexcept { return sampleRate; }
89
90 //==============================================================================
91 /** Creates the next block of audio output.
92
93 Call this to make sound. This will chop up the AudioBuffer into subBlock
94 pieces separated by events in the MIDI buffer, and then call
95 processNextSubBlock on each one of them. In between you will get calls
96 to noteAdded/Changed/Finished, where you can update parameters that
97 depend on those notes to use for your audio rendering.
98 */
99 template <typename floatType>
100 void renderNextBlock (AudioBuffer<floatType>& outputAudio,
101 const MidiBuffer& inputMidi,
102 int startSample,
103 int numSamples);
104
105 //==============================================================================
106 /** Handle incoming MIDI events (called from renderNextBlock).
107
108 The default implementation provided here simply forwards everything
109 to MPEInstrument::processNextMidiEvent, where it is used to update the
110 MPE notes, zones etc. MIDI messages not relevant for MPE are ignored.
111
112 This method can be overridden if you need to do custom MIDI handling
113 on top of MPE. The MPESynthesiser class overrides this to implement
114 callbacks for MIDI program changes and non-MPE-related MIDI controller
115 messages.
116 */
117 virtual void handleMidiEvent (const MidiMessage&);
118
119 //==============================================================================
120 /** Sets a minimum limit on the size to which audio sub-blocks will be divided when rendering.
121
122 When rendering, the audio blocks that are passed into renderNextBlock() will be split up
123 into smaller blocks that lie between all the incoming midi messages, and it is these smaller
124 sub-blocks that are rendered with multiple calls to renderVoices().
125
126 Obviously in a pathological case where there are midi messages on every sample, then
127 renderVoices() could be called once per sample and lead to poor performance, so this
128 setting allows you to set a lower limit on the block size.
129
130 The default setting is 32, which means that midi messages are accurate to about < 1ms
131 accuracy, which is probably fine for most purposes, but you may want to increase or
132 decrease this value for your synth.
133
134 If shouldBeStrict is true, the audio sub-blocks will strictly never be smaller than numSamples.
135
136 If shouldBeStrict is false (default), the first audio sub-block in the buffer is allowed
137 to be smaller, to make sure that the first MIDI event in a buffer will always be sample-accurate
138 (this can sometimes help to avoid quantisation or phasing issues).
139 */
140 void setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict = false) noexcept;
141
142 //==============================================================================
143 /** Puts the synthesiser into legacy mode.
144
145 @param pitchbendRange The note pitchbend range in semitones to use when in legacy mode.
146 Must be between 0 and 96, otherwise behaviour is undefined.
147 The default pitchbend range in legacy mode is +/- 2 semitones.
148 @param channelRange The range of MIDI channels to use for notes when in legacy mode.
149 The default is to use all MIDI channels (1-16).
150
151 To get out of legacy mode, set a new MPE zone layout using setZoneLayout.
152 */
153 void enableLegacyMode (int pitchbendRange = 2,
154 Range<int> channelRange = Range<int> (1, 17));
155
156 /** Returns true if the instrument is in legacy mode, false otherwise. */
157 bool isLegacyModeEnabled() const noexcept;
158
159 /** Returns the range of MIDI channels (1-16) to be used for notes when in legacy mode. */
160 Range<int> getLegacyModeChannelRange() const noexcept;
161
162 /** Re-sets the range of MIDI channels (1-16) to be used for notes when in legacy mode. */
163 void setLegacyModeChannelRange (Range<int> channelRange);
164
165 /** Returns the pitchbend range in semitones (0-96) to be used for notes when in legacy mode. */
166 int getLegacyModePitchbendRange() const noexcept;
167
168 /** Re-sets the pitchbend range in semitones (0-96) to be used for notes when in legacy mode. */
169 void setLegacyModePitchbendRange (int pitchbendRange);
170
171 //==============================================================================
172 using TrackingMode = MPEInstrument::TrackingMode;
173
174 /** Set the MPE tracking mode for the pressure dimension. */
175 void setPressureTrackingMode (TrackingMode modeToUse);
176
177 /** Set the MPE tracking mode for the pitchbend dimension. */
178 void setPitchbendTrackingMode (TrackingMode modeToUse);
179
180 /** Set the MPE tracking mode for the timbre dimension. */
181 void setTimbreTrackingMode (TrackingMode modeToUse);
182
183protected:
184 //==============================================================================
185 /** Implement this method to render your audio inside.
186 @see renderNextBlock
187 */
188 virtual void renderNextSubBlock (AudioBuffer<float>& outputAudio,
189 int startSample,
190 int numSamples) = 0;
191
192 /** Implement this method if you want to render 64-bit audio as well;
193 otherwise leave blank.
194 */
195 virtual void renderNextSubBlock (AudioBuffer<double>& /*outputAudio*/,
196 int /*startSample*/,
197 int /*numSamples*/) {}
198
199protected:
200 //==============================================================================
201 /** @internal */
202 std::unique_ptr<MPEInstrument> instrument;
203
204private:
205 //==============================================================================
206 CriticalSection noteStateLock;
207 double sampleRate = 0.0;
208 int minimumSubBlockSize = 32;
209 bool subBlockSubdivisionIsStrict = false;
210
211 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESynthesiserBase)
212};
213
214} // namespace juce
215
216/** @}*/
A multi-channel buffer containing floating point audio samples.
Derive from this class to be informed about any changes in the expressive MIDI notes played by this i...
This class represents an instrument handling MPE.
This class represents the current MPE zone layout of a device capable of handling MPE.
Holds a sequence of time-stamped midi events.
Encapsulates a MIDI message.
A general-purpose range object, that simply represents any linear range with a start and end point.
Definition juce_Range.h:44
#define JUCE_API
This macro is added to all JUCE public class declarations.
Derive from this class to create a basic audio generator capable of MPE.
std::unique_ptr< MPEInstrument > instrument
double getSampleRate() const noexcept
Returns the current target sample rate at which rendering is being done.