Quality Standards & Integration Layer¶
Purpose: The "glue code" that connects INFRA → CORE → DSP → PLUGINS
Overview¶
This directory contains the critical integration layer that makes all AudioLab components work together. Without this, each layer would be an isolated island.
What this provides: - Shared type system (single source of truth) - Interface contracts (explicit promises between layers) - Composition patterns (how to combine components) - Integration headers (convenient includes) - Declaration standards (coding consistency)
Directory Structure¶
03_10_00_shared_types/¶
Foundation types used across ALL layers
Files:
- audiolab_types.hpp - Sample, SampleRate, ParameterValue, etc.
- buffer_types.hpp - BufferConfig, BufferDescriptor, etc.
- processor_types.hpp - ProcessorState, ProcessorType, etc.
Why: ONE source of truth prevents type mismatches
03_10_01_interface_contracts/¶
Pure virtual interfaces defining layer contracts
Files:
- IAudioProcessor.hpp - THE fundamental processor contract
- IParameter.hpp - Parameter automation contract
- IEventListener.hpp - Event subscription contract
Why: Explicit contracts enable polymorphism and testing
03_10_02_composition_patterns/¶
How to compose AudioLab components
Files:
- dependency_injection.hpp - No globals pattern
Why: Show HOW to use the components together
03_10_03_integration_headers/¶
Convenient single-header includes
Files:
- audiolab.hpp - Master header (everything in one)
Why: Easy to get started (include one header, get everything)
03_10_04_declaration_standards/¶
Coding standards for consistency
Files:
- naming_conventions.md - How to name things
- header_organization.md - Include order, structure
- forward_declarations.md - When/how to forward declare
- api_export_macros.md - DLL export/import
Why: Consistency across entire codebase
Integration Layer Philosophy¶
1. Contract-First¶
Interfaces define WHAT, not HOW:
class IAudioProcessor {
virtual void process(/*...*/) = 0; // Contract
};
class MyEffect : public IAudioProcessor {
void process(/*...*/) override {
// HOW you implement it
}
};
2. Explicit Dependencies¶
No globals, no singletons:
class Compressor {
Compressor(
IEventDispatcher& events, // Injected!
BufferPool& buffers // Injected!
);
};
3. Type Safety¶
Strong typing prevents errors:
4. Zero Circular Dependencies¶
Enforced through interface design:
INFRA (types, interfaces)
↓
CORE (implements interfaces)
↓
DSP (uses core)
↓
PLUGINS (uses everything)
Quick Start Examples¶
Example 1: Minimal Processor¶
#include <audiolab/audiolab.hpp>
class SimpleGain : public audiolab::IAudioProcessor {
void process(
const audiolab::Sample* const* inputs,
audiolab::Sample** outputs,
audiolab::BlockSize num_samples
) override {
for (audiolab::ChannelIndex ch = 0; ch < num_channels_; ++ch) {
for (audiolab::BlockSize i = 0; i < num_samples; ++i) {
outputs[ch][i] = inputs[ch][i] * gain_;
}
}
}
// ... implement other IAudioProcessor methods
};
Example 2: Using Shared Types¶
audiolab::BufferConfig config{
.sample_rate = 48000,
.max_block_size = 512,
.num_channels = 2
};
if (!config.is_valid()) {
throw std::invalid_argument("Invalid config");
}
Example 3: Dependency Injection¶
class MyPlugin {
MyPlugin(
audiolab::IEventDispatcher& events,
audiolab::BufferPool& buffers
) : events_(events), buffers_(buffers) {
// Dependencies explicitly injected
}
private:
audiolab::IEventDispatcher& events_;
audiolab::BufferPool& buffers_;
};
Integration Test¶
See integration_test_example.cpp for a complete working example.
Compile test:
Expected: Clean compile with no errors or warnings
Layer Dependencies¶
┌─────────────────────────────────────┐
│ PLUGINS │
│ (Uses: CORE, DSP, INFRA) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ DSP │
│ (Uses: CORE, INFRA) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ CORE │
│ (Uses: INFRA) │
│ (Implements: IAudioProcessor, etc.) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ INFRA / Integration Layer │
│ (Defines: Types, Interfaces) │
│ (Depends on: Nothing!) │
└─────────────────────────────────────┘
Key: INFRA has NO dependencies. Everything depends on INFRA.
Build Integration¶
CMake¶
# Add include path
target_include_directories(my_plugin PRIVATE
${AUDIOLAB_ROOT}/2 - FOUNDATION/03_INFRA/03_10_quality_standards
)
# Now can use:
# #include <audiolab/audiolab.hpp>
Success Criteria¶
✅ Type System: Single source of truth for all types ✅ Interfaces: Clear contracts between layers ✅ Composition: Patterns for combining components ✅ Integration: Single-header convenience ✅ Standards: Consistent coding conventions ✅ Zero Circular Dependencies: Verified ✅ Compiles: integration_test_example.cpp builds cleanly
Additional Resources¶
- Previous Quality Automation: 00_PREVIOUS_QUALITY_AUTOMATION_README.md
- C++ Core Guidelines - Interfaces
- PIMPL Idiom
- Dependency Injection
Remember: This is the foundation. Get the integration layer right, and everything else follows.