Skip to content

Commit

Permalink
Handle Midi at the sample where it is realized (#5035)
Browse files Browse the repository at this point in the history
My original rough draft handled midi all up front. This now
interlaves the midi iteration with the sample iteration so
midi should arrive at the right block.

Closes #4983
  • Loading branch information
baconpaul authored Sep 9, 2021
1 parent 17c1632 commit e0924c3
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 43 deletions.
114 changes: 71 additions & 43 deletions src/surge_synth_juce/SurgeSynthProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,49 +216,6 @@ void SurgeSynthProcessor::processBlock(AudioBuffer<float> &buffer, MidiBuffer &m
surge->resetStateFromTimeData();
}

for (const MidiMessageMetadata it : midiMessages)
{
MidiMessage m = it.getMessage();
const int ch = m.getChannel() - 1;
juce::ScopedValueSetter<bool> midiAdd(isAddingFromMidi, true);
midiKeyboardState.processNextMidiEvent(m);

if (m.isNoteOn())
{
surge->playNote(ch, m.getNoteNumber(), m.getVelocity(), 0);
}
else if (m.isNoteOff())
{
surge->releaseNote(ch, m.getNoteNumber(), m.getVelocity());
}
else if (m.isChannelPressure())
{
surge->channelAftertouch(ch, m.getChannelPressureValue());
}
else if (m.isAftertouch())
{
surge->polyAftertouch(ch, m.getNoteNumber(), m.getAfterTouchValue());
}
else if (m.isPitchWheel())
{
surge->pitchBend(ch, m.getPitchWheelValue() - 8192);
}
else if (m.isController())
{
surge->channelController(ch, m.getControllerNumber(), m.getControllerValue());
}
else if (m.isProgramChange())
{
// apparently this is not enough to actually execute SurgeSynthesizer::programChange
// for whatever reason!
surge->programChange(ch, m.getProgramChangeNumber());
}
else
{
// std::cout << "Ignoring message " << std::endl;
}
}

midiR rec;
while (midiFromGUI.pop(rec))
{
Expand All @@ -280,8 +237,29 @@ void SurgeSynthProcessor::processBlock(AudioBuffer<float> &buffer, MidiBuffer &m
auto mainInput = getBusBuffer(buffer, true, 0);
auto sceneAOutput = getBusBuffer(buffer, false, 1);
auto sceneBOutput = getBusBuffer(buffer, false, 2);

auto midiIt = midiMessages.findNextSamplePosition(0);
int nextMidi = -1;
if (midiIt != midiMessages.cend())
{
nextMidi = (*midiIt).samplePosition;
}

for (int i = 0; i < buffer.getNumSamples(); i++)
{
if (i == nextMidi)
{
applyMidi(*midiIt);
midiIt++;
if (midiIt == midiMessages.cend())
{
nextMidi = -1;
}
else
{
nextMidi = (*midiIt).samplePosition;
}
}
auto outL = mainOutput.getWritePointer(0, i);
auto outR = mainOutput.getWritePointer(1, i);

Expand Down Expand Up @@ -333,6 +311,13 @@ void SurgeSynthProcessor::processBlock(AudioBuffer<float> &buffer, MidiBuffer &m
blockPos = (blockPos + 1) & (BLOCK_SIZE - 1);
}

// This should, in theory, never happen, but better safe than sorry
while (midiIt != midiMessages.cend())
{
applyMidi(*midiIt);
midiIt++;
}

if (checkNamesEvery++ > 10)
{
checkNamesEvery = 0;
Expand All @@ -343,6 +328,49 @@ void SurgeSynthProcessor::processBlock(AudioBuffer<float> &buffer, MidiBuffer &m
}
}

void SurgeSynthProcessor::applyMidi(const juce::MidiMessageMetadata &it)
{
MidiMessage m = it.getMessage();
const int ch = m.getChannel() - 1;
juce::ScopedValueSetter<bool> midiAdd(isAddingFromMidi, true);
midiKeyboardState.processNextMidiEvent(m);

if (m.isNoteOn())
{
surge->playNote(ch, m.getNoteNumber(), m.getVelocity(), 0);
}
else if (m.isNoteOff())
{
surge->releaseNote(ch, m.getNoteNumber(), m.getVelocity());
}
else if (m.isChannelPressure())
{
surge->channelAftertouch(ch, m.getChannelPressureValue());
}
else if (m.isAftertouch())
{
surge->polyAftertouch(ch, m.getNoteNumber(), m.getAfterTouchValue());
}
else if (m.isPitchWheel())
{
surge->pitchBend(ch, m.getPitchWheelValue() - 8192);
}
else if (m.isController())
{
surge->channelController(ch, m.getControllerNumber(), m.getControllerValue());
}
else if (m.isProgramChange())
{
// apparently this is not enough to actually execute SurgeSynthesizer::programChange
// for whatever reason!
surge->programChange(ch, m.getProgramChangeNumber());
}
else
{
// std::cout << "Ignoring message " << std::endl;
}
}

//==============================================================================
bool SurgeSynthProcessor::hasEditor() const
{
Expand Down
1 change: 1 addition & 0 deletions src/surge_synth_juce/SurgeSynthProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ class SurgeSynthProcessor : public juce::AudioProcessor,
bool canRemoveBusValue = false;
bool canRemoveBus(bool isInput) const override { return canRemoveBusValue; }
void processBlock(juce::AudioBuffer<float> &, juce::MidiBuffer &) override;
void applyMidi(const juce::MidiMessageMetadata &);

//==============================================================================
juce::AudioProcessorEditor *createEditor() override;
Expand Down

0 comments on commit e0924c3

Please sign in to comment.