commit
95165ca650
5 changed files with 61 additions and 13 deletions
|
|
@ -103,10 +103,14 @@ namespace config {
|
||||||
// Wavetable constants; amplitude values are matched to reference
|
// Wavetable constants; amplitude values are matched to reference
|
||||||
static constexpr unsigned tableSize = 1024;
|
static constexpr unsigned tableSize = 1024;
|
||||||
static constexpr double tableRefSampleRate = 44100.0 * 1.1; // +10% aliasing permissivity
|
static constexpr double tableRefSampleRate = 44100.0 * 1.1; // +10% aliasing permissivity
|
||||||
static constexpr double amplitudeSine = 0.625;
|
/**
|
||||||
static constexpr double amplitudeTriangle = 0.625;
|
Default wave amplitudes, adjusted for consistent RMS among all waves.
|
||||||
static constexpr double amplitudeSaw = 0.515;
|
(except square curiously, but it's to match ARIA)
|
||||||
static constexpr double amplitudeSquare = 0.515;
|
*/
|
||||||
|
static constexpr double amplitudeSine = 1.0;
|
||||||
|
static constexpr double amplitudeTriangle = 1.0;
|
||||||
|
static constexpr double amplitudeSaw = 0.8164965809277261; // sqrt(2)/sqrt(3)
|
||||||
|
static constexpr double amplitudeSquare = 0.8164965809277261; // should have been sqrt(2)?
|
||||||
/**
|
/**
|
||||||
Background file loading
|
Background file loading
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -176,13 +176,13 @@ inline void applyGain1(T gain, absl::Span<const T> input, absl::Span<T> output)
|
||||||
* @param size
|
* @param size
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
inline void applyGain1(float gain, float* array, unsigned size) noexcept
|
inline void applyGain1(T gain, T* array, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
applyGain1<T>(gain, array, array, size);
|
applyGain1<T>(gain, array, array, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline void applyGain1(float gain, absl::Span<float> array) noexcept
|
inline void applyGain1(T gain, absl::Span<T> array) noexcept
|
||||||
{
|
{
|
||||||
applyGain1<T>(gain, array.data(), array.data(), array.size());
|
applyGain1<T>(gain, array.data(), array.data(), array.size());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,16 @@ void sfz::Synth::buildRegion(const std::vector<Opcode>& regionOpcodes)
|
||||||
int regionNumber = static_cast<int>(regions.size());
|
int regionNumber = static_cast<int>(regions.size());
|
||||||
auto lastRegion = absl::make_unique<Region>(regionNumber, resources.midiState, defaultPath);
|
auto lastRegion = absl::make_unique<Region>(regionNumber, resources.midiState, defaultPath);
|
||||||
|
|
||||||
|
// Create default connections
|
||||||
|
constexpr unsigned defaultSmoothness = 10;
|
||||||
|
lastRegion->getOrCreateConnection(
|
||||||
|
ModKey::createCC(7, 4, defaultSmoothness, 100, 0),
|
||||||
|
ModKey::createNXYZ(ModId::Amplitude, lastRegion->id));
|
||||||
|
lastRegion->getOrCreateConnection(
|
||||||
|
ModKey::createCC(10, 1, defaultSmoothness, 100, 0),
|
||||||
|
ModKey::createNXYZ(ModId::Pan, lastRegion->id));
|
||||||
|
|
||||||
|
//
|
||||||
auto parseOpcodes = [&](const std::vector<Opcode>& opcodes) {
|
auto parseOpcodes = [&](const std::vector<Opcode>& opcodes) {
|
||||||
for (auto& opcode : opcodes) {
|
for (auto& opcode : opcodes) {
|
||||||
const auto unknown = absl::c_find_if(unknownOpcodes, [&](absl::string_view sv) { return sv.compare(opcode.opcode) == 0; });
|
const auto unknown = absl::c_find_if(unknownOpcodes, [&](absl::string_view sv) { return sv.compare(opcode.opcode) == 0; });
|
||||||
|
|
@ -215,6 +225,10 @@ void sfz::Synth::clear()
|
||||||
polyphonyGroups.emplace_back();
|
polyphonyGroups.emplace_back();
|
||||||
polyphonyGroups.back().setPolyphonyLimit(config::maxVoices);
|
polyphonyGroups.back().setPolyphonyLimit(config::maxVoices);
|
||||||
modificationTime = fs::file_time_type::min();
|
modificationTime = fs::file_time_type::min();
|
||||||
|
|
||||||
|
// set default controllers
|
||||||
|
cc(0, 7, 100); // volume
|
||||||
|
hdcc(0, 10, 0.5f); // pan
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Synth::handleMasterOpcodes(const std::vector<Opcode>& members)
|
void sfz::Synth::handleMasterOpcodes(const std::vector<Opcode>& members)
|
||||||
|
|
|
||||||
|
|
@ -491,6 +491,10 @@ void sfz::Voice::panStageStereo(AudioSpan<float> buffer) noexcept
|
||||||
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
(*modulationSpan)[i] += normalizePercents(mod[i]);
|
||||||
}
|
}
|
||||||
pan(*modulationSpan, leftBuffer, rightBuffer);
|
pan(*modulationSpan, leftBuffer, rightBuffer);
|
||||||
|
|
||||||
|
// add +3dB to compensate for the 2 pan stages (-3dB each stage)
|
||||||
|
applyGain1(1.4125375446227544f, leftBuffer);
|
||||||
|
applyGain1(1.4125375446227544f, rightBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Voice::filterStageMono(AudioSpan<float> buffer) noexcept
|
void sfz::Voice::filterStageMono(AudioSpan<float> buffer) noexcept
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,32 @@ TEST_CASE("[Modulations] Display names")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string createReferenceGraph(std::vector<std::string> lines)
|
||||||
|
{
|
||||||
|
const char* defaultConnections[] = {
|
||||||
|
R"("Controller 7 {curve=4, smooth=10, value=100, step=0}" -> "Amplitude")",
|
||||||
|
R"("Controller 10 {curve=1, smooth=10, value=100, step=0}" -> "Pan")"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const char* line : defaultConnections)
|
||||||
|
lines.push_back(line);
|
||||||
|
|
||||||
|
std::sort(lines.begin(), lines.end());
|
||||||
|
|
||||||
|
std::string graph;
|
||||||
|
graph.reserve(1024);
|
||||||
|
|
||||||
|
graph += "digraph {\n";
|
||||||
|
for (const std::string& line : lines) {
|
||||||
|
graph.push_back('\t');
|
||||||
|
graph += line;
|
||||||
|
graph.push_back('\n');
|
||||||
|
}
|
||||||
|
graph += "}\n";
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
};
|
||||||
|
|
||||||
TEST_CASE("[Modulations] Connection graph from SFZ")
|
TEST_CASE("[Modulations] Connection graph from SFZ")
|
||||||
{
|
{
|
||||||
sfz::Synth synth;
|
sfz::Synth synth;
|
||||||
|
|
@ -89,12 +115,12 @@ pitch_oncc42=71 pitch_smoothcc42=32
|
||||||
pan_oncc36=14.5 pan_stepcc36=1.5
|
pan_oncc36=14.5 pan_stepcc36=1.5
|
||||||
width_oncc425=29
|
width_oncc425=29
|
||||||
)");
|
)");
|
||||||
|
|
||||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||||
REQUIRE(graph == R"(digraph {
|
REQUIRE(graph == createReferenceGraph({
|
||||||
"Controller 20 {curve=3, smooth=0, value=59, step=0}" -> "Amplitude"
|
R"("Controller 20 {curve=3, smooth=0, value=59, step=0}" -> "Amplitude")",
|
||||||
"Controller 36 {curve=0, smooth=0, value=14.5, step=1.5}" -> "Pan"
|
R"("Controller 42 {curve=0, smooth=32, value=71, step=0}" -> "Pitch")",
|
||||||
"Controller 42 {curve=0, smooth=32, value=71, step=0}" -> "Pitch"
|
R"("Controller 36 {curve=0, smooth=0, value=14.5, step=1.5}" -> "Pan")",
|
||||||
"Controller 425 {curve=0, smooth=0, value=29, step=0}" -> "Width"
|
R"("Controller 425 {curve=0, smooth=0, value=29, step=0}" -> "Width")",
|
||||||
}
|
}));
|
||||||
)");
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue