Skip to content

🎯 IMPLEMENTATION PLAN: Parameter Integration (08_03)

📍 UBICACIÓN

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

🤖 INSTRUCCIONES PARA LA IA

Prompt Inicial

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

Workflow Automático

  1. Lee este archivo completo
  2. Organízate en las 5 FASES
  3. Cada fase = 1 prompt (3-4h)
  4. Actualiza checklist al finalizar
  5. Espera confirmación entre fases

📊 DIVISIÓN EN FASES (5 prompts totales)

FASE 1: Aggregation System (Prompt 1)

Duración: 3-4h Objetivo: Sistema de agregación y organización jerárquica

Micro-pipeline: 1. Crear 08_03_00_aggregation_system/ 2. Implementar ParameterGroup.hpp/.cpp 3. Implementar ParameterTree.hpp/.cpp 4. Implementar ParameterDiscovery.hpp/.cpp 5. Implementar ParameterSerializer.hpp/.cpp 6. Tests de agregación 7. CMakeLists.txt + README

Checklist: - [ ] ParameterGroup con jerarquía - [ ] ParameterTree con búsqueda eficiente - [ ] ParameterDiscovery automático - [ ] ParameterSerializer JSON/Binary - [ ] Tests pasan - [ ] Compila sin errores


FASE 2: L5 Hierarchy (Prompt 2)

Duración: 3-4h Objetivo: Sistema jerárquico para suites L5

Micro-pipeline: 1. Crear 08_03_01_l5_hierarchy/ 2. Implementar GlobalParameterManager.hpp/.cpp 3. Implementar SlotParameterManager.hpp/.cpp 4. Implementar RoutingParameterManager.hpp/.cpp 5. Implementar HierarchyNavigator.hpp/.cpp 6. Tests de jerarquía L5 7. Ejemplo de channel strip

Checklist: - [ ] GlobalParameterManager funciona - [ ] SlotParameterManager por slot - [ ] RoutingParameterManager para routing - [ ] HierarchyNavigator navega correctamente - [ ] Ejemplo funciona - [ ] Sincronización correcta


FASE 3: Modulation Matrix (Prompt 3)

Duración: 4-5h Objetivo: Matriz de modulación avanzada

Micro-pipeline: 1. Crear 08_03_02_modulation_matrix/ 2. Implementar ModulationRouter.hpp/.cpp 3. Implementar ModulationDepthControl.hpp/.cpp 4. Implementar PolyphonicModulation.hpp/.cpp 5. Implementar ModulationVisualizer.hpp/.cpp 6. Tests de modulación compleja 7. Ejemplo de synth polifónico

Checklist: - [ ] ModulationRouter enruta correctamente - [ ] ModulationDepthControl smooth - [ ] PolyphonicModulation funciona - [ ] ModulationVisualizer genera datos - [ ] Tests pasan - [ ] Ejemplo suena bien


FASE 4: DAW Automation (Prompt 4)

Duración: 3-4h Objetivo: Integración con automatización DAW

Micro-pipeline: 1. Crear 08_03_03_daw_automation/ 2. Implementar AutomationRecorder.hpp/.cpp 3. Implementar GestureDetector.hpp/.cpp 4. Implementar SmoothingEngine.hpp/.cpp 5. Implementar AutomationCurve.hpp/.cpp 6. Tests de automation 7. Documentación de integración

Checklist: - [ ] AutomationRecorder graba correctamente - [ ] GestureDetector detecta inicio/fin - [ ] SmoothingEngine evita clicks - [ ] AutomationCurve interpolación suave - [ ] Tests pasan - [ ] Docs completas


FASE 5: Gesture Detection + Tests (Prompt 5)

Duración: 3-4h Objetivo: Detección de gestos y tests finales

Micro-pipeline: 1. Crear 08_03_04_gesture_detection/ 2. Implementar TouchDetector.hpp/.cpp 3. Implementar ContinuousVsDiscrete.hpp/.cpp 4. Implementar UndoRedoIntegration.hpp/.cpp 5. Tests completos de integración 6. Benchmarks de performance 7. Documentación completa 8. Commit final

Checklist: - [ ] TouchDetector detecta touch/release - [ ] ContinuousVsDiscrete diferencia - [ ] UndoRedoIntegration funciona - [ ] Tests integración pasan - [ ] Performance aceptable - [ ] Docs completas - [ ] Commit realizado


📝 TAREAS DETALLADAS

TAREA 1.1: ParameterGroup

#pragma once

#include "../../08_00_plugin_infrastructure/08_00_00_contracts/IParameterHost.hpp"
#include <vector>
#include <string>

namespace audiolab {
namespace plugins {
namespace parameters {

class ParameterGroup {
public:
    ParameterGroup(const std::string& name, const std::string& id);

    // Hierarchy
    void addChild(ParameterGroup* child);
    void removeChild(const std::string& childId);
    ParameterGroup* getParent() const { return m_parent; }
    std::vector<ParameterGroup*> getChildren() const;

    // Parameters
    void addParameter(Parameter* param);
    void removeParameter(const std::string& paramId);
    std::vector<Parameter*> getParameters() const;

    // Search
    Parameter* findParameter(const std::string& id, bool recursive = true);
    ParameterGroup* findGroup(const std::string& id, bool recursive = true);

    // Metadata
    const std::string& getName() const { return m_name; }
    const std::string& getId() const { return m_id; }
    void setVisible(bool visible) { m_visible = visible; }
    bool isVisible() const { return m_visible; }

private:
    std::string m_name;
    std::string m_id;
    bool m_visible = true;

    ParameterGroup* m_parent = nullptr;
    std::vector<ParameterGroup*> m_children;
    std::vector<Parameter*> m_parameters;
};

} // namespace parameters
} // namespace plugins
} // namespace audiolab

Tiempo: 1h


TAREA 1.2: ParameterTree

#pragma once

#include "ParameterGroup.hpp"
#include <unordered_map>

namespace audiolab {
namespace plugins {
namespace parameters {

class ParameterTree {
public:
    ParameterTree();

    // Construction
    ParameterGroup* createGroup(const std::string& name, const std::string& id);
    void setRoot(ParameterGroup* root);

    // Search (optimized with hash map)
    Parameter* findParameter(const std::string& id);
    ParameterGroup* findGroup(const std::string& id);

    // Traversal
    void forEach(std::function<void(Parameter*)> callback);
    void forEachGroup(std::function<void(ParameterGroup*)> callback);

    // Serialization
    void serialize(std::ostream& os) const;
    bool deserialize(std::istream& is);

    // Stats
    size_t getTotalParameters() const;
    size_t getTotalGroups() const;
    int getMaxDepth() const;

private:
    ParameterGroup* m_root = nullptr;

    // Cache for fast lookup
    std::unordered_map<std::string, Parameter*> m_paramCache;
    std::unordered_map<std::string, ParameterGroup*> m_groupCache;

    void rebuildCache();
    void visitTree(ParameterGroup* group, std::function<void(ParameterGroup*)> callback);
};

} // namespace parameters
} // namespace plugins
} // namespace audiolab

Tiempo: 1.5h


TAREA 2.1: GlobalParameterManager

#pragma once

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

namespace audiolab {
namespace plugins {
namespace parameters {

/**
 * @brief Gestiona parámetros globales en suites L5
 *
 * Parámetros globales afectan múltiples slots simultáneamente.
 * Ejemplo: Master Volume, Input Gain, Output Gain
 */
class GlobalParameterManager : public IParameterHost {
public:
    GlobalParameterManager();

    // IParameterHost implementation
    void registerParameter(Parameter* param) override;
    float getParameterValue(const std::string& id) const override;
    void setParameterValue(const std::string& id, float value) override;

    // Global-specific
    void linkToSlots(const std::string& paramId, const std::vector<int>& slotIndices);
    void unlinkFromSlots(const std::string& paramId);

    // Broadcast changes to slots
    void broadcastChange(const std::string& paramId, float value);

    // Queries
    bool isGlobal(const std::string& paramId) const;
    std::vector<int> getLinkedSlots(const std::string& paramId) const;

private:
    struct GlobalParam {
        Parameter* param;
        std::vector<int> linkedSlots;
    };

    std::unordered_map<std::string, GlobalParam> m_globalParams;
    std::vector<IParameterHost*> m_slotHosts;  // Referencias a slot managers
};

} // namespace parameters
} // namespace plugins
} // namespace audiolab

Tiempo: 1.5h


TAREA 3.1: ModulationRouter

#pragma once

#include "../../08_02_dsp_integration_layer/08_02_02_modulation_system/ModulationMatrix.hpp"
#include <vector>

namespace audiolab {
namespace plugins {
namespace parameters {

/**
 * @brief Enruta modulación de forma flexible
 *
 * Permite:
 * - N sources → M targets
 * - Bipolar/Unipolar
 * - Depth per-connection
 * - Enable/Disable individual connections
 */
class ModulationRouter {
public:
    struct Connection {
        std::string sourceId;
        std::string targetParamId;
        float depth = 1.0f;
        bool bipolar = false;
        bool enabled = true;
    };

    // Routing
    void addConnection(const Connection& conn);
    void removeConnection(const std::string& sourceId, const std::string& targetParamId);
    void setConnectionEnabled(const std::string& sourceId,
                            const std::string& targetParamId,
                            bool enabled);

    // Depth control
    void setDepth(const std::string& sourceId, const std::string& targetParamId, float depth);
    float getDepth(const std::string& sourceId, const std::string& targetParamId) const;

    // Processing
    void process(uint32_t numSamples);

    // Queries
    std::vector<Connection> getConnections() const;
    std::vector<std::string> getSourcesForTarget(const std::string& targetParamId) const;
    std::vector<std::string> getTargetsForSource(const std::string& sourceId) const;

private:
    std::vector<Connection> m_connections;
    dsp::ModulationMatrix m_matrix;
};

} // namespace parameters
} // namespace plugins
} // namespace audiolab

Tiempo: 2h


TAREA 4.1: AutomationRecorder

#pragma once

#include <vector>
#include <chrono>

namespace audiolab {
namespace plugins {
namespace parameters {

/**
 * @brief Graba automation de parámetros
 *
 * Captura cambios de parámetros con timestamps.
 * Útil para DAW automation y undo/redo.
 */
class AutomationRecorder {
public:
    struct Event {
        std::string paramId;
        float value;
        uint64_t timestamp;  // Microseconds desde start
    };

    // Recording
    void startRecording();
    void stopRecording();
    void recordEvent(const std::string& paramId, float value);

    // Playback
    void startPlayback();
    void stopPlayback();
    std::vector<Event> getEventsInRange(uint64_t startTime, uint64_t endTime) const;

    // Data access
    const std::vector<Event>& getAllEvents() const { return m_events; }
    void clearEvents();

    // Export/Import
    bool exportToFile(const std::string& path) const;
    bool importFromFile(const std::string& path);

private:
    bool m_recording = false;
    bool m_playing = false;
    std::vector<Event> m_events;
    std::chrono::steady_clock::time_point m_startTime;
};

} // namespace parameters
} // namespace plugins
} // namespace audiolab

Tiempo: 1.5h


TAREA 4.2: GestureDetector

#pragma once

#include <functional>
#include <chrono>

namespace audiolab {
namespace plugins {
namespace parameters {

/**
 * @brief Detecta gestos de usuario en parámetros
 *
 * Detecta:
 * - Touch (inicio de cambio)
 * - Release (fin de cambio)
 * - Continuous change (drag)
 * - Discrete change (click/step)
 */
class GestureDetector {
public:
    enum class GestureType {
        Touch,         // Usuario tocó el control
        Release,       // Usuario soltó el control
        Change,        // Valor cambió
        DoubleClick    // Double click para reset
    };

    using GestureCallback = std::function<void(
        const std::string& paramId,
        GestureType type,
        float value
    )>;

    // Configuration
    void setCallback(GestureCallback callback);
    void setDoubleClickTimeout(uint32_t ms);  // Default: 300ms

    // Detection
    void parameterTouched(const std::string& paramId);
    void parameterChanged(const std::string& paramId, float value);
    void parameterReleased(const std::string& paramId);

    // State queries
    bool isTouched(const std::string& paramId) const;
    uint64_t getTouchDuration(const std::string& paramId) const;

private:
    struct TouchState {
        bool touched = false;
        std::chrono::steady_clock::time_point touchTime;
        std::chrono::steady_clock::time_point lastClickTime;
        uint32_t clickCount = 0;
    };

    GestureCallback m_callback;
    uint32_t m_doubleClickTimeout = 300;
    std::unordered_map<std::string, TouchState> m_touchStates;

    void fireGesture(const std::string& paramId, GestureType type, float value);
};

} // namespace parameters
} // namespace plugins
} // namespace audiolab

Tiempo: 1.5h


🎯 Criterios de Aceptación

Funcionalidad

  • Jerarquía de parámetros funciona
  • Búsqueda rápida (O(1))
  • L5 hierarchy sincroniza correctamente
  • Modulación polifónica funciona
  • Automation recording preciso
  • Gesture detection responsive

Performance

  • Búsqueda parámetros < 10μs
  • Modulación no afecta RT thread
  • Automation overhead < 0.1%

Tests

  • Cobertura > 80%
  • Tests de jerarquía pasan
  • Tests de modulación pasan
  • Tests de automation pasan

📦 Dependencias

Depende de: - ✅ 08_00 (Infrastructure) - IParameterHost - ✅ 08_02 (DSP Integration) - ModulationMatrix

Bloqueante para: - 08_10 (L4 Architecture) - 08_11 (L5 Architecture)


💾 Commits

git commit -m "feat(08_03): add parameter aggregation system"
git commit -m "feat(08_03): add L5 hierarchy system"
git commit -m "feat(08_03): add modulation matrix"
git commit -m "feat(08_03): add DAW automation integration"
git commit -m "feat(08_03): add gesture detection and tests"

Estado: 📝 LISTO Estimación: 16-21 horas (5 fases)