refactor config classes
This commit is contained in:
@@ -46,7 +46,7 @@ find_package(Qt6 REQUIRED COMPONENTS
|
|||||||
qt_standard_project_setup()
|
qt_standard_project_setup()
|
||||||
|
|
||||||
add_library(sonobulus_core STATIC
|
add_library(sonobulus_core STATIC
|
||||||
src/ConfigService.cpp
|
src/config/ConfigService.cpp
|
||||||
src/LoggerService.cpp
|
src/LoggerService.cpp
|
||||||
src/TimerComponent.cpp
|
src/TimerComponent.cpp
|
||||||
src/synth/AudioEngine.cpp
|
src/synth/AudioEngine.cpp
|
||||||
@@ -57,7 +57,7 @@ add_library(sonobulus_core STATIC
|
|||||||
src/synth/Synth.cpp
|
src/synth/Synth.cpp
|
||||||
src/synth/Voice.cpp
|
src/synth/Voice.cpp
|
||||||
src/synth/Filter.cpp
|
src/synth/Filter.cpp
|
||||||
src/synth/Instrument.cpp
|
src/synth/Instruments/Instrument.cpp
|
||||||
src/synth/Instruments/PianoString.cpp
|
src/synth/Instruments/PianoString.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,20 @@ Logger = (
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
AudioEngine = (
|
||||||
|
{
|
||||||
|
Id = "Main";
|
||||||
|
|
||||||
|
SampleRate = 44100;
|
||||||
|
Channels = 2;
|
||||||
|
StereoMode = 1;
|
||||||
|
BufferSize = 512;
|
||||||
|
PitchStandard = 440.0;
|
||||||
|
MidiHome = 69;
|
||||||
|
NotesPerOctave = 12;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
KeyboardController = (
|
KeyboardController = (
|
||||||
{
|
{
|
||||||
Id = "Main";
|
Id = "Main";
|
||||||
|
|||||||
@@ -1,128 +0,0 @@
|
|||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <libconfig.h++>
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
struct LoggerConfig {
|
|
||||||
std::string id;
|
|
||||||
std::vector<std::string> flagsEnabled;
|
|
||||||
bool showTime = false;
|
|
||||||
bool showSourceTrace = false;
|
|
||||||
bool coutEnabled = false;
|
|
||||||
bool fileEnabled = false;
|
|
||||||
std::string filePath;
|
|
||||||
|
|
||||||
bool parseConfig(const libconfig::Setting& setting) {
|
|
||||||
|
|
||||||
if (!setting.lookupValue("Id", id)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const libconfig::Setting& flags = setting.lookup("FlagsEnabled");
|
|
||||||
for (int index = 0; index < flags.getLength(); ++index) {
|
|
||||||
flagsEnabled.push_back(static_cast<const char*>(flags[index]));
|
|
||||||
}
|
|
||||||
} catch (const libconfig::SettingException&) {
|
|
||||||
flagsEnabled.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
setting.lookupValue("ShowTime", showTime);
|
|
||||||
setting.lookupValue("ShowSourceTrace", showSourceTrace);
|
|
||||||
setting.lookupValue("CoutEnabled", coutEnabled);
|
|
||||||
setting.lookupValue("FileEnabled", fileEnabled);
|
|
||||||
setting.lookupValue("FilePath", filePath);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AudioConfig {
|
|
||||||
uint32_t sampleRate;
|
|
||||||
uint32_t channels;
|
|
||||||
uint32_t stereoMode;
|
|
||||||
uint32_t bufferSize;
|
|
||||||
float pitchStandard;
|
|
||||||
int32_t midiHome;
|
|
||||||
int32_t notesPerOctave;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct KeymapConfig {
|
|
||||||
std::string id;
|
|
||||||
std::unordered_map<int32_t, uint8_t> keymap;
|
|
||||||
|
|
||||||
bool parseConfig(const libconfig::Setting& setting) {
|
|
||||||
|
|
||||||
if (!setting.lookupValue("Id", id)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const libconfig::Setting& keymapGroup = setting.lookup("Keymap");
|
|
||||||
const libconfig::Setting& notesGroup = setting.lookup("Notes");
|
|
||||||
const libconfig::Setting& keysGroup = setting.lookup("Keys");
|
|
||||||
|
|
||||||
for(size_t i = 0; i < keymapGroup.getLength(); i++) {
|
|
||||||
libconfig::Setting& item = keymapGroup[i];
|
|
||||||
std::string key = item.getName();
|
|
||||||
std::string note = "";
|
|
||||||
if(item.getType() == libconfig::Setting::TypeString) note = std::string(item.c_str());
|
|
||||||
|
|
||||||
int8_t noteId = static_cast<int>(notesGroup[note]) % INT8_MAX;
|
|
||||||
int32_t keyId = static_cast<int>(keysGroup[key]) % INT32_MAX;
|
|
||||||
|
|
||||||
keymap.emplace(keyId, noteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (const libconfig::SettingException&) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConfigService {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
ConfigService(const std::string& filePath);
|
|
||||||
~ConfigService() = default;
|
|
||||||
|
|
||||||
bool loadFromFile(const std::string& filePath);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool getConfig(const std::string& type, const std::string& id, T* config) const {
|
|
||||||
try {
|
|
||||||
const libconfig::Setting& configs = config_.lookup(type);
|
|
||||||
for (int index = 0; index < configs.getLength(); ++index) {
|
|
||||||
const libconfig::Setting& configSetting = configs[index];
|
|
||||||
|
|
||||||
std::string configId;
|
|
||||||
if (!configSetting.lookupValue("Id", configId) || configId != id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return config->parseConfig(configSetting);
|
|
||||||
}
|
|
||||||
} catch (const libconfig::SettingException& ex) {
|
|
||||||
std::cout << "libconfig setting exception: " << ex.what() << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& lastError() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
libconfig::Config config_;
|
|
||||||
std::string lastError_;
|
|
||||||
};
|
|
||||||
@@ -13,17 +13,11 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
LoggerService::LoggerService(ConfigService* config, const std::string& loggerId) {
|
LoggerService::LoggerService(ConfigService* config, const std::string& loggerId) {
|
||||||
|
|
||||||
if(!(config->getConfig<LoggerConfig>("Logger", loggerId, &configuration_))) {
|
if(!(config->getConfig<LoggerParams, LoggerConfig>("Logger", loggerId, &configuration_))) {
|
||||||
std::cout << "Failed to get logger configuration fom config service" << std::endl;
|
std::cout << "Failed to get logger configuration fom config service" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
standardOutputEnabled_ = configuration_.coutEnabled;
|
|
||||||
fileOutputEnabled_ = configuration_.fileEnabled;
|
|
||||||
additionaldetailsEnabled_ = configuration_.showSourceTrace;
|
|
||||||
timeEnabled_ = configuration_.showTime;
|
|
||||||
id_ = configuration_.id;
|
|
||||||
|
|
||||||
for(std::string& flag : configuration_.flagsEnabled) {
|
for(std::string& flag : configuration_.flagsEnabled) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for(const char* validFlag : LogFlagStrings) {
|
for(const char* validFlag : LogFlagStrings) {
|
||||||
@@ -55,7 +49,7 @@ LoggerService::LoggerService(ConfigService* config, const std::string& loggerId)
|
|||||||
fs::create_directories(std::string(BINARY_DIR) + "/" + finaltime);
|
fs::create_directories(std::string(BINARY_DIR) + "/" + finaltime);
|
||||||
std::string logPath = std::string(BINARY_DIR) + "/" + finaltime + "/" + configuration_.filePath;
|
std::string logPath = std::string(BINARY_DIR) + "/" + finaltime + "/" + configuration_.filePath;
|
||||||
|
|
||||||
if(fileOutputEnabled_) outfile_.open(logPath);
|
if(configuration_.fileEnabled) outfile_.open(logPath);
|
||||||
|
|
||||||
log("Logger", LogFlag::Info, "Logger initialized.");
|
log("Logger", LogFlag::Info, "Logger initialized.");
|
||||||
}
|
}
|
||||||
@@ -78,11 +72,11 @@ void LoggerService::log(std::string component, LogFlag flag, std::string message
|
|||||||
|
|
||||||
std::string finalmessage = "";
|
std::string finalmessage = "";
|
||||||
|
|
||||||
if(timeEnabled_) {
|
if(configuration_.showTime) {
|
||||||
finalmessage = finalmessage + "[" + "Not Implemented" + "] ";
|
finalmessage = finalmessage + "[" + "Not Implemented" + "] ";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string componentTrace = "[" + id_ + ": " + component + "] ";
|
std::string componentTrace = "[" + configuration_.id + ": " + component + "] ";
|
||||||
finalmessage += componentTrace; // component is the section of the program (For example Mesh or Engine) that is calling the logger
|
finalmessage += componentTrace; // component is the section of the program (For example Mesh or Engine) that is calling the logger
|
||||||
|
|
||||||
std::string level = "";
|
std::string level = "";
|
||||||
@@ -94,15 +88,15 @@ void LoggerService::log(std::string component, LogFlag flag, std::string message
|
|||||||
finalmessage = finalmessage + "[" + level + "] ";
|
finalmessage = finalmessage + "[" + level + "] ";
|
||||||
finalmessage = finalmessage + message + " ";
|
finalmessage = finalmessage + message + " ";
|
||||||
|
|
||||||
if (additionaldetailsEnabled_) {
|
if (configuration_.showSourceTrace) {
|
||||||
finalmessage = finalmessage + "[Function: " + Source.function_name() + "]" + " " + "[Line: " + std::to_string(Source.line()) + "]" + " " + "[File: " + Source.file_name() + "]";
|
finalmessage = finalmessage + "[Function: " + Source.function_name() + "]" + " " + "[Line: " + std::to_string(Source.line()) + "]" + " " + "[File: " + Source.file_name() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(standardOutputEnabled_) {
|
if(configuration_.coutEnabled) {
|
||||||
std::cout << finalmessage << std::endl;
|
std::cout << finalmessage << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fileOutputEnabled_) {
|
if(configuration_.fileEnabled) {
|
||||||
outfile_ << finalmessage << std::endl;
|
outfile_ << finalmessage << std::endl;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <source_location>
|
#include <source_location>
|
||||||
|
|
||||||
#include "ConfigService.hpp"
|
#include "config/ConfigService.hpp"
|
||||||
|
#include "config/LoggerConfig.hpp"
|
||||||
|
|
||||||
enum LogFlag {
|
enum LogFlag {
|
||||||
Debug,
|
Debug,
|
||||||
@@ -33,14 +34,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool standardOutputEnabled_;
|
|
||||||
bool fileOutputEnabled_;
|
|
||||||
bool additionaldetailsEnabled_;
|
|
||||||
bool timeEnabled_;
|
|
||||||
std::ofstream outfile_;
|
std::ofstream outfile_;
|
||||||
std::string id_;
|
|
||||||
|
|
||||||
std::vector<LogFlag> activeFlags_;
|
std::vector<LogFlag> activeFlags_;
|
||||||
|
|
||||||
LoggerConfig configuration_;
|
LoggerParams configuration_;
|
||||||
};
|
};
|
||||||
41
src/config/AudioConfig.hpp
Normal file
41
src/config/AudioConfig.hpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IConfig.hpp"
|
||||||
|
|
||||||
|
struct AudioParams : IParams {
|
||||||
|
uint32_t sampleRate;
|
||||||
|
uint32_t channels;
|
||||||
|
uint32_t stereoMode;
|
||||||
|
uint32_t bufferSize;
|
||||||
|
float pitchStandard;
|
||||||
|
int32_t midiHome;
|
||||||
|
int32_t notesPerOctave;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class AudioConfig : public IConfig<AudioParams> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using IConfig<AudioParams>::IConfig;
|
||||||
|
|
||||||
|
bool parseConfig(const libconfig::Setting& setting) override {
|
||||||
|
|
||||||
|
if (!setting.lookupValue("Id", params_->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setting.lookupValue("SampleRate", params_->sampleRate);
|
||||||
|
setting.lookupValue("StereoMode", params_->stereoMode);
|
||||||
|
setting.lookupValue("BufferSize", params_->bufferSize);
|
||||||
|
setting.lookupValue("PitchStandard", params_->pitchStandard);
|
||||||
|
setting.lookupValue("MidiHome", params_->midiHome);
|
||||||
|
setting.lookupValue("NotesPerOctave", params_->notesPerOctave);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
56
src/config/ConfigService.hpp
Normal file
56
src/config/ConfigService.hpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libconfig.h++>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "config/IConfig.hpp"
|
||||||
|
|
||||||
|
// TODO: would be cool for the config file to include other config files so theyre a bit more compartmentalized
|
||||||
|
// then the main file will be like a hub and would be more like each component having its own config file
|
||||||
|
class ConfigService {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ConfigService(const std::string& filePath);
|
||||||
|
~ConfigService() = default;
|
||||||
|
|
||||||
|
bool loadFromFile(const std::string& filePath);
|
||||||
|
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
bool getConfig(const std::string& type, const std::string& id, T1* params) const {
|
||||||
|
|
||||||
|
T2 config { params };
|
||||||
|
|
||||||
|
try {
|
||||||
|
const libconfig::Setting& configs = config_.lookup(type);
|
||||||
|
for (int index = 0; index < configs.getLength(); ++index) {
|
||||||
|
const libconfig::Setting& configSetting = configs[index];
|
||||||
|
|
||||||
|
std::string configId;
|
||||||
|
if (!configSetting.lookupValue("Id", configId) || configId != id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.parseConfig(configSetting);
|
||||||
|
}
|
||||||
|
} catch (const libconfig::SettingException& ex) {
|
||||||
|
std::cout << "libconfig setting exception: " << ex.what() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& lastError() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
libconfig::Config config_;
|
||||||
|
std::string lastError_;
|
||||||
|
};
|
||||||
24
src/config/IConfig.hpp
Normal file
24
src/config/IConfig.hpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libconfig.h++>
|
||||||
|
|
||||||
|
struct IParams {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class IConfig {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
IConfig(T* params) : params_(params) { }
|
||||||
|
~IConfig() = default;
|
||||||
|
|
||||||
|
virtual bool parseConfig(const libconfig::Setting& setting) = 0;
|
||||||
|
IParams* params() { return params_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T* params_;
|
||||||
|
|
||||||
|
};
|
||||||
47
src/config/KeymapConfig.hpp
Normal file
47
src/config/KeymapConfig.hpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IConfig.hpp"
|
||||||
|
|
||||||
|
struct KeymapParams : IParams {
|
||||||
|
std::string id;
|
||||||
|
std::unordered_map<int32_t, uint8_t> keymap;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeymapConfig : public IConfig<KeymapParams> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using IConfig<KeymapParams>::IConfig;
|
||||||
|
|
||||||
|
bool parseConfig(const libconfig::Setting& setting) override {
|
||||||
|
|
||||||
|
if (!setting.lookupValue("Id", params_->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const libconfig::Setting& keymapGroup = setting.lookup("Keymap");
|
||||||
|
const libconfig::Setting& notesGroup = setting.lookup("Notes");
|
||||||
|
const libconfig::Setting& keysGroup = setting.lookup("Keys");
|
||||||
|
|
||||||
|
for(size_t i = 0; i < keymapGroup.getLength(); i++) {
|
||||||
|
libconfig::Setting& item = keymapGroup[i];
|
||||||
|
std::string key = item.getName();
|
||||||
|
std::string note = "";
|
||||||
|
if(item.getType() == libconfig::Setting::TypeString) note = std::string(item.c_str());
|
||||||
|
|
||||||
|
int8_t noteId = static_cast<int>(notesGroup[note]) % INT8_MAX;
|
||||||
|
int32_t keyId = static_cast<int>(keysGroup[key]) % INT32_MAX;
|
||||||
|
|
||||||
|
params_->keymap.emplace(keyId, noteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (const libconfig::SettingException&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
47
src/config/LoggerConfig.hpp
Normal file
47
src/config/LoggerConfig.hpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IConfig.hpp"
|
||||||
|
|
||||||
|
struct LoggerParams : IParams {
|
||||||
|
std::string id;
|
||||||
|
std::vector<std::string> flagsEnabled;
|
||||||
|
bool showTime = false;
|
||||||
|
bool showSourceTrace = false;
|
||||||
|
bool coutEnabled = false;
|
||||||
|
bool fileEnabled = false;
|
||||||
|
std::string filePath;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LoggerConfig : public IConfig<LoggerParams> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using IConfig<LoggerParams>::IConfig;
|
||||||
|
|
||||||
|
bool parseConfig(const libconfig::Setting& setting) override {
|
||||||
|
|
||||||
|
if (!setting.lookupValue("Id", params_->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const libconfig::Setting& flags = setting.lookup("FlagsEnabled");
|
||||||
|
for (int index = 0; index < flags.getLength(); ++index) {
|
||||||
|
params_->flagsEnabled.push_back(static_cast<const char*>(flags[index]));
|
||||||
|
}
|
||||||
|
} catch (const libconfig::SettingException&) {
|
||||||
|
params_->flagsEnabled.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setting.lookupValue("ShowTime", params_->showTime);
|
||||||
|
setting.lookupValue("ShowSourceTrace", params_->showSourceTrace);
|
||||||
|
setting.lookupValue("CoutEnabled", params_->coutEnabled);
|
||||||
|
setting.lookupValue("FileEnabled", params_->fileEnabled);
|
||||||
|
setting.lookupValue("FilePath", params_->filePath);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "TimerComponent.hpp"
|
#include "TimerComponent.hpp"
|
||||||
#include "LoggerService.hpp"
|
#include "LoggerService.hpp"
|
||||||
#include "ConfigService.hpp"
|
#include "config/ConfigService.hpp"
|
||||||
#include "synth/AudioEngine.hpp"
|
#include "synth/AudioEngine.hpp"
|
||||||
#include "synth/KeyboardController.hpp"
|
#include "synth/KeyboardController.hpp"
|
||||||
#include "synth/Scope.hpp"
|
#include "synth/Scope.hpp"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <RtAudio.h>
|
#include <RtAudio.h>
|
||||||
|
|
||||||
#include "LoggerService.hpp"
|
#include "LoggerService.hpp"
|
||||||
#include "ConfigService.hpp"
|
#include "config/ConfigService.hpp"
|
||||||
#include "Synth.hpp"
|
#include "Synth.hpp"
|
||||||
#include "NoteQueue.hpp"
|
#include "NoteQueue.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ConfigService.hpp"
|
#include "config/ConfigService.hpp"
|
||||||
#include "LoggerService.hpp"
|
#include "LoggerService.hpp"
|
||||||
|
|
||||||
// an instrument is our state space model. it calculates discrete samples as a function of time, the current states, and the inputs
|
// an instrument is our state space model. it calculates discrete samples as a function of time, the current states, and the inputs
|
||||||
@@ -103,6 +103,7 @@ void PianoString::recalculateConstants() {
|
|||||||
|
|
||||||
waveVelocity_ = 2.0f * frequency_ * L_;
|
waveVelocity_ = 2.0f * frequency_ * L_;
|
||||||
|
|
||||||
|
// calculate number of super-sampling steps needed to maintain string stability
|
||||||
samplingSteps_ = 0;
|
samplingSteps_ = 0;
|
||||||
do {
|
do {
|
||||||
samplingSteps_++;
|
samplingSteps_++;
|
||||||
@@ -117,8 +118,8 @@ void PianoString::recalculateConstants() {
|
|||||||
segmentCount_ = static_cast<size_t>(std::sqrt((-a+std::sqrt(a*a+4.0*b))/(2.0*b))) - 1;
|
segmentCount_ = static_cast<size_t>(std::sqrt((-a+std::sqrt(a*a+4.0*b))/(2.0*b))) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (segmentCount_ < 60);
|
} while (segmentCount_ < 80);
|
||||||
|
// cap segment count at 80 if above
|
||||||
segmentCount_ = std::min(segmentCount_, static_cast<size_t>(80));
|
segmentCount_ = std::min(segmentCount_, static_cast<size_t>(80));
|
||||||
|
|
||||||
dx_ = L_ / static_cast<float>(segmentCount_);
|
dx_ = L_ / static_cast<float>(segmentCount_);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "synth/Instrument.hpp"
|
#include "synth/Instruments/Instrument.hpp"
|
||||||
|
|
||||||
class PianoString : public Instrument {
|
class PianoString : public Instrument {
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ KeyboardController::KeyboardController(QObject* parent) : QObject(parent) {
|
|||||||
KeyboardController::KeyboardController(ConfigService* config, LoggerService* logger, NoteQueue* queue) : config_(config), logger_(logger), queue_(queue) {
|
KeyboardController::KeyboardController(ConfigService* config, LoggerService* logger, NoteQueue* queue) : config_(config), logger_(logger), queue_(queue) {
|
||||||
|
|
||||||
// load keymap from config service
|
// load keymap from config service
|
||||||
if(!(config->getConfig<KeymapConfig>("KeyboardController", "Main", &configuration_))) {
|
if(!(config->getConfig<KeymapParams, KeymapConfig>("KeyboardController", "Main", &configuration_))) {
|
||||||
logger_->log("Keyboard", LogFlag::Error, "Failed to get logger configuration fom config service");
|
logger_->log("Keyboard", LogFlag::Error, "Failed to get logger configuration fom config service");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "NoteQueue.hpp"
|
#include "NoteQueue.hpp"
|
||||||
#include "ConfigService.hpp"
|
#include "config/ConfigService.hpp"
|
||||||
|
#include "config/KeymapConfig.hpp"
|
||||||
#include "LoggerService.hpp"
|
#include "LoggerService.hpp"
|
||||||
|
|
||||||
// The keyboardcontroller handles user inputs from a keyboard and maps them to note events
|
// The keyboardcontroller handles user inputs from a keyboard and maps them to note events
|
||||||
@@ -32,7 +33,7 @@ private:
|
|||||||
LoggerService* logger_;
|
LoggerService* logger_;
|
||||||
|
|
||||||
// keymap is key -> midi note id
|
// keymap is key -> midi note id
|
||||||
KeymapConfig configuration_;
|
KeymapParams configuration_;
|
||||||
|
|
||||||
static constexpr float defaultVelocity_ = 0.8f;
|
static constexpr float defaultVelocity_ = 0.8f;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "NoteQueue.hpp"
|
#include "NoteQueue.hpp"
|
||||||
#include "ConfigService.hpp"
|
#include "config/ConfigService.hpp"
|
||||||
#include "LoggerService.hpp"
|
#include "LoggerService.hpp"
|
||||||
|
|
||||||
class MidiController {
|
class MidiController {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#include "ConfigService.hpp"
|
#include "config/ConfigService.hpp"
|
||||||
#include "LoggerService.hpp"
|
#include "LoggerService.hpp"
|
||||||
|
|
||||||
enum NoteEventType {
|
enum NoteEventType {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
#include "ConfigService.hpp"
|
#include "config/ConfigService.hpp"
|
||||||
#include "LoggerService.hpp"
|
#include "LoggerService.hpp"
|
||||||
|
|
||||||
class ScopeBuffer : public QObject {
|
class ScopeBuffer : public QObject {
|
||||||
|
|||||||
@@ -13,9 +13,6 @@ Synth::Synth(ConfigService* config, LoggerService* logger, ScopeBuffer* scope, N
|
|||||||
|
|
||||||
void Synth::handleNoteEvent(const NoteEvent& event) {
|
void Synth::handleNoteEvent(const NoteEvent& event) {
|
||||||
|
|
||||||
// Voice* v = findVoiceByNote(event.note);
|
|
||||||
// if(v != nullptr) v->noteOff();
|
|
||||||
|
|
||||||
// stop all voices that are currently playing this note
|
// stop all voices that are currently playing this note
|
||||||
for(Voice& v : voices_) {
|
for(Voice& v : voices_) {
|
||||||
if(v.isActive() && v.note() == event.note) {
|
if(v.isActive() && v.note() == event.note) {
|
||||||
@@ -23,8 +20,8 @@ void Synth::handleNoteEvent(const NoteEvent& event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call note-on for an idle voice for the note-event
|
||||||
if(event.type == NoteEventType::NoteOn) {
|
if(event.type == NoteEventType::NoteOn) {
|
||||||
|
|
||||||
Voice* v = findFreeVoice();
|
Voice* v = findFreeVoice();
|
||||||
if(v != nullptr) v->noteOn(event.note, event.velocity);
|
if(v != nullptr) v->noteOn(event.note, event.velocity);
|
||||||
}
|
}
|
||||||
@@ -38,8 +35,9 @@ void Synth::process(float* out, size_t nFrames) {
|
|||||||
handleNoteEvent(noteEvent);
|
handleNoteEvent(noteEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find lowest frequency voice for scope triggering
|
||||||
size_t lowestVoice = 0;
|
size_t lowestVoice = 0;
|
||||||
float lowestFreq = 100000.0f;
|
float lowestFreq = FLT_MAX;
|
||||||
for(size_t i = 0; i < voices_.size(); i++) {
|
for(size_t i = 0; i < voices_.size(); i++) {
|
||||||
if(!voices_[i].isActive()) continue;
|
if(!voices_[i].isActive()) continue;
|
||||||
float currentFreq = voices_[i].frequency();
|
float currentFreq = voices_[i].frequency();
|
||||||
@@ -54,8 +52,11 @@ void Synth::process(float* out, size_t nFrames) {
|
|||||||
float sampleOut = 0.0f;
|
float sampleOut = 0.0f;
|
||||||
bool triggered = false;
|
bool triggered = false;
|
||||||
bool once = false;
|
bool once = false;
|
||||||
|
|
||||||
|
// generate n samples for the output buffer
|
||||||
for(size_t i = 0; i < nFrames; i++) {
|
for(size_t i = 0; i < nFrames; i++) {
|
||||||
|
|
||||||
|
// process all active voices and mix their produced samples
|
||||||
float mix = 0.0f;
|
float mix = 0.0f;
|
||||||
for(size_t j = 0; j < voices_.size(); j++) {
|
for(size_t j = 0; j < voices_.size(); j++) {
|
||||||
bool temp = false;
|
bool temp = false;
|
||||||
@@ -78,7 +79,6 @@ void Synth::process(float* out, size_t nFrames) {
|
|||||||
|
|
||||||
scope_->spinlock(false);
|
scope_->spinlock(false);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Voice* Synth::findFreeVoice() {
|
Voice* Synth::findFreeVoice() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ConfigService.hpp"
|
#include "config/ConfigService.hpp"
|
||||||
#include "LoggerService.hpp"
|
#include "LoggerService.hpp"
|
||||||
#include "NoteQueue.hpp"
|
#include "NoteQueue.hpp"
|
||||||
#include "Voice.hpp"
|
#include "Voice.hpp"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "Instrument.hpp"
|
#include "Instruments/Instrument.hpp"
|
||||||
#include "Instruments/PianoString.hpp"
|
#include "Instruments/PianoString.hpp"
|
||||||
|
|
||||||
// a voice is a tone generator that the synth uses for polyphony
|
// a voice is a tone generator that the synth uses for polyphony
|
||||||
|
|||||||
2
ui/components/SmartSlider.qml
Normal file
2
ui/components/SmartSlider.qml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
haiii :3
|
||||||
Reference in New Issue
Block a user