Skip to content

🎯 IMPLEMENTATION PLAN: DSP Integration Layer (08_02)

📍 UBICACIÓN

Carpeta de trabajo: 4 - INTEGRATION/08_PLUGINS/08_02_dsp_integration_layer/

🤖 INSTRUCCIONES PARA LA IA

Prompt Inicial

Cuando comiences a trabajar en esta carpeta, di:

"Estoy trabajando en la carpeta 08_02_dsp_integration_layer. Voy a implementar el sistema de integración DSP para plugins. Déjame leer el IMPLEMENTATION_PLAN.md y organizarme en fases."

Workflow Automático

  1. Lee este archivo completo antes de empezar
  2. Organízate en las 5 FASES definidas abajo
  3. Cada fase = 1 prompt (aprox. 3-4 horas de trabajo)
  4. Al finalizar cada fase: Actualiza el checklist y haz commit
  5. Entre fases: Espera confirmación del usuario antes de continuar

📊 DIVISIÓN EN FASES (5 prompts totales)

FASE 1: Engine Instantiation (Prompt 1)

Duración estimada: 3-4 horas Objetivo: Sistema de creación y gestión de engines L3

Micro-pipeline: 1. Crear subdirectorio 08_02_00_engine_instantiation/ 2. Implementar EngineFactory.hpp/.cpp - Factory pattern para engines 3. Implementar EnginePool.hpp/.cpp - Pool de engines reutilizables 4. Implementar EngineLifecycleManager.hpp/.cpp - Gestión de ciclo de vida 5. Implementar EngineDescriptor.hpp - Metadata de engines 6. Crear tests de instanciación 7. Crear CMakeLists.txt y README.md 8. Verificar compilación

Checklist: - [ ] EngineFactory implementado con registro dinámico - [ ] EnginePool con gestión de memoria eficiente - [ ] EngineLifecycleManager con state machine - [ ] EngineDescriptor con metadata completa - [ ] Tests de creación/destrucción funcionan - [ ] No hay memory leaks - [ ] CMakeLists.txt funcional


FASE 2: Signal Routing (Prompt 2)

Duración estimada: 4-5 horas Objetivo: Sistema de routing de señales audio con optimizaciones

Micro-pipeline: 1. Crear subdirectorio 08_02_01_signal_routing/ 2. Implementar AudioGraph.hpp/.cpp - Grafo de routing 3. Implementar BufferManager.hpp/.cpp - Gestión automática de buffers 4. Implementar RoutingMatrix.hpp/.cpp - Matriz de conexiones 5. Implementar ZeroCopyOptimizer.hpp/.cpp - Optimizaciones zero-copy 6. Implementar ChannelMapper.hpp/.cpp - Mapeo de canales 7. Crear tests de routing con diferentes topologías 8. Crear benchmarks de performance 9. Verificar real-time safety

Checklist: - [ ] AudioGraph construye grafo correctamente - [ ] BufferManager evita allocaciones en RT - [ ] RoutingMatrix optimiza conexiones - [ ] ZeroCopyOptimizer detecta oportunidades - [ ] ChannelMapper maneja mono/stereo/multi - [ ] Tests con grafos complejos pasan - [ ] Benchmarks muestran overhead < 1% - [ ] RT-safe verificado


FASE 3: Modulation System (Prompt 3)

Duración estimada: 4-5 horas Objetivo: Sistema de modulación sample-accurate

Micro-pipeline: 1. Crear subdirectorio 08_02_02_modulation_system/ 2. Implementar ModulationMatrix.hpp/.cpp - Matriz de routings 3. Implementar LFO.hpp/.cpp - Low Frequency Oscillator 4. Implementar Envelope.hpp/.cpp - ADSR Envelope 5. Implementar ModulationSource.hpp - Interface para sources 6. Implementar ModulationProcessor.hpp/.cpp - Procesador central 7. Implementar SampleAccurateInterpolator.hpp - Interpolación suave 8. Crear tests de modulación 9. Crear ejemplo de filtro modulado

Checklist: - [ ] ModulationMatrix enruta correctamente - [ ] LFO genera formas de onda (sine, saw, square, etc.) - [ ] Envelope implementa ADSR correctamente - [ ] ModulationSource interface clara - [ ] ModulationProcessor sample-accurate - [ ] Interpolación evita clicks - [ ] Tests de modulación pasan - [ ] Ejemplo suena bien


FASE 4: Optimization (Prompt 4)

Duración estimada: 3-4 horas Objetivo: Optimizaciones DSP avanzadas

Micro-pipeline: 1. Crear subdirectorio 08_02_03_optimization/ 2. Implementar SIMDHelpers.hpp - Helpers para SSE/AVX 3. Implementar VectorizationHints.hpp - Hints para compiler 4. Implementar CacheOptimizer.hpp/.cpp - Layouts cache-friendly 5. Implementar BranchPredictor.hpp - Optimización de branches 6. Implementar AlignmentHelpers.hpp - Alineación de memoria 7. Crear benchmarks comparativos 8. Documentar optimizaciones aplicables 9. Crear guía de uso

Checklist: - [ ] SIMDHelpers para operaciones comunes - [ ] VectorizationHints documentados - [ ] CacheOptimizer mejora layouts - [ ] BranchPredictor reduce mispredictions - [ ] AlignmentHelpers para SIMD - [ ] Benchmarks muestran mejoras > 2x - [ ] Guía de optimización completa - [ ] Compatible con ARM/x86


FASE 5: Performance Tracking + Tests (Prompt 5)

Duración estimada: 3-4 horas Objetivo: Sistema de tracking y tests completos

Micro-pipeline: 1. Crear subdirectorio 08_02_04_performance_tracking/ 2. Implementar CPUMonitor.hpp/.cpp - Monitoreo de CPU 3. Implementar RTSafetyValidator.hpp/.cpp - Validador RT-safety 4. Implementar PerformanceBudget.hpp/.cpp - Presupuestos de CPU 5. Implementar ProfileScope.hpp - Profiling por scope 6. Crear tests de integración completos 7. Crear benchmarks end-to-end 8. Escribir documentación completa 9. Commit final

Checklist: - [ ] CPUMonitor mide uso real - [ ] RTSafetyValidator detecta violaciones - [ ] PerformanceBudget rastrea presupuestos - [ ] ProfileScope no afecta performance - [ ] Tests de integración pasan - [ ] Benchmarks documentados - [ ] Documentación completa (4 docs) - [ ] Commit realizado


📝 TAREAS DETALLADAS

TAREA 1.1: EngineFactory

Archivo: 08_02_00_engine_instantiation/EngineFactory.hpp

#pragma once

#include "../../08_00_plugin_infrastructure/08_00_00_contracts/IAudioEngine.hpp"
#include <memory>
#include <functional>
#include <unordered_map>
#include <string>

namespace audiolab {
namespace plugins {
namespace dsp {

using EngineCreator = std::function<std::unique_ptr<IAudioEngine>(const std::string& config)>;

/**
 * @brief Factory for creating DSP engines
 *
 * Supports dynamic registration of engine types at runtime.
 * Thread-safe for concurrent engine creation.
 */
class EngineFactory {
public:
    static EngineFactory& getInstance();

    // Registration
    void registerEngine(const std::string& engineType, EngineCreator creator);
    bool isRegistered(const std::string& engineType) const;

    // Creation
    std::unique_ptr<IAudioEngine> createEngine(
        const std::string& engineType,
        const std::string& config = "");

    // Query
    std::vector<std::string> getRegisteredEngines() const;

private:
    EngineFactory() = default;
    std::unordered_map<std::string, EngineCreator> m_creators;
    mutable std::mutex m_mutex;
};

// Registration macro
#define REGISTER_ENGINE(TYPE, CLASS) \
    namespace { \
        struct CLASS##_Registrar { \
            CLASS##_Registrar() { \
                EngineFactory::getInstance().registerEngine(TYPE, \
                    [](const std::string& cfg) { \
                        return std::make_unique<CLASS>(cfg); \
                    }); \
            } \
        }; \
        static CLASS##_Registrar g_##CLASS##_registrar; \
    }

} // namespace dsp
} // namespace plugins
} // namespace audiolab

Implementación en .cpp: - Constructor singleton con lazy initialization - registerEngine con lock - createEngine con validación - getRegisteredEngines thread-safe

Tiempo: 1 hora


TAREA 1.2: EnginePool

Archivo: 08_02_00_engine_instantiation/EnginePool.hpp

#pragma once

#include "EngineFactory.hpp"
#include <queue>
#include <mutex>
#include <condition_variable>

namespace audiolab {
namespace plugins {
namespace dsp {

/**
 * @brief Pool de engines reutilizables
 *
 * Reduce allocaciones creando pool de engines pre-inicializados.
 * Útil para plugins L5 con slots dinámicos.
 */
class EnginePool {
public:
    EnginePool(const std::string& engineType, size_t initialSize = 4);
    ~EnginePool();

    // Acquire/Release
    std::unique_ptr<IAudioEngine> acquire();
    void release(std::unique_ptr<IAudioEngine> engine);

    // Configuration
    void setMaxSize(size_t maxSize);
    void preallocate(size_t count);

    // Stats
    size_t getActiveCount() const;
    size_t getPoolSize() const;

private:
    std::string m_engineType;
    size_t m_maxSize;

    std::queue<std::unique_ptr<IAudioEngine>> m_pool;
    std::atomic<size_t> m_activeCount{0};

    mutable std::mutex m_mutex;
    std::condition_variable m_cv;

    void createEngine();
};

} // namespace dsp
} // namespace plugins
} // namespace audiolab

Características: - Thread-safe acquire/release - Pre-allocation para evitar RT allocations - Límite máximo configurable - Stats para debugging

Tiempo: 1.5 horas


TAREA 1.3: EngineLifecycleManager

Archivo: 08_02_00_engine_instantiation/EngineLifecycleManager.hpp

#pragma once

#include "../../08_00_plugin_infrastructure/08_00_00_contracts/IAudioEngine.hpp"
#include <memory>

namespace audiolab {
namespace plugins {
namespace dsp {

/**
 * @brief Gestiona el ciclo de vida completo de un engine
 *
 * State machine: Created → Prepared → Active → Suspended → Destroyed
 */
class EngineLifecycleManager {
public:
    enum class State {
        Created,      // Instanciado pero no preparado
        Prepared,     // prepareToPlay() llamado
        Active,       // activate() llamado, procesando
        Suspended,    // deactivate() llamado, pausado
        Destroyed     // Destruido
    };

    explicit EngineLifecycleManager(std::unique_ptr<IAudioEngine> engine);
    ~EngineLifecycleManager();

    // State transitions
    bool prepare(double sampleRate, uint32_t blockSize, uint32_t numChannels);
    bool activate();
    bool suspend();
    bool destroy();

    // Queries
    State getState() const { return m_state; }
    bool isActive() const { return m_state == State::Active; }
    IAudioEngine* getEngine() { return m_engine.get(); }

    // Stats
    uint64_t getProcessedBlocks() const { return m_processedBlocks; }
    double getUptimeSeconds() const;

private:
    std::unique_ptr<IAudioEngine> m_engine;
    State m_state = State::Created;
    std::atomic<uint64_t> m_processedBlocks{0};
    std::chrono::steady_clock::time_point m_activateTime;

    bool validateTransition(State from, State to) const;
};

} // namespace dsp
} // namespace plugins
} // namespace audiolab

Tiempo: 1 hora


TAREA 2.1: AudioGraph

Archivo: 08_02_01_signal_routing/AudioGraph.hpp

#pragma once

#include <vector>
#include <unordered_map>
#include <string>

namespace audiolab {
namespace plugins {
namespace dsp {

/**
 * @brief Grafo de routing de señales audio
 *
 * Representa conexiones entre engines como un DAG.
 * Optimiza orden de procesamiento mediante topological sort.
 */
class AudioGraph {
public:
    struct Node {
        std::string id;
        IAudioEngine* engine;
        std::vector<std::string> inputs;   // IDs de nodos de entrada
        std::vector<std::string> outputs;  // IDs de nodos de salida
    };

    struct Connection {
        std::string sourceNode;
        uint32_t sourcePort;
        std::string destNode;
        uint32_t destPort;
        float gain = 1.0f;
    };

    // Construction
    void addNode(const std::string& id, IAudioEngine* engine);
    void removeNode(const std::string& id);

    void addConnection(const Connection& conn);
    void removeConnection(const std::string& sourceNode, const std::string& destNode);

    // Validation
    bool validate() const;
    bool hasCycles() const;

    // Processing order
    std::vector<std::string> getProcessingOrder() const;
    void rebuild();  // Recalcula orden óptimo

    // Queries
    const Node* getNode(const std::string& id) const;
    std::vector<Connection> getConnections(const std::string& nodeId) const;

private:
    std::unordered_map<std::string, Node> m_nodes;
    std::vector<Connection> m_connections;
    std::vector<std::string> m_processingOrder;

    bool topologicalSort(std::vector<std::string>& order) const;
    bool dfsHasCycle(const std::string& nodeId,
                    std::unordered_set<std::string>& visited,
                    std::unordered_set<std::string>& recStack) const;
};

} // namespace dsp
} // namespace plugins
} // namespace audiolab

Tiempo: 2 horas


TAREA 2.2: BufferManager

Archivo: 08_02_01_signal_routing/BufferManager.hpp

#pragma once

#include "../../../../2 - FOUNDATION/04_CORE/04_05_buffer_management/00_buffer_types/AudioBuffer.hpp"
#include <vector>

namespace audiolab {
namespace plugins {
namespace dsp {

/**
 * @brief Gestiona buffers de audio automáticamente
 *
 * Pre-alloca buffers para evitar allocaciones en real-time.
 * Reusa buffers cuando es posible (zero-copy).
 */
class BufferManager {
public:
    BufferManager(uint32_t maxChannels, uint32_t maxBlockSize);
    ~BufferManager();

    // Adquisición de buffers
    core::AudioBuffer<float>& acquire(uint32_t numChannels);
    void release(core::AudioBuffer<float>& buffer);

    // Zero-copy optimization
    bool canReuse(const core::AudioBuffer<float>& buffer) const;
    void markReusable(core::AudioBuffer<float>& buffer);

    // Stats
    size_t getTotalBuffers() const { return m_buffers.size(); }
    size_t getActiveBuffers() const { return m_activeCount; }

private:
    struct BufferSlot {
        core::AudioBuffer<float> buffer;
        bool inUse = false;
        uint64_t lastUsedFrame = 0;
    };

    uint32_t m_maxChannels;
    uint32_t m_maxBlockSize;
    std::vector<BufferSlot> m_buffers;
    std::atomic<size_t> m_activeCount{0};
    std::atomic<uint64_t> m_frameCounter{0};

    size_t findAvailableSlot(uint32_t numChannels);
};

} // namespace dsp
} // namespace plugins
} // namespace audiolab

Tiempo: 1.5 horas


TAREA 3.1: ModulationMatrix

Archivo: 08_02_02_modulation_system/ModulationMatrix.hpp

#pragma once

#include "../../08_00_plugin_infrastructure/08_00_00_contracts/IModulationTarget.hpp"
#include <vector>
#include <unordered_map>

namespace audiolab {
namespace plugins {
namespace dsp {

/**
 * @brief Matriz de modulación N sources → M targets
 *
 * Enruta múltiples fuentes de modulación (LFOs, envelopes)
 * a múltiples parámetros target con depth control.
 */
class ModulationMatrix {
public:
    struct Routing {
        std::string sourceId;
        std::string targetParamId;
        float depth = 1.0f;
        bool bipolar = false;  // -1..+1 vs 0..1
    };

    // Routing management
    void addRouting(const Routing& routing);
    void removeRouting(const std::string& sourceId, const std::string& targetParamId);
    void setDepth(const std::string& sourceId, const std::string& targetParamId, float depth);

    // Processing
    void process(uint32_t numSamples);

    // Registration
    void registerSource(const std::string& id, IModulationSource* source);
    void registerTarget(IModulationTarget* target);

    // Queries
    std::vector<Routing> getRoutings() const;
    float getCurrentValue(const std::string& targetParamId) const;

private:
    std::unordered_map<std::string, IModulationSource*> m_sources;
    std::vector<IModulationTarget*> m_targets;
    std::vector<Routing> m_routings;

    // Cache para optimization
    std::unordered_map<std::string, float> m_currentValues;
};

} // namespace dsp
} // namespace plugins
} // namespace audiolab

Tiempo: 2 horas


TAREA 3.2: LFO Implementation

Archivo: 08_02_02_modulation_system/LFO.hpp

#pragma once

#include "../../08_00_plugin_infrastructure/08_00_00_contracts/IModulationTarget.hpp"

namespace audiolab {
namespace plugins {
namespace dsp {

/**
 * @brief Low Frequency Oscillator
 *
 * Genera formas de onda para modulación:
 * - Sine, Triangle, Saw, Square, Sample&Hold
 */
class LFO : public IModulationSource {
public:
    enum class Waveform {
        Sine,
        Triangle,
        Saw,
        Square,
        SampleHold,
        Noise
    };

    LFO();

    // IModulationSource
    float getSample(int sampleIndex) override;
    void advance(int numSamples) override;
    void reset() override;

    // Configuration
    void setWaveform(Waveform waveform);
    void setFrequency(float hz);
    void setPhase(float phase01);  // 0..1

    // Tempo sync
    void setTempoSync(bool enable, float bpm, float divisions);

private:
    Waveform m_waveform = Waveform::Sine;
    double m_phase = 0.0;
    double m_phaseIncrement = 0.0;
    float m_sampleRate = 44100.0f;
    float m_frequency = 1.0f;

    // Sample & Hold
    float m_sampleHoldValue = 0.0f;
    int m_sampleHoldCounter = 0;

    float generateSample();
    float sine(double phase);
    float triangle(double phase);
    float saw(double phase);
    float square(double phase);
};

} // namespace dsp
} // namespace plugins
} // namespace audiolab

Tiempo: 1.5 horas


TAREA 4.1: SIMD Helpers

Archivo: 08_02_03_optimization/SIMDHelpers.hpp

#pragma once

#include <immintrin.h>  // SSE, AVX
#include <cstdint>

namespace audiolab {
namespace plugins {
namespace dsp {
namespace simd {

/**
 * @brief SIMD helpers para operaciones DSP comunes
 *
 * Abstrae diferencias entre SSE/AVX/NEON.
 * Auto-detects mejor instruction set disponible.
 */

// ═══════════════════════════════════════════════════════════════
// Vector Operations
// ═══════════════════════════════════════════════════════════════

// Add: dst[i] = a[i] + b[i]
void vectorAdd(float* dst, const float* a, const float* b, size_t count);

// Multiply: dst[i] = a[i] * b[i]
void vectorMultiply(float* dst, const float* a, const float* b, size_t count);

// Multiply-Add: dst[i] += a[i] * b[i]
void vectorMultiplyAdd(float* dst, const float* a, const float* b, size_t count);

// Gain: dst[i] = src[i] * gain
void vectorGain(float* dst, const float* src, float gain, size_t count);

// ═══════════════════════════════════════════════════════════════
// Utility
// ═══════════════════════════════════════════════════════════════

// Check if pointer is aligned for SIMD
bool isAligned(const void* ptr, size_t alignment = 16);

// Get optimal alignment for current CPU
size_t getOptimalAlignment();

// Check SIMD support
struct SIMDSupport {
    bool sse = false;
    bool sse2 = false;
    bool sse3 = false;
    bool sse41 = false;
    bool sse42 = false;
    bool avx = false;
    bool avx2 = false;
    bool fma = false;
    bool avx512 = false;
};

SIMDSupport detectSIMDSupport();

// ═══════════════════════════════════════════════════════════════
// Implementation Macros
// ═══════════════════════════════════════════════════════════════

#if defined(__AVX2__)
    #define AUDIOLAB_SIMD_AVX2
    #define AUDIOLAB_SIMD_WIDTH 8
#elif defined(__AVX__)
    #define AUDIOLAB_SIMD_AVX
    #define AUDIOLAB_SIMD_WIDTH 8
#elif defined(__SSE4_1__)
    #define AUDIOLAB_SIMD_SSE4
    #define AUDIOLAB_SIMD_WIDTH 4
#elif defined(__ARM_NEON)
    #define AUDIOLAB_SIMD_NEON
    #define AUDIOLAB_SIMD_WIDTH 4
#else
    #define AUDIOLAB_SIMD_SCALAR
    #define AUDIOLAB_SIMD_WIDTH 1
#endif

} // namespace simd
} // namespace dsp
} // namespace plugins
} // namespace audiolab

Implementación: Versiones optimizadas para cada instruction set

Tiempo: 2 horas


TAREA 5.1: CPU Monitor

Archivo: 08_02_04_performance_tracking/CPUMonitor.hpp

#pragma once

#include <chrono>
#include <atomic>
#include <array>

namespace audiolab {
namespace plugins {
namespace dsp {

/**
 * @brief Monitorea uso de CPU en real-time
 *
 * Mide tiempo de procesamiento vs tiempo disponible.
 * No afecta performance (usa atomics lock-free).
 */
class CPUMonitor {
public:
    CPUMonitor();

    // Measurement
    void startBlock(uint32_t blockSize, double sampleRate);
    void endBlock();

    // Stats
    float getCurrentCPU() const;      // Current block %
    float getAverageCPU() const;      // Moving average %
    float getPeakCPU() const;         // Peak %
    bool isOverloaded() const;        // CPU > 90%

    // Configuration
    void setWarningThreshold(float percent);  // Default: 80%
    void reset();

private:
    using Clock = std::chrono::high_resolution_clock;
    using TimePoint = Clock::time_point;

    TimePoint m_startTime;
    std::atomic<uint64_t> m_totalCycles{0};
    std::atomic<uint64_t> m_availableCycles{0};

    // Moving average (últimos 100 blocks)
    std::array<float, 100> m_history;
    std::atomic<size_t> m_historyIndex{0};

    float m_peakCPU = 0.0f;
    float m_warningThreshold = 80.0f;
};

// RAII helper para medir scopes
class CPUScope {
public:
    CPUScope(CPUMonitor& monitor, uint32_t blockSize, double sampleRate)
        : m_monitor(monitor) {
        m_monitor.startBlock(blockSize, sampleRate);
    }

    ~CPUScope() {
        m_monitor.endBlock();
    }

private:
    CPUMonitor& m_monitor;
};

} // namespace dsp
} // namespace plugins
} // namespace audiolab

Tiempo: 1.5 horas


🎯 Criterios de Aceptación Final

Funcionalidad

  • Engines se crean/destruyen correctamente
  • Pool reutiliza engines eficientemente
  • AudioGraph enruta señales correctamente
  • Modulación es sample-accurate
  • Optimizaciones SIMD funcionan
  • CPU monitor preciso (±1%)

Performance

  • Overhead routing < 1% CPU
  • Zero allocaciones en RT thread
  • SIMD mejora > 2x vs scalar
  • Pool reduce latencia startup

Tests

  • Cobertura > 85%
  • Tests RT-safety pasan
  • Benchmarks documentados
  • No memory leaks

📦 Dependencias

Depende de: - ✅ 08_00 (Plugin Infrastructure) - IAudioEngine, IModulationTarget - ✅ 04_CORE (Buffer Management) - AudioBuffer

Bloqueante para: - 08_10 (L4 Architecture) - Usa engine instantiation - 08_11 (L5 Architecture) - Usa signal routing


💾 Commits Recomendados

# Fase 1
git commit -m "feat(08_02): add engine instantiation system

- Implement EngineFactory with dynamic registration
- Add EnginePool for resource reuse
- Add EngineLifecycleManager with state machine"

# Fase 2
git commit -m "feat(08_02): add signal routing system

- Implement AudioGraph with cycle detection
- Add BufferManager with zero-copy optimization
- Add RoutingMatrix for flexible connections"

# Fase 3
git commit -m "feat(08_02): add modulation system

- Implement ModulationMatrix for routing
- Add LFO with multiple waveforms
- Add Envelope (ADSR)
- Sample-accurate interpolation"

# Fase 4
git commit -m "feat(08_02): add DSP optimizations

- Add SIMD helpers (SSE/AVX/NEON)
- Add cache optimization utilities
- Add vectorization hints
- Benchmarks show 2-3x speedup"

# Fase 5
git commit -m "feat(08_02): add performance tracking and tests

- Add CPUMonitor for real-time measurement
- Add RT-safety validator
- Add comprehensive tests (85%+ coverage)
- Complete documentation"

Estado: 📝 LISTO PARA IMPLEMENTACIÓN Última actualización: 2025-10-08 Estimación total: 17-22 horas (5 fases de 3-4.5h cada una)