# Midi plugin in Cubase outputting multiple values per step

**URL:** <https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163>\
**Category:** General JUCE discussion\
**Created:** [December 13, 2023, 10:43am UTC](https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163 "2023-12-13T10:43:48Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![instigatorsound](https://avatars.discourse-cdn.com/v4/letter/i/90ced4/32.png) [@instigatorsound](https://forum.juce.com/u/instigatorsound)\
**Post date:** [December 13, 2023, 10:43am UTC](https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163/1 "2023-12-13T10:43:48Z")

</div>

I have an odd issue with Cubase hosting a midi generating plugin as VST3. This works fine in Ableton Live and in Studio One. I have a feeling it is in `int numSamples = buffer.getNumSamples();` but it did work when I was using the deprecated `getCurrentPosition()`. I updated the code to use `getPosition()` and it now puts out exactly 11 notes per step. Which is weird. I’m still learning and trying to debug but I am on an M1 and can’t seem to get the values passed back to the debugger in xcode.

The only things that changed in the code is as follows:

```auto
    if (playHead != nullptr)
    {
        auto* audioPlayHead = playHead.load();
        if (audioPlayHead != nullptr)
        {
            juce::AudioPlayHead::CurrentPositionInfo posInfo;
            if (audioPlayHead->getCurrentPosition(posInfo))
            {
                currentTempo = posInfo.bpm;
                transportIsPlaying = posInfo.isPlaying;
                ppqPosition = posInfo.ppqPosition;
                if (ppqPosition < 0.01) // if the playhead has returned to the beginning
                {
                    currentStep = 0;
                    currentNote = -1;
                }
            }
        }
    }

```

And the new code:

```auto
void MidiSequencerAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    buffer.clear();
    juce::MidiBuffer outputMidi;
    int numSamples = buffer.getNumSamples();

    double currentTempo = 120.0;
    bool transportIsPlaying = false;
    double ppqPosition = 0;

    if (playHead != nullptr)
    {
        auto* audioPlayHead = playHead.load();
        if (audioPlayHead != nullptr)
        {
            auto positionInfo = audioPlayHead->getPosition();
            if (positionInfo) // Check if positionInfo is available
            {
                // Extract bpm if available
                if (auto bpm = positionInfo->getBpm())
                {
                    currentTempo = *bpm;
                }

                transportIsPlaying = positionInfo->getIsPlaying();
                
                // Extract ppqPosition if available
                if (auto ppqPos = positionInfo->getPpqPosition())
                {
                    ppqPosition = *ppqPos;
                }

                if (ppqPosition < 0.01) // if the playhead has returned to the beginning
                {
                    currentStep = 0;
                    currentNote = -1;
                }
            }
        }
    }

    double stepDuration = 60.0 / (currentTempo * stepsPerBeat);
    samplesPerStep = static_cast<int>(getSampleRate() * stepDuration);

    for (int sample = 0; sample < numSamples; ++sample)
    {
        if (transportIsPlaying && sample % samplesPerStep == 0)
        {
            // If there's a note playing, send a note off event
            if (currentNote != -1)
            {
                outputMidi.addEvent(juce::MidiMessage::noteOff(1, currentNote), sample);
                currentNote = -1;
            }

            // If the step is triggered, send a note on event
            if (stepTriggers[currentStep])
            {
                currentNote = stepNotes[currentStep];
                outputMidi.addEvent(juce::MidiMessage::noteOn(1, currentNote, (juce::uint8)127), sample);
                
                
                if (velocityOutputEnabled) {
                    auto velocity = getStepVelocity(currentStep);
                    outputMidi.addEvent(juce::MidiMessage::noteOn(1, currentNote, (juce::uint8)velocity), sample);
                }

                if (cc1OutputEnabled) {
                    auto cc1Value = getStepCC1(currentStep);
                    outputMidi.addEvent(juce::MidiMessage::controllerEvent(1, cc1Channel, cc1Value), sample); }

                if (cc2OutputEnabled) {
                    auto cc2Value = getStepCC2(currentStep);
                    outputMidi.addEvent(juce::MidiMessage::controllerEvent(1, cc2Channel, cc2Value), sample); }
                
            }

            sendChangeMessage();
        }
    }

    midiMessages.swapWith(outputMidi);
}

```

Tested versions are Cubase 12 and 13.

---

<div class="post-metadata">

**Author:** ![Mrugalla](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/mrugalla/32/13092_2.png) [@Mrugalla](https://forum.juce.com/u/Mrugalla)\
**Post date:** [December 13, 2023, 12:39pm UTC](https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163/2 "2023-12-13T12:39:23Z")

</div>

a better way of checking if ppq has returned to 0 is always keeping track of the last ppq and then checking if the abs difference exceeds .5

---

<div class="post-metadata">

**Author:** ![instigatorsound](https://avatars.discourse-cdn.com/v4/letter/i/90ced4/32.png) [@instigatorsound](https://forum.juce.com/u/instigatorsound)\
**Post date:** [December 28, 2023, 11:06pm UTC](https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163/3 "2023-12-28T23:06:06Z")

</div>

I changed that thanks!

I have “fixed” the issue by removing the for loop, but for some reason I am getting a weird delay in Ableton when triggering notes and in Cubase the note length isn’t consistent. Sometimes it is too short, others too long, but it always plays at the right time in Cubase.

```auto
void MidiSequencerAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    buffer.clear();
    juce::MidiBuffer outputMidi;
    double currentTempo = 120;
    double ppqPosition = 0;

    if (playHead != nullptr)
    {
        auto positionInfo = *getPlayHead()->getPosition();

        if (auto bpm = positionInfo.getBpm())
        {
            currentTempo = *bpm;
        }
        bool transportIsPlaying = positionInfo.getIsPlaying();
        if (auto ppqPos = positionInfo.getPpqPosition())
        {
            ppqPosition = *ppqPos;
        }
        
        if (std::abs(ppqPosition - lastPpqPosition) > 0.5)
        {
            currentStep = 0;
            currentNote = -1;
        }

        lastPpqPosition = ppqPosition;

        if (transportIsPlaying)
        {
            int newPlayheadStep = static_cast<int>(ppqPosition * stepsPerBeat) % numSteps;
            
            if (newPlayheadStep != previousPlayheadStep)
            {
                previousPlayheadStep = newPlayheadStep;

//switch logic goes here - REDACTED.

                double samplesPerBeat = (getSampleRate() * 60) / currentTempo;
                int noteOnSample = static_cast<int>(std::round(ppqPosition * samplesPerBeat));
                int noteOffSample = noteOnSample + static_cast<int>(std::round(samplesPerBeat / stepsPerBeat));

                // Trigger the note based on the current step
                if (stepTriggers[currentStep])
                {
                    currentNote = stepNotes[currentStep];

                    // Note On event with velocity
                    auto velocity = (velocityOutputEnabled) ? getStepVelocity(currentStep) : 127;
                    outputMidi.addEvent(juce::MidiMessage::noteOn(1, currentNote, (juce::uint8)velocity), noteOnSample);

                    // Additional MIDI events (CC values)
                    if (cc1OutputEnabled) {
                        auto cc1Value = getStepCC1(currentStep);
                        outputMidi.addEvent(juce::MidiMessage::controllerEvent(1, cc1Channel, cc1Value), noteOnSample);
                    }

                    if (cc2OutputEnabled) {
                        auto cc2Value = getStepCC2(currentStep);
                        outputMidi.addEvent(juce::MidiMessage::controllerEvent(1, cc2Channel, cc2Value), noteOnSample);
                    }
                }
                else
                {
                        outputMidi.addEvent(juce::MidiMessage::noteOff(1, currentNote), noteOffSample);
                }
                sendChangeMessage();
            }
        }
    }

    // Swap with the output MIDI buffer to ensure the events are sent out
    midiMessages.swapWith(outputMidi);
}

```

I think it is either in the midi buffer or the ppqposition and need to revisit that, but I also have removed the other two CCoutput items sending data to the buffer at the same sample time and no difference.

I feel like there has to be a better way to build out a midi sequencer here.

Edit: checked in studio one as well and the timing is late too.

---

<div class="post-metadata">

**Author:** ![holy-city](https://avatars.discourse-cdn.com/v4/letter/h/8491ac/32.png) [@holy-city](https://forum.juce.com/u/holy-city)\
**Post date:** [December 29, 2023, 5:28pm UTC](https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163/4 "2023-12-29T17:28:24Z")

</div>

Couple of things that jump out

```c++
double samplesPerBeat = (getSampleRate() * 60) / currentTempo;

```

`getSampleRate() * 60` implicitly casts to an `int`. Make sure to use `60.0` or `60.` when multiplying by a floating point literal (and enable warnings).

```c++
  double currentTempo = 120;
  // ... 
        if (auto bpm = positionInfo.getBpm())
        {
            currentTempo = *bpm;
        }

```

What if `bpm` is null?

> I feel like there has to be a better way to build out a midi sequencer here.

VST3 doesn’t really support MIDI output from plugins (or input, for that matter). JUCE is translating MIDI to VST3’s note event data type.

---

<div class="post-metadata">

**Author:** ![instigatorsound](https://avatars.discourse-cdn.com/v4/letter/i/90ced4/32.png) [@instigatorsound](https://forum.juce.com/u/instigatorsound)\
**Post date:** [December 29, 2023, 6:48pm UTC](https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163/5 "2023-12-29T18:48:46Z")

</div>

Thanks, I changed those. Sadly didn’t change much, but I did change the following:

```auto
            double samplesPerBeat = (getSampleRate() * 60.0) / currentTempo;
            int samplesPerStep = static_cast<int>(samplesPerBeat / stepsPerBeat);
            int noteOnSample = static_cast<int>(ppqPosition * samplesPerStep);
            int noteOffSample = noteOnSample + static_cast<int>(samplesPerBeat / stepsPerBeat);

```

Where I managed to get the noteOnSample rates from

0  
5632  
11136  
16640

to:

0  
5535  
11038  
16542

which is closer to 5512 from what the samples at 44.1k should be at 16th notes. Looks like I have some math to do.

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [December 29, 2023, 8:01pm UTC](https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163/6 "2023-12-29T20:01:17Z")

</div>

> [@holy-city](#):
>
> `getSampleRate() * 60` implicitly casts to an `int`. Make sure to use `60.0` or `60.` when multiplying by a floating point literal (and enable warnings).

I’m afraid you confused some things here.

You might have confused it with accidental integer divisions, where people would expect a floating point.

The multiplication indeed promotes one operand to match the other. But the int 60 will be propagated to match the double returned from getSampleRate().

It would have been a problem if you did it in a different order:

```auto
double samplesPerBeat = getSampleRate() * (60 / currentTempo);

```

If currentTempo was an int, this would indeed first do an integer division with data loss and multiply with the double afterwards.

But the advice you give will help: enable warnings!

---

<div class="post-metadata">

**Author:** ![holy-city](https://avatars.discourse-cdn.com/v4/letter/h/8491ac/32.png) [@holy-city](https://forum.juce.com/u/holy-city)\
**Post date:** [December 29, 2023, 8:40pm UTC](https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163/7 "2023-12-29T20:40:24Z")

</div>

This is sufficiently easy to mix up that I always make sure my literals match the types I’m using! 😄

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [December 29, 2023, 8:41pm UTC](https://forum.juce.com/t/midi-plugin-in-cubase-outputting-multiple-values-per-step/59163/8 "2023-12-29T20:41:45Z")

</div>

That’s a good habit anyway 🙂
