From 320250b8311de4910f946226cc57e5f153aa9bc5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 9 Apr 2022 01:50:44 -0500 Subject: [PATCH] MIDI out improvements --- src/engine/engine.cpp | 13 +++++++++++++ src/engine/engine.h | 7 +++++-- src/engine/playback.cpp | 22 +++++++++++++++++++--- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 78ae1ce4..f11f967d 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -873,6 +873,11 @@ void DivEngine::play() { for (int i=0; imidiOut!=NULL) { + int pos=totalTicksR/6; + output->midiOut->send(TAMidiMessage(TA_MIDI_POSITION,(pos>>7)&0x7f,pos&0x7f)); + output->midiOut->send(TAMidiMessage(TA_MIDI_MACHINE_PLAY,0,0)); + } BUSY_END; } @@ -918,6 +923,14 @@ void DivEngine::stop() { for (int i=0; inotifyPlaybackStop(); } + if (output) if (output->midiOut!=NULL) { + output->midiOut->send(TAMidiMessage(TA_MIDI_MACHINE_STOP,0,0)); + for (int i=0; i=0) { + output->midiOut->send(TAMidiMessage(0x80|(i&15),chan[i].curMidiNote,0)); + } + } + } BUSY_END; } diff --git a/src/engine/engine.h b/src/engine/engine.h index 89005675..6741a00e 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -86,7 +86,8 @@ struct DivChannelState { bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff; bool arpYield, delayLocked, inPorta, scheduledSlideReset, shorthandPorta, noteOnInhibit, resetArp; - int midiNote, curMidiNote; + int midiNote, curMidiNote, midiPitch; + bool midiAftertouch; DivChannelState(): note(-1), @@ -130,7 +131,9 @@ struct DivChannelState { noteOnInhibit(false), resetArp(false), midiNote(-1), - curMidiNote(-1) {} + curMidiNote(-1), + midiPitch(-1), + midiAftertouch(false) {} }; struct DivNoteEvent { diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 8e1f1d66..1776b046 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -201,16 +201,24 @@ int DivEngine::dispatchCmd(DivCommand c) { chan[c.chan].curMidiNote=-1; break; case DIV_CMD_INSTRUMENT: - output->midiOut->send(TAMidiMessage(0xc0|(c.chan&15),c.value,0)); + if (chan[c.chan].lastIns!=c.value) { + output->midiOut->send(TAMidiMessage(0xc0|(c.chan&15),c.value,0)); + } break; case DIV_CMD_VOLUME: - //output->midiOut->send(TAMidiMessage(0xb0|(c.chan&15),0x07,scaledVol)); + if (chan[c.chan].curMidiNote>=0 && chan[c.chan].midiAftertouch) { + chan[c.chan].midiAftertouch=false; + output->midiOut->send(TAMidiMessage(0xa0|(c.chan&15),chan[c.chan].curMidiNote,scaledVol)); + } break; case DIV_CMD_PITCH: { int pitchBend=8192+(c.value<<5); if (pitchBend<0) pitchBend=0; if (pitchBend>16383) pitchBend=16383; - output->midiOut->send(TAMidiMessage(0xe0|(c.chan&15),pitchBend&0x7f,pitchBend>>7)); + if (pitchBend!=chan[c.chan].midiPitch) { + chan[c.chan].midiPitch=pitchBend; + output->midiOut->send(TAMidiMessage(0xe0|(c.chan&15),pitchBend&0x7f,pitchBend>>7)); + } break; } default: @@ -963,6 +971,9 @@ void DivEngine::processRow(int i, bool afterDelay) { // volume if (pat->data[whatRow][3]!=-1) { if (dispatchCmd(DivCommand(DIV_ALWAYS_SET_VOLUME,i)) || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[whatRow][3]) { + if (pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0) { + chan[i].midiAftertouch=true; + } chan[i].volume=pat->data[whatRow][3]<<8; dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8)); } @@ -1436,6 +1447,11 @@ bool DivEngine::nextTick(bool noAccum) { cycles++; } + // MIDI clock + if (output) if (!skipping && output->midiOut!=NULL) { + output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0)); + } + while (!pendingNotes.empty()) { DivNoteEvent& note=pendingNotes.front(); if (note.on) {