Skip to content

daftpy/dtracker_engine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dtracker_engine

A modular C++ audio engine library built with RtAudio. Designed to be used as the backend for a Qt-based audio tracker GUI.

Core Concepts and Architecture

The engine is built with a layered architecture that emphasizes testability and separation of concerns:

  • Interface-based Design: Core components like Engine and PlaybackManager are defined by abstract interfaces (IEngine and IPlaybackManager). 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 UnitPool pre-allocates and recycles SamplePlaybackUnit objects for audio playback
    • A BufferPool pre-allocates and recycles audio buffers (PCMData) for thread-safe data transport to the GUI.
  • Sample Instancing: The SampleManager separates 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 with RtAudio.

    • 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).

Hierarchical Playback Graph

Audio playback is handled by a compositional graph of PlaybackUnit objects.

  • Engine -> owns a master -> MixerPlaybackUnit
    • MixerPlaybackUnit -> 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.

Features

  • C++17 Design Utilizes smart pointers and move semantics, when possible, to prevent memory errors and improve efficiency.
  • Dynamic Playback Control: A RenderContext is 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 SampleManager and TrackManager use std::mutex to protect their data structures. The PlaybackManager uses std::atomic for simple state like BPM, and std::mutex to manage the lifecycle of shared visualization queues. The SampleManager also 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.

Roadmap / Future Work

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 .wav file.
  • Architectural Refinements: Investigating moving the master clock out of individual playback units and into the PlaybackManager to handle global song-level synchronization.

Requirements

  • CMake 3.27+
  • C++17-compatible compiler (e.g., MSVC, Clang, GCC)
  • RtAudio (fetched automatically)
  • GoogleTest for testing (fetched automatically)

Build Instructions

1. Clone the project

git clone https://github.com/yourname/dtracker_engine.git
cd dtracker_engine

2. Configure and build

🔧 Debug Build (without tests)

cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build --config Debug

Builds the dtracker_engine static library in debug mode.

🚦 Debug Build (with tests)

cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON
cmake --build build --config Debug
ctest --test-dir build --output-on-failure -C Debug

Includes and runs unit tests.

🚀 Release Build

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

Builds the optimized release version of the static library.

About

Lightweight C++ audio engine for dtracker using RtAudio.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors