diff --git a/src/ConfigService.hpp b/src/ConfigService.hpp index c0b9260..41b1cf4 100644 --- a/src/ConfigService.hpp +++ b/src/ConfigService.hpp @@ -75,7 +75,8 @@ struct KeymapConfig { if(item.getType() == libconfig::Setting::TypeString) note = std::string(item.c_str()); int8_t noteId = static_cast(notesGroup[note]) % INT8_MAX; - int32_t keyId = static_cast(keysGroup[key]) % INT8_MAX; + int32_t keyId = static_cast(keysGroup[key]) % INT32_MAX; + keymap.emplace(keyId, noteId); } diff --git a/src/main.cpp b/src/main.cpp index 873cf58..1006c2a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,8 +17,20 @@ int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; + + // create app objects + ConfigService config = ConfigService("config/sonobulus.cfg"); + LoggerService logger = LoggerService(&config, "Engine"); + NoteQueue queue = NoteQueue(); + KeyboardController keyboard(&config, &logger, &queue); + + // audio synthesizer doohickey + AudioEngine audioEngine = AudioEngine(&config, &logger, &queue); + audioEngine.start(); + // attach backend gui components qmlRegisterType("AppDemo", 1, 0, "TimerComponent"); + engine.rootContext()->setContextProperty("keyboardController", &keyboard); // adds the TimerComponent type (exposed in qml as "TimerComponent") to the module named"AppDemo" (numbers mean version 1.0) // load qml @@ -31,16 +43,6 @@ int main(int argc, char* argv[]) { return -1; } - // create app objects - ConfigService config = ConfigService("config/sonobulus.cfg"); - LoggerService logger = LoggerService(&config, "Engine"); - NoteQueue queue = NoteQueue(); - KeyboardController keyboard = KeyboardController(&config, &logger, &queue); - - // audio synthesizer doohickey - AudioEngine audioEngine = AudioEngine(&logger); - audioEngine.start(); - // execute app return app.exec(); } diff --git a/src/synth/AudioEngine.cpp b/src/synth/AudioEngine.cpp index 19854aa..45bf5bd 100644 --- a/src/synth/AudioEngine.cpp +++ b/src/synth/AudioEngine.cpp @@ -4,8 +4,9 @@ #include #include #include +#include -AudioEngine::AudioEngine(LoggerService* logger) : logger_(logger) { +AudioEngine::AudioEngine(ConfigService* config, LoggerService* logger, NoteQueue* noteQueue) : config_(config), logger_(logger), noteQueue_(noteQueue) { if(audioDevice_.getDeviceCount() < 1) { std::cout << "No audio devices found" << std::endl; @@ -69,6 +70,12 @@ int32_t AudioEngine::audioCallback(void* outputBuffer, void* inputBuffer, uint32 int32_t AudioEngine::process(float* out, size_t nFrames) { + NoteEvent noteEvent; + while(noteQueue_->pop(noteEvent)) { + std::string msg = "[NoteEvent] Type: " + std::to_string(noteEvent.type) +" Velocity: " + std::to_string(noteEvent.velocity) + " Note:" + std::to_string(noteEvent.note); + logger_->log("Audio", LogFlag::Debug, msg); + } + for(size_t i = 0; i < nFrames; i++) { // simulate a sine wave diff --git a/src/synth/AudioEngine.hpp b/src/synth/AudioEngine.hpp index 9abe9ed..bd5ff17 100644 --- a/src/synth/AudioEngine.hpp +++ b/src/synth/AudioEngine.hpp @@ -6,6 +6,8 @@ #include #include "LoggerService.hpp" +#include "ConfigService.hpp" +#include "NoteQueue.hpp" #if defined(_WIN32) @@ -18,7 +20,7 @@ class AudioEngine { public: - AudioEngine(LoggerService* logger); + AudioEngine(ConfigService* config, LoggerService* logger, NoteQueue* noteQueue); ~AudioEngine(); bool start(); @@ -40,5 +42,7 @@ private: float phase_ = 0.0f; LoggerService* logger_; + ConfigService* config_; + NoteQueue* noteQueue_; }; diff --git a/src/synth/KeyboardController.cpp b/src/synth/KeyboardController.cpp index 1aef283..d914cde 100644 --- a/src/synth/KeyboardController.cpp +++ b/src/synth/KeyboardController.cpp @@ -5,6 +5,10 @@ // #include #include +KeyboardController::KeyboardController(QObject* parent) : QObject(parent) { + +} + KeyboardController::KeyboardController(ConfigService* config, LoggerService* logger, NoteQueue* queue) : config_(config), logger_(logger), queue_(queue) { // load keymap from config service @@ -15,11 +19,10 @@ KeyboardController::KeyboardController(ConfigService* config, LoggerService* log } -void KeyboardController::handleKeyPress(QKeyEvent* e) { - if (e->isAutoRepeat()) return; +void KeyboardController::keyDownEvent(int key, int modifiers, const QString& text) { - auto it = keymap_.find(e->key()); - if (it == keymap_.end()) return; + auto it = configuration_.keymap.find(key); + if (it == configuration_.keymap.end()) return; queue_->push({ NoteEventType::NoteOn, @@ -27,13 +30,13 @@ void KeyboardController::handleKeyPress(QKeyEvent* e) { 0.8f, std::chrono::high_resolution_clock::now() }); + } -void KeyboardController::handleKeyRelease(QKeyEvent* e) { - if (e->isAutoRepeat()) return; +void KeyboardController::keyUpEvent(int key, int modifiers, const QString& text) { - auto it = keymap_.find(e->key()); - if (it == keymap_.end()) return; + auto it = configuration_.keymap.find(key); + if (it == configuration_.keymap.end()) return; queue_->push({ NoteEventType::NoteOff, diff --git a/src/synth/KeyboardController.hpp b/src/synth/KeyboardController.hpp index 06e71f2..4095481 100644 --- a/src/synth/KeyboardController.hpp +++ b/src/synth/KeyboardController.hpp @@ -2,6 +2,7 @@ // the keyboard controller acts as an instrument input device for creating note events from a computer keyboard #pragma once +#include #include #include @@ -10,14 +11,17 @@ #include "LoggerService.hpp" // The keyboardcontroller handles user inputs from a keyboard and maps them to note events -class KeyboardController { +class KeyboardController : public QObject { + Q_OBJECT + public: - explicit KeyboardController(ConfigService* config, LoggerService* logger, NoteQueue* queue); + explicit KeyboardController(QObject* parent = nullptr); + KeyboardController(ConfigService* config, LoggerService* logger, NoteQueue* queue); ~KeyboardController() = default; - void handleKeyPress(QKeyEvent* e); - void handleKeyRelease(QKeyEvent* e); + Q_INVOKABLE void keyDownEvent(int key, int modifiers, const QString& text); + Q_INVOKABLE void keyUpEvent(int key, int modifiers, const QString& text); private: @@ -26,8 +30,6 @@ private: LoggerService* logger_; // keymap is key -> midi note id - std::unordered_map keymap_; - KeymapConfig configuration_; }; diff --git a/src/synth/NoteQueue.hpp b/src/synth/NoteQueue.hpp index 80c9ba4..6ea894e 100644 --- a/src/synth/NoteQueue.hpp +++ b/src/synth/NoteQueue.hpp @@ -9,8 +9,8 @@ #define SYNTH_NOTE_QUEUE_SIZE 128 -enum class NoteEventType { - NoteOn, +enum NoteEventType { + NoteOn = 0, NoteOff }; diff --git a/ui/Main.qml b/ui/Main.qml index c06abb3..8e4bdbe 100644 --- a/ui/Main.qml +++ b/ui/Main.qml @@ -30,4 +30,23 @@ ApplicationWindow { } } + Item { + anchors.fill: parent + focus: true + + Keys.onPressed: (event) => { + if(!event.isAutoRepeat) { + keyboardController.keyDownEvent(event.key, event.modifiers, event.text) + event.accepted = true + } + } + + Keys.onReleased: (event) => { + if(!event.isAutoRepeat) { + keyboardController.keyUpEvent(event.key, event.modifiers, event.text) + event.accepted = true + } + } + } + }