TonnSDK - Getting Started Guide¶
Introduction¶
TonnSDK is an advanced audio production library that provides automatic multitrack audio mixing, reprocessing, and professional mastering capabilities. This guide will help you get started with integrating and using TonnSDK in your application.
System Requirements¶
- C++17 compatible compiler
- CMake 3.15 or higher
- libsndfile (for audio I/O in examples)
- nlohmann/json (automatically fetched by CMake)
Quick Start¶
1. Setup¶
- Include the TonnSDK headers in your project
- Link against the TonnSDK library
- Ensure you have a valid license key
2. Basic Usage¶
Mixing Example¶
#include "TonnSDK.h"
#include "MixTrackSettings.h"
// Initialize the SDK with sample rate and musical style
tonn::TonnSDK sdk(44100.0f, tonn::MusicalStyle::ROCK_INDIE);
// Initialize with license key (required)
if (!sdk.initialize("your_license_key_here")) {
std::cerr << "Failed to initialize SDK: " << sdk.getLastErrorMessage() << std::endl;
return 1;
}
// Configure track settings
tonn::MixTrackSettings drumSettings(tonn::GroupType::DRUMS_GROUP,
tonn::PresenceSetting::NORMAL,
tonn::MusicalStyle::ROCK_INDIE);
// Add tracks to the SDK
sdk.addTrack("path/to/drums.wav", drumSettings);
// Process the mix
tonn::MixResult result = sdk.process();
// Access the final mix
auto leftChannel = result.audio_x.first;
auto rightChannel = result.audio_x.second;
// Access individual processed stems
for (size_t i = 0; i < result.stems.size(); ++i) {
std::cout << "Stem " << i << ": " << result.trackNames[i] << std::endl;
}
Mastering Example¶
#include "TonnSDK.h"
#include "MasteringSettings.h"
// Initialize the SDK for mastering
tonn::TonnSDK sdk(44100.0f, tonn::MusicalStyle::POP);
// Initialize with license key
if (!sdk.initialize("your_license_key_here")) {
std::cerr << "Failed to initialize SDK: " << sdk.getLastErrorMessage() << std::endl;
return 1;
}
// Configure mastering settings
tonn::MasteringSettings settings;
settings.setLoudnessPreference(tonn::MasteringLoudnessTarget::MEDIUM);
// Load mix for mastering
sdk.addMix("path/to/mix.wav", settings);
// Process mastering
tonn::MasteringResult result = sdk.processMastering();
if (result.success) {
std::cout << "Measured LUFS: " << result.measuredLUFS << std::endl;
std::cout << "Peak Level: " << result.peakLevel << " dB" << std::endl;
// Access mastered audio
auto leftChannel = result.audio.first;
auto rightChannel = result.audio.second;
}
3. GPU-Accelerated Mixing¶
Enable GPU-accelerated mixing for faster processing and higher quality mixes:
#include "TonnSDK.h"
// Initialize SDK
tonn::TonnSDK sdk(44100.0f, tonn::MusicalStyle::ROCK_INDIE);
sdk.initialize("your_license_key");
// Enable GPU mixing (requires NVIDIA GPU with CUDA 12.2+)
sdk.setMixingModel(tonn::MixingModel::GPU_STATIC);
// Add tracks and process as normal
sdk.addTrack("drums.wav", drumSettings);
sdk.addTrack("bass.wav", bassSettings);
tonn::MixResult result = sdk.process();
// If GPU is not available, the SDK falls back to CPU automatically
Note: The default mode is CPU_STATIC which requires no GPU. Use GPU_STATIC when an NVIDIA GPU with CUDA is available for faster, higher quality results.
4. Creative Compression¶
Enable or disable genre-specific stylized compression:
#include "TonnSDK.h"
// Initialize SDK
tonn::TonnSDK sdk(44100.0f, tonn::MusicalStyle::ROCK_INDIE);
sdk.setLicenseKey("your_license_key");
// Creative compression is ENABLED by default
// Disable it for a more transparent, natural sound:
sdk.setCreativeCompressionEnabled(false);
// Or enable it for genre-specific compression character:
sdk.setCreativeCompressionEnabled(true);
// Check current state:
bool isEnabled = sdk.isCreativeCompressionEnabled();
std::cout << "Creative compression: " << (isEnabled ? "ON" : "OFF") << std::endl;
// Add tracks and process as normal
sdk.addTrackFromBuffer(audioBuffer, settings, "vocals.wav");
tonn::MixResult result = sdk.process();
// Access the FX Chain JSON to see all applied effects
std::cout << result.fxChainsJson << std::endl;
5. FX Chain JSON Export¶
Access the complete effects chain for all tracks:
tonn::MixResult result = sdk.process();
// fxChainsJson contains ordered JSON with all effects per track
if (!result.fxChainsJson.empty()) {
std::cout << "FX Chain Settings:" << std::endl;
std::cout << result.fxChainsJson << std::endl;
// Save to file for DAW integration or analysis
std::ofstream fxFile("fx_chain_settings.json");
fxFile << result.fxChainsJson;
}
The JSON structure includes: - Track identification (ID, name, group type) - Ordered FX chain: Low Cut → Pre-Gain → EQ → Corrective Compression → Creative Compression → Pan → Post-Gain → Reverb → Sidechain - All parameters for each effect slot
6. Settings-Only Processing¶
For faster parameter calculation without audio processing:
// Get optimized settings only (10-50x faster)
tonn::MixResult settingsResult = sdk.process(true);
// Access calculated parameters
for (const auto& settings : settingsResult.mixTrackSettings) {
std::cout << "Pan angle: " << settings.getPanAngle() << " degrees" << std::endl;
std::cout << "Gain: " << settings.getGain() << "x" << std::endl;
}
7. Running the Test Suite¶
Validate your installation and license with the comprehensive test suite:
# Navigate to the tests directory
cd tests/
# Build the tests
./build_tests.sh
# Run all tests
./run_tests.sh
# Or run specific test categories
./run_tests.sh unit # Unit tests only
./run_tests.sh integration # Integration tests only
./run_tests.sh performance # Performance tests only
8. Running the Examples¶
The SDK includes comprehensive example applications demonstrating the complete production pipeline:
# Navigate to the examples directory
cd examples/
# Build examples (requires libsndfile)
mkdir build && cd build
cmake ..
make
# Run the simple mixing example (CPU mode — default)
./TonnSDK_Simple_Mixing_Example ../configs/rock_config.json
# Run with GPU-accelerated mixing (requires NVIDIA GPU + CUDA)
./TonnSDK_Simple_Mixing_Example ../configs/rock_config.json --gpu
# Run with settings-only mode for faster processing
./TonnSDK_Simple_Mixing_Example ../configs/rock_config.json --settings-only
# Run with AudioReprocessor demonstration after initial mixing
./TonnSDK_Simple_Mixing_Example ../configs/rock_config.json --reprocess
# Run with Mastering after mixing
./TonnSDK_Simple_Mixing_Example ../configs/rock_config.json --master
# Complete production workflow: Mix → Reprocess → Master
./TonnSDK_Simple_Mixing_Example ../configs/rock_config.json --reprocess --master
What's New¶
v2.0.0 - Latest Release¶
PostProductionSDK: Complete film/TV/ad post-production audio processing. Includes dialogue enhancement, auto-ducking, and format-specific mastering (FILM, TV, STREAMING, BROADCAST, ADMIX, PODCAST). See docs/API_Reference.md for full details.
Metal GPU Support: GPU-accelerated processing on macOS via Metal, in addition to CUDA on Linux.
v1.6.1¶
Mastering HIGH Setting Fix: Fixed a bug in the mastering pipeline when using the MasteringLoudnessTarget::HIGH setting. Mastering with HIGH now produces correct results across all musical styles.
v1.6¶
GPU-Accelerated Mixing: New GPU mixing model for faster processing and higher quality mixes. Enable with setMixingModel(MixingModel::GPU_STATIC) or --gpu flag in examples. Tested primarily on CUDA (NVIDIA GPUs). CPU fallback happens automatically if GPU is not available.
Performance & Quality Improvements: General improvements to mix quality and processing speed.
AudioReprocessor Bug Fix: AudioReprocessor now correctly applies creative compression.
Clean Output: SDK no longer prints diagnostic output by default, providing clean integration for production use.
v1.5¶
Creative Compression: Genre-specific stylized compression that automatically applies professional compression presets based on musical style and instrument type. Enable/disable via setCreativeCompressionEnabled().
FX Chain JSON Export: fxChainsJson field in MixResult provides a complete ordered JSON export of all applied effects per track.
Improved Parameter Estimation: Improved panning and dynamic range compression parameter estimation.
v1.4.2 - Mastering Performance¶
Mastering Performance Optimizations: Version 1.4.2 introduces significant performance improvements for mastering operations. Optimized processing algorithms provide faster mastering workflow, enhanced efficiency in loudness measurement and normalization, and improved limiting and peak control processing speed. Better resource utilization reduces processing time for all mastering loudness targets (LOW, MEDIUM, HIGH).
v1.4.1 - Memory Management Enhancement¶
Memory Management Enhancement: Version 1.4.1 removes the hard 14 GB memory limit constraint, allowing the SDK to dynamically manage memory based on available system resources. This provides improved flexibility for processing large-scale audio projects and better performance for high-track-count sessions.
v1.4.0 - Professional Mastering¶
Professional Mastering: Version 1.4.0 introduced industry-standard mastering capabilities with three loudness targets (LOW, MEDIUM, HIGH) optimized for streaming, balanced output, and competitive loudness. Complete production pipeline from raw tracks to distribution-ready masters.
Complete Production Workflow: Integrated workflow demonstrating Mix → Reprocess → Master in a single example, providing end-to-end music production capabilities.
Enhanced Examples: Updated simple_mixing_example.cpp with --master and --full flags to demonstrate the complete production pipeline including mastering.
Previous Releases¶
v1.3.2 - Performance improvements and code optimizations for better mix performance.
v1.3.1 - Enhanced stability, skip quiet tracks feature, and pre-gain preservation fix.
Example Code¶
See the examples/ directory for complete working examples:
- simple_mixing_example.cpp: Comprehensive example showing the complete production pipeline: mixing, AudioReprocessor, and mastering
Key API Components¶
TonnSDK Class¶
The main entry point for the SDK:
// Constructor: requires sample rate and musical style, with optional quiet track handling
TonnSDK(float sampleRate, MusicalStyle style = MusicalStyle::ROCK_INDIE, bool skipQuietTracks = false);
// Required initialization with license
bool initialize(const std::string& licenseKey);
// === MIXING API ===
// Add tracks from files or buffers
void addTrack(const std::string& filePath, const MixTrackSettings& settings);
void addTrackFromBuffer(const std::vector<std::vector<float>>& audioBuffer,
const MixTrackSettings& settings);
void addTrackFromBuffer(const std::vector<std::vector<float>>& audioBuffer,
const MixTrackSettings& settings,
const std::string& trackName);
// Process the mix (with optional settings-only mode)
MixResult process(bool settingsOnly = false, bool generateStems = true);
// === MIXING MODEL API ===
void setMixingModel(MixingModel model); // Set CPU_STATIC (default) or GPU_STATIC
MixingModel getMixingModel() const; // Get current mixing model
// === CREATIVE COMPRESSION API ===
void setCreativeCompressionEnabled(bool enabled); // Enable/disable genre-specific compression
bool isCreativeCompressionEnabled() const; // Check current state
// === MASTERING API ===
// Add mix for mastering
void addMix(const std::string& filePath, const MasteringSettings& settings);
void addMixFromBuffer(const std::vector<std::vector<float>>& audioBuffer,
const MasteringSettings& settings);
// Process mastering
MasteringResult processMastering();
// === REPROCESSING API ===
// AudioReprocessor integration
std::unique_ptr<AudioReprocessor> createReprocessor() const;
bool saveOriginalStems(const std::string& directoryPath, bool includeSettings = true) const;
AudioReprocessor Class¶
For offline reprocessing of existing stems:
// Constructor
AudioReprocessor(float sampleRate, MusicalStyle style = MusicalStyle::ROCK_INDIE);
// Load stems for reprocessing
bool loadStem(const std::string& filePath, const MixTrackSettings& originalSettings);
bool loadStem(const std::vector<std::vector<float>>& audioBuffer,
const MixTrackSettings& originalSettings,
const std::string& trackName = "");
// Reprocess with modified settings
ReprocessResult reprocess(std::vector<MixTrackSettings> modifiedSettings);
// Save results
bool saveReprocessedMix(const ReprocessResult& result, const std::string& filePath);
bool saveReprocessedStem(const ReprocessResult& result, size_t stemIndex, const std::string& filePath);
MixTrackSettings Class¶
Configuration for individual audio tracks:
- GroupType: Instrument classification (DRUMS_GROUP, VOCAL_GROUP, etc.)
- PresenceSetting: Importance level (BACKGROUND, NORMAL, LEAD)
- MusicalStyle: Genre optimization
- EQ, compression, and panning settings
MasteringSettings Class¶
Configuration for mastering operations:
- MasteringLoudnessTarget: Target loudness level (LOW, MEDIUM, HIGH)
- LOW: -14 LUFS (Streaming-optimized)
- MEDIUM: -10 LUFS (Balanced)
- HIGH: -8 LUFS (Competitive)
MixResult Structure¶
Contains the processing results:
- audio_x: Final stereo mix (left/right channels)
- mixTrackSettings: Optimized track settings
- stems: Individual processed tracks
- trackNames: Track names corresponding to stems
- trackLengthInSecs: Duration information
- fxChainsJson: Complete FX chain data as ordered JSON
MasteringResult Structure¶
Contains the mastering results:
- audio: Mastered stereo audio (left/right channels)
- measuredLUFS: Measured loudness in LUFS
- peakLevel: Peak level in dB
- trackLengthInSecs: Duration information
- success: Whether mastering was successful
ReprocessResult Structure¶
Contains the AudioReprocessor results:
- mixedAudio: Reprocessed stereo mix (left/right channels)
- processedStems: Individual reprocessed stems
- trackNames: Track names corresponding to stems
- lengthInSeconds: Duration information
- success: Whether reprocessing was successful
- errorMessage: Error message if reprocessing failed
Performance Tips¶
- Use
process(true)for settings-only mode when you only need parameters - Process in background threads for non-blocking operation
- Use the advanced subgroup mixing approach for large sessions
- Use AudioReprocessor for quick iteration on mix parameters without full re-mixing
Error Handling¶
Always check return values and error messages:
if (!sdk.initialize(licenseKey)) {
std::cerr << "SDK initialization failed: " << sdk.getLastErrorMessage() << std::endl;
}
try {
tonn::MixResult result = sdk.process();
if (result.audio_x.first.empty()) {
std::cerr << "Processing failed: " << sdk.getLastErrorMessage() << std::endl;
}
} catch (const std::exception& e) {
std::cerr << "Exception during processing: " << e.what() << std::endl;
}
For detailed API documentation, see docs/API_Reference.md and docs/Best_Practices.md.
Getting Started with Post-Production¶
The post-production module targets film, television, streaming, podcast, and commercial workflows. It centers on PostProductionSDK (session and processing), PostProdTrackSettings (per-track configuration), and PostProdResult (mixed output and loudness metadata). Public headers:
public/PostProductionSDK.hpublic/PostProdTrackSettings.h
Licensing matches the rest of TonnSDK: supply a valid key to initialize(). In deployments, the key is commonly read from the TONNSDK_LICENSE_KEY environment variable and passed into initialize().
Supporting enums include PostProdGroupType, PostProdFormat, DialoguePriority, DialogueEnhancementMode, DuckingPreset, and PostProdReverbSetting.
1. Initialization (sample rate and format)¶
Construct PostProductionSDK with the session sample rate (Hz) and a PostProdFormat target. The format sets the mastering/loudness context for the mix; you can change it later with setFormat().
#include "public/PostProductionSDK.h"
#include "public/PostProdTrackSettings.h"
// 48 kHz film delivery
tonn::PostProductionSDK sdk(48000.0f, tonn::PostProdFormat::FILM);
Call initialize() with your license key before adding tracks or processing.
2. Track types (PostProdGroupType)¶
Classify each stem with PostProdGroupType:
DIALOGUE_MAIN— primary dialogueDIALOGUE_SECONDARY— secondary or background dialogueMUSIC— score or source musicSFX— sound effectsAMBIENCE— atmospheres and bedsFOLEY— foleyADR— automated dialogue replacementVOICEOVER_LP— voice-over tuned for lower-pitched voicesVOICEOVER_HP— voice-over tuned for higher-pitched voices
The public API also defines OTHER for material that does not fit the categories above.
3. Adding tracks (PostProdTrackSettings)¶
Build settings with the constructor PostProdTrackSettings(PostProdGroupType, DialoguePriority, PostProdFormat), then optionally adjust pan, gain, reverb, EQ, compression, dialogue processing, and ducking. Add file-based stems with addTrack(), or in-memory audio as std::vector<std::vector<float>> (one inner vector per channel) with addTrackFromBuffer(). Both return bool; on failure, use getLastErrorMessage().
tonn::PostProdTrackSettings dialogue(
tonn::PostProdGroupType::DIALOGUE_MAIN,
tonn::DialoguePriority::HIGH,
tonn::PostProdFormat::FILM);
if (!sdk.addTrack("/path/to/dialogue.wav", dialogue)) {
std::cerr << sdk.getLastErrorMessage() << std::endl;
}
4. Dialogue enhancement and ducking¶
Dialogue enhancement improves intelligibility on dialogue-class tracks. Enable and set mode per track with setDialogueEnhancementEnabled() and setDialogueEnhancementMode() (DialogueEnhancementMode::PRESERVE, ENHANCE, or AD_ENHANCED). At session level, setDialogueEnhancementEnabled() on PostProductionSDK toggles the feature globally.
Ducking lowers level on beds (e.g. music, ambience) when dialogue is present. Typical pattern:
- Mark dialogue (or another control source) with
setIsDuckingSidechain(true)on that track’s settings. - On tracks that should yield to dialogue, call
setDuckingEnabled(true)andsetDuckingPreset()(e.g.DuckingPreset::LIGHT,MEDIUM,HEAVY,AD_MIX, orCUSTOMwith the custom dB/threshold/attack/release setters).
Session-wide auto-ducking can be enabled with PostProductionSDK::setAutoDuckingEnabled().
5. Processing and reading PostProdResult¶
Run the pipeline with process(). The first argument is generateStems (default false); when true, PostProdResult::stems and trackNames are populated. An optional progress callback can report stage and fraction complete, or cancel by returning false.
Important PostProdResult fields:
success,errorMessageaudioLeft,audioRight— final stereo mixtrackLengthInSecs- Loudness and dynamics:
measuredLUFS,dialogueLUFS,dialogueLRA,truePeakDb,dynamicRangeLU,shortTermLoudnessMax - Compliance flags:
meetsLoudnessSpec,meetsDialogueSpec,meetsPeakSpec,meetsProgramLRASpec,meetsDialogueLRASpec,formatDescription - With stems:
stems(pairs of left/right vectors per track),trackNames
tonn::PostProdResult result = sdk.process(/*generateStems=*/false);
if (!result.success) {
std::cerr << result.errorMessage << std::endl;
return 1;
}
// Interleaved or per-channel write-out is application-specific
const std::vector<float>& L = result.audioLeft;
const std::vector<float>& R = result.audioRight;
6. Output formats (PostProdFormat)¶
| Enumerator | Typical integrated loudness target |
|---|---|
FILM |
-24 LUFS (cinema-style delivery) |
TV |
-23 LUFS |
STREAMING |
-27 LUFS (post-prod streaming delivery) |
YOUTUBE |
-14 LUFS |
BROADCAST |
-23 LUFS (strict broadcast / EBU-style constraints) |
ADMIX |
-23 LUFS (commercial / ad-mix workflows; auto-ducking oriented) |
PODCAST |
-16 LUFS |
Use getTargetLoudness(), getMaxTruePeak(), getFormatDescription(), and getLoudnessTolerance() on the SDK for the active format’s parameters.
7. Minimal film mixing workflow (example)¶
The following sketch wires a two-stem film session: main dialogue (enhancement + sidechain source) and music (ducked). It assumes TONNSDK_LICENSE_KEY is set in the environment.
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include "public/PostProductionSDK.h"
#include "public/PostProdTrackSettings.h"
int main() {
const char* envKey = std::getenv("TONNSDK_LICENSE_KEY");
if (!envKey || std::strlen(envKey) == 0) {
std::cerr << "Set TONNSDK_LICENSE_KEY\n";
return 1;
}
tonn::PostProductionSDK sdk(48000.0f, tonn::PostProdFormat::FILM);
if (!sdk.initialize(std::string(envKey))) {
std::cerr << "Init failed: " << sdk.getLastErrorMessage() << std::endl;
return 1;
}
sdk.setAutoDuckingEnabled(true);
sdk.setDialogueEnhancementEnabled(true);
sdk.setMasteringEnabled(true);
tonn::PostProdTrackSettings dialogue(
tonn::PostProdGroupType::DIALOGUE_MAIN,
tonn::DialoguePriority::HIGH,
tonn::PostProdFormat::FILM);
dialogue.setDialogueEnhancementEnabled(true);
dialogue.setDialogueEnhancementMode(tonn::DialogueEnhancementMode::ENHANCE);
dialogue.setIsDuckingSidechain(true);
tonn::PostProdTrackSettings music(
tonn::PostProdGroupType::MUSIC,
tonn::DialoguePriority::NORMAL,
tonn::PostProdFormat::FILM);
music.setDuckingEnabled(true);
music.setDuckingPreset(tonn::DuckingPreset::MEDIUM);
if (!sdk.addTrack("dialogue.wav", dialogue) ||
!sdk.addTrack("music.wav", music)) {
std::cerr << sdk.getLastErrorMessage() << std::endl;
return 1;
}
tonn::PostProdResult result = sdk.process(false);
if (!result.success) {
std::cerr << result.errorMessage << std::endl;
return 1;
}
std::cout << "LUFS: " << result.measuredLUFS
<< " meets spec: " << (result.meetsLoudnessSpec ? "yes" : "no")
<< std::endl;
return 0;
}
For a fuller JSON-driven pipeline (multiple stems, stems export, format overrides), see examples/post_production_example.cpp in the SDK package.