Skip to content

Build Fix Analysis - Voice Management System

Date: 2025-10-15

Problem Summary

The VoiceAllocator implementation does not match the IVoiceAllocator interface, causing compilation errors.

Compilation Errors

1. Struct Redefinition

Error:

error C2011: 'AudioLab::Engine::VoiceAllocatorConfig': nueva definición del tipo 'struct'

Cause: - VoiceAllocatorConfig is defined in IVoiceAllocator.h (line 53) - Redefined in VoiceAllocator.h (line 37)

Fix: Remove the redefinition in VoiceAllocator.h and use the interface version.

Differences between definitions:

// IVoiceAllocator.h (Interface)
struct VoiceAllocatorConfig {
    uint32_t maxVoices = 16;
    VoiceStealingStrategy stealingStrategy = VoiceStealingStrategy::OLDEST;
    PolyphonyMode polyphonyMode = PolyphonyMode::POLYPHONIC;
    uint8_t unisonVoices = 2;
    float unisonDetune = 0.1f;
    bool enableVoiceStealing = true;
    float stealingThreshold = 0.01f;
};

// VoiceAllocator.h (Implementation - DUPLICATE)
struct VoiceAllocatorConfig {
    size_t maxVoices = 16;              // Should be uint32_t
    VoiceStealingStrategy stealingStrategy = VoiceStealingStrategy::OLDEST;
    PolyphonyMode polyphonyMode = PolyphonyMode::POLYPHONIC;
    bool enableStealing = true;          // Should be enableVoiceStealing
    uint8_t unisonVoices = 2;
    float unisonDetune = 0.1f;
    float unisonSpread = 1.0f;           // NOT in interface
};

2. Method Signature Mismatches

Missing from Implementation:

// Interface has these, implementation doesn't:
virtual size_t deallocateInactive() = 0;
virtual IVoice* findVoiceByID(uint32_t voiceID) = 0;
virtual size_t getIdleVoiceCount() const = 0;
virtual size_t getTotalVoiceCount() const = 0;
virtual void releaseAll() = 0;
virtual void killAll() = 0;
virtual void reset() = 0;
virtual void updateStats() = 0;

Extra in Implementation (not in interface):

// Implementation has these, interface doesn't:
void setVoicePool(std::vector<std::unique_ptr<IVoice>>&& voices) override;
size_t getVoicePoolSize() const override;
void deallocateAll() override;
void setUnisonVoices(uint8_t numVoices) override;
uint8_t getUnisonVoices() const override;
void setUnisonDetune(float detuneAmount) override;
float getUnisonDetune() const override;

Wrong Return Type:

// Implementation:
size_t getMaxPolyphony() const override;

// Interface expects:
uint32_t getMaxPolyphony() const override;

Wrong Parameter Type:

// Implementation:
void setMaxPolyphony(size_t maxVoices) override;

// Interface expects:
void setMaxPolyphony(uint32_t maxVoices) override;

3. VoiceAllocatorStats Field Mismatches

Error:

error C2039: "peakVoiceCount": no es un miembro de "AudioLab::Engine::VoiceAllocatorStats"

Interface definition:

struct VoiceAllocatorStats {
    uint32_t totalVoices = 0;
    uint32_t activeVoices = 0;
    uint32_t idleVoices = 0;
    uint32_t allocationsTotal = 0;
    uint32_t stealsTotal = 0;
    uint32_t failedAllocations = 0;
    float averagePolyphony = 0.0f;
    float peakPolyphony = 0.0f;       // Note: peakPolyphony, not peakVoiceCount
};

Implementation uses:

std::atomic<uint64_t> m_peakVoiceCount{0};  // Should be peakPolyphony

4. Function Call Mismatches

calculateUnisonDetune()

// Implementation call (VoiceAllocator.cpp:588):
float detune = calculateUnisonDetune(i);

// Implementation signature (VoiceAllocator.h:298):
float calculateUnisonDetune(size_t voiceIndex, size_t totalVoices) const;

// Missing second parameter!

calculateUnisonPan()

// Implementation call (VoiceAllocator.cpp:589):
float pan = calculateUnisonPan(i);

// Implementation signature (VoiceAllocator.h:306):
float calculateUnisonPan(size_t voiceIndex, size_t totalVoices) const;

// Missing second parameter!

Required Fixes

Fix 1: Remove VoiceAllocatorConfig Redefinition

File: VoiceAllocator.h Action: Delete lines 34-45 (struct VoiceAllocatorConfig)

Fix 2: Add Missing Interface Methods

File: VoiceAllocator.h Action: Add declarations:

size_t deallocateInactive() override;
IVoice* findVoiceByID(uint32_t voiceID) override;
size_t getIdleVoiceCount() const override;
size_t getTotalVoiceCount() const override;
void releaseAll() override;
void killAll() override;
void reset() override;
void updateStats() override;

Fix 3: Remove Non-Interface Methods

File: VoiceAllocator.h Action: Remove override keyword and make these non-virtual (or remove entirely):

// Remove these or make them non-virtual helper methods:
void setVoicePool(...);
size_t getVoicePoolSize() const;
void deallocateAll();
void setUnisonVoices(...);
uint8_t getUnisonVoices() const;
void setUnisonDetune(...);
float getUnisonDetune() const;

Fix 4: Fix Method Signatures

File: VoiceAllocator.h Action: Change:

// From:
void setMaxPolyphony(size_t maxVoices) override;
size_t getMaxPolyphony() const override;

// To:
void setMaxPolyphony(uint32_t maxVoices) override;
uint32_t getMaxPolyphony() const override;

Fix 5: Fix VoiceAllocatorStats Usage

File: VoiceAllocator.cpp Action: Replace all uses of peakVoiceCount with peakPolyphony:

// From:
stats.peakVoiceCount = ...

// To:
stats.peakPolyphony = ...

Fix 6: Fix Function Calls

File: VoiceAllocator.cpp (line ~588) Action: Add missing parameters:

// From:
float detune = calculateUnisonDetune(i);
float pan = calculateUnisonPan(i);

// To:
float detune = calculateUnisonDetune(i, m_config.unisonVoices);
float pan = calculateUnisonPan(i, m_config.unisonVoices);

Fix 7: Handle unisonSpread

Decision: Keep unisonSpread as implementation detail Action: Store in class but don't override interface (it's a non-virtual extension)

Implementation Strategy

  1. ✅ Create fixed VoiceAllocator.h
  2. ✅ Create fixed VoiceAllocator.cpp
  3. ✅ Rebuild project
  4. ✅ Run tests
  5. ✅ Update documentation

Next Steps

  1. Fix VoiceAllocator.h
  2. Fix VoiceAllocator.cpp
  3. Update test files if needed
  4. Rebuild and verify
  5. Update PROGRESS.md