From de199fd8a1c3c63692d212cc9c9ed537fec82c8b Mon Sep 17 00:00:00 2001 From: Bliblank Date: Fri, 5 Jun 2026 14:16:20 -0500 Subject: [PATCH] project setup --- .gitignore | 2 ++ CMakeLists.txt | 18 ++++++++++++ README.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ config/.gitkeep | 0 lib/.gitkeep | 0 scripts/.gitkeep | 0 src/main.cpp | 9 ++++++ 7 files changed, 103 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 config/.gitkeep create mode 100644 lib/.gitkeep create mode 100644 scripts/.gitkeep create mode 100644 src/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9bea9b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +build/* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5ec1c19 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,18 @@ + +cmake_minimum_required(VERSION 4.0) +project(sonobulus LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# add_library(sonobulus_core STATIC +# # empty +# ) + +add_executable(sonobulus + src/main.cpp +) + +# target_link_libraries(sonobulus +# sonobulus_core +# ) diff --git a/README.md b/README.md new file mode 100644 index 0000000..0112d98 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ + +# sonobulus + +A QML C++ digital synthesizer app utilizing state-space modelling for complex physically-based audio synthesis. + +This project is a spinoff of [metabolus](https://git.vxbard.net/homeburger/metabalus) which used a traditional oscillator -> envelope -> filter model + QT Widgets. +The general project architecture (like audio engine and midi interface) will function largely the same, but with a revamped UI framework. I'm smarter now. + +### State Space Theory +This synthesizer is an attempt to create more complex and tunable audio effects than previously possible with the traditional model. +State-space modelling is able to represent physical dynamical systems and their responses to certain inputs. For example, we can create a model of a fixed string +with a certain elasticity and observe its position in response to being struck with a hammer- the resulting time-variant response function should closely relate +to a single piano tone. The mathematical model involves a vector of states (e.g. position, velocity, tension) and a vector of inputs (e.g. impulse of velocity). +The system's matrices tune the system's output behavior (e.g. air pressure) as a result of the states and inputs. Behavior can quickly get very complex, much more +complex than simple oscillators can produce. For an oscillator based synthesizer, many additions are usually added to approach the complexity needed to model real +world instruments: filters, envelopes, low-frequency modulators, post-processing plugins, etc., whereas a state-based model can already include all kinds of +behavior built-in. There are quite a few modern synthesizers that use this approach already, but the 80's style stayed away due to the real-time computing +requirements (hundreds or even thousands of calculations for a single sample at 44.1k samples per second). Hopefully, at the bare minimum, this synthesizer aims +to produce somewhat well-sounding instruments and music performance. + +## Development plan: +- [ ] Build & project setup, get working hello-world program. +- [ ] QML hello-world program: basic increment/reset counter +- [ ] RtAudio hello-world: basic sine output +- [ ] Connect UI control to sound output, add a slider for frequency control +- [ ] Add note control a keyboard. Coordinate on-off events to + start and stop tone generation +- [ ] Add note control via a MIDI interface using RtMidi. Ideally should be able to connect + to external midi controllers/apps (like musescore) +- [ ] Create a UI scope to visualize the synthesized composite waveform +- [ ] Check cross-platform combatibility for Windows & Linux, especially MIDI interfacing +- [ ] Checkpoint at a rudimentary keyboard instrument producing a basic sine output +- [ ] Will flesh out future goals when I do the math on how complicated implementing + state-space modelling in c++ is + +## Build Instructions + +Prerequisites: +CMake: https://cmake.org/download/ \ +QtWidgets: https://www.qt.io/development/download-qt-installer-oss + +Compiler that supports C++20. Builds have been tested with GCC12 & MSVC17 + +Clone repository +```PowerShell +git clone https://git.vxbard.net/homeburger/sonobulus.git +git clone --recurse-submodules https://git.vxbard.net/homeburger/sonobulus.git # if there's submodules +git submodule update --init --recursive # if you cloned without submodules and need them +``` + +Build: +```PowerShell +# configure +> cmake -S . -B build +# build +> cmake --build build -j +``` + +Execute: +```Powershell +> .\build\Debug\sonobulus.exe +> .\build\Release\sonobulus.exe +``` +```bash +$ ./build/sonobulus +``` + +## Configurations +There is a plan eventually to use config files so app behavior can be tweaked without needing to recompile. Will flesh out more once more of the app's structure takes shape. + +## Instrument Profiles +Later into the app's development I have this vision: the state-space model of an instrument can be saved to a file. The app can allow parameter tweaking and re-saving of an instruments matrices. +Far far into the future there may be a dynamic process for constructing your own instrument models and a way for the app to load and play those instruments. At the end of the day, a state-space +model is just a set of 2 n-dimensional matrix equations and a profile would only need to be able to represent each element in the matrices. diff --git a/config/.gitkeep b/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/lib/.gitkeep b/lib/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/scripts/.gitkeep b/scripts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..8863874 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,9 @@ + +#include + +int main(int argc, char* argv[]) { + + std::cout << "hi mom !" << std::endl; + + return 0; +} \ No newline at end of file