Interface Contracts¶
Purpose: Explicit contracts defining behavior across layer boundaries
Overview¶
Interfaces define WHAT components must do, not HOW they do it. These are pure virtual classes (abstract interfaces) that define contracts between AudioLab layers.
Core Interfaces¶
IAudioProcessor.hpp¶
THE fundamental contract - all audio processors implement this
Lifecycle: Uninitialized → Prepared → Active → Processing
Thread Safety: Explicit (GUI thread vs RT thread)
Key Methods:
- prepare() - Configure for processing
- process() - RT-safe audio processing
- get_state() - Query current state
Use: Every audio effect, synth, analyzer
IParameter.hpp¶
Parameter automation contract
All parameters normalized [0.0, 1.0] Thread-Safe: Can be called from any thread Use: Automatable controls (gain, frequency, etc.)
IEventListener.hpp¶
Event subscription contract
Template-based: Type-safe event handling Use: Responding to parameter changes, MIDI events, etc.
Design Principles¶
1. Explicit Contracts¶
Interfaces make promises explicit:
class IAudioProcessor {
// Promise: I will process audio in real-time
virtual void process(/*...*/) = 0;
};
2. Dependency Inversion¶
High-level modules depend on interfaces, not concrete implementations:
class PluginHost {
void add_processor(IAudioProcessor& processor); // Interface, not concrete class
};
3. Testability¶
Interfaces enable mocking:
Usage Patterns¶
Implementing an Interface¶
class MyEffect : public audiolab::IAudioProcessor {
public:
void prepare(const audiolab::BufferConfig& config) override {
// Implementation
}
void process(const audiolab::Sample* const* inputs,
audiolab::Sample** outputs,
audiolab::BlockSize num_samples) override {
// RT-safe implementation
}
// ... implement all pure virtual methods
};
Using an Interface¶
void use_processor(audiolab::IAudioProcessor& processor) {
audiolab::BufferConfig config{48000, 512, 2};
processor.prepare(config);
processor.activate();
// Process audio...
}
Best Practices¶
✅ Do¶
- Keep interfaces focused (Single Responsibility)
- Use pure virtual functions (
= 0) - Document thread-safety requirements
- Use
noexceptwhere appropriate - Make interfaces non-copyable
❌ Don't¶
- Add data members to interfaces
- Use interfaces as namespaces
- Make interfaces too large (Interface Segregation)
- Forget to make destructor virtual
Future Interfaces¶
As AudioLab grows:
- IMIDIProcessor - MIDI processing
- IModulator - Modulation sources
- IVisualization - Visual components
- IPresetManager - Preset handling
Remember: Interfaces are contracts. Breaking them breaks everything that depends on them.