Loading...
Searching...
No Matches
juce_Synthesiser.cpp
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
SynthesiserSound::SynthesiserSound() {}
SynthesiserSound::~SynthesiserSound() {}
//==============================================================================
SynthesiserVoice::SynthesiserVoice() {}
SynthesiserVoice::~SynthesiserVoice() {}
bool SynthesiserVoice::isPlayingChannel (const int midiChannel) const
{
return currentPlayingMidiChannel == midiChannel;
}
void SynthesiserVoice::setCurrentPlaybackSampleRate (const double newRate)
{
currentSampleRate = newRate;
}
bool SynthesiserVoice::isVoiceActive() const
{
return getCurrentlyPlayingNote() >= 0;
}
void SynthesiserVoice::clearCurrentNote()
{
currentlyPlayingNote = -1;
currentlyPlayingSound = nullptr;
currentPlayingMidiChannel = 0;
}
void SynthesiserVoice::aftertouchChanged (int) {}
void SynthesiserVoice::channelPressureChanged (int) {}
bool SynthesiserVoice::wasStartedBefore (const SynthesiserVoice& other) const noexcept
{
return noteOnTime < other.noteOnTime;
}
void SynthesiserVoice::renderNextBlock (AudioBuffer<double>& outputBuffer,
int startSample, int numSamples)
{
AudioBuffer<double> subBuffer (outputBuffer.getArrayOfWritePointers(),
outputBuffer.getNumChannels(),
startSample, numSamples);
tempBuffer.makeCopyOf (subBuffer, true);
renderNextBlock (tempBuffer, 0, numSamples);
subBuffer.makeCopyOf (tempBuffer, true);
}
//==============================================================================
Synthesiser::Synthesiser()
{
for (int i = 0; i < numElementsInArray (lastPitchWheelValues); ++i)
lastPitchWheelValues[i] = 0x2000;
}
Synthesiser::~Synthesiser()
{
}
//==============================================================================
SynthesiserVoice* Synthesiser::getVoice (const int index) const
{
const ScopedLock sl (lock);
return voices [index];
}
void Synthesiser::clearVoices()
{
const ScopedLock sl (lock);
voices.clear();
}
SynthesiserVoice* Synthesiser::addVoice (SynthesiserVoice* const newVoice)
{
SynthesiserVoice* voice;
{
const ScopedLock sl (lock);
newVoice->setCurrentPlaybackSampleRate (sampleRate);
voice = voices.add (newVoice);
}
{
const ScopedLock sl (stealLock);
usableVoicesToStealArray.ensureStorageAllocated (voices.size() + 1);
}
return voice;
}
void Synthesiser::removeVoice (const int index)
{
const ScopedLock sl (lock);
voices.remove (index);
}
void Synthesiser::clearSounds()
{
const ScopedLock sl (lock);
sounds.clear();
}
SynthesiserSound* Synthesiser::addSound (const SynthesiserSound::Ptr& newSound)
{
const ScopedLock sl (lock);
return sounds.add (newSound);
}
void Synthesiser::removeSound (const int index)
{
const ScopedLock sl (lock);
sounds.remove (index);
}
void Synthesiser::setNoteStealingEnabled (const bool shouldSteal)
{
shouldStealNotes = shouldSteal;
}
void Synthesiser::setMinimumRenderingSubdivisionSize (int numSamples, bool shouldBeStrict) noexcept
{
jassert (numSamples > 0); // it wouldn't make much sense for this to be less than 1
minimumSubBlockSize = numSamples;
subBlockSubdivisionIsStrict = shouldBeStrict;
}
//==============================================================================
void Synthesiser::setCurrentPlaybackSampleRate (const double newRate)
{
if (! approximatelyEqual (sampleRate, newRate))
{
const ScopedLock sl (lock);
allNotesOff (0, false);
sampleRate = newRate;
for (auto* voice : voices)
voice->setCurrentPlaybackSampleRate (newRate);
}
}
template <typename floatType>
void Synthesiser::processNextBlock (AudioBuffer<floatType>& outputAudio,
const MidiBuffer& midiData,
int startSample,
int numSamples)
{
// must set the sample rate before using this!
jassert (! exactlyEqual (sampleRate, 0.0));
const int targetChannels = outputAudio.getNumChannels();
auto midiIterator = midiData.findNextSamplePosition (startSample);
bool firstEvent = true;
const ScopedLock sl (lock);
for (; numSamples > 0; ++midiIterator)
{
if (midiIterator == midiData.cend())
{
if (targetChannels > 0)
renderVoices (outputAudio, startSample, numSamples);
return;
}
const auto metadata = *midiIterator;
const int samplesToNextMidiMessage = metadata.samplePosition - startSample;
if (samplesToNextMidiMessage >= numSamples)
{
if (targetChannels > 0)
renderVoices (outputAudio, startSample, numSamples);
handleMidiEvent (metadata.getMessage());
break;
}
if (samplesToNextMidiMessage < ((firstEvent && ! subBlockSubdivisionIsStrict) ? 1 : minimumSubBlockSize))
{
handleMidiEvent (metadata.getMessage());
continue;
}
firstEvent = false;
if (targetChannels > 0)
renderVoices (outputAudio, startSample, samplesToNextMidiMessage);
handleMidiEvent (metadata.getMessage());
startSample += samplesToNextMidiMessage;
numSamples -= samplesToNextMidiMessage;
}
std::for_each (midiIterator,
midiData.cend(),
[&] (const MidiMessageMetadata& meta) { handleMidiEvent (meta.getMessage()); });
}
// explicit template instantiation
template void Synthesiser::processNextBlock<float> (AudioBuffer<float>&, const MidiBuffer&, int, int);
template void Synthesiser::processNextBlock<double> (AudioBuffer<double>&, const MidiBuffer&, int, int);
void Synthesiser::renderNextBlock (AudioBuffer<float>& outputAudio, const MidiBuffer& inputMidi,
int startSample, int numSamples)
{
processNextBlock (outputAudio, inputMidi, startSample, numSamples);
}
void Synthesiser::renderNextBlock (AudioBuffer<double>& outputAudio, const MidiBuffer& inputMidi,
int startSample, int numSamples)
{
processNextBlock (outputAudio, inputMidi, startSample, numSamples);
}
void Synthesiser::renderVoices (AudioBuffer<float>& buffer, int startSample, int numSamples)
{
for (auto* voice : voices)
voice->renderNextBlock (buffer, startSample, numSamples);
}
void Synthesiser::renderVoices (AudioBuffer<double>& buffer, int startSample, int numSamples)
{
for (auto* voice : voices)
voice->renderNextBlock (buffer, startSample, numSamples);
}
void Synthesiser::handleMidiEvent (const MidiMessage& m)
{
const int channel = m.getChannel();
if (m.isNoteOn())
{
noteOn (channel, m.getNoteNumber(), m.getFloatVelocity());
}
else if (m.isNoteOff())
{
noteOff (channel, m.getNoteNumber(), m.getFloatVelocity(), true);
}
else if (m.isAllNotesOff() || m.isAllSoundOff())
{
allNotesOff (channel, true);
}
else if (m.isPitchWheel())
{
const int wheelPos = m.getPitchWheelValue();
lastPitchWheelValues [channel - 1] = wheelPos;
handlePitchWheel (channel, wheelPos);
}
else if (m.isAftertouch())
{
handleAftertouch (channel, m.getNoteNumber(), m.getAfterTouchValue());
}
else if (m.isChannelPressure())
{
handleChannelPressure (channel, m.getChannelPressureValue());
}
else if (m.isController())
{
handleController (channel, m.getControllerNumber(), m.getControllerValue());
}
else if (m.isProgramChange())
{
handleProgramChange (channel, m.getProgramChangeNumber());
}
}
//==============================================================================
void Synthesiser::noteOn (const int midiChannel,
const int midiNoteNumber,
const float velocity)
{
const ScopedLock sl (lock);
for (auto* sound : sounds)
{
if (sound->appliesToNote (midiNoteNumber) && sound->appliesToChannel (midiChannel))
{
// If hitting a note that's still ringing, stop it first (it could be
// still playing because of the sustain or sostenuto pedal).
for (auto* voice : voices)
if (voice->getCurrentlyPlayingNote() == midiNoteNumber && voice->isPlayingChannel (midiChannel))
stopVoice (voice, 1.0f, true);
startVoice (findFreeVoice (sound, midiChannel, midiNoteNumber, shouldStealNotes),
sound, midiChannel, midiNoteNumber, velocity);
}
}
}
void Synthesiser::startVoice (SynthesiserVoice* const voice,
SynthesiserSound* const sound,
const int midiChannel,
const int midiNoteNumber,
const float velocity)
{
if (voice != nullptr && sound != nullptr)
{
if (voice->currentlyPlayingSound != nullptr)
voice->stopNote (0.0f, false);
voice->currentlyPlayingNote = midiNoteNumber;
voice->currentPlayingMidiChannel = midiChannel;
voice->noteOnTime = ++lastNoteOnCounter;
voice->currentlyPlayingSound = sound;
voice->setKeyDown (true);
voice->setSostenutoPedalDown (false);
voice->setSustainPedalDown (sustainPedalsDown[midiChannel]);
voice->startNote (midiNoteNumber, velocity, sound,
lastPitchWheelValues [midiChannel - 1]);
}
}
void Synthesiser::stopVoice (SynthesiserVoice* voice, float velocity, const bool allowTailOff)
{
jassert (voice != nullptr);
voice->stopNote (velocity, allowTailOff);
// the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()!
jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == nullptr));
}
void Synthesiser::noteOff (const int midiChannel,
const int midiNoteNumber,
const float velocity,
const bool allowTailOff)
{
const ScopedLock sl (lock);
for (auto* voice : voices)
{
if (voice->getCurrentlyPlayingNote() == midiNoteNumber
&& voice->isPlayingChannel (midiChannel))
{
if (auto sound = voice->getCurrentlyPlayingSound())
{
if (sound->appliesToNote (midiNoteNumber)
&& sound->appliesToChannel (midiChannel))
{
jassert (! voice->keyIsDown || voice->isSustainPedalDown() == sustainPedalsDown [midiChannel]);
voice->setKeyDown (false);
if (! (voice->isSustainPedalDown() || voice->isSostenutoPedalDown()))
stopVoice (voice, velocity, allowTailOff);
}
}
}
}
}
void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff)
{
const ScopedLock sl (lock);
for (auto* voice : voices)
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->stopNote (1.0f, allowTailOff);
sustainPedalsDown.clear();
}
void Synthesiser::handlePitchWheel (const int midiChannel, const int wheelValue)
{
const ScopedLock sl (lock);
for (auto* voice : voices)
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->pitchWheelMoved (wheelValue);
}
void Synthesiser::handleController (const int midiChannel,
const int controllerNumber,
const int controllerValue)
{
switch (controllerNumber)
{
case 0x40: handleSustainPedal (midiChannel, controllerValue >= 64); break;
case 0x42: handleSostenutoPedal (midiChannel, controllerValue >= 64); break;
case 0x43: handleSoftPedal (midiChannel, controllerValue >= 64); break;
default: break;
}
const ScopedLock sl (lock);
for (auto* voice : voices)
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->controllerMoved (controllerNumber, controllerValue);
}
void Synthesiser::handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue)
{
const ScopedLock sl (lock);
for (auto* voice : voices)
if (voice->getCurrentlyPlayingNote() == midiNoteNumber
&& (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)))
voice->aftertouchChanged (aftertouchValue);
}
void Synthesiser::handleChannelPressure (int midiChannel, int channelPressureValue)
{
const ScopedLock sl (lock);
for (auto* voice : voices)
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->channelPressureChanged (channelPressureValue);
}
void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
{
jassert (midiChannel > 0 && midiChannel <= 16);
const ScopedLock sl (lock);
if (isDown)
{
sustainPedalsDown.setBit (midiChannel);
for (auto* voice : voices)
if (voice->isPlayingChannel (midiChannel) && voice->isKeyDown())
voice->setSustainPedalDown (true);
}
else
{
for (auto* voice : voices)
{
if (voice->isPlayingChannel (midiChannel))
{
voice->setSustainPedalDown (false);
if (! (voice->isKeyDown() || voice->isSostenutoPedalDown()))
stopVoice (voice, 1.0f, true);
}
}
sustainPedalsDown.clearBit (midiChannel);
}
}
void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown)
{
jassert (midiChannel > 0 && midiChannel <= 16);
const ScopedLock sl (lock);
for (auto* voice : voices)
{
if (voice->isPlayingChannel (midiChannel))
{
if (isDown)
voice->setSostenutoPedalDown (true);
else if (voice->isSostenutoPedalDown())
stopVoice (voice, 1.0f, true);
}
}
}
void Synthesiser::handleSoftPedal ([[maybe_unused]] int midiChannel, bool /*isDown*/)
{
jassert (midiChannel > 0 && midiChannel <= 16);
}
void Synthesiser::handleProgramChange ([[maybe_unused]] int midiChannel,
[[maybe_unused]] int programNumber)
{
jassert (midiChannel > 0 && midiChannel <= 16);
}
//==============================================================================
SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay,
int midiChannel, int midiNoteNumber,
const bool stealIfNoneAvailable) const
{
const ScopedLock sl (lock);
for (auto* voice : voices)
if ((! voice->isVoiceActive()) && voice->canPlaySound (soundToPlay))
return voice;
if (stealIfNoneAvailable)
return findVoiceToSteal (soundToPlay, midiChannel, midiNoteNumber);
return nullptr;
}
SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
int /*midiChannel*/, int midiNoteNumber) const
{
// This voice-stealing algorithm applies the following heuristics:
// - Re-use the oldest notes first
// - Protect the lowest & topmost notes, even if sustained, but not if they've been released.
// apparently you are trying to render audio without having any voices...
jassert (! voices.isEmpty());
// These are the voices we want to protect (ie: only steal if unavoidable)
SynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase
SynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase
// All major OSes use double-locking so this will be lock- and wait-free as long as the lock is not
// contended. This is always the case if you do not call findVoiceToSteal on multiple threads at
// the same time.
const ScopedLock sl (stealLock);
// this is a list of voices we can steal, sorted by how long they've been running
usableVoicesToStealArray.clear();
for (auto* voice : voices)
{
if (voice->canPlaySound (soundToPlay))
{
jassert (voice->isVoiceActive()); // We wouldn't be here otherwise
usableVoicesToStealArray.add (voice);
// NB: Using a functor rather than a lambda here due to scare-stories about
// compilers generating code containing heap allocations..
struct Sorter
{
bool operator() (const SynthesiserVoice* a, const SynthesiserVoice* b) const noexcept { return a->wasStartedBefore (*b); }
};
std::sort (usableVoicesToStealArray.begin(), usableVoicesToStealArray.end(), Sorter());
if (! voice->isPlayingButReleased()) // Don't protect released notes
{
auto note = voice->getCurrentlyPlayingNote();
if (low == nullptr || note < low->getCurrentlyPlayingNote())
low = voice;
if (top == nullptr || note > top->getCurrentlyPlayingNote())
top = voice;
}
}
}
// Eliminate pathological cases (ie: only 1 note playing): we always give precedence to the lowest note(s)
if (top == low)
top = nullptr;
// The oldest note that's playing with the target pitch is ideal..
for (auto* voice : usableVoicesToStealArray)
if (voice->getCurrentlyPlayingNote() == midiNoteNumber)
return voice;
// Oldest voice that has been released (no finger on it and not held by sustain pedal)
for (auto* voice : usableVoicesToStealArray)
if (voice != low && voice != top && voice->isPlayingButReleased())
return voice;
// Oldest voice that doesn't have a finger on it:
for (auto* voice : usableVoicesToStealArray)
if (voice != low && voice != top && ! voice->isKeyDown())
return voice;
// Oldest voice that isn't protected
for (auto* voice : usableVoicesToStealArray)
if (voice != low && voice != top)
return voice;
// We've only got "protected" voices now: lowest note takes priority
jassert (low != nullptr);
// Duophonic synth: give priority to the bass note:
if (top != nullptr)
return top;
return low;
}
} // namespace juce
juce::AudioBuffer
Definition juce_AudioSampleBuffer.h:34
juce::AudioBuffer::makeCopyOf
void makeCopyOf(const AudioBuffer< OtherType > &other, bool avoidReallocating=false)
Definition juce_AudioSampleBuffer.h:525
juce::AudioBuffer::getNumChannels
int getNumChannels() const noexcept
Definition juce_AudioSampleBuffer.h:236
juce::AudioBuffer::getArrayOfWritePointers
Type *const * getArrayOfWritePointers() noexcept
Definition juce_AudioSampleBuffer.h:342
juce::MidiBuffer
Definition juce_MidiBuffer.h:145
juce::MidiBuffer::findNextSamplePosition
MidiBufferIterator findNextSamplePosition(int samplePosition) const noexcept
Definition juce_MidiBuffer.cpp:203
juce::MidiBuffer::cend
MidiBufferIterator cend() const noexcept
Definition juce_MidiBuffer.h:268
juce::MidiMessage
Definition juce_MidiMessage.h:35
juce::MidiMessage::isAftertouch
bool isAftertouch() const noexcept
Definition juce_MidiMessage.cpp:471
juce::MidiMessage::isNoteOn
bool isNoteOn(bool returnTrueForVelocity0=false) const noexcept
Definition juce_MidiMessage.cpp:410
juce::MidiMessage::getFloatVelocity
float getFloatVelocity() const noexcept
Definition juce_MidiMessage.cpp:451
juce::MidiMessage::getChannel
int getChannel() const noexcept
Definition juce_MidiMessage.cpp:379
juce::MidiMessage::isProgramChange
bool isProgramChange() const noexcept
Definition juce_MidiMessage.cpp:524
juce::MidiMessage::isController
bool isController() const noexcept
Definition juce_MidiMessage.cpp:563
juce::MidiMessage::isAllSoundOff
bool isAllSoundOff() const noexcept
Definition juce_MidiMessage.cpp:647
juce::MidiMessage::getControllerNumber
int getControllerNumber() const noexcept
Definition juce_MidiMessage.cpp:574
juce::MidiMessage::getChannelPressureValue
int getChannelPressureValue() const noexcept
Definition juce_MidiMessage.cpp:500
juce::MidiMessage::isNoteOff
bool isNoteOff(bool returnTrueForNoteOnVelocity0=true) const noexcept
Definition juce_MidiMessage.cpp:418
juce::MidiMessage::isPitchWheel
bool isPitchWheel() const noexcept
Definition juce_MidiMessage.cpp:542
juce::MidiMessage::getNoteNumber
int getNoteNumber() const noexcept
Definition juce_MidiMessage.cpp:432
juce::MidiMessage::getProgramChangeNumber
int getProgramChangeNumber() const noexcept
Definition juce_MidiMessage.cpp:529
juce::MidiMessage::getAfterTouchValue
int getAfterTouchValue() const noexcept
Definition juce_MidiMessage.cpp:476
juce::MidiMessage::getControllerValue
int getControllerValue() const noexcept
Definition juce_MidiMessage.cpp:580
juce::MidiMessage::isAllNotesOff
bool isAllNotesOff() const noexcept
Definition juce_MidiMessage.cpp:636
juce::MidiMessage::isChannelPressure
bool isChannelPressure() const noexcept
Definition juce_MidiMessage.cpp:495
juce::MidiMessage::getPitchWheelValue
int getPitchWheelValue() const noexcept
Definition juce_MidiMessage.cpp:547
juce::SynthesiserSound
Definition juce_Synthesiser.h:42
juce::SynthesiserSound::~SynthesiserSound
~SynthesiserSound() override
Definition juce_Synthesiser.cpp:27
juce::SynthesiserSound::Ptr
ReferenceCountedObjectPtr< SynthesiserSound > Ptr
Definition juce_Synthesiser.h:67
juce::SynthesiserVoice
Definition juce_Synthesiser.h:88
juce::SynthesiserVoice::stopNote
virtual void stopNote(float velocity, bool allowTailOff)=0
juce::SynthesiserVoice::setSustainPedalDown
void setSustainPedalDown(bool isNowDown) noexcept
Definition juce_Synthesiser.h:232
juce::SynthesiserVoice::SynthesiserVoice
SynthesiserVoice()
Definition juce_Synthesiser.cpp:30
juce::SynthesiserVoice::channelPressureChanged
virtual void channelPressureChanged(int newChannelPressureValue)
Definition juce_Synthesiser.cpp:56
juce::SynthesiserVoice::setSostenutoPedalDown
void setSostenutoPedalDown(bool isNowDown) noexcept
Definition juce_Synthesiser.h:238
juce::SynthesiserVoice::renderNextBlock
virtual void renderNextBlock(AudioBuffer< float > &outputBuffer, int startSample, int numSamples)=0
juce::SynthesiserVoice::isPlayingChannel
virtual bool isPlayingChannel(int midiChannel) const
Definition juce_Synthesiser.cpp:33
juce::SynthesiserVoice::isKeyDown
bool isKeyDown() const noexcept
Definition juce_Synthesiser.h:221
juce::SynthesiserVoice::setKeyDown
void setKeyDown(bool isNowDown) noexcept
Definition juce_Synthesiser.h:226
juce::SynthesiserVoice::setCurrentPlaybackSampleRate
virtual void setCurrentPlaybackSampleRate(double newRate)
Definition juce_Synthesiser.cpp:38
juce::SynthesiserVoice::aftertouchChanged
virtual void aftertouchChanged(int newAftertouchValue)
Definition juce_Synthesiser.cpp:55
juce::SynthesiserVoice::getCurrentlyPlayingNote
int getCurrentlyPlayingNote() const noexcept
Definition juce_Synthesiser.h:101
juce::SynthesiserVoice::startNote
virtual void startNote(int midiNoteNumber, float velocity, SynthesiserSound *sound, int currentPitchWheelPosition)=0
juce::SynthesiserVoice::clearCurrentNote
void clearCurrentNote()
Definition juce_Synthesiser.cpp:48
juce::SynthesiserVoice::wasStartedBefore
bool wasStartedBefore(const SynthesiserVoice &other) const noexcept
Definition juce_Synthesiser.cpp:58
juce::SynthesiserVoice::~SynthesiserVoice
virtual ~SynthesiserVoice()
Definition juce_Synthesiser.cpp:31
juce::SynthesiserVoice::isPlayingButReleased
bool isPlayingButReleased() const noexcept
Definition juce_Synthesiser.h:241
juce::SynthesiserVoice::getCurrentlyPlayingSound
SynthesiserSound::Ptr getCurrentlyPlayingSound() const noexcept
Definition juce_Synthesiser.h:106
juce::SynthesiserVoice::isVoiceActive
virtual bool isVoiceActive() const
Definition juce_Synthesiser.cpp:43
juce::Synthesiser::Synthesiser
Synthesiser()
Definition juce_Synthesiser.cpp:76
juce::Synthesiser::~Synthesiser
virtual ~Synthesiser()
Definition juce_Synthesiser.cpp:82
juce::Synthesiser::findFreeVoice
virtual SynthesiserVoice * findFreeVoice(SynthesiserSound *soundToPlay, int midiChannel, int midiNoteNumber, bool stealIfNoneAvailable) const
Definition juce_Synthesiser.cpp:497
juce::Synthesiser::handleProgramChange
virtual void handleProgramChange(int midiChannel, int programNumber)
Definition juce_Synthesiser.cpp:490
juce::Synthesiser::removeVoice
void removeVoice(int index)
Definition juce_Synthesiser.cpp:117
juce::Synthesiser::startVoice
void startVoice(SynthesiserVoice *voice, SynthesiserSound *sound, int midiChannel, int midiNoteNumber, float velocity)
Definition juce_Synthesiser.cpp:317
juce::Synthesiser::handleAftertouch
virtual void handleAftertouch(int midiChannel, int midiNoteNumber, int aftertouchValue)
Definition juce_Synthesiser.cpp:419
juce::Synthesiser::renderNextBlock
void renderNextBlock(AudioBuffer< float > &outputAudio, const MidiBuffer &inputMidi, int startSample, int numSamples)
Definition juce_Synthesiser.cpp:230
juce::Synthesiser::handleController
virtual void handleController(int midiChannel, int controllerNumber, int controllerValue)
Definition juce_Synthesiser.cpp:400
juce::Synthesiser::clearSounds
void clearSounds()
Definition juce_Synthesiser.cpp:123
juce::Synthesiser::findVoiceToSteal
virtual SynthesiserVoice * findVoiceToSteal(SynthesiserSound *soundToPlay, int midiChannel, int midiNoteNumber) const
Definition juce_Synthesiser.cpp:513
juce::Synthesiser::handleSoftPedal
virtual void handleSoftPedal(int midiChannel, bool isDown)
Definition juce_Synthesiser.cpp:485
juce::Synthesiser::removeSound
void removeSound(int index)
Definition juce_Synthesiser.cpp:135
juce::Synthesiser::allNotesOff
virtual void allNotesOff(int midiChannel, bool allowTailOff)
Definition juce_Synthesiser.cpp:380
juce::Synthesiser::addVoice
SynthesiserVoice * addVoice(SynthesiserVoice *newVoice)
Definition juce_Synthesiser.cpp:99
juce::Synthesiser::stopVoice
void stopVoice(SynthesiserVoice *, float velocity, bool allowTailOff)
Definition juce_Synthesiser.cpp:341
juce::Synthesiser::addSound
SynthesiserSound * addSound(const SynthesiserSound::Ptr &newSound)
Definition juce_Synthesiser.cpp:129
juce::Synthesiser::renderVoices
virtual void renderVoices(AudioBuffer< float > &outputAudio, int startSample, int numSamples)
Definition juce_Synthesiser.cpp:242
juce::Synthesiser::handleMidiEvent
virtual void handleMidiEvent(const MidiMessage &)
Definition juce_Synthesiser.cpp:254
juce::Synthesiser::setNoteStealingEnabled
void setNoteStealingEnabled(bool shouldStealNotes)
Definition juce_Synthesiser.cpp:141
juce::Synthesiser::handlePitchWheel
virtual void handlePitchWheel(int midiChannel, int wheelValue)
Definition juce_Synthesiser.cpp:391
juce::Synthesiser::lock
CriticalSection lock
Definition juce_Synthesiser.h:563
juce::Synthesiser::lastPitchWheelValues
int lastPitchWheelValues[16]
Definition juce_Synthesiser.h:569
juce::Synthesiser::noteOn
virtual void noteOn(int midiChannel, int midiNoteNumber, float velocity)
Definition juce_Synthesiser.cpp:295
juce::Synthesiser::getVoice
SynthesiserVoice * getVoice(int index) const
Definition juce_Synthesiser.cpp:87
juce::Synthesiser::noteOff
virtual void noteOff(int midiChannel, int midiNoteNumber, float velocity, bool allowTailOff)
Definition juce_Synthesiser.cpp:351
juce::Synthesiser::handleChannelPressure
virtual void handleChannelPressure(int midiChannel, int channelPressureValue)
Definition juce_Synthesiser.cpp:429
juce::Synthesiser::clearVoices
void clearVoices()
Definition juce_Synthesiser.cpp:93
juce::Synthesiser::setCurrentPlaybackSampleRate
virtual void setCurrentPlaybackSampleRate(double sampleRate)
Definition juce_Synthesiser.cpp:154
juce::Synthesiser::setMinimumRenderingSubdivisionSize
void setMinimumRenderingSubdivisionSize(int numSamples, bool shouldBeStrict=false) noexcept
Definition juce_Synthesiser.cpp:146
juce::Synthesiser::handleSustainPedal
virtual void handleSustainPedal(int midiChannel, bool isDown)
Definition juce_Synthesiser.cpp:438
juce::Synthesiser::handleSostenutoPedal
virtual void handleSostenutoPedal(int midiChannel, bool isDown)
Definition juce_Synthesiser.cpp:468