mirror of
https://github.com/VARCem/munt.git
synced 2026-07-09 02:26:09 +00:00
SMFDriver now flushes / discards all the MidiSession buffers
when seeking / pausing / stopping playback as appropriate. Also, the buffers are purged when closing the SynthRoute.
This commit is contained in:
@@ -163,7 +163,13 @@ bool QMidiBuffer::nextEvent() {
|
||||
return retieveEvents();
|
||||
}
|
||||
|
||||
void QMidiBuffer::discardEvents() {
|
||||
bytesRead += bytesToRead;
|
||||
popEvents();
|
||||
}
|
||||
|
||||
void QMidiBuffer::popEvents() {
|
||||
if (readPointer == NULL) return;
|
||||
ringBuffer.advanceReadPointer(bytesRead);
|
||||
readPointer = NULL;
|
||||
bytesRead = 0;
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
quint64 getEventTimestamp() const;
|
||||
quint32 getEventData(const uchar *&sysexData) const;
|
||||
bool nextEvent();
|
||||
void discardEvents();
|
||||
void popEvents();
|
||||
|
||||
private:
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
* - Merging MIDI streams coming from several MIDI sessions
|
||||
*/
|
||||
|
||||
#include <climits>
|
||||
|
||||
#include "SynthRoute.h"
|
||||
#include "MidiSession.h"
|
||||
#include "QMidiBuffer.h"
|
||||
@@ -118,6 +120,7 @@ bool SynthRoute::close() {
|
||||
audioStream = NULL;
|
||||
qSynth.close();
|
||||
disableExclusiveMidiMode();
|
||||
discardMidiBuffers();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -269,11 +272,33 @@ bool SynthRoute::playMIDISysex(MidiSession &midiSession, const Bit8u *sysex, Bit
|
||||
}
|
||||
}
|
||||
|
||||
void SynthRoute::mergeMidiStreams(uint renderingPassFrameLength) {
|
||||
if (audioStream == NULL) return; // May happen during startup, occasionally.
|
||||
void SynthRoute::discardMidiBuffers() {
|
||||
if (!multiMidiMode) return;
|
||||
QMutexLocker midiSessionsLocker(&midiSessionsMutex);
|
||||
QVarLengthArray<QMidiBuffer *, 16> streamBuffers;
|
||||
const quint64 renderingPassEndTimestamp = audioStream->computeMIDITimestamp(renderingPassFrameLength);
|
||||
|
||||
for (int i = 0; i < midiSessions.size(); i++) {
|
||||
QMidiBuffer *midiBuffer = midiSessions[i]->getQMidiBuffer();
|
||||
while (midiBuffer->retieveEvents()) {
|
||||
midiBuffer->discardEvents();
|
||||
}
|
||||
}
|
||||
|
||||
qSynth.flushMIDIQueue();
|
||||
}
|
||||
|
||||
void SynthRoute::flushMIDIQueue() {
|
||||
if (multiMidiMode) mergeMidiStreams(0);
|
||||
qSynth.flushMIDIQueue();
|
||||
}
|
||||
|
||||
// When renderingPassFrameLength == 0, all pending messages are merged.
|
||||
void SynthRoute::mergeMidiStreams(uint renderingPassFrameLength) {
|
||||
QMutexLocker midiSessionsLocker(&midiSessionsMutex);
|
||||
QVarLengthArray<QMidiBuffer *, 16> streamBuffers;
|
||||
const quint64 renderingPassEndTimestamp = renderingPassFrameLength == 0
|
||||
? std::numeric_limits<quint64>::max()
|
||||
: audioStream->computeMIDITimestamp(renderingPassFrameLength);
|
||||
|
||||
for (int i = 0; i < midiSessions.size(); i++) {
|
||||
QMidiBuffer *midiBuffer = midiSessions[i]->getQMidiBuffer();
|
||||
@@ -317,12 +342,14 @@ void SynthRoute::mergeMidiStreams(uint renderingPassFrameLength) {
|
||||
}
|
||||
|
||||
void SynthRoute::render(MT32Emu::Bit16s *buffer, uint length) {
|
||||
if (multiMidiMode) mergeMidiStreams(length);
|
||||
// Occasionally, audioStream may appear NULL during startup.
|
||||
if (multiMidiMode && audioStream != NULL) mergeMidiStreams(length);
|
||||
qSynth.render(buffer, length);
|
||||
}
|
||||
|
||||
void SynthRoute::render(float *buffer, uint length) {
|
||||
if (multiMidiMode) mergeMidiStreams(length);
|
||||
// Occasionally, audioStream may appear NULL during startup.
|
||||
if (multiMidiMode && audioStream != NULL) mergeMidiStreams(length);
|
||||
qSynth.render(buffer, length);
|
||||
}
|
||||
|
||||
@@ -336,10 +363,6 @@ void SynthRoute::enableRealtimeMode() {
|
||||
qSynth.enableRealtime();
|
||||
}
|
||||
|
||||
void SynthRoute::flushMIDIQueue() {
|
||||
qSynth.flushMIDIQueue();
|
||||
}
|
||||
|
||||
void SynthRoute::playMIDIShortMessageNow(Bit32u msg) {
|
||||
qSynth.playMIDIShortMessageNow(msg);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ private:
|
||||
|
||||
void setState(SynthRouteState newState);
|
||||
void disableExclusiveMidiMode();
|
||||
void mergeMidiStreams(uint renderingPassFrameLength);
|
||||
|
||||
public:
|
||||
SynthRoute(QObject *parent = NULL);
|
||||
@@ -65,7 +66,7 @@ public:
|
||||
bool playMIDISysex(MidiSession &midiSession, const MT32Emu::Bit8u *sysex, MT32Emu::Bit32u sysexLen, quint64 timestamp);
|
||||
bool pushMIDIShortMessage(MidiSession &midiSession, MT32Emu::Bit32u msg, MasterClockNanos midiNanos);
|
||||
bool pushMIDISysex(MidiSession &midiSession, const MT32Emu::Bit8u *sysex, unsigned int sysexLen, MasterClockNanos midiNanos);
|
||||
void mergeMidiStreams(uint renderingPassFrameLength);
|
||||
void discardMidiBuffers();
|
||||
void render(MT32Emu::Bit16s *buffer, uint length);
|
||||
void render(float *buffer, uint length);
|
||||
void audioStreamFailed();
|
||||
|
||||
@@ -26,7 +26,11 @@ static const MasterClockNanos MAX_SLEEP_TIME = 200 * MasterClock::NANOS_PER_MILL
|
||||
|
||||
static void sendAllSoundOff(SynthRoute *synthRoute, bool resetAllControllers) {
|
||||
if (synthRoute->getState() != SynthRouteState_OPEN) return;
|
||||
synthRoute->flushMIDIQueue();
|
||||
if (resetAllControllers) {
|
||||
synthRoute->discardMidiBuffers();
|
||||
} else {
|
||||
synthRoute->flushMIDIQueue();
|
||||
}
|
||||
for (quint8 i = 0; i < 16; i++) {
|
||||
// All notes off
|
||||
quint32 msg = 0x7FB0 | i;
|
||||
|
||||
Reference in New Issue
Block a user