27 : instrument (defaultInstrument)
103template <
typename floatType>
115 const auto endSample = startSample + numSamples;
159 minimumSubBlockSize = numSamples;
198 void handleMidiEvent (
const MidiMessage& m)
override
201 events.order.emplace_back (CallbackKind::midi);
207 void renderNextSubBlock (AudioBuffer<float>&,
209 int numSamples)
override
211 events.blocks.push_back ({ startSample, numSamples });
212 events.order.emplace_back (CallbackKind::process);
220 for (
int i = 0; i != bufferLength; ++i)
221 result.addEvent ({}, i);
230 void runTest()
override
238 beginTest (
"Rendering sparse subblocks works");
240 const int blockSize = 512;
241 const auto midi = [&] { MidiBuffer b; b.addEvent ({}, blockSize / 2);
return b; }();
242 AudioBuffer<float>
audio (1, blockSize);
247 synth.setMinimumRenderingSubdivisionSize (1,
false);
248 synth.setCurrentPlaybackSampleRate (44100);
255 expect (e.blocks.size() == 2);
256 expect (e.messages.size() == 1);
261 CallbackKind::process });
265 beginTest (
"Rendering subblocks processes only contained midi events");
267 const int blockSize = 512;
269 AudioBuffer<float>
audio (1, blockSize);
274 synth.setMinimumRenderingSubdivisionSize (1,
false);
275 synth.setCurrentPlaybackSampleRate (44100);
283 expect (e.blocks.size() == 0);
284 expect (e.messages.size() == 0);
292 expect (e.blocks.size() == 0);
293 expect (e.messages.size() == 0);
301 expect (e.blocks.size() == 1);
302 expect (e.messages.size() == 1);
306 CallbackKind::process });
311 expect (e.blocks.size() == blockSize);
312 expect (e.messages.size() == blockSize);
315 expect (e.order.front() == CallbackKind::midi);
319 beginTest (
"Subblocks respect their minimum size");
321 const int blockSize = 512;
323 AudioBuffer<float>
audio (1, blockSize);
327 if (info.
size() <= 1)
336 for (
auto strict : {
false,
true })
342 synth.setCurrentPlaybackSampleRate (44100);
345 const auto& e =
synth.events;
346 expectWithinAbsoluteError (
float (e.blocks.size()),
349 expect (e.messages.size() == blockSize);
358 synth.setMinimumRenderingSubdivisionSize (32,
true);
359 synth.setCurrentPlaybackSampleRate (44100);
360 synth.renderNextBlock (
audio, MidiBuffer{}, 0, 16);
364 expect (
synth.events.messages.empty());
A multi-channel buffer containing floating point audio samples.
Automatically locks and unlocks a mutex object.
This class represents an instrument handling MPE.
void setPitchbendTrackingMode(TrackingMode modeToUse)
Set the MPE tracking mode for the pitchbend dimension.
void setLegacyModeChannelRange(Range< int > channelRange)
Re-sets the range of MIDI channels (1-16) to be used for notes when in legacy mode.
MPEZoneLayout getZoneLayout() const noexcept
Returns the current zone layout of the instrument.
void enableLegacyMode(int pitchbendRange=2, Range< int > channelRange=Range< int >(1, 17))
Puts the instrument into legacy mode.
TrackingMode
The MPE note tracking mode.
void setZoneLayout(MPEZoneLayout newLayout)
Re-sets the zone layout of the instrument to the one passed in.
virtual void processNextMidiEvent(const MidiMessage &message)
Process a MIDI message and trigger the appropriate method calls (noteOn, noteOff etc....
void setLegacyModePitchbendRange(int pitchbendRange)
Re-sets the pitchbend range in semitones (0-96) to be used for notes when in legacy mode.
bool isLegacyModeEnabled() const noexcept
Returns true if the instrument is in legacy mode, false otherwise.
void setPressureTrackingMode(TrackingMode modeToUse)
Set the MPE tracking mode for the pressure dimension.
void addListener(Listener *listenerToAdd)
Adds a listener.
void setTimbreTrackingMode(TrackingMode modeToUse)
Set the MPE tracking mode for the timbre dimension.
void releaseAllNotes()
Discard all currently playing notes.
Range< int > getLegacyModeChannelRange() const noexcept
Returns the range of MIDI channels (1-16) to be used for notes when in legacy mode.
int getLegacyModePitchbendRange() const noexcept
Returns the pitchbend range in semitones (0-96) to be used for notes when in legacy mode.
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.
This is a base class for classes that perform a unit test.
T emplace_back(T... args)
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
RangedDirectoryIterator begin(const RangedDirectoryIterator &it)
Returns the iterator that was passed in.
void setPitchbendTrackingMode(TrackingMode modeToUse)
Set the MPE tracking mode for the pitchbend dimension.
virtual void handleMidiEvent(const MidiMessage &)
Handle incoming MIDI events (called from renderNextBlock).
bool isLegacyModeEnabled() const noexcept
Returns true if the instrument is in legacy mode, false otherwise.
MPEZoneLayout getZoneLayout() const noexcept
Returns the synthesiser's internal MPE zone layout.
void setZoneLayout(MPEZoneLayout newLayout)
Re-sets the synthesiser's internal MPE zone layout to the one passed in.
int getLegacyModePitchbendRange() const noexcept
Returns the pitchbend range in semitones (0-96) to be used for notes when in legacy mode.
void setLegacyModeChannelRange(Range< int > channelRange)
Re-sets the range of MIDI channels (1-16) to be used for notes when in legacy mode.
void setLegacyModePitchbendRange(int pitchbendRange)
Re-sets the pitchbend range in semitones (0-96) to be used for notes when in legacy mode.
void enableLegacyMode(int pitchbendRange=2, Range< int > channelRange=Range< int >(1, 17))
Puts the synthesiser into legacy mode.
void setTimbreTrackingMode(TrackingMode modeToUse)
Set the MPE tracking mode for the timbre dimension.
void setPressureTrackingMode(TrackingMode modeToUse)
Set the MPE tracking mode for the pressure dimension.
Range< int > getLegacyModeChannelRange() const noexcept
Returns the range of MIDI channels (1-16) to be used for notes when in legacy mode.
virtual void setCurrentPlaybackSampleRate(double sampleRate)
Tells the synthesiser what the sample rate is for the audio it's being used to render.
void renderNextBlock(AudioBuffer< floatType > &outputAudio, const MidiBuffer &inputMidi, int startSample, int numSamples)
Creates the next block of audio output.
void setMinimumRenderingSubdivisionSize(int numSamples, bool shouldBeStrict=false) noexcept
Sets a minimum limit on the size to which audio sub-blocks will be divided when rendering.
virtual void renderNextSubBlock(AudioBuffer< float > &outputAudio, int startSample, int numSamples)=0
Implement this method to render your audio inside.
MPESynthesiserBase()
Constructor.