sfizz/sources/Synth.cpp
2019-07-29 02:13:03 +02:00

110 lines
No EOL
3 KiB
C++

#include "Synth.h"
#include "Helpers.h"
#include <iostream>
void sfz::Synth::callback(std::string_view header, std::vector<Opcode> members)
{
switch (hash(header))
{
case hash("global"):
// We shouldn't have multiple global headers in file
ASSERT(!hasGlobal);
globalOpcodes = std::move(members);
hasGlobal = true;
break;
case hash("control"):
// We shouldn't have multiple control headers in file
ASSERT(!hasControl)
hasControl = true;
break;
case hash("master"):
masterOpcodes = std::move(members);
numMasters++;
break;
case hash("group"):
groupOpcodes = std::move(members);
numGroups++;
break;
case hash("region"):
buildRegion(members);
break;
case hash("curve"):
// TODO: implement curves
numCurves++;
break;
case hash("effect"):
// TODO: implement curves
break;
default:
std::cerr << "Unknown header: " << header << '\n';
}
}
void sfz::Synth::buildRegion(const std::vector<Opcode>& regionOpcodes)
{
auto& lastRegion = regions.emplace_back();
for (auto& opcode: globalOpcodes)
lastRegion.parseOpcode(opcode);
for (auto& opcode: masterOpcodes)
lastRegion.parseOpcode(opcode);
for (auto& opcode: groupOpcodes)
lastRegion.parseOpcode(opcode);
for (auto& opcode: regionOpcodes)
lastRegion.parseOpcode(opcode);
}
void sfz::Synth::clear()
{
hasGlobal = false;
hasControl = false;
numGroups = 0;
numMasters = 0;
numCurves = 0;
defaultSwitch = std::nullopt;
for (auto& state: ccState)
state = 0;
ccNames.clear();
globalOpcodes.clear();
masterOpcodes.clear();
groupOpcodes.clear();
regions.clear();
}
void sfz::Synth::handleGlobalOpcodes(const std::vector<Opcode>& members)
{
for (auto& member: members)
{
if (member.opcode == "sw_default")
setValueFromOpcode(member, defaultSwitch, Default::keyRange);
}
}
void sfz::Synth::handleControlOpcodes(const std::vector<Opcode>& members)
{
for (auto& member: members)
{
switch (hash(member.opcode))
{
case hash("set_cc"):
if (member.parameter && Default::ccRange.containsWithEnd(*member.parameter))
setValueFromOpcode(member, ccState[*member.parameter], Default::ccRange);
break;
case hash("label_cc"):
if (member.parameter && Default::ccRange.containsWithEnd(*member.parameter))
ccNames.emplace_back(*member.parameter, member.value);
break;
case hash("default_path"):
if (auto newPath = std::filesystem::path(member.value); std::filesystem::exists(newPath))
rootDirectory = newPath;
default:
// Unsupported control opcode
ASSERTFALSE;
}
}
}
bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
{
clear();
return sfz::Parser::loadSfzFile(filename);
}