Midi Message is not sent in graph

Hi, There’ a think that I cannot understand:

I created two plugins that I load in juce audioPluginHost as internal plugins that give me the possibility to: open a midi device and to send throw a midi channel index incoming messages and get incoming midi messages in processblock and send them to a midi output port.

.h:

    Array<MidiMessage> incomingMessages; // needs me to show incoming or outgoing messages in a monitor
    MidiBuffer collectorBuffer = MidiBuffer(); 
    double sampleRate = 48000;

    void prepareToPlay (double samplRate, int samplPerBlock) override { sampleRate = samplRate; }

.cpp:

void MidiIO::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiBuffer)
{
    buffer.clear();
    
    MidiBuffer newMidiBuffer;
    
    if (deviceType == MidiIO::IODeviceType::input)
    {
        midiBuffer.clear();
        midiBuffer.data = collectorBuffer.data;
        collectorBuffer.clear();
    } else {
        for (const MidiMessageMetadata metadata : midiBuffer)
        {
            incomingMessages.add (metadata.getMessage());
            sendMessage(ayra::Messages::newMidiMessage);
            sendToOutputs(metadata.getMessage());
        }
    }
}

void MidiIO::handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message)
{
    if (deviceType == IODeviceType::input)
    {
        auto timestamp = message.getTimeStamp();
        int sampleNumber =  (int) (timestamp * sampleRate );

        collectorBuffer.addEvent (message, sampleNumber);
        
        incomingMessages.add (message);
        sendMessage(ayra::Messages::newMidiMessage);
    }
}

If I connect midiInputPlugin to MidiOutputPlugin in MidiOutputPlugin monitor I can see the midi messages sent from midiInputPlugin, but if I connect midiInputPlugin to for example a twin2 this one don’t produces any sound… ideas ?

The timestamps of messages received in handleIncomingMidiMessage are different to the timestamps of messages returned by processBlock. In processBlock, the timestamp of a message is a sample position relative to the start of the current audio block. In handleIncomingMidiMessage, the timestamp of each message is an absolute time in seconds. You might find MidiMessageCollector useful for automatically converting between these time representations.

Also, be aware that handleIncomingMidiMessage and processBlock are called on different threads, so you need to take thread safety into account when accessing objects. At the moment, it’s unsafe to access collectorBuffer from both functions. Another benefit of MidiMessageCollector is that it is safe for its handleIncomingMidiMessage function to be called concurrently with removeNextBlockOfMessages.

1 Like

I don’t know how to thank you… I was going crazy, now it works fine :heart::pray:

Here the Code:

.h

    MidiMessageCollector midiCollector {};
    double sampleRate = 48000;

.cpp

void MidiIO::prepareToPlay (double samplRate, int samplPerBlock)
{
    sampleRate = samplRate;
    midiCollector.reset(sampleRate);
}

void MidiIO::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiBuffer)
{
    buffer.clear();
    
    MidiBuffer newMidiBuffer;
    
    if (deviceType == MidiIO::IODeviceType::input)
    {
        midiBuffer.clear();
        midiCollector.removeNextBlockOfMessages(midiBuffer, buffer.getNumSamples());
    } else {
        for (const MidiMessageMetadata metadata : midiBuffer)
        {
            incomingMessages.add (metadata.getMessage());
            sendMessage(ayra::Messages::newMidiMessage);
            sendToOutputs(metadata.getMessage());
        }
    }
}

void MidiIO::handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message)
{
    if (deviceType == IODeviceType::input)
    {
        midiCollector.addMessageToQueue(message);
        incomingMessages.add (message);
        sendMessage(ayra::Messages::newMidiMessage);
    }
}