Skip to content

Delay Plugin Example - Using AudioLab CORE

Ejemplo completo de cómo construir un plugin de audio usando la biblioteca 04_CORE


🎯 Qué Demuestra Este Ejemplo

Este es un delay plugin funcional que muestra cómo usar CORE para crear procesadores de audio profesionales:

Componentes de CORE Usados

Componente De Dónde Viene Para Qué Se Usa
AudioProcessor 04_10_audio_processor Clase base con lifecycle management
Parameter<T> 04_08_parameter_system Parámetros con smoothing automático
RingBuffer<T> 04_03_memory_management Delay line con interpolación
AudioBuffer<T> 04_05_buffer_management Buffer multi-canal RT-safe
ProcessorConfig 04_10_audio_processor Configuración (sample rate, buffer size)

🏗️ Arquitectura del Ejemplo

delay_example/
├── delay_plugin.hpp       # Plugin class (hereda de AudioProcessor)
├── main.cpp               # Programa de prueba standalone
├── CMakeLists.txt         # Build config (muestra cómo enlazar CORE)
└── README.md              # Este archivo

Flujo de Datos

┌─────────────────────────────────────────┐
│  DelayPlugin (tu código - 200 líneas)  │
│  ┌──────────────────────────────────┐  │
│  │ on_process() {                   │  │
│  │   input → delayLine → output     │  │
│  │ }                                │  │
│  └──────────────────────────────────┘  │
└─────────────────────────────────────────┘
                  │ hereda de
┌─────────────────────────────────────────┐
│  04_CORE (biblioteca compartida)        │
│  ┌──────────────────────────────────┐  │
│  │ AudioProcessor                   │  │
│  │   - prepareToPlay()              │  │
│  │   - processBlock()               │  │
│  │   - releaseResources()           │  │
│  ├──────────────────────────────────┤  │
│  │ RingBuffer<float>                │  │
│  │   - write(sample)                │  │
│  │   - readInterpolated(delay)      │  │
│  ├──────────────────────────────────┤  │
│  │ Parameter<float>                 │  │
│  │   - get() / set()                │  │
│  │   - Automatic smoothing          │  │
│  └──────────────────────────────────┘  │
└─────────────────────────────────────────┘

🚀 Cómo Compilar y Ejecutar

Prerequisitos

# Asegurar que CORE está compilado
cd C:/AudioDev/audio-lab/build
cmake --build . --target audiolab_core

Compilar el Ejemplo

# Opción 1: Desde raíz del proyecto (recomendado)
cd C:/AudioDev/audio-lab/build
cmake ..
cmake --build . --target delay_example

# Opción 2: Compilar solo el ejemplo
cd C:/AudioDev/audio-lab/05_MODULES/05_99_EXAMPLES/delay_example
mkdir build && cd build
cmake ..
cmake --build .

Ejecutar

# Desde build directory
./delay_example

# Output esperado:
# ====================================
# AudioLab Delay Plugin Example
# ====================================
# Creating delay plugin...
#   Name: Simple Delay
#   Vendor: AudioLab Examples
#   ...

📖 Código Explicado

1. Herencia de AudioProcessor

class DelayPlugin : public core::AudioProcessor {
public:
    DelayPlugin()
        : AudioProcessor(core::ProcessorInfo{
            "Simple Delay",
            "AudioLab Examples",
            "com.audiolab.delay",
            "1.0.0"
          })
    {}
    // ...
};

¿Qué obtenemos gratis? - ✅ Lifecycle management (prepare, activate, process, deactivate, release) - ✅ State management (Uninitialized → Initialized → Active → Suspended) - ✅ RT-safety enforcement (no allocations en processBlock) - ✅ Bypass automático cuando inactive - ✅ Thread-safety para config

2. Uso de RingBuffer para Delay Line

private:
    core::containers::RingBuffer<float> delayLine_;

protected:
    void on_prepare(const core::ProcessorConfig& config) override {
        // Allocate delay buffer (NOT RT-safe, OK here)
        size_t maxSamples = config.sample_rate * 2.0;  // 2 seconds
        delayLine_.resize(maxSamples);
    }

    void on_process(...) noexcept override {
        // RT-safe operations
        float delayed = delayLine_.readInterpolated(delaySamples);
        delayLine_.write(feedbackSample);
    }
};

Beneficios del RingBuffer de CORE: - ✅ Power-of-2 sizing automático (eficiente modulo) - ✅ Interpolación linear/cubic incluida - ✅ Zero allocations después de resize() - ✅ API simple y clara

3. Sistema de Parámetros

private:
    core::Parameter<float> delayTimeMs_;
    core::Parameter<float> feedback_;
    core::Parameter<float> mix_;

public:
    DelayPlugin()
        : delayTimeMs_("Delay Time", 0.0f, 2000.0f, 500.0f)  // min, max, default
        , feedback_("Feedback", 0.0f, 0.95f, 0.3f)
        , mix_("Mix", 0.0f, 1.0f, 0.5f)
    {}

    void on_process(...) noexcept override {
        float delay = delayTimeMs_.get();  // RT-safe read
        // ...
    }

Beneficios del Parameter de CORE: - ✅ Range validation automática - ✅ Smoothing automático (evita clicks) - ✅ Thread-safe (GUI puede escribir, Audio lee) - ✅ Default/min/max built-in


🧪 Testing

El ejemplo incluye un main.cpp que:

  1. Crea el plugin
  2. Prepara con config (48kHz, 512 samples, stereo)
  3. Configura parámetros (250ms delay, 50% feedback, 50% mix)
  4. Activa el plugin
  5. Procesa 1 segundo de audio (440Hz sine wave)
  6. Analiza la salida (peak values)
  7. Limpia recursos

Salida Esperada

====================================
AudioLab Delay Plugin Example
====================================

Creating delay plugin...
  Name: Simple Delay
  Vendor: AudioLab Examples
  ID: com.audiolab.delay
  Version: 1.0.0

Preparing to play...
  Sample Rate: 48000 Hz
  Buffer Size: 512 samples
  Channels: 2

Setting parameters...
  Delay Time: 250 ms
  Feedback: 50%
  Mix: 50%

Activating plugin...
  Status: Active

Processing audio...
  Processed 94 blocks
  Total samples: 48000

Output analysis:
  Peak Left: 0.707 (-3.01 dB)
  Peak Right: 0.707 (-3.01 dB)

Cleaning up...
  Status: Inactive

====================================
Example completed successfully!
====================================

💡 Lecciones Clave

1. CORE hace el trabajo pesado

Sin CORE, tendrías que implementar: - Lifecycle state machine (100+ líneas) - RT-safe ring buffer (200+ líneas) - Parameter smoothing (50+ líneas) - Thread-safe config management (50+ líneas)

Total: ~400 líneas de código complejo

Con CORE: ~150 líneas de lógica DSP pura

2. RT-Safety por diseño

// ❌ WRONG: Esto NO compilaría (on_process es noexcept)
void on_process(...) noexcept override {
    std::vector<float> temp(1024);  // ❌ Allocation!
}

// ✅ CORRECT: Pre-allocated en prepare()
void on_prepare(...) override {
    temp_.resize(1024);  // ✅ Allocation OK here
}

void on_process(...) noexcept override {
    // temp_ already allocated ✅
}

3. Reutilización masiva

Este mismo patrón se aplica a: - Reverb (usa RingBuffer para comb filters) - Compressor (usa Parameter para threshold/ratio) - EQ (usa AudioProcessor base) - Synth (usa PoolAllocator de CORE para voices)


🔗 Ver También


📊 Métricas de Este Ejemplo

Métrica Valor
Líneas de código ~150 (delay logic)
Líneas de CORE usadas ~2000 (heredadas)
Ratio de reutilización 13:1
Tiempo de desarrollo ~2 horas (vs 2 semanas sin CORE)

¿Siguiente paso? Crea tu propio plugin modificando este ejemplo: - Cambia el algoritmo (reverb, chorus, flanger) - Añade más parámetros - Implementa modulación - Integra con JUCE/VST3

CORE hace todo lo aburrido. Tú haces la música. 🎵