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 
27 namespace 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 {
52 public:
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  */
65  MPESynthesiserBase (MPEInstrument* instrument);
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 
183 protected:
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 
199 protected:
200  //==============================================================================
201  /** @internal */
202  std::unique_ptr<MPEInstrument> instrument;
203 
204 private:
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 /** @}*/
juce::AudioBuffer
A multi-channel buffer containing floating point audio samples.
Definition: juce_AudioSampleBuffer.h:37
juce::MPEInstrument
This class represents an instrument handling MPE.
Definition: juce_MPEInstrument.h:59
juce::MPESynthesiserBase::instrument
std::unique_ptr< MPEInstrument > instrument
Definition: juce_MPESynthesiserBase.h:202
JUCE_API
#define JUCE_API
This macro is added to all JUCE public class declarations.
Definition: juce_StandardHeader.h:143
juce::MidiBuffer
Holds a sequence of time-stamped midi events.
Definition: juce_MidiBuffer.h:46
juce::MPEZoneLayout
This class represents the current MPE zone layout of a device capable of handling MPE.
Definition: juce_MPEZoneLayout.h:48
juce::MPESynthesiserBase::getSampleRate
double getSampleRate() const noexcept
Returns the current target sample rate at which rendering is being done.
Definition: juce_MPESynthesiserBase.h:88
juce::MidiMessage
Encapsulates a MIDI message.
Definition: juce_MidiMessage.h:38
juce::Range
A general-purpose range object, that simply represents any linear range with a start and end point.
Definition: juce_Range.h:43
juce::MPESynthesiserBase
Derive from this class to create a basic audio generator capable of MPE.
Definition: juce_MPESynthesiserBase.h:50
juce::CriticalSection
A re-entrant mutex.
Definition: juce_CriticalSection.h:46
juce::MPEInstrument::Listener
Derive from this class to be informed about any changes in the expressive MIDI notes played by this i...
Definition: juce_MPEInstrument.h:244