From cea3e4715beea6b755cf50e71dcd0ebee47ad203 Mon Sep 17 00:00:00 2001
From: Jean Pierre Cimalando
Date: Fri, 3 Apr 2020 15:37:47 +0200
Subject: [PATCH 001/444] Add oscillator unison
---
src/sfizz/Defaults.h | 4 ++
src/sfizz/Range.h | 4 +-
src/sfizz/Region.cpp | 6 +++
src/sfizz/Region.h | 11 +++-
src/sfizz/Synth.cpp | 2 +-
src/sfizz/Voice.cpp | 109 ++++++++++++++++++++++++++++++++++-----
src/sfizz/Voice.h | 14 ++++-
src/sfizz/Wavetables.cpp | 8 +--
src/sfizz/Wavetables.h | 4 +-
tests/DemoWavetables.cpp | 2 +-
10 files changed, 139 insertions(+), 25 deletions(-)
diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h
index 0e35ca490..2066cb19a 100644
--- a/src/sfizz/Defaults.h
+++ b/src/sfizz/Defaults.h
@@ -63,6 +63,10 @@ namespace Default
// Wavetable oscillator
constexpr float oscillatorPhase { 0.0 };
constexpr Range oscillatorPhaseRange { -1.0, 360.0 };
+ constexpr int oscillatorMulti { 1 };
+ constexpr Range oscillatorMultiRange { 1, 9 };
+ constexpr float oscillatorDetune { 0 };
+ constexpr Range oscillatorDetuneRange { -9600, 9600 };
// Instrument setting: voice lifecycle
constexpr uint32_t group { 0 };
diff --git a/src/sfizz/Range.h b/src/sfizz/Range.h
index b39b7c0d5..9f3395657 100644
--- a/src/sfizz/Range.h
+++ b/src/sfizz/Range.h
@@ -28,8 +28,8 @@ class Range {
{
}
- Type getStart() const noexcept { return _start; }
- Type getEnd() const noexcept { return _end; }
+ constexpr Type getStart() const noexcept { return _start; }
+ constexpr Type getEnd() const noexcept { return _end; }
/**
* @brief Get the range as an std::pair of the endpoints
*
diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp
index 76806b48e..234878e93 100644
--- a/src/sfizz/Region.cpp
+++ b/src/sfizz/Region.cpp
@@ -102,6 +102,12 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
if (auto value = readBooleanFromOpcode(opcode))
oscillator = *value;
break;
+ case hash("oscillator_multi"):
+ setValueFromOpcode(opcode, oscillatorMulti, Default::oscillatorMultiRange);
+ break;
+ case hash("oscillator_detune"):
+ setValueFromOpcode(opcode, oscillatorDetune, Default::oscillatorDetuneRange);
+ break;
// Instrument settings: voice lifecycle
case hash("group"): // fallthrough
diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h
index a7a4e7105..73f3bc531 100644
--- a/src/sfizz/Region.h
+++ b/src/sfizz/Region.h
@@ -60,6 +60,13 @@ struct Region {
* @return false
*/
bool isGenerator() const noexcept { return sample.size() > 0 ? sample[0] == '*' : false; }
+ /**
+ * @brief Is stereo (has stereo sample or is unison oscillator)?
+ *
+ * @return true
+ * @return false
+ */
+ bool isStereo() const noexcept { return hasStereoSample || ((oscillator || isGenerator()) && oscillatorMulti >= 3); }
/**
* @brief Is a looping region (at least potentially)?
*
@@ -235,6 +242,8 @@ struct Region {
// Wavetable oscillator
float oscillatorPhase { Default::oscillatorPhase };
bool oscillator = false;
+ int oscillatorMulti = Default::oscillatorMulti;
+ float oscillatorDetune = Default::oscillatorDetune;
// Instrument settings: voice lifecycle
uint32_t group { Default::group }; // group
@@ -318,7 +327,7 @@ struct Region {
EGDescription pitchEG;
EGDescription filterEG;
- bool isStereo { false };
+ bool hasStereoSample { false };
// Effects
std::vector gainToEffect;
diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp
index 25393b4de..54d7fc12b 100644
--- a/src/sfizz/Synth.cpp
+++ b/src/sfizz/Synth.cpp
@@ -379,7 +379,7 @@ bool sfz::Synth::loadSfzFile(const fs::path& file)
}
if (fileInformation->numChannels == 2)
- region->isStereo = true;
+ region->hasStereoSample = true;
// TODO: adjust with LFO targets
const auto maxOffset = region->offset + region->offsetRandom;
diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp
index 4aa4e0bd6..775d220d4 100644
--- a/src/sfizz/Voice.cpp
+++ b/src/sfizz/Voice.cpp
@@ -21,7 +21,8 @@ sfz::Voice::Voice(sfz::Resources& resources)
filters.reserve(config::filtersPerVoice);
equalizers.reserve(config::eqsPerVoice);
- waveOscillator.init(sampleRate);
+ for (WavetableOscillator& osc : waveOscillators)
+ osc.init(sampleRate);
}
void sfz::Voice::startVoice(Region* region, int delay, int number, float value, sfz::Voice::TriggerType triggerType) noexcept
@@ -59,12 +60,18 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value,
wave = resources.wavePool.getWaveSaw();
break;
}
- waveOscillator.setWavetable(wave);
- waveOscillator.setPhase(region->getPhase());
+ for (WavetableOscillator& osc : waveOscillators) {
+ osc.setWavetable(wave);
+ osc.setPhase(region->getPhase());
+ }
+ setupOscillatorUnison();
} else if (region->oscillator) {
const WavetableMulti* wave = resources.wavePool.getFileWave(region->sample);
- waveOscillator.setWavetable(wave);
- waveOscillator.setPhase(region->getPhase());
+ for (WavetableOscillator& osc : waveOscillators) {
+ osc.setWavetable(wave);
+ osc.setPhase(region->getPhase());
+ }
+ setupOscillatorUnison();
} else {
currentPromise = resources.filePool.getFilePromise(region->sample);
if (currentPromise == nullptr) {
@@ -83,7 +90,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value,
ASSERT((filters.capacity() - filters.size()) >= region->filters.size());
ASSERT((equalizers.capacity() - equalizers.size()) >= region->equalizers.size());
- const unsigned numChannels = region->isStereo ? 2 : 1;
+ const unsigned numChannels = region->isStereo() ? 2 : 1;
for (auto& filter: region->filters) {
auto newFilter = resources.filterPool.getFilter(filter, numChannels, number, value);
if (newFilter)
@@ -187,7 +194,8 @@ void sfz::Voice::setSampleRate(float sampleRate) noexcept
{
this->sampleRate = sampleRate;
- waveOscillator.init(sampleRate);
+ for (WavetableOscillator& osc : waveOscillators)
+ osc.init(sampleRate);
}
void sfz::Voice::setSamplesPerBlock(int samplesPerBlock) noexcept
@@ -218,7 +226,7 @@ void sfz::Voice::renderBlock(AudioSpan buffer) noexcept
fillWithData(delayed_buffer);
}
- if (region->isStereo) {
+ if (region->isStereo()) {
ampStageStereo(buffer);
panStageStereo(buffer);
filterStageStereo(buffer);
@@ -518,9 +526,10 @@ void sfz::Voice::fillWithGenerator(AudioSpan buffer) noexcept
absl::c_generate(leftSpan, [&](){ return noiseDist(Random::randomGenerator); });
absl::c_generate(rightSpan, [&](){ return noiseDist(Random::randomGenerator); });
} else {
- const auto numSamples = buffer.getNumFrames();
- auto frequencies = resources.bufferPool.getBuffer(numSamples);
- auto bends = resources.bufferPool.getBuffer(numSamples);
+ const auto numFrames = buffer.getNumFrames();
+
+ auto frequencies = resources.bufferPool.getBuffer(numFrames);
+ auto bends = resources.bufferPool.getBuffer(numFrames);
if (!frequencies || !bends)
return;
@@ -544,8 +553,25 @@ void sfz::Voice::fillWithGenerator(AudioSpan buffer) noexcept
applyGain(*bends, *frequencies);
}
- waveOscillator.processModulated(frequencies->data(), leftSpan.data(), buffer.getNumFrames());
- copy(leftSpan, rightSpan);
+ if (waveUnisonSize == 1) {
+ WavetableOscillator& osc = waveOscillators[0];
+ osc.processModulated(frequencies->data(), 1.0, leftSpan.data(), buffer.getNumFrames());
+ copy(leftSpan, rightSpan);
+ }
+ else {
+ buffer.fill(0.0f);
+
+ auto tempSpan = resources.bufferPool.getBuffer(numFrames);
+ if (!tempSpan)
+ return;
+
+ for (unsigned i = 0, n = waveUnisonSize; i < n; ++i) {
+ WavetableOscillator& osc = waveOscillators[i];
+ osc.processModulated(frequencies->data(), waveDetuneRatio[i], tempSpan->data(), numFrames);
+ sfz::multiplyAdd(waveLeftGain[i], *tempSpan, leftSpan);
+ sfz::multiplyAdd(waveRightGain[i], *tempSpan, rightSpan);
+ }
+ }
}
}
@@ -620,3 +646,60 @@ void sfz::Voice::setMaxEQsPerVoice(size_t numFilters)
ASSERT(equalizers.size() == 0);
equalizers.reserve(numFilters);
}
+
+void sfz::Voice::setupOscillatorUnison()
+{
+ int m = region->oscillatorMulti;
+ float d = region->oscillatorDetune;
+
+ // 3-9: unison mode, 1: normal/RM, 2: PM/FM
+ // TODO(jpc) RM/FM/PM synthesis
+ if (m < 3) {
+ waveUnisonSize = 1;
+ waveDetuneRatio[0] = 1.0;
+ waveLeftGain[0] = 1.0;
+ waveRightGain[0] = 1.0;
+ return;
+ }
+
+ // oscillator count, aka. unison size
+ waveUnisonSize = m;
+
+ // detune (cents)
+ float detunes[maxWaveOscillators];
+ detunes[0] = 0.0;
+ detunes[1] = -d;
+ detunes[2] = +d;
+ for (int i = 3; i < m; ++i)
+ detunes[i] = d * ((i & 1) ? -0.25f : +0.25f) * ((i - 1) / 2);
+
+ // detune (ratio)
+ for (int i = 0; i < m; ++i)
+ waveDetuneRatio[i] = std::exp2(detunes[i] * (0.01f / 12.0f));
+
+ // gains
+ waveLeftGain[0] = 0.0;
+ waveRightGain[m - 1] = 0.0;
+ for (int i = 0; i < m - 1; ++i) {
+ float g = 1 - i / float(m - 1);
+ waveLeftGain[m - 1 - i] = g;
+ waveRightGain[i] = g;
+ }
+
+#if 0
+ fprintf(stderr, "\n");
+ fprintf(stderr, "# Left:\n");
+ for (int i = m - 1; i >= 0; --i) {
+ if (waveLeftGain[i] != 0)
+ fprintf(stderr, "[%d] %10g cents, %10g dB\n", i, detunes[i], 20.0f * std::log10(waveLeftGain[i]));
+ }
+ fprintf(stderr, "\n");
+ fprintf(stderr, "# Right:\n");
+ for (int i = 0; i < m; ++i) {
+ if (waveRightGain[i] != 0)
+ fprintf(stderr, "[%d] %10g cents, %10g dB\n", i, detunes[i], 20.0f * std::log10(waveRightGain[i]));
+ }
+#endif
+}
+
+constexpr unsigned sfz::Voice::maxWaveOscillators;
diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h
index f0a70af90..afde9b53e 100644
--- a/src/sfizz/Voice.h
+++ b/src/sfizz/Voice.h
@@ -244,6 +244,10 @@ class Voice {
void panStageStereo(AudioSpan buffer) noexcept;
void filterStageMono(AudioSpan buffer) noexcept;
void filterStageStereo(AudioSpan buffer) noexcept;
+ /**
+ * @brief Initialize frequency and gain coefficients for the oscillators.
+ */
+ void setupOscillatorUnison();
Region* region { nullptr };
@@ -284,7 +288,15 @@ class Voice {
ADSREnvelope egEnvelope;
float bendStepFactor { centsFactor(1) };
- WavetableOscillator waveOscillator;
+ static constexpr unsigned maxWaveOscillators = Default::oscillatorMultiRange.getEnd();
+
+ WavetableOscillator waveOscillators[maxWaveOscillators];
+
+ // unison of oscillators
+ unsigned waveUnisonSize { 0 };
+ float waveDetuneRatio[maxWaveOscillators] { };
+ float waveLeftGain[maxWaveOscillators] { };
+ float waveRightGain[maxWaveOscillators] { };
Duration dataDuration;
Duration amplitudeDuration;
diff --git a/src/sfizz/Wavetables.cpp b/src/sfizz/Wavetables.cpp
index c65b244a3..b04c0a8c0 100644
--- a/src/sfizz/Wavetables.cpp
+++ b/src/sfizz/Wavetables.cpp
@@ -34,10 +34,10 @@ void WavetableOscillator::setPhase(float phase)
_phase = phase;
}
-void WavetableOscillator::process(float frequency, float* output, unsigned nframes)
+void WavetableOscillator::process(float frequency, float detuneRatio, float* output, unsigned nframes)
{
float phase = _phase;
- float phaseInc = frequency * _sampleInterval;
+ float phaseInc = frequency * (detuneRatio * _sampleInterval);
const WavetableMulti& multi = *_multi;
unsigned tableSize = multi.tableSize();
@@ -56,7 +56,7 @@ void WavetableOscillator::process(float frequency, float* output, unsigned nfram
_phase = phase;
}
-void WavetableOscillator::processModulated(const float* frequencies, float* output, unsigned nframes)
+void WavetableOscillator::processModulated(const float* frequencies, float detuneRatio, float* output, unsigned nframes)
{
float phase = _phase;
float sampleInterval = _sampleInterval;
@@ -66,7 +66,7 @@ void WavetableOscillator::processModulated(const float* frequencies, float* outp
for (unsigned i = 0; i < nframes; ++i) {
float frequency = frequencies[i];
- float phaseInc = frequency * sampleInterval;
+ float phaseInc = frequency * (detuneRatio * sampleInterval);
absl::Span table = multi.getTableForFrequency(frequency);
float position = phase * tableSize;
diff --git a/src/sfizz/Wavetables.h b/src/sfizz/Wavetables.h
index 6290f01f9..3d0c90399 100644
--- a/src/sfizz/Wavetables.h
+++ b/src/sfizz/Wavetables.h
@@ -47,12 +47,12 @@ class WavetableOscillator {
/**
Compute a cycle of the oscillator, with constant frequency.
*/
- void process(float frequency, float* output, unsigned nframes);
+ void process(float frequency, float detuneRatio, float* output, unsigned nframes);
/**
Compute a cycle of the oscillator, with varying frequency.
*/
- void processModulated(const float* frequencies, float* output, unsigned nframes);
+ void processModulated(const float* frequencies, float detuneRatio, float* output, unsigned nframes);
private:
/**
diff --git a/tests/DemoWavetables.cpp b/tests/DemoWavetables.cpp
index d5b9ba5ad..e573260bf 100644
--- a/tests/DemoWavetables.cpp
+++ b/tests/DemoWavetables.cpp
@@ -172,7 +172,7 @@ int DemoApp::processAudio(jack_nframes_t nframes, void* cbdata)
self->fSweepCurrent = sweepCurrent;
// compute oscillator
- osc.processModulated(frequency, left, nframes);
+ osc.processModulated(frequency, 1.0, left, nframes);
std::memcpy(right, left, nframes * sizeof(float));
return 0;
From b338ac0ff9fc959893df800a1288fff6f3a98320 Mon Sep 17 00:00:00 2001
From: Jean Pierre Cimalando
Date: Fri, 3 Apr 2020 17:25:30 +0200
Subject: [PATCH 002/444] Update tests
---
tests/FilesT.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp
index f4bdc3c44..f0a4db39a 100644
--- a/tests/FilesT.cpp
+++ b/tests/FilesT.cpp
@@ -254,9 +254,9 @@ TEST_CASE("[Files] Channels (channels.sfz)")
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/channels.sfz");
REQUIRE(synth.getNumRegions() == 2);
REQUIRE(synth.getRegionView(0)->sample == "mono_sample.wav");
- REQUIRE(!synth.getRegionView(0)->isStereo);
+ REQUIRE(!synth.getRegionView(0)->isStereo());
REQUIRE(synth.getRegionView(1)->sample == "stereo_sample.wav");
- REQUIRE(synth.getRegionView(1)->isStereo);
+ REQUIRE(synth.getRegionView(1)->isStereo());
}
TEST_CASE("[Files] sw_default")
From db3521027e749c5511a9ed5a4bdfc29b1934a4d9 Mon Sep 17 00:00:00 2001
From: Jean Pierre Cimalando
Date: Fri, 3 Apr 2020 17:29:37 +0200
Subject: [PATCH 003/444] Fix some clang-tidy warnings
---
src/sfizz/Synth.cpp | 2 +-
src/sfizz/Voice.cpp | 8 +++++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp
index 54d7fc12b..ec102de37 100644
--- a/src/sfizz/Synth.cpp
+++ b/src/sfizz/Synth.cpp
@@ -785,7 +785,7 @@ void sfz::Synth::pitchWheel(int delay, int pitch) noexcept
{
ASSERT(pitch <= 8192);
ASSERT(pitch >= -8192);
- const auto normalizedPitch = normalizeBend(pitch);
+ const auto normalizedPitch = normalizeBend(float(pitch));
ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration };
resources.midiState.pitchBendEvent(delay, normalizedPitch);
diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp
index 775d220d4..4a9c6c76f 100644
--- a/src/sfizz/Voice.cpp
+++ b/src/sfizz/Voice.cpp
@@ -670,8 +670,10 @@ void sfz::Voice::setupOscillatorUnison()
detunes[0] = 0.0;
detunes[1] = -d;
detunes[2] = +d;
- for (int i = 3; i < m; ++i)
- detunes[i] = d * ((i & 1) ? -0.25f : +0.25f) * ((i - 1) / 2);
+ for (int i = 3; i < m; ++i) {
+ int n = (i - 1) / 2;
+ detunes[i] = d * ((i & 1) ? -0.25f : +0.25f) * float(n);
+ }
// detune (ratio)
for (int i = 0; i < m; ++i)
@@ -681,7 +683,7 @@ void sfz::Voice::setupOscillatorUnison()
waveLeftGain[0] = 0.0;
waveRightGain[m - 1] = 0.0;
for (int i = 0; i < m - 1; ++i) {
- float g = 1 - i / float(m - 1);
+ float g = 1.0f - float(i) / float(m - 1);
waveLeftGain[m - 1 - i] = g;
waveRightGain[i] = g;
}
From 7d4e9b144f5984d4bae002c787dd7a607e10d85f Mon Sep 17 00:00:00 2001
From: Jean Pierre Cimalando
Date: Sat, 4 Apr 2020 19:50:45 +0200
Subject: [PATCH 004/444] Pass the option -msse also on x86_64 In some cases of
chroot-based debian build environments where the host is 64-bit and target
32-bit, the system processor of cmake is not correctly set. To work this
around, pass the -msse2 flag also in case of 64-bit system processor; it will
be harmless for the case of normal builds.
---
cmake/SfizzConfig.cmake | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmake/SfizzConfig.cmake b/cmake/SfizzConfig.cmake
index bbf9f43ee..77415fdf2 100644
--- a/cmake/SfizzConfig.cmake
+++ b/cmake/SfizzConfig.cmake
@@ -32,7 +32,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_compile_options(-Wextra)
add_compile_options(-ffast-math)
add_compile_options(-fno-omit-frame-pointer) # For debugging purposes
- if (SFIZZ_SYSTEM_PROCESSOR MATCHES "^i.86$")
+ if (SFIZZ_SYSTEM_PROCESSOR MATCHES "^(i.86|x86_64)$")
add_compile_options(-msse2)
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
From 0dca7dbc5e3603e17716b54b31682b24ad727e75 Mon Sep 17 00:00:00 2001
From: Jean Pierre Cimalando
Date: Sat, 4 Apr 2020 23:14:15 +0200
Subject: [PATCH 005/444] Add tests for oscillator_multi
---
tests/FilesT.cpp | 37 +++++++++++++++++++++++++++++
tests/TestFiles/channels_multi.sfz | 6 +++++
tests/TestFiles/ramp_wave.wav | Bin 0 -> 2092 bytes
3 files changed, 43 insertions(+)
create mode 100644 tests/TestFiles/channels_multi.sfz
create mode 100644 tests/TestFiles/ramp_wave.wav
diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp
index f0a4db39a..51f5e40fb 100644
--- a/tests/FilesT.cpp
+++ b/tests/FilesT.cpp
@@ -259,6 +259,43 @@ TEST_CASE("[Files] Channels (channels.sfz)")
REQUIRE(synth.getRegionView(1)->isStereo());
}
+TEST_CASE("[Files] Channels (channels_multi.sfz)")
+{
+ sfz::Synth synth;
+ synth.loadSfzFile(fs::current_path() / "tests/TestFiles/channels_multi.sfz");
+ REQUIRE(synth.getNumRegions() == 6);
+
+ REQUIRE(synth.getRegionView(0)->sample == "*sine");
+ REQUIRE(!synth.getRegionView(0)->isStereo());
+ REQUIRE(synth.getRegionView(0)->isGenerator());
+ REQUIRE(!synth.getRegionView(0)->oscillator);
+
+ REQUIRE(synth.getRegionView(1)->sample == "*sine");
+ REQUIRE(synth.getRegionView(1)->isStereo());
+ REQUIRE(synth.getRegionView(1)->isGenerator());
+ REQUIRE(!synth.getRegionView(1)->oscillator);
+
+ REQUIRE(synth.getRegionView(2)->sample == "ramp_wave.wav");
+ REQUIRE(!synth.getRegionView(2)->isStereo());
+ REQUIRE(!synth.getRegionView(2)->isGenerator());
+ REQUIRE(synth.getRegionView(2)->oscillator);
+
+ REQUIRE(synth.getRegionView(3)->sample == "ramp_wave.wav");
+ REQUIRE(synth.getRegionView(3)->isStereo());
+ REQUIRE(!synth.getRegionView(3)->isGenerator());
+ REQUIRE(synth.getRegionView(3)->oscillator);
+
+ REQUIRE(synth.getRegionView(4)->sample == "*sine");
+ REQUIRE(!synth.getRegionView(4)->isStereo());
+ REQUIRE(synth.getRegionView(4)->isGenerator());
+ REQUIRE(!synth.getRegionView(4)->oscillator);
+
+ REQUIRE(synth.getRegionView(5)->sample == "*sine");
+ REQUIRE(!synth.getRegionView(5)->isStereo());
+ REQUIRE(synth.getRegionView(5)->isGenerator());
+ REQUIRE(!synth.getRegionView(5)->oscillator);
+}
+
TEST_CASE("[Files] sw_default")
{
sfz::Synth synth;
diff --git a/tests/TestFiles/channels_multi.sfz b/tests/TestFiles/channels_multi.sfz
new file mode 100644
index 000000000..8146ba45d
--- /dev/null
+++ b/tests/TestFiles/channels_multi.sfz
@@ -0,0 +1,6 @@
+ sample=*sine
+ sample=*sine oscillator_multi=3
+ sample=ramp_wave.wav oscillator=on
+ sample=ramp_wave.wav oscillator=on oscillator_multi=3
+ sample=*sine oscillator_multi=1
+ sample=*sine oscillator_multi=2
diff --git a/tests/TestFiles/ramp_wave.wav b/tests/TestFiles/ramp_wave.wav
new file mode 100644
index 0000000000000000000000000000000000000000..838d85566d14272034eddd1e3f4e87c2f451b747
GIT binary patch
literal 2092
zcmWO6Q)=8FMFYwr$&-JK45v+f(0pJV-5I)KP90Z||TT8Br3!~aK+B14XZQN|cUTV40S`rFg45!
zbHl`NHQWq$!^H?S!i;bu#7H&LjC3Q#C^gEAa-&3~iZqcfQjAuk&1g4Tj8S9E7&k_Y
zRb$OqH&%>O&!a0POMk!&3d<9Y)~7_2Dd?MR2$7kw^3|T
zo6IJ+No-b|&1Sb*Y*Aax7Pm!gRa?zgw^eLY+srn%O>9@&&33n4>`*(*4!1+>R6EU1
zw^Qs=yUZ@POYBy=&2G0_>`{Bn9=AvAReQ}|w^!^_`^-MKPwZFw&3?CE98d?$0e3)H
zWsP+f7@3$E96ECB;2<8PgM1JU;UPN2hu|yJ~
zI3B0td>l^T2|B?i;3S@;lYA0R;VC-Br{FZ6rqg^H&fpn3!)M?uo~5&V7S7>0I>+bW
zJf5fXd>$^~1-if&;38h6i+m9-;U&7nm*6s9rptU8uHY5A!dKubUZtyi6|Uhmy2jVw
zI$o#id>wA!4Z6WM;3nRrn|u>);Vrtwx8OG3rrUfQ?%*A|!*}2=-le;I7w+Lby2tn6
zKHjJMd>;Vu6
z_&)?FNbr9gFbYNCC=eB+QdEu#(J&fC<7f~aqf>N_4lytW#o!na6Jt_LjtQ|a7RBON
z5F2AtY>o|aFb>7xI1m@(Qe2J;@h~36<9HAs<5PT&4+$^6J_E|kQp;mX3h*j7(_uF1X(Z(W#KH46|+)S&I;Ku8)f5ckR7vAcFqnt
zFbCz}9FP-pQclhZxiA;y;#`m$b5m~44S6sR<>5S#7xPkH&I|c4ALZkGkRS6?e$EdC
zumBa{0#FbOQb8^Vg|HA6;zCdu3sYe(3`MXA72zUK6pK<(E(*o47!~7UP#lX>aV`!e
zumqLh5>OILQb{ferLYv0;!;o=OH*ks4P~$lmEkf_7RypuE(;PRNtS>THCps2l~z`H
zCClk@wwx~~%j@#Cye}^+=nA%iuOKVxingM!D1&vd4fesZlCESc`AV{~u52s&$}&WU
z*bpBgtLQ4WimxK8>Z-P?uPUqQYPOoMCade}wz{t_Yv>xbhOZ%O>YBEuuPJNkTDF$2
zC2Q;2wzjV=>*zYRj;|x@>bkbBuPf{6dbXagC+q9_w!W_~8|VhMfo~u~b*K&Xp)yQ|
z*)Sg_8|sF(p>HS~=|;AZZzLP*#vsc$Nq>1MW>Zzh}T=C-+S
zE?ejpwuNsY!*#d~_u;aoZfRTkma>&@Wn1}HvbAn)Tl?0sjc#Mx_%^bwZfo26wz8dW
zXWRL9vb}C^+xzyigYIBE_ztq8?r1yujPWIOpzva{}NJNwSEi|%5(_%5=m?rOXG
zuCkl%X1n=rvb*kXyZi34hwfo}_#U#S?rD4ap0bzjWqbKvGD1h#2p=JP>)y7v?=Ac2
zKDLkVBm3&Uwy*Ci`{{nRpYJF8>;AUC?=J`F0d{~NAP4G!cAy_92kAj}kRK!m>%n%g
RA1sIHA$Eu#BDL05{{!ji#B=}v
literal 0
HcmV?d00001
From 4e7f15328ac221d918977aa3a8f767d032d0b0f5 Mon Sep 17 00:00:00 2001
From: redtide
Date: Mon, 6 Apr 2020 14:19:55 +0200
Subject: [PATCH 006/444] Auto update the api index page
---
.travis/update_dox.sh | 4 +++-
doxygen/scripts/generate_api_index.sh | 11 +++++++++--
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/.travis/update_dox.sh b/.travis/update_dox.sh
index e838dc055..55ea08f4c 100755
--- a/.travis/update_dox.sh
+++ b/.travis/update_dox.sh
@@ -5,11 +5,13 @@ set -x # No fail, we need to go back to the original branch at the end
mkdir build && cd build && cmake -DSFIZZ_JACK=OFF -DSFIZZ_SHARED=OFF -DSFIZZ_LV2=OFF .. && cd ..
doxygen Doxyfile
+./doxygen/scripts/generate_api_index.sh
git fetch --depth=1 https://github.com/${TRAVIS_REPO_SLUG}.git refs/heads/gh-pages:refs/remotes/origin/gh-pages
git checkout origin/gh-pages
git checkout -b gh-pages
mv _api api/${TRAVIS_TAG}
-git add api/${TRAVIS_TAG} && git commit -m "Release ${TRAVIS_TAG} (Travis build: ${TRAVIS_BUILD_NUMBER})"
+mv api_index.md api/index.md
+git add api && git commit -m "Release ${TRAVIS_TAG} (Travis build: ${TRAVIS_BUILD_NUMBER})"
git remote add origin-pages https://${GITHUB_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git > /dev/null 2>&1
git push --quiet --set-upstream origin-pages gh-pages
git checkout ${TRAVIS_BRANCH}
diff --git a/doxygen/scripts/generate_api_index.sh b/doxygen/scripts/generate_api_index.sh
index 34a494d09..af618b6f2 100755
--- a/doxygen/scripts/generate_api_index.sh
+++ b/doxygen/scripts/generate_api_index.sh
@@ -1,12 +1,19 @@
#!/bin/bash
# Must be called from the root directory
-cat >>index.md <>api_index.md <> index.md
+ tag=$(echo "${tag}" | sed -r 's/v//g')
+ tags+=("${tag}")
fi
done
+IFS=$'\n' tags=($(sort <<<"${tags[*]}")); unset IFS
+for tag in "${tags[@]}"; do
+ echo "- [${tag}](${tag})" >> api_index.md
+done
From 75c898d50c63d33154ecd10b123692596bf28558 Mon Sep 17 00:00:00 2001
From: Paul Fd
Date: Tue, 7 Apr 2020 01:06:39 +0200
Subject: [PATCH 007/444] Added an external API for the external definitions
---
src/sfizz.h | 19 +++++++++++++++++++
src/sfizz.hpp | 15 +++++++++++++++
src/sfizz/sfizz.cpp | 10 ++++++++++
src/sfizz/sfizz_wrapper.cpp | 12 ++++++++++++
4 files changed, 56 insertions(+)
diff --git a/src/sfizz.h b/src/sfizz.h
index 5e5c6af87..36f6216d9 100644
--- a/src/sfizz.h
+++ b/src/sfizz.h
@@ -394,6 +394,25 @@ SFIZZ_EXPORTED_API void sfizz_set_logging_prefix(sfizz_synth_t* synth, const cha
*/
SFIZZ_EXPORTED_API void sfizz_all_sound_off(sfizz_synth_t* synth);
+/**
+ * @brief Add external definitions prior to loading;
+ * Note that these do not get reset by loading or resetting the synth.
+ * You need to call sfizz_clear_external_definitions() to erase them.
+ *
+ * @param synth
+ * @param id
+ * @param value
+ */
+SFIZZ_EXPORTED_API void sfizz_add_external_definitions(sfizz_synth_t* synth, const char* id, const char* value);
+
+/**
+ * @brief Clears external definitions for the next file loading.
+ *
+ * @param synth
+ */
+SFIZZ_EXPORTED_API void sfizz_clear_external_definitions(sfizz_synth_t* synth);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/sfizz.hpp b/src/sfizz.hpp
index d0e62e37b..911b5eac7 100644
--- a/src/sfizz.hpp
+++ b/src/sfizz.hpp
@@ -284,6 +284,21 @@ class SFIZZ_EXPORTED_API Sfizz
*
*/
void allSoundOff() noexcept;
+
+ /**
+ * @brief Add external definitions prior to loading;
+ * Note that these do not get reset by loading or resetting the synth.
+ * You need to call clearExternalDefintions() to erase them.
+ *
+ * @param id
+ * @param value
+ */
+ void addExternalDefinition(const std::string& id, const std::string& value);
+ /**
+ * @brief Clears external definitions for the next file loading.
+ *
+ */
+ void clearExternalDefinitions();
private:
std::unique_ptr synth;
};
diff --git a/src/sfizz/sfizz.cpp b/src/sfizz/sfizz.cpp
index 08f88c1ac..3e17af01f 100644
--- a/src/sfizz/sfizz.cpp
+++ b/src/sfizz/sfizz.cpp
@@ -210,3 +210,13 @@ void sfz::Sfizz::allSoundOff() noexcept
{
synth->allSoundOff();
}
+
+void sfz::Sfizz::addExternalDefinition(const std::string& id, const std::string& value)
+{
+ synth->getParser().addExternalDefinition(id, value);
+}
+
+void sfz::Sfizz::clearExternalDefinitions()
+{
+ synth->getParser().clearExternalDefinitions();
+}
diff --git a/src/sfizz/sfizz_wrapper.cpp b/src/sfizz/sfizz_wrapper.cpp
index bc62c4c74..3c9d88f09 100644
--- a/src/sfizz/sfizz_wrapper.cpp
+++ b/src/sfizz/sfizz_wrapper.cpp
@@ -256,6 +256,18 @@ void sfizz_all_sound_off(sfizz_synth_t* synth)
return self->allSoundOff();
}
+void sfizz_add_external_definitions(sfizz_synth_t* synth, const char* id, const char* value)
+{
+ auto self = reinterpret_cast(synth);
+ self->getParser().addExternalDefinition(id, value);
+}
+
+void sfizz_clear_external_definitions(sfizz_synth_t* synth)
+{
+ auto self = reinterpret_cast(synth);
+ self->getParser().clearExternalDefinitions();
+}
+
#ifdef __cplusplus
}
#endif
From c4c4278ee393832cc5f0be82e36218204d9bdbc0 Mon Sep 17 00:00:00 2001
From: Jean Pierre Cimalando
Date: Tue, 7 Apr 2020 16:12:29 +0200
Subject: [PATCH 008/444] Move the oscillator count to Config.h
---
src/sfizz/Config.h | 1 +
src/sfizz/Defaults.h | 2 +-
src/sfizz/Voice.cpp | 4 +---
src/sfizz/Voice.h | 10 ++++------
4 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/src/sfizz/Config.h b/src/sfizz/Config.h
index a71ad3db5..727a125fb 100644
--- a/src/sfizz/Config.h
+++ b/src/sfizz/Config.h
@@ -60,6 +60,7 @@ namespace config {
constexpr int filtersInPool { maxVoices * 2 };
constexpr int filtersPerVoice { 2 };
constexpr int eqsPerVoice { 3 };
+ constexpr int oscillatorsPerVoice { 9 };
constexpr float noiseVariance { 0.25f };
/**
Minimum interval in frames between recomputations of coefficients of the
diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h
index 2066cb19a..158da5970 100644
--- a/src/sfizz/Defaults.h
+++ b/src/sfizz/Defaults.h
@@ -64,7 +64,7 @@ namespace Default
constexpr float oscillatorPhase { 0.0 };
constexpr Range oscillatorPhaseRange { -1.0, 360.0 };
constexpr int oscillatorMulti { 1 };
- constexpr Range oscillatorMultiRange { 1, 9 };
+ constexpr Range oscillatorMultiRange { 1, config::oscillatorsPerVoice };
constexpr float oscillatorDetune { 0 };
constexpr Range oscillatorDetuneRange { -9600, 9600 };
diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp
index 4a9c6c76f..251a11670 100644
--- a/src/sfizz/Voice.cpp
+++ b/src/sfizz/Voice.cpp
@@ -666,7 +666,7 @@ void sfz::Voice::setupOscillatorUnison()
waveUnisonSize = m;
// detune (cents)
- float detunes[maxWaveOscillators];
+ float detunes[config::oscillatorsPerVoice];
detunes[0] = 0.0;
detunes[1] = -d;
detunes[2] = +d;
@@ -703,5 +703,3 @@ void sfz::Voice::setupOscillatorUnison()
}
#endif
}
-
-constexpr unsigned sfz::Voice::maxWaveOscillators;
diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h
index afde9b53e..1723c4165 100644
--- a/src/sfizz/Voice.h
+++ b/src/sfizz/Voice.h
@@ -288,15 +288,13 @@ class Voice {
ADSREnvelope egEnvelope;
float bendStepFactor { centsFactor(1) };
- static constexpr unsigned maxWaveOscillators = Default::oscillatorMultiRange.getEnd();
-
- WavetableOscillator waveOscillators[maxWaveOscillators];
+ WavetableOscillator waveOscillators[config::oscillatorsPerVoice];
// unison of oscillators
unsigned waveUnisonSize { 0 };
- float waveDetuneRatio[maxWaveOscillators] { };
- float waveLeftGain[maxWaveOscillators] { };
- float waveRightGain[maxWaveOscillators] { };
+ float waveDetuneRatio[config::oscillatorsPerVoice] { };
+ float waveLeftGain[config::oscillatorsPerVoice] { };
+ float waveRightGain[config::oscillatorsPerVoice] { };
Duration dataDuration;
Duration amplitudeDuration;
From c2360bad454fa91901aae0c7e2ec8f81b53cc8c2 Mon Sep 17 00:00:00 2001
From: Paul Fd
Date: Tue, 7 Apr 2020 16:24:38 +0200
Subject: [PATCH 009/444] Feed master opcodes to the handleGroupOpcodes
---
src/sfizz/Synth.cpp | 14 ++++++++++----
src/sfizz/Synth.h | 2 +-
tests/SynthT.cpp | 22 ++++++++++++++++++++++
tests/TestFiles/master_polyphony.sfz | 7 +++++++
4 files changed, 40 insertions(+), 5 deletions(-)
create mode 100644 tests/TestFiles/master_polyphony.sfz
diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp
index 25393b4de..7f4df9d7f 100644
--- a/src/sfizz/Synth.cpp
+++ b/src/sfizz/Synth.cpp
@@ -67,7 +67,7 @@ void sfz::Synth::onParseFullBlock(const std::string& header, const std::vector& members)
}
}
-void sfz::Synth::handleGroupOpcodes(const std::vector& members)
+void sfz::Synth::handleGroupOpcodes(const std::vector& members, const std::vector& masterMembers)
{
absl::optional groupIdx;
unsigned maxPolyphony { config::maxVoices };
- for (auto& member : members) {
+ const auto parseOpcode = [&](const Opcode& member) {
switch (member.lettersOnlyHash) {
case hash("group"):
setValueFromOpcode(member, groupIdx, Default::groupRange);
@@ -191,7 +191,13 @@ void sfz::Synth::handleGroupOpcodes(const std::vector& members)
setValueFromOpcode(member, maxPolyphony, Range(0, config::maxVoices));
break;
}
- }
+ };
+
+ for (auto& member : masterMembers)
+ parseOpcode(member);
+
+ for (auto& member : members)
+ parseOpcode(member);
if (groupIdx)
setGroupPolyphony(*groupIdx, maxPolyphony);
diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h
index a9ce64ab5..16017f3a8 100644
--- a/src/sfizz/Synth.h
+++ b/src/sfizz/Synth.h
@@ -454,7 +454,7 @@ class Synth final : public Parser::Listener {
*
* @param members the opcodes of the block
*/
- void handleGroupOpcodes(const std::vector& members);
+ void handleGroupOpcodes(const std::vector& members, const std::vector& masterMembers);
/**
* @brief Helper function to dispatch opcodes
*
diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp
index 0434d9ce2..bd0d28cce 100644
--- a/tests/SynthT.cpp
+++ b/tests/SynthT.cpp
@@ -397,3 +397,25 @@ TEST_CASE("[Synth] Not self-masking")
REQUIRE(synth.getVoiceView(2)->getTriggerValue() == 64_norm);
REQUIRE(!synth.getVoiceView(2)->canBeStolen());
}
+
+TEST_CASE("[Synth] Polyphony in master")
+{
+ sfz::Synth synth;
+ synth.loadSfzFile(fs::current_path() / "tests/TestFiles/master_polyphony.sfz");
+ synth.noteOn(0, 65, 64);
+ synth.noteOn(0, 65, 64);
+ synth.noteOn(0, 65, 64);
+ REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note
+ synth.allSoundOff();
+ REQUIRE(synth.getNumActiveVoices() == 0);
+ synth.noteOn(0, 63, 64);
+ synth.noteOn(0, 63, 64);
+ synth.noteOn(0, 63, 64);
+ REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note
+ synth.allSoundOff();
+ REQUIRE(synth.getNumActiveVoices() == 0);
+ synth.noteOn(0, 61, 64);
+ synth.noteOn(0, 61, 64);
+ synth.noteOn(0, 61, 64);
+ REQUIRE(synth.getNumActiveVoices() == 3);
+}
diff --git a/tests/TestFiles/master_polyphony.sfz b/tests/TestFiles/master_polyphony.sfz
new file mode 100644
index 000000000..88d7bd7a9
--- /dev/null
+++ b/tests/TestFiles/master_polyphony.sfz
@@ -0,0 +1,7 @@
+ polyphony=2
+ group=2
+ sample=*sine key=65
+ group=3
+ sample=*sine key=63
+ // Empty master resets the polyphony
+ sample=*sine key=61
From b2a4f8a559bb08f3501432cf86cd1c69eca3f73f Mon Sep 17 00:00:00 2001
From: Paul Fd
Date: Tue, 7 Apr 2020 16:26:00 +0200
Subject: [PATCH 010/444] global clears master and group, master clears group
---
src/sfizz/Synth.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp
index 7f4df9d7f..f9f9abd2a 100644
--- a/src/sfizz/Synth.cpp
+++ b/src/sfizz/Synth.cpp
@@ -55,6 +55,8 @@ void sfz::Synth::onParseFullBlock(const std::string& header, const std::vector
Date: Tue, 7 Apr 2020 18:41:55 +0200
Subject: [PATCH 011/444] Update doxygen related files, added c++ API
documentation
---
doxygen/pages/index.md | 3 ++-
doxygen/scripts/Doxyfile.in | 48 ++++++++++++++++++++-----------------
2 files changed, 28 insertions(+), 23 deletions(-)
diff --git a/doxygen/pages/index.md b/doxygen/pages/index.md
index 47aff24b1..a7e12b3f1 100644
--- a/doxygen/pages/index.md
+++ b/doxygen/pages/index.md
@@ -2,4 +2,5 @@
SFZ file format library
-[public API](sfizz_8h.html)
+- [public C API](sfizz_8h.html)
+- [public C++ API](classsfz_1_1_sfizz.html)
diff --git a/doxygen/scripts/Doxyfile.in b/doxygen/scripts/Doxyfile.in
index 53dc1502b..0f7eb945d 100644
--- a/doxygen/scripts/Doxyfile.in
+++ b/doxygen/scripts/Doxyfile.in
@@ -1,4 +1,4 @@
-# Doxyfile 1.8.16
+# Doxyfile 1.8.17
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -251,8 +251,8 @@ TAB_SIZE = 4
# commands \{ and \} for these it is advised to use the version @{ and @} or use
# a double escape (\\{ and \\})
-ALIASES = true=true \
- false=false
+ALIASES = "true=true" \
+ "false=false"
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
@@ -300,7 +300,7 @@ OPTIMIZE_OUTPUT_SLICE = NO
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
@@ -515,7 +515,7 @@ EXTRACT_ANON_NSPACES = NO
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
-HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
@@ -523,11 +523,11 @@ HIDE_UNDOC_MEMBERS = YES
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
-HIDE_UNDOC_CLASSES = YES
+HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO, these declarations will be
-# included in the documentation.
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
@@ -843,17 +843,20 @@ INPUT_ENCODING = UTF-8
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
-# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
-# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
+# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
+# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
+# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.h \
- *.md
+ *.md \
+ *.hpp
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
-RECURSIVE = YES
+RECURSIVE = NO
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
@@ -862,12 +865,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE = sfizz/ghc \
- sfizz/mathfuns \
- sfizz/atomicops.h \
- sfizz/MathHelpers.h \
- sfizz/readerwriterqueue.h \
- sfizz/ScopedFTZ.h
+EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -1220,9 +1218,9 @@ HTML_TIMESTAMP = YES
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that
-# are dynamically created via Javascript. If disabled, the navigation index will
+# are dynamically created via JavaScript. If disabled, the navigation index will
# consists of multiple levels of tabs that are statically embedded in every HTML
-# page. Disable this option to support browsers that do not have Javascript,
+# page. Disable this option to support browsers that do not have JavaScript,
# like the Qt help browser.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1510,8 +1508,14 @@ FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE =
+
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# https://www.mathjax.org) which uses client side Javascript for the rendering
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
@@ -1581,7 +1585,7 @@ MATHJAX_CODEFILE =
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
From 33f9e6bf327a45ef7ae28e5edba5dd0b7728402c Mon Sep 17 00:00:00 2001
From: redtide
Date: Tue, 7 Apr 2020 18:42:41 +0200
Subject: [PATCH 012/444] Updated API doxygen documentation
---
src/sfizz.h | 222 +++++++++++++++++++++++---------------------------
src/sfizz.hpp | 158 ++++++++++++++++++-----------------
2 files changed, 187 insertions(+), 193 deletions(-)
diff --git a/src/sfizz.h b/src/sfizz.h
index 5e5c6af87..42585a9de 100644
--- a/src/sfizz.h
+++ b/src/sfizz.h
@@ -27,7 +27,13 @@
extern "C" {
#endif
+/**
+ * @brief Synth handle
+ */
typedef struct sfizz_synth_t sfizz_synth_t;
+/**
+ * @brief Oversampling factor
+ */
typedef enum {
SFIZZ_OVERSAMPLING_X1 = 1,
SFIZZ_OVERSAMPLING_X2 = 2,
@@ -40,14 +46,13 @@ typedef enum {
* using sfizz_free(). The synth by default is set at 48 kHz
* and a maximum block size of 1024. You should change these values
* if they are not correct for your application.
- *
- * @return sfizz_synth_t*
*/
SFIZZ_EXPORTED_API sfizz_synth_t* sfizz_create_synth();
+
/**
* @brief Frees an existing sfizz synth.
*
- * @param synth The synth to destroy
+ * @param synth The synth to destroy.
*/
SFIZZ_EXPORTED_API void sfizz_free(sfizz_synth_t* synth);
@@ -60,88 +65,76 @@ SFIZZ_EXPORTED_API void sfizz_free(sfizz_synth_t* synth);
* @param path A null-terminated string representing a path to an SFZ
* file.
*
- * @return true when file loading went OK.
- * @return false if some error occured while loading.
+ * @return @true when file loading went OK,
+ * @false if some error occured while loading.
*/
SFIZZ_EXPORTED_API bool sfizz_load_file(sfizz_synth_t* synth, const char* path);
/**
- * @brief Returns the number of regions in the currently loaded SFZ file.
+ * @brief Return the number of regions in the currently loaded SFZ file.
*
- * @param synth The synth
- *
- * @return int the number of regions
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API int sfizz_get_num_regions(sfizz_synth_t* synth);
/**
- * @brief Returns the number of groups in the currently loaded SFZ file.
- *
- * @param synth The synth
+ * @brief Return the number of groups in the currently loaded SFZ file.
*
- * @return int the number of groups
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API int sfizz_get_num_groups(sfizz_synth_t* synth);
/**
- * @brief Returns the number of masters in the currently loaded SFZ file.
- *
- * @param synth The synth
+ * @brief Return the number of masters in the currently loaded SFZ file.
*
- * @return int the number of masters
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API int sfizz_get_num_masters(sfizz_synth_t* synth);
/**
- * @brief Returns the number of curves in the currently loaded SFZ file.
+ * @brief Return the number of curves in the currently loaded SFZ file.
*
- * @param synth The synth
- *
- * @return int the number of curves
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API int sfizz_get_num_curves(sfizz_synth_t* synth);
/**
* @brief Export a MIDI Name document describing the the currently loaded
* SFZ file.
*
- * @param synth The synth
- * @param model the model name used if a non-empty string, otherwise generated
+ * @param synth The synth.
+ * @param model The model name used if a non-empty string, otherwise generated.
*
- * @return char* a newly allocated XML string, which must be freed after use
+ * @return A newly allocated XML string, which must be freed after use.
*/
SFIZZ_EXPORTED_API char* sfizz_export_midnam(sfizz_synth_t* synth, const char* model);
/**
- * @brief Returns the number of preloaded samples for the current SFZ file.
+ * @brief Return the number of preloaded samples for the current SFZ file.
*
- * @param synth The synth
- *
- * @return int the number of preloaded samples
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API size_t sfizz_get_num_preloaded_samples(sfizz_synth_t* synth);
/**
- * @brief Returns the number of active voices. Note that this function is a
+ * @brief Return the number of active voices. Note that this function is a
* basic indicator and does not aim to be perfect. In particular, it
* runs on the calling thread so voices may well start or stop while
* the function is checking which voice is active.
*
- * @param synth The synth
- *
- * @return size_t the number of playing voices
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API int sfizz_get_num_active_voices(sfizz_synth_t* synth);
/**
- * @brief Sets the expected number of samples per block. If unsure, give an
+ * @brief Set the expected number of samples per block. If unsure, give an
* upper bound since right now ugly things may happen if you go over
* this number.
*
- * @param synth The synth
- * @param samples_per_block the number of samples per block
+ * @param synth The synth.
+ * @param samples_per_block The number of samples per block.
*/
SFIZZ_EXPORTED_API void sfizz_set_samples_per_block(sfizz_synth_t* synth, int samples_per_block);
/**
- * @brief Sets the sample rate for the synth. This is the output sample
+ * @brief Set the sample rate for the synth. This is the output sample
* rate. This setting does not affect the internal processing.
*
* @param synth The synth
- * @param sample_rate the sample rate
+ * @param sample_rate The sample rate.
*/
SFIZZ_EXPORTED_API void sfizz_set_sample_rate(sfizz_synth_t* synth, float sample_rate);
@@ -150,10 +143,10 @@ SFIZZ_EXPORTED_API void sfizz_set_sample_rate(sfizz_synth_t* synth, float sample
* needs to happen before the call to sfizz_render_block in each
* block and should appear in order of the delays.
*
- * @param synth The synth
- * @param delay the delay of the event in the block, in samples.
- * @param note_number the MIDI note number
- * @param velocity the MIDI velocity
+ * @param synth The synth.
+ * @param delay The delay of the event in the block, in samples.
+ * @param note_number The MIDI note number.
+ * @param velocity The MIDI velocity.
*/
SFIZZ_EXPORTED_API void sfizz_send_note_on(sfizz_synth_t* synth, int delay, int note_number, char velocity);
@@ -164,10 +157,10 @@ SFIZZ_EXPORTED_API void sfizz_send_note_on(sfizz_synth_t* synth, int delay, int
* As per the SFZ spec the velocity of note-off events is usually replaced by
* the note-on velocity.
*
- * @param synth The synth
- * @param delay the delay of the event in the block, in samples.
- * @param note_number the MIDI note number
- * @param velocity the MIDI velocity
+ * @param synth The synth.
+ * @param delay The delay of the event in the block, in samples.
+ * @param note_number The MIDI note number.
+ * @param velocity The MIDI velocity.
*/
SFIZZ_EXPORTED_API void sfizz_send_note_off(sfizz_synth_t* synth, int delay, int note_number, char velocity);
@@ -176,38 +169,39 @@ SFIZZ_EXPORTED_API void sfizz_send_note_off(sfizz_synth_t* synth, int delay, int
* to happen before the call to sfizz_render_block in each block and
* should appear in order of the delays.
*
- * @param synth The synth
- * @param delay the delay of the event in the block, in samples.
- * @param cc_number the MIDI CC number
- * @param cc_value the MIDI CC value
+ * @param synth The synth.
+ * @param delay The delay of the event in the block, in samples.
+ * @param cc_number The MIDI CC number.
+ * @param cc_value The MIDI CC value.
*/
SFIZZ_EXPORTED_API void sfizz_send_cc(sfizz_synth_t* synth, int delay, int cc_number, char cc_value);
+
/**
* @brief Send a pitch wheel event. As with all MIDI events, this needs
* to happen before the call to sfizz_render_block in each block and
* should appear in order of the delays.
*
- * @param synth The synth
- * @param delay The delay
- * @param pitch The pitch
+ * @param synth The synth.
+ * @param delay The delay.
+ * @param pitch The pitch.
*/
SFIZZ_EXPORTED_API void sfizz_send_pitch_wheel(sfizz_synth_t* synth, int delay, int pitch);
/**
- * @brief Send an aftertouch event. (CURRENTLY UNIMPLEMENTED)
+ * @brief Send an aftertouch event. (CURRENTLY UNIMPLEMENTED)
*
- * @param synth
- * @param delay
- * @param aftertouch
+ * @param synth
+ * @param delay
+ * @param aftertouch
*/
SFIZZ_EXPORTED_API void sfizz_send_aftertouch(sfizz_synth_t* synth, int delay, char aftertouch);
/**
* @brief Send a tempo event. (CURRENTLY UNIMPLEMENTED)
*
- * @param synth The synth
- * @param delay The delay
- * @param seconds_per_quarter The seconds per quarter
+ * @param synth The synth.
+ * @param delay The delay.
+ * @param seconds_per_quarter The seconds per quarter.
*/
SFIZZ_EXPORTED_API void sfizz_send_tempo(sfizz_synth_t* synth, int delay, float seconds_per_quarter);
@@ -219,11 +213,11 @@ SFIZZ_EXPORTED_API void sfizz_send_tempo(sfizz_synth_t* synth, int delay, float
* block. The synth will memorize the inputs and render sample
* accurates envelopes depending on the input events passed to it.
*
- * @param synth The synth
- * @param channels pointers to the left and right channel of the
- * output
- * @param num_channels should be equal to 2 for the time being.
- * @param num_frames number of frames to fill. This should be less than
+ * @param synth The synth.
+ * @param channels Pointers to the left and right channel of the
+ * output.
+ * @param num_channels Should be equal to 2 for the time being.
+ * @param num_frames Number of frames to fill. This should be less than
* or equal to the expected samples_per_block.
*/
SFIZZ_EXPORTED_API void sfizz_render_block(sfizz_synth_t* synth, float** channels, int num_channels, int num_frames);
@@ -232,18 +226,16 @@ SFIZZ_EXPORTED_API void sfizz_render_block(sfizz_synth_t* synth, float** channel
* @brief Get the size of the preloaded data. This returns the number of
* floats used in the preloading buffers.
*
- * @param synth The synth
- *
- * @return the preloaded data size in sizeof(floats)
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API unsigned int sfizz_get_preload_size(sfizz_synth_t* synth);
/**
- * @brief Sets the size of the preloaded data in number of floats (not
+ * @brief Set the size of the preloaded data in number of floats (not
* bytes). This will disable the callbacks for the duration of the
* load.
*
- * @param synth The synth
- * @param[in] preload_size The preload size
+ * @param synth The synth.
+ * @param[in] preload_size The preload size.
*/
SFIZZ_EXPORTED_API void sfizz_set_preload_size(sfizz_synth_t* synth, unsigned int preload_size);
@@ -252,9 +244,7 @@ SFIZZ_EXPORTED_API void sfizz_set_preload_size(sfizz_synth_t* synth, unsigned in
* the engine, not the output or expected rate of the calling
* function. For the latter use the `get_sample_rate()` functions.
*
- * @param synth The synth
- *
- * @return The internal sample rate of the engine
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API sfizz_oversampling_factor_t sfizz_get_oversampling_factor(sfizz_synth_t* synth);
/**
@@ -272,51 +262,46 @@ SFIZZ_EXPORTED_API sfizz_oversampling_factor_t sfizz_get_oversampling_factor(sfi
* to compensate for the memory increase, but the full loading will
* need to take place anyway.
*
- * @param synth The synth
- * @param[in] preload_size The preload size
+ * @param synth The synth.
+ * @param[in] oversampling The oversampling factor.
*
- * @return True if the oversampling factor was correct
+ * @return @true if the oversampling factor was correct, @false otherwise.
*/
SFIZZ_EXPORTED_API bool sfizz_set_oversampling_factor(sfizz_synth_t* synth, sfizz_oversampling_factor_t oversampling);
/**
* @brief Set the global instrument volume.
*
- * @param synth The synth
- * @param volume the new volume
+ * @param synth The synth.
+ * @param volume The new volume.
*/
SFIZZ_EXPORTED_API void sfizz_set_volume(sfizz_synth_t* synth, float volume);
/**
- * @brief Get the global instrument volume.
- *
- * @param synth The synth
+ * @brief Return the global instrument volume.
*
- * @return float the instrument volume
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API float sfizz_get_volume(sfizz_synth_t* synth);
/**
- * @brief Sets the number of voices used by the synth
+ * @brief Set the number of voices used by the synth.
*
- * @param synth The synth
- * @param num_voices The number voices
+ * @param synth The synth.
+ * @param num_voices The number of voices.
*/
SFIZZ_EXPORTED_API void sfizz_set_num_voices(sfizz_synth_t* synth, int num_voices);
/**
- * @brief Returns the number of voices
+ * @brief Return the number of voices.
*
- * @param synth
- * @return num_voices
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API int sfizz_get_num_voices(sfizz_synth_t* synth);
/**
- * @brief Get the number of allocated buffers from the synth.
+ * @brief Return the number of allocated buffers from the synth.
*
- * @param synth The synth
- *
- * @return The number of buffers held by the synth
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API int sfizz_get_num_buffers(sfizz_synth_t* synth);
/**
@@ -324,73 +309,70 @@ SFIZZ_EXPORTED_API int sfizz_get_num_buffers(sfizz_synth_t* synth);
* value can be less than the actual memory usage since it only
* counts the buffer objects managed by sfizz.
*
- * @param synth The synth
- *
- * @return The number of bytes held by the synth in buffers;
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API int sfizz_get_num_bytes(sfizz_synth_t* synth);
/**
- * @brief Enables freewheeling on the synth.
+ * @brief Enable freewheeling on the synth.
*
- * @param synth
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API void sfizz_enable_freewheeling(sfizz_synth_t* synth);
/**
- * @brief Disables freewheeling on the synth.
+ * @brief Disable freewheeling on the synth.
*
- * @param synth
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API void sfizz_disable_freewheeling(sfizz_synth_t* synth);
/**
- * @brief Get a comma separated list of unknown opcodes. The caller has to free()
- * the string returned. This function allocates memory, do not call on the
- * audio thread.
+ * @brief Return a comma separated list of unknown opcodes.
+ * The caller has to free() the string returned.
+ * This function allocates memory, do not call on the audio thread.
*
- * @param synth
- * @return char*
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API char* sfizz_get_unknown_opcodes(sfizz_synth_t* synth);
/**
- * @brief Check if the SFZ should be reloaded.
+ * @brief Check if the SFZ should be reloaded.
+ * Depending on the platform this can create file descriptors.
*
- * Depending on the platform this can create file descriptors.
+ * @param synth The synth.
*
- * @param synth
- * @return true if any included files (including the root file) have
- * been modified since the sfz file was loaded.
- * @return false
+ * @return @true if any included files (including the root file) have
+ * been modified since the sfz file was loaded, @false otherwise.
*/
SFIZZ_EXPORTED_API bool sfizz_should_reload_file(sfizz_synth_t* synth);
/**
- * @brief Enable logging of timings to sidecar CSV files. This can produce
- * many outputs so use with caution.
+ * @brief Enable logging of timings to sidecar CSV files. This can produce
+ * many outputs so use with caution.
*
- * @param synth
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API void sfizz_enable_logging(sfizz_synth_t* synth);
/**
- * @brief Disable logging
+ * @brief Disable logging.
*
- * @param synth
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API void sfizz_disable_logging(sfizz_synth_t* synth);
/**
- * @brief Enable logging of timings to sidecar CSV files. This can produce
- * many outputs so use with caution.
+ * @brief Enable logging of timings to sidecar CSV files. This can produce
+ * many outputs so use with caution.
*
- * @param synth
+ * @param synth The synth.
+ * @param prefix The prefix.
*/
SFIZZ_EXPORTED_API void sfizz_set_logging_prefix(sfizz_synth_t* synth, const char* prefix);
/**
- * @brief Shuts down the current processing, clear buffers and reset the voices.
+ * @brief Shuts down the current processing, clear buffers and reset the voices.
*
- * @param synth
+ * @param synth The synth.
*/
SFIZZ_EXPORTED_API void sfizz_all_sound_off(sfizz_synth_t* synth);
diff --git a/src/sfizz.hpp b/src/sfizz.hpp
index d0e62e37b..b2af98c19 100644
--- a/src/sfizz.hpp
+++ b/src/sfizz.hpp
@@ -4,6 +4,11 @@
// 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
+/**
+ @file
+ @brief sfizz public C++ API
+*/
+
#include
#include
#include
@@ -21,6 +26,9 @@
namespace sfz
{
class Synth;
+/**
+ * @brief Main class
+ */
class SFIZZ_EXPORTED_API Sfizz
{
public:
@@ -32,6 +40,7 @@ class SFIZZ_EXPORTED_API Sfizz
*/
Sfizz();
~Sfizz();
+
/**
* @brief Empties the current regions and load a new SFZ file into the synth.
*
@@ -39,68 +48,70 @@ class SFIZZ_EXPORTED_API Sfizz
* 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.
+ * @param path The path to the file to load, as string.
+ *
+ * @return @false if the file was not found or no regions were loaded,
+ * @true otherwise.
*/
bool loadSfzFile(const std::string& path);
+
/**
- * @brief Get the current number of regions loaded
- *
- * @return int
+ * @brief Return the current number of regions loaded.
*/
int getNumRegions() const noexcept;
+
/**
- * @brief Get the current number of groups loaded
- *
- * @return int
+ * @brief Return the current number of groups loaded.
*/
int getNumGroups() const noexcept;
+
/**
- * @brief Get the current number of masters loaded
- *
- * @return int
+ * @brief Return the current number of masters loaded.
*/
int getNumMasters() const noexcept;
+
/**
- * @brief Get the current number of curves loaded
- *
- * @return int
+ * @brief Return the current number of curves loaded.
*/
int getNumCurves() const noexcept;
+
+ /**
+ * @brief Return a list of unsupported opcodes, if any.
+ */
const std::vector& getUnknownOpcodes() const noexcept;
+
/**
- * @brief Get the number of preloaded samples in the synth
- *
- * @return size_t
+ * @brief Return the number of preloaded samples in the synth.
*/
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
+ * @param samplesPerBlock The number of samples per block.
*/
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
+ * @param sampleRate The sample rate.
*/
void setSampleRate(float sampleRate) noexcept;
+
/**
- * @brief Get the current value for the volume, in dB.
- *
- * @return float
+ * @brief Return the current value for the volume, in dB.
*/
float getVolume() const noexcept;
- /**
+
+ /**
* @brief Set the value for the volume. This value will be
* clamped within sfz::default::volumeRange.
*
- * @param volume
+ * @param volume The new volume.
*/
void setVolume(float volume) noexcept;
@@ -109,125 +120,122 @@ class SFIZZ_EXPORTED_API Sfizz
*
* @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
+ * @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
+ * @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
+ * @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
+ * @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
+ * @brief Send a aftertouch event to the synth. (CURRENTLY UNIMPLEMENTED)
*
* @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
+ * @param aftertouch the aftertouch value.
*/
void aftertouch(int delay, uint8_t aftertouch) noexcept;
+
/**
- * @brief Send a tempo event to the synth
+ * @brief Send a tempo event to the synth. (CURRENTLY UNIMPLEMENTED)
*
* @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
+ * @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
+ * @param buffers the buffers to write the next block into.
+ * @param numFrames 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
+ * @brief Return the number of active voices.
*/
int getNumActiveVoices() const noexcept;
+
/**
- * @brief Get the total number of voices in the synth (the polyphony)
- *
- * @return int
+ * @brief Return the total number of voices in the synth (the polyphony).
*/
int getNumVoices() const noexcept;
+
/**
- * @brief Change the number of voices (the polyphony)
+ * @brief Change the number of voices (the polyphony).
*
- * @param numVoices
+ * @param numVoices The number of voices.
*/
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
+ * @param factor The oversampling factor.
+ *
+ * @return @true if the factor did indeed change, @false otherwise.
*/
bool setOversamplingFactor(int factor) noexcept;
/**
- * @brief get the current oversampling factor
- *
- * @return Oversampling
+ * @brief Return the current oversampling factor.
*/
int getOversamplingFactor() const noexcept;
/**
* @brief Set the preloaded file size. This will disable the callback.
*
- * @param factor
+ * @param preloadSize The preload size.
*/
void setPreloadSize(uint32_t preloadSize) noexcept;
/**
- * @brief get the current preloaded file size
- *
- * @return Oversampling
+ * @brief Return the current preloaded file size.
*/
uint32_t getPreloadSize() const noexcept;
/**
- * @brief Gets the number of allocated buffers.
- *
- * @return The allocated buffers.
+ * @brief Return the number of allocated buffers.
*/
int getAllocatedBuffers() const noexcept;
/**
- * @brief Gets the number of bytes allocated through the buffers
- *
- * @return The allocated bytes.
+ * @brief Return the number of bytes allocated through the buffers.
*/
int getAllocatedBytes() const noexcept;
@@ -235,55 +243,59 @@ class SFIZZ_EXPORTED_API Sfizz
* @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
+ * @return @true if any included files (including the root file) have
+ * been modified since the sfz file was loaded, @false otherwise.
*/
bool shouldReloadFile();
+
/**
* @brief Enable logging of timings to sidecar CSV files. This can produce
* many outputs so use with caution.
*
- * @param prefix the file prefix to use for logging
+ * @param prefix the file prefix to use for logging.
*/
void enableLogging() noexcept;
+
/**
* @brief Enable logging of timings to sidecar CSV files. This can produce
* many outputs so use with caution.
*
- * @param prefix the file prefix to use for logging
+ * @param prefix the file prefix to use for logging.
*/
void enableLogging(const std::string& prefix) noexcept;
+
/**
- * @brief Set the logging prefix
+ * @brief Set the logging prefix.
*
* @param prefix
*/
void setLoggingPrefix(const std::string& prefix) noexcept;
+
/**
- * @brief Disable logging;
- *
+ * @brief Disable logging.
*/
void disableLogging() noexcept;
+
/**
* @brief Shuts down the current processing, clear buffers and reset the voices.
- *
*/
void allSoundOff() noexcept;
+
private:
std::unique_ptr synth;
};
From 819e4da275594ad64738021a615bf4068ac28a12 Mon Sep 17 00:00:00 2001
From: redtide
Date: Wed, 8 Apr 2020 12:09:40 +0200
Subject: [PATCH 013/444] Try to reflect site navigation in Doxygen pages
header
---
doxygen/layout/custom_footer.html | 2 +-
doxygen/layout/custom_header.html | 113 ++++++++++++++++++++++++------
2 files changed, 92 insertions(+), 23 deletions(-)
diff --git a/doxygen/layout/custom_footer.html b/doxygen/layout/custom_footer.html
index 016704967..15ed43273 100644
--- a/doxygen/layout/custom_footer.html
+++ b/doxygen/layout/custom_footer.html
@@ -6,7 +6,7 @@
target="_new">Doxygen $doxygenversion
-
+