262 lines
8.1 KiB
C++
262 lines
8.1 KiB
C++
// SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
|
// license. You should have receive a LICENSE.md file along with the code.
|
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <memory>
|
|
#include "sfizz/Macros.h"
|
|
|
|
namespace sfz
|
|
{
|
|
class Synth;
|
|
class SFIZZ_EXPORTED_API Sfizz
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Construct a new Sfizz object. The synth by default is set at 48 kHz
|
|
* and a block size of 1024. You should change these values if they are not
|
|
* suited to your application.
|
|
*
|
|
*/
|
|
Sfizz();
|
|
~Sfizz();
|
|
/**
|
|
* @brief Empties the current regions and load a new SFZ file into the synth.
|
|
*
|
|
* This function will disable all callbacks so it is safe to call from a
|
|
* UI thread for example, although it may generate a click. However it is
|
|
* not reentrant, so you should not call it from concurrent threads.
|
|
*
|
|
* @param file
|
|
* @return true
|
|
* @return false if the file was not found or no regions were loaded.
|
|
*/
|
|
bool loadSfzFile(const std::string& path);
|
|
/**
|
|
* @brief Get the current number of regions loaded
|
|
*
|
|
* @return int
|
|
*/
|
|
int getNumRegions() const noexcept;
|
|
/**
|
|
* @brief Get the current number of groups loaded
|
|
*
|
|
* @return int
|
|
*/
|
|
int getNumGroups() const noexcept;
|
|
/**
|
|
* @brief Get the current number of masters loaded
|
|
*
|
|
* @return int
|
|
*/
|
|
int getNumMasters() const noexcept;
|
|
/**
|
|
* @brief Get the current number of curves loaded
|
|
*
|
|
* @return int
|
|
*/
|
|
int getNumCurves() const noexcept;
|
|
const std::vector<std::string>& getUnknownOpcodes() const noexcept;
|
|
/**
|
|
* @brief Get the number of preloaded samples in the synth
|
|
*
|
|
* @return size_t
|
|
*/
|
|
size_t getNumPreloadedSamples() const noexcept;
|
|
/**
|
|
* @brief Set the maximum size of the blocks for the callback. The actual
|
|
* size can be lower in each callback but should not be larger
|
|
* than this value.
|
|
*
|
|
* @param samplesPerBlock
|
|
*/
|
|
void setSamplesPerBlock(int samplesPerBlock) noexcept;
|
|
/**
|
|
* @brief Set the sample rate. If you do not call it it is initialized
|
|
* to sfz::config::defaultSampleRate.
|
|
*
|
|
* @param sampleRate
|
|
*/
|
|
void setSampleRate(float sampleRate) noexcept;
|
|
/**
|
|
* @brief Get the current value for the volume, in dB.
|
|
*
|
|
* @return float
|
|
*/
|
|
float getVolume() const noexcept;
|
|
/**
|
|
* @brief Set the value for the volume. This value will be
|
|
* clamped within sfz::default::volumeRange.
|
|
*
|
|
* @param volume
|
|
*/
|
|
void setVolume(float volume) noexcept;
|
|
|
|
/**
|
|
* @brief Send a note on event to the synth
|
|
*
|
|
* @param delay the delay at which the event occurs; this should be lower
|
|
* than the size of the block in the next call to renderBlock().
|
|
* @param noteNumber the midi note number
|
|
* @param velocity the midi note velocity
|
|
*/
|
|
void noteOn(int delay, int noteNumber, uint8_t velocity) noexcept;
|
|
/**
|
|
* @brief Send a note off event to the synth
|
|
*
|
|
* @param delay the delay at which the event occurs; this should be lower
|
|
* than the size of the block in the next call to renderBlock().
|
|
* @param noteNumber the midi note number
|
|
* @param velocity the midi note velocity
|
|
*/
|
|
void noteOff(int delay, int noteNumber, uint8_t velocity) noexcept;
|
|
/**
|
|
* @brief Send a CC event to the synth
|
|
*
|
|
* @param delay the delay at which the event occurs; this should be lower than the size of
|
|
* the block in the next call to renderBlock().
|
|
* @param ccNumber the cc number
|
|
* @param ccValue the cc value
|
|
*/
|
|
void cc(int delay, int ccNumber, uint8_t ccValue) noexcept;
|
|
/**
|
|
* @brief Send a pitch bend event to the synth
|
|
*
|
|
* @param delay the delay at which the event occurs; this should be lower
|
|
* than the size of the block in the next call to
|
|
* renderBlock().
|
|
* @param pitch the pitch value centered between -8192 and 8192
|
|
*/
|
|
void pitchWheel(int delay, int pitch) noexcept;
|
|
/**
|
|
* @brief Send a aftertouch event to the synth
|
|
*
|
|
* @param delay the delay at which the event occurs; this should be lower than the size of
|
|
* the block in the next call to renderBlock().
|
|
* @param aftertouch the aftertouch value
|
|
*/
|
|
void aftertouch(int delay, uint8_t aftertouch) noexcept;
|
|
/**
|
|
* @brief Send a tempo event to the synth
|
|
*
|
|
* @param delay the delay at which the event occurs; this should be lower than the size of
|
|
* the block in the next call to renderBlock().
|
|
* @param secondsPerQuarter the new period of the quarter note
|
|
*/
|
|
void tempo(int delay, float secondsPerQuarter) noexcept;
|
|
/**
|
|
* @brief Render an block of audio data in the buffer. This call will reset
|
|
* the synth in its waiting state for the next batch of events. The buffers must
|
|
* be float[numSamples][numOutputs * 2].
|
|
*
|
|
* @param buffers the buffers to write the next block into
|
|
* @param numSamples the number of stereo frames in the block
|
|
* @param numOutputs the number of stereo outputs
|
|
*/
|
|
void renderBlock(float** buffers, size_t numFrames, int numOutputs = 1) noexcept;
|
|
|
|
/**
|
|
* @brief Get the number of active voices
|
|
*
|
|
* @return int
|
|
*/
|
|
int getNumActiveVoices() const noexcept;
|
|
/**
|
|
* @brief Get the total number of voices in the synth (the polyphony)
|
|
*
|
|
* @return int
|
|
*/
|
|
int getNumVoices() const noexcept;
|
|
/**
|
|
* @brief Change the number of voices (the polyphony)
|
|
*
|
|
* @param numVoices
|
|
*/
|
|
void setNumVoices(int numVoices) noexcept;
|
|
|
|
/**
|
|
* @brief Set the oversampling factor to a new value. This will disable all callbacks
|
|
* kill all the voices, and trigger a reloading of every file in the FilePool under
|
|
* the new oversampling.
|
|
*
|
|
* @param factor
|
|
* @return true if the factor did indeed change
|
|
*/
|
|
bool setOversamplingFactor(int factor) noexcept;
|
|
|
|
/**
|
|
* @brief get the current oversampling factor
|
|
*
|
|
* @return Oversampling
|
|
*/
|
|
int getOversamplingFactor() const noexcept;
|
|
|
|
/**
|
|
* @brief Set the preloaded file size. This will disable the callback.
|
|
*
|
|
* @param factor
|
|
*/
|
|
void setPreloadSize(uint32_t preloadSize) noexcept;
|
|
|
|
/**
|
|
* @brief get the current preloaded file size
|
|
*
|
|
* @return Oversampling
|
|
*/
|
|
uint32_t getPreloadSize() const noexcept;
|
|
|
|
/**
|
|
* @brief Gets the number of allocated buffers.
|
|
*
|
|
* @return The allocated buffers.
|
|
*/
|
|
int getAllocatedBuffers() const noexcept;
|
|
|
|
/**
|
|
* @brief Gets the number of bytes allocated through the buffers
|
|
*
|
|
* @return The allocated bytes.
|
|
*/
|
|
int getAllocatedBytes() const noexcept;
|
|
|
|
/**
|
|
* @brief Enable freewheeling on the synth. This will wait for background
|
|
* loaded files to finish loading before each render callback to ensure that
|
|
* there will be no dropouts.
|
|
*
|
|
*/
|
|
void enableFreeWheeling() noexcept;
|
|
/**
|
|
* @brief Disable freewheeling on the synth. You should disable freewheeling
|
|
* before live use of the plugin otherwise the audio thread will lock.
|
|
*
|
|
*/
|
|
void disableFreeWheeling() noexcept;
|
|
/**
|
|
* @brief Check if the SFZ should be reloaded.
|
|
*
|
|
* Depending on the platform this can create file descriptors.
|
|
*
|
|
* @return true if any included files (including the root file) have
|
|
* been modified since the sfz file was loaded.
|
|
* @return false
|
|
*/
|
|
bool shouldReloadFile();
|
|
/**
|
|
* @brief Enable logging of timings to sidecar CSV files. This can produce
|
|
* many outputs so use with caution.
|
|
*
|
|
*/
|
|
void enableLogging() noexcept;
|
|
/**
|
|
* @brief Disable logging;
|
|
*
|
|
*/
|
|
void disableLogging() noexcept;
|
|
private:
|
|
std::unique_ptr<sfz::Synth> synth;
|
|
};
|
|
}
|