A modular C++ audio engine library built with RtAudio. Designed to be used as the backend for a Qt-based audio tracker GUI.
The engine is built with a layered architecture that emphasizes testability and separation of concerns:
-
Interface-based Design: Core components like
EngineandPlaybackManagerare defined by abstract interfaces (IEngineandIPlaybackManager). This allows for easy mocking and testing. -
Real-Time Safety: The engine guarantees real-time safety by eliminating dynamic memory allocation on the critical audio thread. Both pools use smart pointers with custom deleters to ensure automatic resource management.
- A
UnitPoolpre-allocates and recycles SamplePlaybackUnit objects for audio playback - A
BufferPoolpre-allocates and recycles audio buffers (PCMData) for thread-safe data transport to the GUI.
- A
-
Sample Instancing: The
SampleManagerseparates the concept of raw audio samples stored in the cache and the instances stored in the manager. This allows hundreds of sounds in a project to efficiently share the same underlying audio data safely. -
Thread-Safe Communication: A high-performance, lock-free SPSC (Single-Producer, Single-Consumer) queue is used to safely "tap" the final audio output and stream visualization data from the real-time audio thread without blocking.
-
Component Layers: The system is organized into clear service layers:
-
Engine: The low-level service that communicates withRtAudio. -
SampleManager: Provides caching and management for all audio samples. -
TrackManager: Manages the data for musical tracks and their pattern sequences. -
PlaybackManager: The high-level API for controlling all playback (previews, patterns, tracks).
-
Audio playback is handled by a compositional graph of PlaybackUnit objects.
Engine-> owns a master ->MixerPlaybackUnitMixerPlaybackUnit-> can contain ->TrackPlaybackUnit(s)TrackPlaybackUnit-> can contain a sequence of ->PatternPlaybackUnit(s)PatternPlaybackUnit-> triggers ->SamplePlaybackUnit(s)
This hierarchy allows complex arrangements to be built from simple, reusable parts. A TrackPlaybackUnit applies track-level effects (volume/pan) to the output of the pattern it's currently playing.
- C++17 Design Utilizes smart pointers and move semantics, when possible, to prevent memory errors and improve efficiency.
- Dynamic Playback Control: A
RenderContextis passed down the entire playback graph on every audio frame. This allows global parameters like BPM and looping state to be changed on the fly from the UI in a completely thread-safe manner. - Decoupled Architecture: Core components are abstracted behind interfaces for improved flexibility and testability.
- Thread-Safe Data Management: The engine uses multiple strategies for thread safety. The
SampleManagerandTrackManagerusestd::mutexto protect their data structures. ThePlaybackManagerusesstd::atomicfor simple state like BPM, andstd::mutexto manage the lifecycle of shared visualization queues. TheSampleManageralso features a thread-safe LRU cache for efficient memory usage. - Comprehensive Test Suite: Built with GoogleTest and a clean separation between unit and integration tests.
While the core playback engine is robust and functional, several key features are planned for future development:
- Polyphonic Patterns: The pattern system currently supports one note per step. The next step is to upgrade the data model to allow for chords and layered notes.
- Effects Processing: Implementing a basic effects chain (e.g., Delay, Filter) for each track.
- MIDI Input: Adding support for real-time MIDI keyboard input to trigger samples.
- Offline Rendering: A feature to export the final mix to a
.wavfile. - Architectural Refinements: Investigating moving the master clock out of individual playback units and into the
PlaybackManagerto handle global song-level synchronization.
- CMake 3.27+
- C++17-compatible compiler (e.g., MSVC, Clang, GCC)
- RtAudio (fetched automatically)
- GoogleTest for testing (fetched automatically)
git clone https://github.com/yourname/dtracker_engine.git
cd dtracker_enginecmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build --config DebugBuilds the dtracker_engine static library in debug mode.
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
cmake --build build --config Debug
ctest --test-dir build --output-on-failure -C DebugIncludes and runs unit tests.
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config ReleaseBuilds the optimized release version of the static library.