diff --git a/src/code.cpp b/src/code.cpp index 427b94e..f0b6749 100644 --- a/src/code.cpp +++ b/src/code.cpp @@ -1,9 +1,41 @@ #include "code.h" +#include +#include +#include +#include + namespace SELCAL { Code::Code(std::string s) : code(s) { + std::transform(s.begin(), s.end(), s.begin(), ::toupper); + std::regex pattern( + "([0-9A-Z]{" + std::to_string(KEYS_PER_GROUP) + "})" + + GROUP_SEPARATOR + + "([0-9A-Z]{" + std::to_string(KEYS_PER_GROUP) + "})" + ); + std::smatch match; + if (std::regex_match(s, match, pattern)) { + // The first match[0] is always the entire string for a successful match + for (std::size_t i = 1; i < match.size(); ++i) { + std::ssub_match sub_match = match[i]; + std::string piece = sub_match.str(); + + Group group; + std::transform(piece.begin(), piece.end(), group.begin(), [](char c) { + return static_cast(c); + }); + groups.push_back(group); + } + } + else { + throw new std::runtime_error("Could not parse SELCAL"); + } +} + +const std::vector& Code::getGroups() const { + return groups; } bool Code::isValid() const { diff --git a/src/code.h b/src/code.h index ed3609d..7a3c061 100644 --- a/src/code.h +++ b/src/code.h @@ -51,11 +51,13 @@ class Code { public: Code(std::string s); + const std::vector& getGroups() const; + private: bool isValid() const; const std::string code; - const std::vector groups; + std::vector groups; }; } // SELCAL diff --git a/src/main.cpp b/src/main.cpp index eecf55d..ee75fd0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,16 @@ int main(int argc, char** argv) { + SELCAL::Code code{"A5-CD"}; + + for (auto& group : code.getGroups()) { + std::cout + << magic_enum::enum_name(group[0]) << " + " + << magic_enum::enum_name(group[1]) + << std::endl; + } + + Synth synth; for(int i = 1; i < argc; ++i) { @@ -21,7 +31,7 @@ int main(int argc, char** argv) { << ":(" << program.bankNumber << ", " << program.programNumber << ")" << std::endl; - if (program.name == "Tuba") { + if (program.name == "Square Wave") { std::cout << "Loading program!" << std::endl; synth.loadProgram(program); } @@ -67,41 +77,51 @@ int main(int argc, char** argv) { for (auto pair : keyFrequencies) { - std::cout - << magic_enum::enum_name(pair.first) << " = " - << pair.second << " Hz " - << " or MIDI key " << frequencyToMidi(pair.second) - << std::endl; - // fluidsynth wants tunings in MIDI cents, which effectively means MIDI key * 100. // As we only care about the SELCAL 32 tones, only tune those specific keys. We don't // need to tune the full 128-key keyboard. constexpr double MIDI_CENT_SCALE = 100.0; const int keyIndex = static_cast(pair.first); - tunings[keyIndex] = frequencyToMidi(pair.second * MIDI_CENT_SCALE); + tunings[keyIndex] = frequencyToMidi(pair.second) * MIDI_CENT_SCALE; + + std::cout + << magic_enum::enum_name(pair.first) << " = " + << pair.second << " Hz " + << " or MIDI key " << frequencyToMidi(pair.second) * MIDI_CENT_SCALE + << std::endl; } - bool success = synth.setTuning(tunings); - std::cout << "Set tuning: " << (success ? "success" : "failed") << std::endl; - - fluid_synth_t* raw_synth = synth.getSynth(); + constexpr int ALL_CHANNELS = -1; + bool success; using namespace std::chrono_literals; - int i, key; - for(i = 0; i < 12; i++) - { - /* Generate a random key */ - key = 30 + (int)(12.0f * rand() / (float) RAND_MAX); - /* Play a note */ - fluid_synth_noteon(raw_synth, 0, key, 100); + success = synth.setTuning(tunings); + std::cout << "Set tuning: " << (success ? "success" : "failed") << std::endl; - /* Sleep for 1 second */ + for (auto& group : code.getGroups()) { + fluid_synth_noteon(raw_synth, 0, static_cast(group[0]), 100); + fluid_synth_noteon(raw_synth, 1, static_cast(group[1]), 100); std::this_thread::sleep_for(1s); - /* Stop the note */ - fluid_synth_noteoff(raw_synth, 0, key); + // Silence between tone groups + fluid_synth_all_notes_off(raw_synth, ALL_CHANNELS); + std::this_thread::sleep_for(200ms); } + /* + success = synth.resetTuning(); + std::cout << "Set tuning: " << (success ? "success" : "failed") << std::endl; + + for (auto& group : code.getGroups()) { + fluid_synth_noteon(raw_synth, 0, static_cast(group[0]), 100); + fluid_synth_noteon(raw_synth, 1, static_cast(group[1]), 100); + std::this_thread::sleep_for(1s); + + // Silence between tone groups + fluid_synth_all_notes_off(raw_synth, ALL_CHANNELS); + std::this_thread::sleep_for(200ms); + } + */ } diff --git a/src/synth.cpp b/src/synth.cpp index 112ef27..22e4277 100644 --- a/src/synth.cpp +++ b/src/synth.cpp @@ -77,6 +77,11 @@ bool Synth::setTuning(const std::array& pitches) { 1 ); + if (result == FLUID_OK) { + result = fluid_synth_activate_tuning(synth, 0, 0, 0, 1); + result = fluid_synth_activate_tuning(synth, 1, 0, 0, 1); + } + return result == FLUID_OK; }