PostProductionSDK - Getting Started Guide

Introduction

PostProductionSDK is a dedicated class for post-production audio workflows, separate from the music-focused TonnSDK. It provides intelligent dialogue enhancement, automatic sidechain ducking, delivery format mastering, and loudness compliance reporting for film, TV, streaming, advertising, and podcasting.

The module consists of two public headers: - PostProductionSDK.h contains the main processor class - PostProdTrackSettings.h contains per-track configuration

PostProductionSDK and TonnSDK are independent. You can use either or both in the same application, each with its own license feature.

System Requirements

  • C++17 compatible compiler
  • CMake 3.15 or higher
  • libsndfile (for audio I/O in examples)
  • A valid license key with LicenseFeature::POST_PRODUCTION enabled

Quick Start

1. Initialize the SDK

Construct a PostProductionSDK with a sample rate and a delivery format, then call initialize() with your license key:

#include "PostProductionSDK.h"
#include "PostProdTrackSettings.h"

tonn::PostProductionSDK sdk(48000.0f, tonn::PostProdFormat::FILM);

if (!sdk.initialize("your_license_key")) {
    std::cerr << sdk.getLastErrorMessage() << std::endl;
    return 1;
}

The delivery format determines loudness targets, true peak limits, and compliance thresholds. You can change it later with sdk.setFormat().

2. Understand Track Types

Every track is assigned a PostProdGroupType that tells the engine how to treat it in the mix:

Type Value Description
DIALOGUE_MAIN 1 Primary character speech, narration
DIALOGUE_SECONDARY 2 Background conversations, walla, crowd
MUSIC 3 Score, background music, soundtrack
SFX 4 Sound effects, designed sounds
AMBIENCE 5 Room tone, atmosphere, environmental sounds
FOLEY 6 Footsteps, cloth rustles, prop handling
ADR 7 Automated Dialogue Replacement (re-recorded lines)
VOICEOVER_LP 8 Low-pitched voiceover (warm, full-bodied treatment)
VOICEOVER_HP 10 High-pitched voiceover (bright, reduced plosives)
OTHER 9 Miscellaneous

3. Configure and Add Tracks

Create a PostProdTrackSettings with the track type, dialogue priority, and format, then add the track to the SDK:

// Dialogue track
tonn::PostProdTrackSettings dialogue(
    tonn::PostProdGroupType::DIALOGUE_MAIN,
    tonn::DialoguePriority::HIGH,
    tonn::PostProdFormat::FILM);

sdk.addTrack("dialogue.wav", dialogue);

// Music track
tonn::PostProdTrackSettings music(
    tonn::PostProdGroupType::MUSIC,
    tonn::DialoguePriority::NORMAL,
    tonn::PostProdFormat::FILM);

sdk.addTrack("score.wav", music);

You can also add tracks from in-memory buffers:

std::vector<std::vector<float>> audioBuffer = { leftChannel, rightChannel };
sdk.addTrackFromBuffer(audioBuffer, music, "score");

Both addTrack() and addTrackFromBuffer() return bool to indicate success.

4. Process and Read Results

Call process() to generate the final mix. Pass true to also get individually processed stems:

tonn::PostProdResult result = sdk.process();

if (result.success) {
    // Final stereo mix
    std::vector<float>& left = result.audioLeft;
    std::vector<float>& right = result.audioRight;

    // Loudness measurements
    std::cout << "Loudness: " << result.measuredLUFS << " LUFS" << std::endl;
    std::cout << "True peak: " << result.truePeakDb << " dBTP" << std::endl;
    std::cout << "Duration: " << result.trackLengthInSecs << "s" << std::endl;

    // Compliance flags
    std::cout << "Meets loudness spec: " << (result.meetsLoudnessSpec ? "yes" : "no") << std::endl;
    std::cout << "Meets peak spec: " << (result.meetsPeakSpec ? "yes" : "no") << std::endl;
    std::cout << "Format: " << result.formatDescription << std::endl;
} else {
    std::cerr << "Processing failed: " << result.errorMessage << std::endl;
}

5. Generate Processed Stems

Pass true to process() to populate result.stems and result.trackNames:

tonn::PostProdResult result = sdk.process(true);

if (result.success) {
    for (size_t i = 0; i < result.stems.size(); ++i) {
        auto& [stemLeft, stemRight] = result.stems[i];
        std::cout << "Stem: " << result.trackNames[i]
                  << " (" << stemLeft.size() << " samples)" << std::endl;
    }
}

Complete Example: Film Scene Mix

This example loads dialogue, music, and ambience tracks, applies dialogue enhancement and sidechain ducking, and masters to the Film delivery format:

#include "PostProductionSDK.h"
#include "PostProdTrackSettings.h"
#include <iostream>

int main() {
    // Initialize for Film delivery at 48 kHz
    tonn::PostProductionSDK sdk(48000.0f, tonn::PostProdFormat::FILM);

    if (!sdk.initialize("your_license_key")) {
        std::cerr << sdk.getLastErrorMessage() << std::endl;
        return 1;
    }

    // Dialogue: enhanced clarity, acts as ducking sidechain source
    tonn::PostProdTrackSettings dialogue(
        tonn::PostProdGroupType::DIALOGUE_MAIN,
        tonn::DialoguePriority::HIGH,
        tonn::PostProdFormat::FILM);
    dialogue.setDialogueEnhancementEnabled(true);
    dialogue.setDialogueEnhancementMode(tonn::DialogueEnhancementMode::ENHANCE);
    dialogue.setIsDuckingSidechain(true);

    // Music: ducked when dialogue plays
    tonn::PostProdTrackSettings music(
        tonn::PostProdGroupType::MUSIC,
        tonn::DialoguePriority::NORMAL,
        tonn::PostProdFormat::FILM);
    music.setDuckingEnabled(true);
    music.setDuckingPreset(tonn::DuckingPreset::MEDIUM);

    // Ambience: light ducking to keep atmosphere present
    tonn::PostProdTrackSettings ambience(
        tonn::PostProdGroupType::AMBIENCE,
        tonn::DialoguePriority::LOW,
        tonn::PostProdFormat::FILM);
    ambience.setDuckingEnabled(true);
    ambience.setDuckingPreset(tonn::DuckingPreset::LIGHT);

    // Add tracks
    sdk.addTrack("dialogue.wav", dialogue);
    sdk.addTrack("score.wav", music);
    sdk.addTrack("room_tone.wav", ambience);

    // Process with stems
    tonn::PostProdResult result = sdk.process(true);

    if (result.success) {
        std::cout << "Mix complete" << std::endl;
        std::cout << "Loudness: " << result.measuredLUFS << " LUFS" << std::endl;
        std::cout << "True peak: " << result.truePeakDb << " dBTP" << std::endl;
        std::cout << "Meets loudness spec: " << (result.meetsLoudnessSpec ? "yes" : "no") << std::endl;
        std::cout << "Meets dialogue spec: " << (result.meetsDialogueSpec ? "yes" : "no") << std::endl;
        std::cout << "Meets peak spec: " << (result.meetsPeakSpec ? "yes" : "no") << std::endl;
    } else {
        std::cerr << "Error: " << result.errorMessage << std::endl;
        return 1;
    }

    return 0;
}

Next Steps

  • Post-Production Features: Deep dive into dialogue enhancement, ducking presets, delivery formats, compliance reporting, and more.
  • Post-Production Examples: Walkthroughs of the shipped example applications with JSON config formats and build instructions.
  • API Reference: Full method signatures for the music mixing and mastering SDK.