Skip to content

๐Ÿ“‹ 08_00_00_contracts - Specification

๐ŸŽฏ Purpose

Define abstract base interfaces that all AudioLab plugins must implement. These contracts establish the fundamental API surface for plugin lifecycle, state management, parameter control, and audio processing.


๐Ÿ—๏ธ Architecture Philosophy

Contract-Based Design

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  CONTRACTS (Abstract Interfaces)                             โ”‚
โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚
โ”‚  IPluginProcessor  โ”‚  IAudioEngine  โ”‚  IStateManager        โ”‚
โ”‚  IParameterHost    โ”‚  IModTarget    โ”‚  IUIController        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ†“ implements
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  CONCRETE IMPLEMENTATIONS (L4/L5 Plugins)                    โ”‚
โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚
โ”‚  TS_Reverb         โ”‚  TS_Compressor โ”‚  TS_MasterSuite       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Benefits: - โœ… Polymorphic plugin handling - โœ… Testable via mocks - โœ… Clear separation of concerns - โœ… Future-proof extensibility


๐Ÿ“ฆ Required Interfaces

1. IPluginProcessor (Core Lifecycle)

Responsibility: Universal plugin lifecycle and identification

class IPluginProcessor {
public:
    // Lifecycle
    virtual void initialize(float sampleRate, int maxBlockSize) = 0;
    virtual void shutdown() = 0;
    virtual void reset() = 0;

    // Processing
    virtual void process(AudioBuffer& buffer) = 0;
    virtual void processReplacing(float** inputs, float** outputs,
                                   int numSamples) = 0;

    // Identity
    virtual const char* getName() const = 0;
    virtual const char* getVersion() const = 0;
    virtual const char* getVendor() const = 0;

    // Configuration
    virtual int getLatencySamples() const = 0;
    virtual bool supportsBypass() const = 0;
    virtual void setBypass(bool bypass) = 0;

    virtual ~IPluginProcessor() = default;
};

2. IStateManager (Persistence)

Responsibility: Save/load plugin state for DAW sessions and presets

class IStateManager {
public:
    // State serialization
    virtual bool saveState(MemoryBlock& destData) = 0;
    virtual bool loadState(const void* data, size_t sizeInBytes) = 0;

    // Preset management
    virtual bool savePreset(const std::string& path) = 0;
    virtual bool loadPreset(const std::string& path) = 0;

    // Versioning
    virtual int getStateVersion() const = 0;
    virtual bool canLoadVersion(int version) const = 0;

    // Migration
    virtual bool migrateState(int fromVersion, int toVersion,
                             void* data, size_t& size) = 0;

    virtual ~IStateManager() = default;
};

3. IParameterHost (Control System)

Responsibility: Parameter registration, access, and automation

class IParameterHost {
public:
    // Parameter registration
    virtual void registerParameter(Parameter* param) = 0;
    virtual void unregisterParameter(const std::string& id) = 0;

    // Access
    virtual Parameter* getParameter(const std::string& id) = 0;
    virtual Parameter* getParameterByIndex(int index) = 0;
    virtual int getParameterCount() const = 0;

    // Value manipulation
    virtual float getParameterValue(const std::string& id) const = 0;
    virtual void setParameterValue(const std::string& id, float value) = 0;
    virtual void setParameterValueNormalized(const std::string& id,
                                            float normalizedValue) = 0;

    // Automation
    virtual void beginParameterGesture(const std::string& id) = 0;
    virtual void endParameterGesture(const std::string& id) = 0;

    // Listeners
    virtual void addParameterListener(IParameterListener* listener) = 0;
    virtual void removeParameterListener(IParameterListener* listener) = 0;

    virtual ~IParameterHost() = default;
};

4. IAudioEngine (DSP Processing)

Responsibility: Sample-accurate audio processing abstraction

class IAudioEngine {
public:
    // Configuration
    virtual void setSampleRate(float sampleRate) = 0;
    virtual void setBlockSize(int blockSize) = 0;
    virtual void prepareToPlay(float sampleRate, int blockSize) = 0;
    virtual void releaseResources() = 0;

    // Processing
    virtual void processBlock(AudioBuffer& buffer) = 0;
    virtual void processBlockWithModulation(AudioBuffer& buffer,
                                           const ModulationState& modState) = 0;

    // Characteristics
    virtual int getLatencySamples() const = 0;
    virtual float getTailLengthSeconds() const = 0;
    virtual bool supportsSidechain() const = 0;

    // Real-time safety
    virtual bool isRealTimeSafe() const = 0;

    virtual ~IAudioEngine() = default;
};

5. IModulationTarget (Modulation System)

Responsibility: Allow parameters to be modulated by LFOs, envelopes, etc.

class IModulationTarget {
public:
    // Modulation routing
    virtual void addModulationSource(const std::string& paramId,
                                    IModulationSource* source,
                                    float depth) = 0;
    virtual void removeModulationSource(const std::string& paramId,
                                       IModulationSource* source) = 0;

    // Modulation amount
    virtual void setModulationDepth(const std::string& paramId,
                                   IModulationSource* source,
                                   float depth) = 0;
    virtual float getModulationDepth(const std::string& paramId,
                                    IModulationSource* source) const = 0;

    // Query
    virtual bool isModulatable(const std::string& paramId) const = 0;
    virtual int getModulationSourceCount(const std::string& paramId) const = 0;

    virtual ~IModulationTarget() = default;
};

6. IUIController (GUI Communication)

Responsibility: Thread-safe communication between DSP and UI

class IUIController {
public:
    // UI lifecycle
    virtual void attachUI() = 0;
    virtual void detachUI() = 0;
    virtual bool hasUI() const = 0;

    // Parameter synchronization
    virtual void notifyParameterChanged(const std::string& id, float value) = 0;
    virtual void requestParameterUpdate(const std::string& id) = 0;

    // Visualization data
    virtual bool getMeterValues(float* levels, int numChannels) = 0;
    virtual bool getSpectrumData(float* magnitudes, int numBins) = 0;

    // Thread-safe messaging
    virtual void postMessage(const UIMessage& message) = 0;
    virtual bool pollMessage(UIMessage& outMessage) = 0;

    virtual ~IUIController() = default;
};

โœ… Acceptance Criteria

Compilation

  • All interface headers compile without errors
  • No external dependencies (except standard library)
  • Compatible with C++17
  • Compiles on Windows (MSVC), macOS (Clang), Linux (GCC)

Design

  • All methods are pure virtual (= 0)
  • Interfaces cannot be instantiated
  • Virtual destructors present
  • No implementation in headers (pure interface)

Documentation

  • Each interface has class-level doxygen comment
  • Each method has doxygen comment with:
  • Brief description
  • Parameter descriptions
  • Return value description
  • Thread-safety notes (if applicable)

Testability

  • Concrete test implementation compiles
  • Mock implementations can be created
  • Interfaces can be used polymorphically

๐Ÿงช Test Requirements

Unit Tests

// test_contracts.cpp

TEST_CASE("Interfaces are abstract", "[contracts][unit]") {
    REQUIRE(std::is_abstract<IPluginProcessor>::value);
    REQUIRE(std::is_abstract<IStateManager>::value);
    REQUIRE(std::is_abstract<IParameterHost>::value);
    REQUIRE(std::is_abstract<IAudioEngine>::value);
    REQUIRE(std::is_abstract<IModulationTarget>::value);
    REQUIRE(std::is_abstract<IUIController>::value);
}

TEST_CASE("Interfaces have virtual destructors", "[contracts][unit]") {
    REQUIRE(std::has_virtual_destructor<IPluginProcessor>::value);
    // ... etc for all interfaces
}

Integration Tests

TEST_CASE("Concrete implementation compiles", "[contracts][integration]") {
    class TestProcessor : public IPluginProcessor {
        void initialize(float sr, int bs) override {}
        void shutdown() override {}
        void reset() override {}
        void process(AudioBuffer& buffer) override {}
        void processReplacing(float** in, float** out, int n) override {}
        const char* getName() const override { return "Test"; }
        const char* getVersion() const override { return "1.0"; }
        const char* getVendor() const override { return "AudioLab"; }
        int getLatencySamples() const override { return 0; }
        bool supportsBypass() const override { return true; }
        void setBypass(bool b) override {}
    };

    TestProcessor processor;
    REQUIRE(processor.getName() == std::string("Test"));
}

๐Ÿ“š Documentation Structure

Each interface header should have:

/**
 * @file IPluginProcessor.hpp
 * @brief Core plugin lifecycle and processing interface
 *
 * This interface defines the fundamental contract that all AudioLab plugins
 * must implement. It provides lifecycle management (initialize/shutdown),
 * audio processing (process), and basic plugin identification.
 *
 * @see IStateManager for state persistence
 * @see IParameterHost for parameter management
 *
 * @ingroup Contracts
 */

namespace audiolab {

/**
 * @brief Core plugin processor interface
 *
 * All AudioLab plugins (L4 and L5) must implement this interface.
 * It provides the fundamental operations for plugin lifecycle and
 * audio processing.
 *
 * Thread Safety:
 * - initialize(), shutdown(), reset() called from main thread only
 * - process() called from real-time audio thread
 * - getName(), getVersion() etc. are thread-safe (const methods)
 */
class IPluginProcessor {
public:
    /**
     * @brief Initialize the plugin with audio configuration
     *
     * Called by the host before audio processing begins. Allocate
     * resources, prepare buffers, and configure internal state.
     *
     * @param sampleRate Sample rate in Hz (e.g., 48000.0)
     * @param maxBlockSize Maximum block size in samples
     *
     * @note This is called from the main thread, not the audio thread.
     * @note May be called multiple times (e.g., sample rate change).
     */
    virtual void initialize(float sampleRate, int maxBlockSize) = 0;

    // ... etc
};

} // namespace audiolab

๐Ÿ”— Dependencies

Internal Dependencies

  • 04_CORE/04_00_type_system โ†’ AudioBuffer, MemoryBlock, Parameter types
  • 04_CORE/04_01_core_interfaces โ†’ IParameterListener, IModulationSource

External Dependencies

  • C++ Standard Library only
  • No third-party dependencies

๐Ÿ“Š Success Metrics

  • โœ… All 6 interfaces defined
  • โœ… 100% doxygen documentation coverage
  • โœ… Compiles on all platforms (Windows/macOS/Linux)
  • โœ… All tests pass
  • โœ… Example implementations provided
  • โœ… Zero warnings at -Wall -Wextra

๐Ÿš€ Implementation Roadmap

Phase 1: Core Interfaces (Week 1)

  • IPluginProcessor
  • IAudioEngine
  • Tests for core interfaces

Phase 2: State & Parameters (Week 1)

  • IStateManager
  • IParameterHost
  • Tests for state/parameter interfaces

Phase 3: Advanced Features (Week 2)

  • IModulationTarget
  • IUIController
  • Integration tests

Phase 4: Documentation & Examples (Week 2)

  • Complete doxygen docs
  • Example implementations
  • Usage guide

Status: ๐Ÿ”ด Not Started Assigned: TBD Priority: ๐Ÿ”ฅ Critical (Foundation for all plugins)


Generated with AudioLab ๐ŸŽต