Skip to main content

Overview

The pd::Instance class wraps libpd and provides a C++ interface for managing Pure Data instances. It handles DSP processing, MIDI events, message passing, patch loading, and communication between the GUI and the Pure Data audio engine. Location: Source/Pd/Instance.h

Class Declaration

namespace pd {
    class Instance : public AsyncUpdater {
        // ...
    };
}

Constructor and Initialization

Instance
constructor
explicit Instance();
Creates a new Pure Data instance. Each instance is isolated from others.
initialisePd
void
void initialisePd(String& pdlua_version);
Initialize Pure Data and load required libraries. Call this before using the instance.

DSP Control

prepareDSP
void
void prepareDSP(int nins, int nouts, double samplerate);
Prepare DSP processing with specified channel counts and sample rate.Parameters:
  • nins - Number of input channels
  • nouts - Number of output channels
  • samplerate - Sample rate in Hz
startDSP
void
void startDSP();
void releaseDSP();
Start or stop DSP processing.
performDSP
void
void performDSP(float const* inputs, float* outputs);
Process one block of audio. Call this from your audio callback.Parameters:
  • inputs - Interleaved input audio buffer
  • outputs - Interleaved output audio buffer
Buffer size is determined by getBlockSize().
getBlockSize
int
static int getBlockSize();
Get Pure Data’s block size (typically 64 samples).

Sending MIDI to Pure Data

sendNoteOn
void
void sendNoteOn(int channel, int pitch, int velocity) const;
Send MIDI note on message.
sendControlChange
void
void sendControlChange(int channel, int controller, int value) const;
Send MIDI control change message.
sendProgramChange
void
void sendProgramChange(int channel, int value) const;
Send MIDI program change message.
sendPitchBend
void
void sendPitchBend(int channel, int value) const;
Send MIDI pitch bend message (value range: 0-16383).
sendAfterTouch
void
void sendAfterTouch(int channel, int value) const;
Send MIDI channel aftertouch message.
sendPolyAfterTouch
void
void sendPolyAfterTouch(int channel, int pitch, int value) const;
Send MIDI polyphonic aftertouch message.
sendMidiByte
void
void sendMidiByte(int port, int byte) const;
void sendSysEx(int port, int byte) const;
void sendSysRealTime(int port, int byte) const;
Send raw MIDI bytes, SysEx, or real-time messages.

Receiving MIDI from Pure Data

These are pure virtual methods that must be implemented by subclasses:
receiveNoteOn
virtual
virtual void receiveNoteOn(int channel, int pitch, int velocity) = 0;
virtual void receiveControlChange(int channel, int controller, int value) = 0;
virtual void receiveProgramChange(int channel, int value) = 0;
virtual void receivePitchBend(int channel, int value) = 0;
virtual void receiveAftertouch(int channel, int value) = 0;
virtual void receivePolyAftertouch(int channel, int pitch, int value) = 0;
virtual void receiveMidiByte(int port, int byte) = 0;
Callbacks for MIDI messages coming from Pure Data (e.g., from [noteout], [ctlout], etc.).

Sending Messages to Pure Data

sendBang
void
void sendBang(char const* receiver) const;
Send bang to a receiver.Example:
instance->sendBang("trigger-event");
sendFloat
void
void sendFloat(char const* receiver, float value) const;
Send float value to a receiver.Example:
instance->sendFloat("frequency", 440.0f);
sendSymbol
void
void sendSymbol(char const* receiver, char const* symbol) const;
Send symbol to a receiver.Example:
instance->sendSymbol("mode", "lowpass");
sendList
void
void sendList(char const* receiver, SmallArray<pd::Atom> const& list) const;
Send list of atoms to a receiver.Example:
SmallArray<pd::Atom> list = {1.0f, 2.0f, 3.0f};
instance->sendList("data-receiver", list);
sendMessage
void
void sendMessage(char const* receiver, char const* msg, SmallArray<pd::Atom> const& list) const;
Send named message with arguments to a receiver.Example:
SmallArray<pd::Atom> args = {100.0f, 200.0f};
instance->sendMessage("osc", "range", args);
sendDirectMessage
void
void sendDirectMessage(void* object, SmallString const& msg, SmallArray<Atom>&& list);
void sendDirectMessage(void* object, SmallArray<pd::Atom>&& list);
void sendDirectMessage(void* object, SmallString const& msg);
void sendDirectMessage(void* object, float msg);
Send message directly to a specific Pure Data object (not by name).

Patch Management

openPatch
Patch::Ptr
Patch::Ptr openPatch(File const& toOpen);
Open a Pure Data patch file. Returns a smart pointer to the loaded patch.Example:
auto patch = instance->openPatch(File("/path/to/synth.pd"));
if (patch) {
    DBG("Patch loaded successfully");
}
patches
SmallArray<pd::Patch::Ptr>
SmallArray<pd::Patch::Ptr, 16> patches;
Array of all currently opened patches.

Message Listeners

registerMessageListener
void
void registerMessageListener(void* object, MessageListener* messageListener);
void unregisterMessageListener(MessageListener* messageListener);
Register/unregister listeners for messages from specific Pure Data objects.

Thread Safety

lockAudioThread
void
void lockAudioThread();
void unlockAudioThread();
Lock/unlock the audio thread mutex. Use this when accessing Pure Data from the GUI thread.Example:
instance->lockAudioThread();
// Safe to modify Pure Data state here
instance->sendFloat("param", value);
instance->unlockAudioThread();
enqueueFunctionAsync
void
void enqueueFunctionAsync(std::function<void()> const& fn);

template<typename T>
void enqueueFunctionAsync(WeakReference& ref, std::function<void(T*)> const& fn);
Enqueue a function to be executed safely from the message thread.Example:
instance->enqueueFunctionAsync([this]() {
    // This runs on the message thread
    updateGUI();
});

Symbol Generation

generateSymbol
t_symbol*
t_symbol* generateSymbol(String const& symbol) const;
t_symbol* generateSymbol(SmallString const& symbol) const;
t_symbol* generateSymbol(char const* symbol) const;
Generate a Pure Data symbol from a string. Symbols are interned (unique).

Console and Logging

logMessage
void
void logMessage(String const& message);
void logError(String const& message);
void logWarning(String const& message);
Log messages to the plugdata console.
getConsoleMessages
std::deque&
std::deque<std::tuple<void*, String, int, int, int>>& getConsoleMessages() const;
std::deque<std::tuple<void*, String, int, int, int>>& getConsoleHistory() const;
Access console message queues.

Virtual Methods (Must Implement)

receiveSysMessage
virtual
virtual void receiveSysMessage(SmallString const& selector, SmallArray<pd::Atom> const& list) = 0;
Receive system messages from Pure Data.
updateConsole
virtual
virtual void updateConsole(int numMessages, bool newWarning) = 0;
Called when console needs updating.
titleChanged
virtual
virtual void titleChanged() = 0;
Called when patch title changes.

Properties

instance
void*
Pointer to the underlying libpd instance.
messageReceiver
void*
Pure Data receiver for system messages.
parameterReceiver
void*
Pure Data receiver for parameter messages.
audioLock
CriticalSection const
Mutex for thread-safe audio operations.

Usage Example

// Create and initialize instance
class MyPdInstance : public pd::Instance {
public:
    void receiveNoteOn(int ch, int pitch, int vel) override {
        DBG("Note: " + String(pitch));
    }
    
    void receiveSysMessage(SmallString const& sel, SmallArray<pd::Atom> const& list) override {
        // Handle system messages
    }
    
    void updateConsole(int num, bool warn) override { }
    void titleChanged() override { }
    // ... implement other virtual methods
};

MyPdInstance instance;
String pdluaVer;
instance.initialisePd(pdluaVer);
instance.prepareDSP(2, 2, 48000.0);
instance.startDSP();

// Load and use a patch
auto patch = instance.openPatch(File("synth.pd"));
instance.sendFloat("frequency", 440.0f);
instance.sendBang("trigger");

// In audio callback
instance.performDSP(inputs, outputs);

See Also

  • PluginProcessor - Inherits from pd::Instance
  • pd::Patch - Patch management
  • pd::Atom - Pure Data atom wrapper
  • MessageListener - Message listening interface

Build docs developers (and LLMs) love