SwapWith crashes my code

Happens as soon as I play a note.

/*
  ==============================================================================

    MidiProcessor.h
    Created: 28 Jan 2023 11:48:25am
    Author:  charles

  ==============================================================================
*/

#pragma once
#include "JuceHeader.h"



class MidiProcessor
{
    juce::int64 now;
    juce::int64 before=0;
    juce::int64 interval;
    std::list <int> chordlist;

    
    
    public:
    
    
    int noteoncount[128] = {0};
        void process(juce::MidiBuffer& midiMessages)
    {
            juce::MidiBuffer::Iterator it(midiMessages);
            juce::MidiMessage currentMessage;
            int samplePos;
            int transposition;
            juce::MidiBuffer processedBuffer;
           
            
            while (it.getNextEvent(currentMessage,samplePos))
            {

                if (currentMessage.isNoteOnOrOff()) {
                    currentMessage.setChannel(4);
                    currentMessage.setNoteNumber(44);
                    processedBuffer.clear();
                    processedBuffer.addEvent(currentMessage, samplePos);

                    midiMessages.swapWith(processedBuffer);


                    }
                
            }
            
            
    }
   
};


SwapWith doesn’t copy any data but just swaps the pointer to the memory location. That’s a problem for the caller of process, because processBuffer is allocated on the stack and Is destroyed when it goes out of scope

processedBuffer should be a global?

global variables are never a good solution in my opinion. I can’t really recommend any change without having more context about the code or what it is you are trying to accomplish

Context is that I’m trying to modify midi as it passed through the plugin

My code comes from

Juce Tutorial 60 - Create your first MIDI Plug-in with Eyal Amir (Xfer Records)

It is called here (in PluginProcessor.c):

void NewProjectAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    juce::ScopedNoDenormals noDenormals;
    auto totalNumInputChannels  = getTotalNumInputChannels();
    auto totalNumOutputChannels = getTotalNumOutputChannels();

    // In case we have more outputs than inputs, this code clears any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    // This is here to avoid people getting screaming feedback
    // when they first compile a plugin, but obviously you don't need to keep
    // this code if your algorithm always overwrites all the output channels.
    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());
       theMidi.process(midiMessages);

    // This is the place where you'd normally do the guts of your plugin's
    // audio processing...
    // Make sure to reset the state if your inner loop is processing
    // the samples and the outer loop is handling the channels.
    // Alternatively, you can process the samples with the channels
    // interleaved by keeping the same state.
    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        auto* channelData = buffer.getWritePointer (channel);

        // ..do something to the data...
    }
}

The you should copy the MidiBuffer in your process method, clear it, iterate the copy, and add the modified MidiMessages back to the original (incoming) midiBuffer. I don’t think you should be using swapWith for that, it doesn’t create a deep copy as I previously stated.

1 Like

I want to replace the midi messages with my modifications, how do I stop the original messages from passing through?

You can clear the incoming midi buffer before you add your new message.

  1. Copy incoming midi buffer
  2. Clear incoming midi buffer
  3. Iterate copied midi buffer
    3.1 Add modified midi message to incoming midi buffer
1 Like

Maybe unrelated, but I don’t think the swapWith belongs inside the while loop

Why is that?

Because the number of events is unknown. if it is more than one event you will swap the buffer back.

But the actual problem is, that the swap invalidates your iterator.

The iterator it iterates over the midiMessages. Inside the loop you pull the array under the bottom of the iterator away, so it points to thin air.

You should process the whole midiMessages filling the processedBuffer. When done you call swapWith once to replace the midiMessages with your processedBuffer.