Upload files to "Source"

This commit is contained in:
ed
2025-10-22 17:14:36 +00:00
parent 989632d1e0
commit 24db9795e9

View File

@@ -1,79 +1,47 @@
#pragma once #pragma once
#include <JuceHeader.h>
#include "SynthVoice.h" #include "SynthVoice.h"
#include <JuceHeader.h>
//==============================================================================
// MPESynthesiser wrapper that owns voices, installs a catch-all Sound,
// forwards prepare() to each voice, and renders MIDI blocks.
class NeuralAudioEngine : public juce::MPESynthesiser class NeuralAudioEngine : public juce::MPESynthesiser
{ {
public: public:
static constexpr int maxNumVoices = 8; static constexpr int maxNumVoices = 8;
explicit NeuralAudioEngine (NeuralSharedParams& sp) explicit NeuralAudioEngine(NeuralSharedParams& sp)
{ {
// Call Synthesiser base API explicitly via a base pointer (portable on MSVC). // Create MPE voices
auto* base = static_cast<juce::Synthesiser*>(this);
base->clearVoices();
base->clearSounds();
// Create voices (MPESynthesiser takes ownership)
for (int i = 0; i < maxNumVoices; ++i) for (int i = 0; i < maxNumVoices; ++i)
addVoice (new NeuralSynthVoice (sp)); addVoice(new NeuralSynthVoice(sp)); // <-- takes MPESynthesiserVoice*
// Catch-all Sound so any MIDI note/channel is accepted. // MPE synths do not use addSound(); note events are routed via MPE zones.
struct AnySound final : public juce::SynthesiserSound setVoiceStealingEnabled(true);
{
bool appliesToNote (int) override { return true; }
bool appliesToChannel (int) override { return true; }
};
// Use raw pointer for this JUCE API on your version.
base->addSound (new AnySound());
// Respond to standard MIDI in non-MPE hosts
enableLegacyMode();
setVoiceStealingEnabled (true);
} }
// Called from processor::prepareToPlay() void prepare(const juce::dsp::ProcessSpec& spec) noexcept
void prepare (const juce::dsp::ProcessSpec& spec) noexcept
{ {
setCurrentPlaybackSampleRate (spec.sampleRate); setCurrentPlaybackSampleRate(spec.sampleRate);
for (auto* v : voices) for (auto* v : voices)
if (auto* nv = dynamic_cast<NeuralSynthVoice*> (v)) if (auto* nv = dynamic_cast<NeuralSynthVoice*>(v))
nv->prepare (spec); nv->prepare(spec);
} }
// Forward the MIDI-buffer overload so MIDI is consumed.
void renderNextBlock (juce::AudioBuffer<float>& outputAudio,
juce::MidiBuffer& midiMessages,
int startSample,
int numSamples)
{
juce::MPESynthesiser::renderNextBlock (outputAudio, midiMessages,
startSample, numSamples);
}
// Utility: apply a lambda to all voices
template <typename VoiceFunc> template <typename VoiceFunc>
void applyToVoices (VoiceFunc&& fn) noexcept void applyToVoices(VoiceFunc&& fn) noexcept
{ {
for (auto* v : voices) for (auto* v : voices)
if (auto* nv = dynamic_cast<NeuralSynthVoice*> (v)) fn(dynamic_cast<NeuralSynthVoice*>(v));
fn (nv);
} }
private: private:
// Keep base rendering behaviour for the sub-block overload. // keep base render
using juce::MPESynthesiser::renderNextSubBlock; using juce::MPESynthesiser::renderNextSubBlock;
void renderNextSubBlock (juce::AudioBuffer<float>& buffer, void renderNextSubBlock(juce::AudioBuffer<float>& outputAudio,
int startSample, int startSample,
int numSamples) override int numSamples) override
{ {
juce::MPESynthesiser::renderNextSubBlock (buffer, startSample, numSamples); juce::MPESynthesiser::renderNextSubBlock(outputAudio, startSample, numSamples);
} }
}; };