make basic audio engine parameters configurable

This commit is contained in:
2026-01-24 14:07:38 -06:00
parent a4ea6490a4
commit 69a507d57b
10 changed files with 78 additions and 56 deletions

View File

@@ -47,7 +47,6 @@ if (-not ($dependencies_found -eq $libraries.Count)) {
# configure # configure
Write-Host "Configuring metabolus..." Write-Host "Configuring metabolus..."
cmake -S . -B $BUILD_DIR -G "Visual Studio 17 2022" ` cmake -S . -B $BUILD_DIR -G "Visual Studio 17 2022" `
-DCMAKE_BUILD_TYPE=Release `
-DQt6_ROOT="$QT_ROOT\lib\cmake\Qt6" ` -DQt6_ROOT="$QT_ROOT\lib\cmake\Qt6" `
-DRtAudio_ROOT="$RTAUDIO_ROOT" ` -DRtAudio_ROOT="$RTAUDIO_ROOT" `
-DRtMidi_ROOT="$RTMIDI_ROOT" ` -DRtMidi_ROOT="$RTMIDI_ROOT" `
@@ -56,7 +55,7 @@ cmake -S . -B $BUILD_DIR -G "Visual Studio 17 2022" `
# build # build
Write-Host "Building metabolus..." Write-Host "Building metabolus..."
cmake --build $BUILD_DIR cmake --build $BUILD_DIR --config $CONFIG
# TODO: install # TODO: install
@@ -64,14 +63,14 @@ cmake --build $BUILD_DIR
Write-Host "Deploying metabolus..." Write-Host "Deploying metabolus..."
cd $BUILD_DIR cd $BUILD_DIR
& "$QT_ROOT\bin\windeployqt6.exe" .\Debug\metabolus.exe & "$QT_ROOT\bin\windeployqt6.exe" .\$CONFIG\metabolus.exe
# copy dlls # copy dlls
Copy-Item -Path "$RTAUDIO_ROOT\bin\rtaudio.dll" -Destination .\Debug Copy-Item -Path "$RTAUDIO_ROOT\bin\rtaudio.dll" -Destination .\$CONFIG
Copy-Item -Path "$RTMIDI_ROOT\bin\rtmidi.dll" -Destination .\Debug Copy-Item -Path "$RTMIDI_ROOT\bin\rtmidi.dll" -Destination .\$CONFIG
Copy-Item -Path "$YAMLCPP_ROOT\bin\yaml-cpp.dll" -Destination .\Debug Copy-Item -Path "$YAMLCPP_ROOT\bin\yaml-cpp.dll" -Destination .\$CONFIG
# copy configs, but don't overwrite # copy configs, but don't overwrite
Copy-Item -Path "$CONFIG_ROOT" -Destination ".\Debug\" -Recurse -ErrorAction SilentlyContinue Copy-Item -Path "$CONFIG_ROOT" -Destination ".\$CONFIG\" -Recurse -ErrorAction SilentlyContinue
cd $PROJECT_ROOT cd $PROJECT_ROOT

View File

@@ -1,6 +1,8 @@
echo "Installing dependencies ... " echo "Installing dependencies ... "
# TODO: add a clean (like delete build dirs) script
$project_root = $PWD $project_root = $PWD
if (-not (Test-Path -Path "$PWD\build\lib")) { if (-not (Test-Path -Path "$PWD\build\lib")) {
@@ -12,21 +14,28 @@ $build_lib_dir = "$PWD\build\lib"
# rtaudio # rtaudio
mkdir "$build_lib_dir\rtaudio" -Force mkdir "$build_lib_dir\rtaudio" -Force
cd $project_root\lib\rtaudio cd $project_root\lib\rtaudio
cmake -S . -B build -G "Visual Studio 17 2022" -DRTDUIO_API_WASAPI=ON -DRTAUDIO_API_DS=OFF -DRT_AUDIO_API_ASIO=OFF -DRTAUDIO_BUILD_SHARED_LIBS=ON cmake -S . -B build -G "Visual Studio 17 2022" `
-DRTDUIO_API_WASAPI=ON `
-DRTAUDIO_API_DS=OFF `
-DRT_AUDIO_API_ASIO=OFF `
-DRTAUDIO_BUILD_SHARED_LIBS=ON
cmake --build build --config Release cmake --build build --config Release
cmake --install build --prefix "$build_lib_dir\rtaudio" cmake --install build --prefix "$build_lib_dir\rtaudio"
# rtmidi # rtmidi
mkdir "$build_lib_dir\rtmidi" -Force mkdir "$build_lib_dir\rtmidi" -Force
cd $project_root\lib\rtmidi cd $project_root\lib\rtmidi
cmake -S . -B build -G "Visual Studio 17 2022" -DRT_MIDI_API_WINMM=ON -DRTMIDI_BUILD_SHARED_LIBS=ON cmake -S . -B build -G "Visual Studio 17 2022" `
-DRT_MIDI_API_WINMM=ON `
-DRTMIDI_BUILD_SHARED_LIBS=ON
cmake --build build --config Release cmake --build build --config Release
cmake --install build --prefix "$build_lib_dir\rtmidi" cmake --install build --prefix "$build_lib_dir\rtmidi"
# yaml-cpp # yaml-cpp
mkdir "$build_lib_dir\yaml-cpp" -Force mkdir "$build_lib_dir\yaml-cpp" -Force
cd $project_root\lib\yaml-cpp cd $project_root\lib\yaml-cpp
cmake -S . -B build -G "Visual Studio 17 2022" -DYAML_BUILD_SHARED_LIBS=ON cmake -S . -B build -G "Visual Studio 17 2022" `
-DYAML_BUILD_SHARED_LIBS=ON
cmake --build build --config Release cmake --build build --config Release
cmake --install build --prefix "$build_lib_dir\yaml-cpp" cmake --install build --prefix "$build_lib_dir\yaml-cpp"

View File

@@ -11,39 +11,34 @@ namespace fs = std::filesystem;
ConfigInterface::ConfigInterface() { ConfigInterface::ConfigInterface() {
std::string audioConfig = configRoot + "/" + filename; //std::cout << "Config constructor" << std::endl;
std::cout << "CWD: " << fs::current_path() << std::endl;
std::cout << "Audio config: " << fs::absolute(audioConfig).string() << std::endl;
// opening the file myself because YAML::LoadFile didn't seem to work on windows
std::ifstream file(fs::absolute(audioConfig).string());
if(file.good()) {
std::cout << "File exists" << std::endl;
} else {
std::cout << "File does not exist" << std::endl;
} }
//YAML::Node config; int ConfigInterface::getValue(ConfigFile file, std::string key, int defaultVal) {
/*
// assemble filepath
std::string filepath = configRoot + "/" + filePaths[static_cast<int>(file)];
filepath = fs::absolute(filepath).string();
// attempt to open file
YAML::Node config;
try { try {
YAML::Node config = YAML::Load("{sampleRate: 44100}"); YAML::Node config = YAML::LoadFile(filepath);
std::cout << "Loaded config file" << std::endl;
std::cout << "Type enum: " << static_cast<int>(config.Type()) << std::endl; // read key if it exists
if(config[key]) {
if(config["sampleRate"]) { return config[key].as<int>(defaultVal);
//int sampleRate = config["sampleRate"].as<int>();
//std::cout << sampleRate << std::endl;
} else { } else {
std::cout << "Key does not exist" << std::endl; return -1; // key does not exist
} }
} catch(const std::exception& e) { } catch(const std::exception& e) {
std::cerr << e.what() << '\n'; std::cerr << e.what() << std::endl;
return -1;
} }
*/
YAML::Node n = YAML::Load("{sampleRate: 44100}"); // unreachable
std::cout << n["sampleRate"].as<int>() << "\n"; return -1;
} }

View File

@@ -2,6 +2,17 @@
#pragma once #pragma once
#include <string> #include <string>
#include <vector>
enum class ConfigFile {
Audio = 0
// other files here
};
// might have a config file for specifying paths to other config files instead of this
const std::vector<std::string> filePaths = {
"audio.yaml"
};
class ConfigInterface { class ConfigInterface {
@@ -10,9 +21,10 @@ public:
ConfigInterface(); ConfigInterface();
~ConfigInterface() = default; ~ConfigInterface() = default;
int getValue(ConfigFile file, std::string key, int defaultVal);
private: private:
const std::string configRoot = "config"; const std::string configRoot = "config";
const std::string filename = "audio.yaml";
}; };

View File

@@ -10,8 +10,6 @@ int main(int argc, char *argv[]) {
// std::cout << "Main()" << std::endl; // std::cout << "Main()" << std::endl;
ConfigInterface config = ConfigInterface();
QApplication app(argc, argv); QApplication app(argc, argv);
MainWindow window; // entry point goes to MainWindow::MainWindow() MainWindow window; // entry point goes to MainWindow::MainWindow()

View File

@@ -3,14 +3,11 @@
#include <iostream> #include <iostream>
AudioEngine::AudioEngine() : synth_(params_) { AudioEngine::AudioEngine(ConfigInterface* config) : synth_(params_), config_(config) {
if(audio_.getDeviceCount() < 1) { if(audio_.getDeviceCount() < 1) {
throw std::runtime_error("No audio devices found"); throw std::runtime_error("No audio devices found");
} }
// TODO: get audio configurations
synth_.setSampleRate(sampleRate_);
synth_.setScopeBuffer(&scope_); synth_.setScopeBuffer(&scope_);
} }
@@ -21,6 +18,13 @@ AudioEngine::~AudioEngine() {
bool AudioEngine::start() { bool AudioEngine::start() {
// get config values
sampleRate_ = config_->getValue(ConfigFile::Audio, "sampleRate", sampleRate_);
bufferFrames_ = config_->getValue(ConfigFile::Audio, "bufferSize", bufferFrames_);
channels_ = config_->getValue(ConfigFile::Audio, "channels", channels_);
synth_.setSampleRate(sampleRate_);
// initialize the audio engine // initialize the audio engine
RtAudio::StreamParameters params; RtAudio::StreamParameters params;
params.deviceId = audio_.getDefaultOutputDevice(); params.deviceId = audio_.getDefaultOutputDevice();

View File

@@ -7,6 +7,7 @@
#include "Synth.h" #include "Synth.h"
#include "../KeyboardController.h" #include "../KeyboardController.h"
#include "../ConfigInterface.h"
#if defined(_WIN32) #if defined(_WIN32)
#define AUDIO_API RtAudio::WINDOWS_WASAPI #define AUDIO_API RtAudio::WINDOWS_WASAPI
@@ -17,7 +18,7 @@
class AudioEngine { class AudioEngine {
public: public:
AudioEngine(); AudioEngine(ConfigInterface* config);
~AudioEngine(); ~AudioEngine();
// starts the audio stream. returns true on success and false on failure // starts the audio stream. returns true on success and false on failure
@@ -43,6 +44,7 @@ private:
NoteQueue noteQueue_; // stores note events for passing between threads NoteQueue noteQueue_; // stores note events for passing between threads
Synth synth_; // generates audio Synth synth_; // generates audio
ScopeBuffer scope_ { 1024 }; // stores audio samples for visualization ScopeBuffer scope_ { 1024 }; // stores audio samples for visualization
ConfigInterface* config_; // access to config files
RtAudio audio_{AUDIO_API}; // audio device RtAudio audio_{AUDIO_API}; // audio device
// TODO: id like a yml config file or something for these // TODO: id like a yml config file or something for these

View File

@@ -11,11 +11,12 @@ void ScopeBuffer::push(float sample) {
buffer_[w % buffer_.size()] = sample; buffer_[w % buffer_.size()] = sample;
} }
// TODO: needs a mutex to prevent flickering // TODO: needs a mutex/spinlock to prevent flickering
// outputs value from the scope buffer, called by the scope widget // outputs value from the scope buffer, called by the scope widget
void ScopeBuffer::read(std::vector<float>& out) const { void ScopeBuffer::read(std::vector<float>& out) const {
while(!spinLock_) { int x = 1 + 1; } // yeah this didn't work, maybe it needs to be atomic or something
//while(!spinLock_) { int x = 1 + 1; }
size_t w = writeIndex_.load(std::memory_order_relaxed); size_t w = writeIndex_.load(std::memory_order_relaxed);
for (size_t i = 0; i < out.size(); i++) { for (size_t i = 0; i < out.size(); i++) {

View File

@@ -8,7 +8,7 @@
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
ui_(new Ui::MainWindow), ui_(new Ui::MainWindow),
audio_(new AudioEngine()), audio_(new AudioEngine(&config_)),
keyboard_(audio_->noteQueue()), keyboard_(audio_->noteQueue()),
midi_(audio_->noteQueue()) { midi_(audio_->noteQueue()) {

View File

@@ -6,6 +6,7 @@
#include "../synth/AudioEngine.h" #include "../synth/AudioEngine.h"
#include "../MidiController.h" #include "../MidiController.h"
#include "../ConfigInterface.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }
@@ -32,5 +33,6 @@ private:
AudioEngine* audio_ = nullptr; AudioEngine* audio_ = nullptr;
KeyboardController keyboard_; KeyboardController keyboard_;
MidiController midi_; MidiController midi_;
ConfigInterface config_;
}; };