Fixed tunings, can play actual SELCAL tones

This commit is contained in:
Jono Targett 2024-05-24 21:12:59 +09:30
parent e3335005d0
commit 1188afaf4b
4 changed files with 82 additions and 23 deletions

View File

@ -1,9 +1,41 @@
#include "code.h"
#include <regex>
#include <iterator>
#include <algorithm>
#include <iostream>
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<Key>(c);
});
groups.push_back(group);
}
}
else {
throw new std::runtime_error("Could not parse SELCAL");
}
}
const std::vector<Group>& Code::getGroups() const {
return groups;
}
bool Code::isValid() const {

View File

@ -51,11 +51,13 @@ class Code {
public:
Code(std::string s);
const std::vector<Group>& getGroups() const;
private:
bool isValid() const;
const std::string code;
const std::vector<Group> groups;
std::vector<Group> groups;
};
} // SELCAL

View File

@ -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<int>(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<int>(group[0]), 100);
fluid_synth_noteon(raw_synth, 1, static_cast<int>(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<int>(group[0]), 100);
fluid_synth_noteon(raw_synth, 1, static_cast<int>(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);
}
*/
}

View File

@ -77,6 +77,11 @@ bool Synth::setTuning(const std::array<double, NUM_MIDI_NOTES>& 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;
}