Skip to content

Commit

Permalink
Merge pull request #267 from jpcima/quality-api
Browse files Browse the repository at this point in the history
Add the sample quality API
  • Loading branch information
jpcima authored Jun 14, 2020
2 parents 3994089 + b144ec0 commit 9e764b1
Show file tree
Hide file tree
Showing 14 changed files with 249 additions and 9 deletions.
34 changes: 34 additions & 0 deletions src/sfizz.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
*
Expand Down
33 changes: 33 additions & 0 deletions src/sfizz.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ class SFIZZ_EXPORTED_API Sfizz
Sfizz();
~Sfizz();

/**
* @brief Processing mode
*/
enum ProcessMode {
ProcessLive,
ProcessFreewheeling,
};

/**
* @brief Empties the current regions and load a new SFZ file into the synth.
*
Expand Down Expand Up @@ -174,6 +182,31 @@ class SFIZZ_EXPORTED_API Sfizz
*/
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.
*/
Expand Down
1 change: 1 addition & 0 deletions src/sfizz/Defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion src/sfizz/Region.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/sfizz/Region.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/sfizz/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -21,6 +22,7 @@ class WavetableMulti;

struct Resources
{
SynthConfig synthConfig;
BufferPool bufferPool;
MidiState midiState;
Logger logger;
Expand Down
41 changes: 36 additions & 5 deletions src/sfizz/Synth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down Expand Up @@ -1112,6 +1112,37 @@ 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)
{
CHECK(quality >= 1 && quality <= 10);
quality = clamp(quality, 1, 10);

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;
Expand Down Expand Up @@ -1200,15 +1231,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");
}
}
Expand Down
25 changes: 24 additions & 1 deletion src/sfizz/Synth.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ class Synth final : public Voice::StateListener, public Parser::Listener {
* @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.
*
Expand Down Expand Up @@ -255,6 +264,21 @@ class Synth final : public Voice::StateListener, public Parser::Listener {
* @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.
*
Expand Down Expand Up @@ -669,7 +693,6 @@ class Synth final : public Voice::StateListener, public Parser::Listener {
std::uniform_real_distribution<float> randNoteDistribution { 0, 1 };

std::mutex callbackGuard;
bool freeWheeling { false };

// Singletons passed as references to the voices
Resources resources;
Expand Down
24 changes: 24 additions & 0 deletions src/sfizz/SynthConfig.h
Original file line number Diff line number Diff line change
@@ -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;
}
};
}
8 changes: 7 additions & 1 deletion src/sfizz/Voice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value,
egEnvelope.reset(region->amplitudeEG, *region, resources.midiState, delay, value, sampleRate);
}

int sfz::Voice::getCurrentSampleQuality() const noexcept
{
return (region && region->sampleQuality) ?
*region->sampleQuality : resources.synthConfig.currentSampleQuality();
}

bool sfz::Voice::isFree() const noexcept
{
return (state == State::idle);
Expand Down Expand Up @@ -511,7 +517,7 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
}
}

const int quality = region->sampleQuality;
const int quality = getCurrentSampleQuality();

switch (quality) {
default:
Expand Down
7 changes: 7 additions & 0 deletions src/sfizz/Voice.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ class Voice {
*/
void startVoice(Region* region, int delay, int number, float value, TriggerType triggerType) noexcept;

/**
* @brief Get the sample quality determined by the active region.
*
* @return int
*/
int getCurrentSampleQuality() const noexcept;

/**
* @brief Register a note-off event; this may trigger a release.
*
Expand Down
10 changes: 10 additions & 0 deletions src/sfizz/sfizz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
12 changes: 12 additions & 0 deletions src/sfizz/sfizz_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 9e764b1

Please sign in to comment.