added pitch to save voice profile

This commit is contained in:
2026-01-31 00:59:07 -06:00
parent d1123138a3
commit 00851f4fbc
5 changed files with 57 additions and 16 deletions

View File

@@ -66,7 +66,7 @@ void ConfigInterface::loadProfile(std::string filename) {
std::cout << "Parameter profile version " << version << "is outdated below the compatible version " << CONFIG_VERSION << std::endl;
return;
} else {
std::cout << version << std::endl;
std::cout << "Parameter profile version " << version << std::endl;
}
// extract values from the config file
@@ -74,6 +74,27 @@ void ConfigInterface::loadProfile(std::string filename) {
std::array<ParamDefault, 5> fCutoffProfile = loadEnvProfile(&config, "FilterCutoff");
std::array<ParamDefault, 5> fResonanceProfile = loadEnvProfile(&config, "FilterResonance");
std::array<ParamDefault, 3> masterPitchOffsets = {{
{ config["MasterOctaveOffset"][0].as<float>(), config["MasterOctaveOffset"][1].as<float>(), config["MasterOctaveOffset"][2].as<float>() },
{ config["MasterSemitoneOffset"][0].as<float>(), config["MasterSemitoneOffset"][1].as<float>(), config["MasterSemitoneOffset"][2].as<float>() },
{ config["MasterPitchOffset"][0].as<float>(), config["MasterPitchOffset"][1].as<float>(), config["MasterPitchOffset"][2].as<float>() },
}};
std::array<ParamDefault, 3> osc1PitchOffsets = {{
{ config["Osc1OctaveOffset"][0].as<float>(), config["Osc1OctaveOffset"][1].as<float>(), config["Osc1OctaveOffset"][2].as<float>() },
{ config["Osc1SemitoneOffset"][0].as<float>(), config["Osc1SemitoneOffset"][1].as<float>(), config["Osc1SemitoneOffset"][2].as<float>() },
{ config["Osc1PitchOffset"][0].as<float>(), config["Osc1PitchOffset"][1].as<float>(), config["Osc1PitchOffset"][2].as<float>() },
}};
std::array<ParamDefault, 3> osc2PitchOffsets = {{
{ config["Osc2OctaveOffset"][0].as<float>(), config["Osc2OctaveOffset"][1].as<float>(), config["Osc2OctaveOffset"][2].as<float>() },
{ config["Osc2SemitoneOffset"][0].as<float>(), config["Osc2SemitoneOffset"][1].as<float>(), config["Osc2SemitoneOffset"][2].as<float>() },
{ config["Osc2PitchOffset"][0].as<float>(), config["Osc2PitchOffset"][1].as<float>(), config["Osc2PitchOffset"][2].as<float>() },
}};
std::array<ParamDefault, 3> osc3PitchOffsets = {{
{ config["Osc3OctaveOffset"][0].as<float>(), config["Osc3OctaveOffset"][1].as<float>(), config["Osc3OctaveOffset"][2].as<float>() },
{ config["Osc3SemitoneOffset"][0].as<float>(), config["Osc3SemitoneOffset"][1].as<float>(), config["Osc3SemitoneOffset"][2].as<float>() },
{ config["Osc3PitchOffset"][0].as<float>(), config["Osc3PitchOffset"][1].as<float>(), config["Osc3PitchOffset"][2].as<float>() },
}};
// TODO: remove this once all the parameters are set properly
params_->resetToDefaults();
@@ -81,8 +102,19 @@ void ConfigInterface::loadProfile(std::string filename) {
params_->set(EnvelopeId::Osc1Volume, osc1VolumeProfile[0].def, osc1VolumeProfile[1].def, osc1VolumeProfile[2].def, osc1VolumeProfile[3].def, osc1VolumeProfile[4].def);
params_->set(EnvelopeId::FilterCutoff, fCutoffProfile[0].def, fCutoffProfile[1].def, fCutoffProfile[2].def, fCutoffProfile[3].def, fCutoffProfile[4].def);
params_->set(EnvelopeId::FilterResonance, fResonanceProfile[0].def, fResonanceProfile[1].def, fResonanceProfile[2].def, fResonanceProfile[3].def, fResonanceProfile[4].def);
// TODO: why do I bother passing in 5 values independently when I can just do an array ?
// VVV look down there its so easy
// TODO: why do I bother passing in 5 values independently when I can just do an array like in loadEnvProfile ?
params_->set(ParamId::MasterOctaveOffset, masterPitchOffsets[0].def);
params_->set(ParamId::MasterSemitoneOffset, masterPitchOffsets[1].def);
params_->set(ParamId::MasterPitchOffset, masterPitchOffsets[2].def);
params_->set(ParamId::Osc1OctaveOffset, osc1PitchOffsets[0].def);
params_->set(ParamId::Osc1SemitoneOffset, osc1PitchOffsets[1].def);
params_->set(ParamId::Osc1PitchOffset, osc1PitchOffsets[2].def);
params_->set(ParamId::Osc2OctaveOffset, osc2PitchOffsets[0].def);
params_->set(ParamId::Osc2SemitoneOffset, osc2PitchOffsets[1].def);
params_->set(ParamId::Osc2PitchOffset, osc2PitchOffsets[2].def);
params_->set(ParamId::Osc3OctaveOffset, osc3PitchOffsets[0].def);
params_->set(ParamId::Osc3SemitoneOffset, osc3PitchOffsets[1].def);
params_->set(ParamId::Osc3PitchOffset, osc3PitchOffsets[2].def);
// TODO:
// load wavetable settings

View File

@@ -9,6 +9,9 @@ enum class ParamId : uint16_t {
Osc1Frequency,
Osc1WaveSelector1,
Osc1WaveSelector2,
MasterOctaveOffset,
MasterSemitoneOffset,
MasterPitchOffset,
Osc1OctaveOffset,
Osc1SemitoneOffset,
Osc1PitchOffset,
@@ -73,6 +76,9 @@ constexpr std::array<ParamDefault, static_cast<size_t>(ParamId::Count)> PARAM_DE
{ 100.0f, 20.0f, 600.0f}, // Osc1Freq
{ 2.0f, 0.0f, 0.0f}, // OscWaveSelector1
{ 1.0f, 0.0f, 0.0f}, // OscWaveSelector2
{ 0.0f, -5.0f, 5.0f}, // MasterOctaveOffset
{ 0.0f, -12.0f, 12.0f}, // MasterSemitoneOffset
{ 0.0f, -100.0f, 100.0f}, // MasterPitchOffset
{ 0.0f, -5.0f, 5.0f}, // Osc1OctaveOffset
{ 0.0f, -12.0f, 12.0f}, // Osc1SemitoneOffset
{ 0.0f, -100.0f, 100.0f}, // Osc1PitchOffset

View File

@@ -89,14 +89,14 @@ float Voice::process(float* params, bool& scopeTrigger) {
// calculate the note/pitch of the oscillators
bool temp = false;
uint8_t osc1NoteOffset = static_cast<uint8_t>((SYNTH_NOTES_PER_OCTAVE+1) * getParam(ParamId::Osc1OctaveOffset) + getParam(ParamId::Osc1SemitoneOffset));
uint8_t osc2NoteOffset = static_cast<uint8_t>((SYNTH_NOTES_PER_OCTAVE+1) * getParam(ParamId::Osc2OctaveOffset) + getParam(ParamId::Osc2SemitoneOffset));
uint8_t osc3NoteOffset = static_cast<uint8_t>((SYNTH_NOTES_PER_OCTAVE+1) * getParam(ParamId::Osc3OctaveOffset) + getParam(ParamId::Osc3SemitoneOffset));
uint8_t osc1NoteOffset = static_cast<uint8_t>(std::round((SYNTH_NOTES_PER_OCTAVE) * (getParam(ParamId::Osc1OctaveOffset) + getParam(ParamId::MasterOctaveOffset)) + getParam(ParamId::Osc1SemitoneOffset) + getParam(ParamId::MasterSemitoneOffset)));
uint8_t osc2NoteOffset = static_cast<uint8_t>(std::round((SYNTH_NOTES_PER_OCTAVE) * (getParam(ParamId::Osc2OctaveOffset) + getParam(ParamId::MasterOctaveOffset)) + getParam(ParamId::Osc2SemitoneOffset) + getParam(ParamId::MasterSemitoneOffset)));
uint8_t osc3NoteOffset = static_cast<uint8_t>(std::round((SYNTH_NOTES_PER_OCTAVE) * (getParam(ParamId::Osc3OctaveOffset) + getParam(ParamId::MasterOctaveOffset)) + getParam(ParamId::Osc3SemitoneOffset) + getParam(ParamId::MasterSemitoneOffset)));
// sample oscillators
float osc1 = oscillators_[0].process(osc1NoteOffset + note_, getParam(ParamId::Osc1PitchOffset)/100.0f, scopeTrigger);
float osc2 = oscillators_[1].process(osc2NoteOffset + note_, getParam(ParamId::Osc2PitchOffset)/100.0f, temp);
float osc3 = oscillators_[2].process(osc3NoteOffset + note_, getParam(ParamId::Osc3PitchOffset)/100.0f, temp);
float osc1 = oscillators_[0].process(osc1NoteOffset + note_, (getParam(ParamId::Osc1PitchOffset) + getParam(ParamId::MasterPitchOffset))/100.0f, scopeTrigger);
float osc2 = oscillators_[1].process(osc2NoteOffset + note_, (getParam(ParamId::Osc2PitchOffset) + getParam(ParamId::MasterPitchOffset))/100.0f, temp);
float osc3 = oscillators_[2].process(osc3NoteOffset + note_, (getParam(ParamId::Osc3PitchOffset) + getParam(ParamId::MasterPitchOffset))/100.0f, temp);
// mix oscillators
float sampleOut = (osc1 + osc2*0.25f + osc3*0.125f) * gain;