Add the sample quality API
This commit is contained in:
parent
3994089233
commit
336a435773
12 changed files with 180 additions and 9 deletions
34
src/sfizz.h
34
src/sfizz.h
|
|
@ -40,6 +40,13 @@ typedef enum {
|
|||
SFIZZ_OVERSAMPLING_X4 = 4,
|
||||
SFIZZ_OVERSAMPLING_X8 = 8
|
||||
} sfizz_oversampling_factor_t;
|
||||
/**
|
||||
* @brief Processing mode
|
||||
*/
|
||||
typedef enum {
|
||||
SFIZZ_PROCESS_LIVE,
|
||||
SFIZZ_PROCESS_FREEWHEELING,
|
||||
} sfizz_process_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Creates a sfizz synth. This object has to be freed by the caller
|
||||
|
|
@ -366,6 +373,33 @@ SFIZZ_EXPORTED_API sfizz_oversampling_factor_t sfizz_get_oversampling_factor(sfi
|
|||
*/
|
||||
SFIZZ_EXPORTED_API bool sfizz_set_oversampling_factor(sfizz_synth_t* synth, sfizz_oversampling_factor_t oversampling);
|
||||
|
||||
/**
|
||||
* @brief Get the default resampling quality. This is the quality setting
|
||||
* which the engine uses when the instrument does not use the
|
||||
* opcode `sample_quality`. The engine uses distinct default quality
|
||||
* settings for live mode and freewheeling mode, which both can be
|
||||
* accessed by the means of this function.
|
||||
*
|
||||
* @param synth The synth.
|
||||
* @param[in] mode The processing mode.
|
||||
*
|
||||
* @return The sample quality for the given mode, in the range 1 to 10.
|
||||
*/
|
||||
SFIZZ_EXPORTED_API int sfizz_get_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Set the default resampling quality. This is the quality setting
|
||||
* which the engine uses when the instrument does not use the
|
||||
* opcode `sample_quality`. The engine uses distinct default quality
|
||||
* settings for live mode and freewheeling mode, which both can be
|
||||
* accessed by the means of this function.
|
||||
*
|
||||
* @param synth The synth.
|
||||
* @param[in] mode The processing mode.
|
||||
* @param[in] quality The desired sample quality, in the range 1 to 10.
|
||||
*/
|
||||
SFIZZ_EXPORTED_API void sfizz_set_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode, int quality);
|
||||
|
||||
/**
|
||||
* @brief Set the global instrument volume.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -43,6 +43,14 @@ public:
|
|||
Sfizz();
|
||||
~Sfizz();
|
||||
|
||||
/**
|
||||
* @brief Processing mode
|
||||
*/
|
||||
enum ProcessMode {
|
||||
ProcessLive,
|
||||
ProcessFreewheeling,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Empties the current regions and load a new SFZ file into the synth.
|
||||
*
|
||||
|
|
@ -174,6 +182,31 @@ public:
|
|||
*/
|
||||
void setSampleRate(float sampleRate) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get the default resampling quality. This is the quality setting
|
||||
* which the engine uses when the instrument does not use the
|
||||
* opcode `sample_quality`. The engine uses distinct default quality
|
||||
* settings for live mode and freewheeling mode, which both can be
|
||||
* accessed by the means of this function.
|
||||
*
|
||||
* @param[in] mode The processing mode.
|
||||
*
|
||||
* @return The sample quality for the given mode, in the range 1 to 10.
|
||||
*/
|
||||
int getSampleQuality(ProcessMode mode);
|
||||
|
||||
/**
|
||||
* @brief Set the default resampling quality. This is the quality setting
|
||||
* which the engine uses when the instrument does not use the
|
||||
* opcode `sample_quality`. The engine uses distinct default quality
|
||||
* settings for live mode and freewheeling mode, which both can be
|
||||
* accessed by the means of this function.
|
||||
*
|
||||
* @param[in] mode The processing mode.
|
||||
* @param[in] quality The desired sample quality, in the range 1 to 10.
|
||||
*/
|
||||
void setSampleQuality(ProcessMode mode, int quality);
|
||||
|
||||
/**
|
||||
* @brief Return the current value for the volume, in dB.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ namespace Default
|
|||
|
||||
// ***** SFZ v2 ********
|
||||
constexpr int sampleQuality { 2 };
|
||||
constexpr int sampleQualityInFreewheelingMode { 10 }; // for future use, possibly excessive
|
||||
constexpr Range<int> sampleQualityRange { 1, 10 }; // sample_quality
|
||||
|
||||
constexpr bool checkSustain { true }; // sustain_sw
|
||||
|
|
|
|||
|
|
@ -62,7 +62,10 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
|
|||
break;
|
||||
case hash("sample_quality"):
|
||||
{
|
||||
setValueFromOpcode(opcode, sampleQuality, Default::sampleQualityRange);
|
||||
if (opcode.value == "-1")
|
||||
sampleQuality.reset();
|
||||
else
|
||||
setValueFromOpcode(opcode, sampleQuality, Default::sampleQualityRange);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ struct Region {
|
|||
|
||||
// Sound source: sample playback
|
||||
FileId sampleId {}; // Sample
|
||||
int sampleQuality { Default::sampleQuality };
|
||||
absl::optional<int> sampleQuality {};
|
||||
float delay { Default::delay }; // delay
|
||||
float delayRandom { Default::delayRandom }; // delay_random
|
||||
int64_t offset { Default::offset }; // offset
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#pragma once
|
||||
#include "SynthConfig.h"
|
||||
#include "FilePool.h"
|
||||
#include "BufferPool.h"
|
||||
#include "FilterPool.h"
|
||||
|
|
@ -21,6 +22,7 @@ class WavetableMulti;
|
|||
|
||||
struct Resources
|
||||
{
|
||||
SynthConfig synthConfig;
|
||||
BufferPool bufferPool;
|
||||
MidiState midiState;
|
||||
Logger logger;
|
||||
|
|
|
|||
|
|
@ -667,7 +667,7 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
buffer.fill(0.0f);
|
||||
}
|
||||
|
||||
if (freeWheeling)
|
||||
if (resources.synthConfig.freeWheeling)
|
||||
resources.filePool.waitForBackgroundLoading();
|
||||
|
||||
const std::unique_lock<std::mutex> lock { callbackGuard, std::try_to_lock };
|
||||
|
|
@ -1112,6 +1112,34 @@ size_t sfz::Synth::getNumPreloadedSamples() const noexcept
|
|||
return resources.filePool.getNumPreloadedSamples();
|
||||
}
|
||||
|
||||
int sfz::Synth::getSampleQuality(ProcessMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case ProcessLive:
|
||||
return resources.synthConfig.liveSampleQuality;
|
||||
case ProcessFreewheeling:
|
||||
return resources.synthConfig.freeWheelingSampleQuality;
|
||||
default:
|
||||
CHECK(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void sfz::Synth::setSampleQuality(ProcessMode mode, int quality)
|
||||
{
|
||||
switch (mode) {
|
||||
case ProcessLive:
|
||||
resources.synthConfig.liveSampleQuality = quality;
|
||||
break;
|
||||
case ProcessFreewheeling:
|
||||
resources.synthConfig.freeWheelingSampleQuality = quality;
|
||||
break;
|
||||
default:
|
||||
CHECK(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float sfz::Synth::getVolume() const noexcept
|
||||
{
|
||||
return volume;
|
||||
|
|
@ -1200,15 +1228,15 @@ uint32_t sfz::Synth::getPreloadSize() const noexcept
|
|||
|
||||
void sfz::Synth::enableFreeWheeling() noexcept
|
||||
{
|
||||
if (!freeWheeling) {
|
||||
freeWheeling = true;
|
||||
if (!resources.synthConfig.freeWheeling) {
|
||||
resources.synthConfig.freeWheeling = true;
|
||||
DBG("Enabling freewheeling");
|
||||
}
|
||||
}
|
||||
void sfz::Synth::disableFreeWheeling() noexcept
|
||||
{
|
||||
if (freeWheeling) {
|
||||
freeWheeling = false;
|
||||
if (resources.synthConfig.freeWheeling) {
|
||||
resources.synthConfig.freeWheeling = false;
|
||||
DBG("Disabling freewheeling");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,15 @@ public:
|
|||
* @param numVoices
|
||||
*/
|
||||
Synth(int numVoices);
|
||||
|
||||
/**
|
||||
* @brief Processing mode
|
||||
*/
|
||||
enum ProcessMode {
|
||||
ProcessLive,
|
||||
ProcessFreewheeling,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Empties the current regions and load a new SFZ file into the synth.
|
||||
*
|
||||
|
|
@ -255,6 +264,21 @@ public:
|
|||
* @param sampleRate
|
||||
*/
|
||||
void setSampleRate(float sampleRate) noexcept;
|
||||
/**
|
||||
* @brief Get the default resampling quality for the given mode.
|
||||
*
|
||||
* @param mode the processing mode
|
||||
*
|
||||
* @return the quality setting
|
||||
*/
|
||||
int getSampleQuality(ProcessMode mode);
|
||||
/**
|
||||
* @brief Set the default resampling quality for the given mode.
|
||||
*
|
||||
* @param mode the processing mode
|
||||
* @param quality the quality setting
|
||||
*/
|
||||
void setSampleQuality(ProcessMode mode, int quality);
|
||||
/**
|
||||
* @brief Get the current value for the volume, in dB.
|
||||
*
|
||||
|
|
@ -669,7 +693,6 @@ private:
|
|||
std::uniform_real_distribution<float> randNoteDistribution { 0, 1 };
|
||||
|
||||
std::mutex callbackGuard;
|
||||
bool freeWheeling { false };
|
||||
|
||||
// Singletons passed as references to the voices
|
||||
Resources resources;
|
||||
|
|
|
|||
24
src/sfizz/SynthConfig.h
Normal file
24
src/sfizz/SynthConfig.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// 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
|
||||
|
||||
#pragma once
|
||||
#include "Defaults.h"
|
||||
|
||||
namespace sfz
|
||||
{
|
||||
struct SynthConfig
|
||||
{
|
||||
bool freeWheeling { false };
|
||||
|
||||
int liveSampleQuality { sfz::Default::sampleQuality };
|
||||
int freeWheelingSampleQuality { sfz::Default::sampleQualityInFreewheelingMode };
|
||||
|
||||
int currentSampleQuality() const noexcept
|
||||
{
|
||||
return freeWheeling ? freeWheelingSampleQuality : liveSampleQuality;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -511,7 +511,8 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
const int quality = region->sampleQuality;
|
||||
const int quality = region->sampleQuality ?
|
||||
*region->sampleQuality : resources.synthConfig.currentSampleQuality();
|
||||
|
||||
switch (quality) {
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -103,6 +103,16 @@ void sfz::Sfizz::setSampleRate(float sampleRate) noexcept
|
|||
synth->setSampleRate(sampleRate);
|
||||
}
|
||||
|
||||
int sfz::Sfizz::getSampleQuality(ProcessMode mode)
|
||||
{
|
||||
return synth->getSampleQuality(static_cast<sfz::Synth::ProcessMode>(mode));
|
||||
}
|
||||
|
||||
void sfz::Sfizz::setSampleQuality(ProcessMode mode, int quality)
|
||||
{
|
||||
synth->setSampleQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
|
||||
}
|
||||
|
||||
float sfz::Sfizz::getVolume() const noexcept
|
||||
{
|
||||
return synth->getVolume();
|
||||
|
|
|
|||
|
|
@ -210,6 +210,18 @@ bool sfizz_set_oversampling_factor(sfizz_synth_t* synth, sfizz_oversampling_fact
|
|||
}
|
||||
}
|
||||
|
||||
int sfizz_get_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode)
|
||||
{
|
||||
auto self = reinterpret_cast<sfz::Synth*>(synth);
|
||||
return self->getSampleQuality(static_cast<sfz::Synth::ProcessMode>(mode));
|
||||
}
|
||||
|
||||
void sfizz_set_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode, int quality)
|
||||
{
|
||||
auto self = reinterpret_cast<sfz::Synth*>(synth);
|
||||
return self->setSampleQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
|
||||
}
|
||||
|
||||
void sfizz_set_volume(sfizz_synth_t* synth, float volume)
|
||||
{
|
||||
auto self = reinterpret_cast<sfz::Synth*>(synth);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue