Documented the voices
This commit is contained in:
parent
fd52e93294
commit
ffa134b02b
1 changed files with 190 additions and 2 deletions
|
|
@ -36,49 +36,237 @@
|
|||
#include <memory>
|
||||
|
||||
namespace sfz {
|
||||
/**
|
||||
* @brief The SFZ voice are the polyphony holders. They get activated by the synth
|
||||
* and tasked to play a given region until the end, stopping on note-offs, off-groups
|
||||
* or natural sample decay.
|
||||
*
|
||||
*/
|
||||
class Voice {
|
||||
public:
|
||||
Voice() = delete;
|
||||
/**
|
||||
* @brief Construct a new voice with the midistate singleton
|
||||
*
|
||||
* @param midiState
|
||||
*/
|
||||
Voice(const MidiState& midiState);
|
||||
enum class TriggerType {
|
||||
NoteOn,
|
||||
NoteOff,
|
||||
CC
|
||||
};
|
||||
/**
|
||||
* @brief Change the sample rate of the voice. This is used to compute all
|
||||
* pitch related transformations so it needs to be propagated from the synth
|
||||
* at all times.
|
||||
*
|
||||
* @param sampleRate
|
||||
*/
|
||||
void setSampleRate(float sampleRate) noexcept;
|
||||
/**
|
||||
* @brief Set the expected block size. If the block size is not fixed, set an
|
||||
* upper bound. The voice will adapt at each callback to the actual number of
|
||||
* samples requested but this function will allocate temporary buffers that are
|
||||
* needed for proper functioning.
|
||||
*
|
||||
* @param samplesPerBlock
|
||||
*/
|
||||
void setSamplesPerBlock(int samplesPerBlock) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start playing a region after a short delay for different triggers (note on, off, cc)
|
||||
*
|
||||
* @param region
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param number
|
||||
* @param value
|
||||
* @param triggerType
|
||||
*/
|
||||
void startVoice(Region* region, int delay, int channel, int number, uint8_t value, TriggerType triggerType) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Tells the voice that it should expect to receive a file at some point using the
|
||||
* setFileData() function. The ticket is a unique identifier that will prevent the file data
|
||||
* to be set "too late"; if the voice receives the file for an older ticket, it will discard
|
||||
* it.
|
||||
*
|
||||
* @param ticket
|
||||
*/
|
||||
void expectFileData(unsigned ticket);
|
||||
/**
|
||||
* @brief Sets the file data for a given ticket. The voice can freely release and destroy the
|
||||
* shared pointer, as it will be garbage collected by the file pool afterwards.
|
||||
*
|
||||
* @param file
|
||||
* @param ticket
|
||||
*/
|
||||
void setFileData(std::shared_ptr<AudioBuffer<float>> file, unsigned ticket) noexcept;
|
||||
/**
|
||||
* @brief Register a note-off event; this may trigger a release.
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param noteNumber
|
||||
* @param velocity
|
||||
*/
|
||||
void registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity) noexcept;
|
||||
/**
|
||||
* @brief Register a CC event; this may trigger a release. If the voice is playing and its
|
||||
* region has CC modifiers, it will use this value to compute the CC envelope to apply to the
|
||||
* parameter.
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param ccNumber
|
||||
* @param ccValue
|
||||
*/
|
||||
void registerCC(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept;
|
||||
/**
|
||||
* @brief Register a pitch wheel event; for now this does nothing
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param pitch
|
||||
*/
|
||||
void registerPitchWheel(int delay, int channel, int pitch) noexcept;
|
||||
/**
|
||||
* @brief Register an aftertouch event; for now this does nothing
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param aftertouch
|
||||
*/
|
||||
void registerAftertouch(int delay, int channel, uint8_t aftertouch) noexcept;
|
||||
/**
|
||||
* @brief Register a tempo event; for now this does nothing
|
||||
*
|
||||
* @param delay
|
||||
* @param channel
|
||||
* @param pitch
|
||||
*/
|
||||
void registerTempo(int delay, float secondsPerQuarter) noexcept;
|
||||
/**
|
||||
* @brief Checks if the voice should be offed by another starting in the group specified.
|
||||
* This will trigger the release if true.
|
||||
*
|
||||
* @param delay
|
||||
* @param group
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool checkOffGroup(int delay, uint32_t group) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Render a block of data for this voice into the span
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
void renderBlock(AudioSpan<float, 2> buffer) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Is the voice free?
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool isFree() const noexcept;
|
||||
/**
|
||||
* @brief Can the voice be "stolen" and reused (i.e. is it releasing)
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool canBeStolen() const noexcept;
|
||||
/**
|
||||
* @brief Get the number that triggered the voice (note number or cc number)
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int getTriggerNumber() const noexcept;
|
||||
/**
|
||||
* @brief Get the channel that triggered the voice
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int getTriggerChannel() const noexcept;
|
||||
/**
|
||||
* @brief Get the value that triggered the voice (note velocity or cc value)
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t getTriggerValue() const noexcept;
|
||||
/**
|
||||
* @brief Get the type of trigger
|
||||
*
|
||||
* @return TriggerType
|
||||
*/
|
||||
TriggerType getTriggerType() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Reset the voice to its initial values
|
||||
*
|
||||
*/
|
||||
void reset() noexcept;
|
||||
/**
|
||||
* @brief Clear the loaded file data if it's not useful anymore
|
||||
*
|
||||
*/
|
||||
void garbageCollect() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get the mean squared power of the last rendered block. This is used
|
||||
* to determine which voice to steal if there are too many notes flying around.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
float getMeanSquaredAverage() const noexcept;
|
||||
/**
|
||||
* @brief Get the position of the voice in the source, in samples
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t getSourcePosition() const noexcept;
|
||||
private:
|
||||
/**
|
||||
* @brief Fill a span with data from a file source. This is the first step
|
||||
* in rendering each block of data.
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
void fillWithData(AudioSpan<float> buffer) noexcept;
|
||||
/**
|
||||
* @brief Fill a span with data from a generator source. This is the first step
|
||||
* in rendering each block of data.
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
void fillWithGenerator(AudioSpan<float> buffer) noexcept;
|
||||
/**
|
||||
* @brief Computes the values for the envelope depending on the note or CC number and the velocity/cc value
|
||||
*
|
||||
* @param delay
|
||||
* @param velocity
|
||||
*/
|
||||
void prepareEGEnvelope(int delay, uint8_t velocity) noexcept;
|
||||
/**
|
||||
* @brief The function processing a mono sample source
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
void processMono(AudioSpan<float> buffer) noexcept;
|
||||
/**
|
||||
* @brief The function processing a stereo sample source
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
void processStereo(AudioSpan<float> buffer) noexcept;
|
||||
/**
|
||||
* @brief Release the voice after a given delay
|
||||
*
|
||||
* @param delay
|
||||
*/
|
||||
void release(int delay) noexcept;
|
||||
Region* region { nullptr };
|
||||
|
||||
|
|
@ -137,4 +325,4 @@ private:
|
|||
LEAK_DETECTOR(Voice);
|
||||
};
|
||||
|
||||
} // namespace sfz
|
||||
} // namespace sfz
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue