initial commit
This commit is contained in:
37
.clang-format
Normal file
37
.clang-format
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
# This configuration requires clang-format 3.8 or higher.
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: Mozilla
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
AccessModifierOffset: '0'
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: 'true'
|
||||||
|
AlignConsecutiveDeclarations: 'true'
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: 'true'
|
||||||
|
AlignTrailingComments: 'true'
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: 'false'
|
||||||
|
AllowShortCaseLabelsOnASingleLine: 'false'
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortLoopsOnASingleLine: 'false'
|
||||||
|
AlwaysBreakBeforeMultilineStrings: 'false'
|
||||||
|
BreakBeforeBraces: Allman
|
||||||
|
BreakBeforeTernaryOperators: 'true'
|
||||||
|
ColumnLimit: '0'
|
||||||
|
FixNamespaceComments: 'true'
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IndentCaseLabels: 'true'
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
|
IndentWidth: '2'
|
||||||
|
NamespaceIndentation: None
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReflowComments: 'true'
|
||||||
|
SortIncludes: 'true'
|
||||||
|
SortUsingDeclarations: 'true'
|
||||||
|
SpacesBeforeTrailingComments: 5
|
||||||
|
TabWidth: '2'
|
||||||
|
UseTab: Never
|
||||||
|
|
||||||
|
...
|
||||||
95
.gitignore
vendored
Normal file
95
.gitignore
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
# ---> C
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
|
||||||
|
# ---> C++
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# ---> Environment
|
||||||
|
# Executables
|
||||||
|
build/
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# Editor's mess
|
||||||
|
.vscode/
|
||||||
|
.vs/
|
||||||
|
*/.idea/copilot*
|
||||||
|
|
||||||
85
README.md
Normal file
85
README.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# volaTileMidi 🎹✨
|
||||||
|
|
||||||
|
A high-performance, cross-platform MIDI visualizer and interactive piano trainer written in modern C++.
|
||||||
|
|
||||||
|
The name is a geeky nod to the C++ `volatile` keyword and the smooth, cascading visual notes (**vola-Tile**) that stream down to your keyboard. It connects directly to your USB MIDI piano to offer real-time interaction with zero perceived latency.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Features
|
||||||
|
|
||||||
|
* **Real-time MIDI Input:** Connects to any USB/Midi keyboard instantly using `RtMidi`.
|
||||||
|
* **Lock-Free Architecture:** Uses a custom Single-Producer Single-Consumer (SPSC) lock-free ring buffer to forward MIDI events from the driver thread to the main loop without blocking or stuttering.
|
||||||
|
* **Modern 2D Rendering:** Powered by `SDL3` leveraging GPU acceleration for perfectly smooth rendering at high refresh rates.
|
||||||
|
* **Accurate MIDI Parsing:** Pre-calculates MIDI track events from `.mid` files using `libremidi`, converting native MIDI ticks into absolute time seconds while fully respecting mid-song tempo changes.
|
||||||
|
* **Resolution Independent:** Uses a logical rendering viewport size ensuring the falling tiles and keyboard stay perfectly proportioned regardless of your window size or monitor aspect ratio.
|
||||||
|
* **Cross-Platform:** Built from the ground up to compile and run natively on both **Windows** and **Linux** (ALSA/PipeWire).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Tech Stack & Dependencies
|
||||||
|
|
||||||
|
* **Language:** Modern C++ (C++20 recommended)
|
||||||
|
* **Build System:** CMake
|
||||||
|
* **Windowing & Graphics:** [SDL3](https://github.com/libsdl-org/SDL)
|
||||||
|
* **MIDI I/O:** [RtMidi](https://github.com/garyscavone/rtmidi)
|
||||||
|
* **MIDI File Parsing:** [libremidi](https://github.com/jcelerier/libremidi)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ Architecture Architecture Overview
|
||||||
|
|
||||||
|
The core design centers around a `CoreManager` class that orchestrates the engine lifecycle, ensuring a strict separation between hardware input, logic updates, and presentation:
|
||||||
|
|
||||||
|
```
|
||||||
|
[ USB Piano Input ] ──> (RtMidi Driver Thread / Lambda)
|
||||||
|
│
|
||||||
|
[ SpscMidiQueue (Lock-Free) ]
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[ SDL3 Main Loop ] ──> CoreManager::update() ──> CoreManager::render()
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **Hardware Thread:** `RtMidi` captures key presses via a low-overhead driver callback. It instantly pushes lightweight events into the lock-free queue.
|
||||||
|
2. **Main Loop Thread:** The `CoreManager` pumps OS events, consumes all pending live MIDI events, updates the scrolling timeline based on a precise delta time, and renders the active shapes to the screen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 Building from Source
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
Make sure you have a C++20 compliant compiler, CMake, and the necessary development packages installed.
|
||||||
|
|
||||||
|
#### On Linux (Ubuntu/Debian example):
|
||||||
|
```bash
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install build-essential cmake libasound2-dev libjack-jackd2-dev
|
||||||
|
# Install SDL3 from source or repository when fully available on your distro
|
||||||
|
```
|
||||||
|
|
||||||
|
# Clone the repository
|
||||||
|
git clone [https://github.com/yourusername/volaTileMidi.git](https://github.com/yourusername/volaTileMidi.git)
|
||||||
|
cd volaTileMidi
|
||||||
|
|
||||||
|
# Configure CMake
|
||||||
|
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
|
# Build the project
|
||||||
|
cmake --build build --config Release
|
||||||
|
|
||||||
|
🗺️ Roadmap / Todo
|
||||||
|
[ ] Initialize SDL3 window context and abstract coordinate system viewport.
|
||||||
|
|
||||||
|
[ ] Implement the SpscMidiQueue lock-free ring buffer.
|
||||||
|
|
||||||
|
[ ] Bind RtMidi with a non-capturing lambda callback forwarding to CoreManager.
|
||||||
|
|
||||||
|
[ ] Render the basic 88-key static virtual keyboard.
|
||||||
|
|
||||||
|
[ ] Integrate libremidi parser for absolute timeline conversion (Ticks ➔ Seconds).
|
||||||
|
|
||||||
|
[ ] Implement the interactive "Practice Mode" where the scrolling pauses until the correct key is pressed.
|
||||||
|
|
||||||
|
📄 License
|
||||||
|
This project is open-source. Feel free to use, modify, and distribute it as you see fit.
|
||||||
Reference in New Issue
Block a user