From d9cd5e6490cc940116930fa631ad75ccbe1227a4 Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Tue, 5 Dec 2006 12:48:32 +0000 Subject: fixed dropping midi events --- muse/muse/audio.cpp | 26 +++++++++++++++++++++----- muse/muse/audio.h | 1 + muse/muse/driver/audiodev.h | 3 ++- muse/muse/driver/dummyaudio.cpp | 3 +++ muse/muse/driver/jackaudio.h | 7 ++++--- muse/muse/midievent.cpp | 8 ++++++-- muse/muse/midififo.cpp | 19 +++++++++++++++++++ muse/muse/midififo.h | 2 ++ muse/muse/midiinport.cpp | 6 +++++- muse/muse/synth.cpp | 17 ++++++++++------- 10 files changed, 73 insertions(+), 19 deletions(-) diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp index 9d719d33..f706edcf 100644 --- a/muse/muse/audio.cpp +++ b/muse/muse/audio.cpp @@ -309,6 +309,9 @@ void Audio::process(unsigned frames, int jackState) extern int watchAudio; ++watchAudio; // make a simple watchdog happy + // + // process messages from gui + // if (msg) { processMsg(); msg = 0; // dont process again @@ -344,15 +347,15 @@ void Audio::process(unsigned frames, int jackState) startRolling(); } - if (idle || state == START_PLAY) { + if (idle || (state == START_PLAY)) { // deliver silence OutputList* ol = song->outputs(); for (iAudioOutput i = ol->begin(); i != ol->end(); ++i) (*i)->silence(frames); return; } - unsigned framePos = _pos.frame(); + unsigned framePos = _pos.frame(); if (state == PLAY) { // // clear prefetch FIFO if left/right locators @@ -436,6 +439,8 @@ void Audio::process(unsigned frames, int jackState) // process midi //----------------------------------------- + unsigned startFrame = _pos.frame(); + unsigned endFrame = startFrame + segmentSize; SynthIList* sl = song->syntis(); { MidiOutPortList* ol = song->midiOutPorts(); @@ -448,11 +453,11 @@ void Audio::process(unsigned frames, int jackState) for (iMidiInPort i = mil->begin(); i != mil->end(); ++i) (*i)->beforeProcess(); for (iMidiTrack i = mtl->begin(); i != mtl->end(); ++i) - (*i)->processMidi(_curTickPos, _nextTickPos, _pos.frame(), _pos.frame() + segmentSize); + (*i)->processMidi(_curTickPos, _nextTickPos, startFrame, endFrame); for (iMidiOutPort i = ol->begin(); i != ol->end(); ++i) - (*i)->processMidi(_curTickPos, _nextTickPos, _pos.frame(), _pos.frame() + segmentSize); + (*i)->processMidi(_curTickPos, _nextTickPos, startFrame, endFrame); for (iSynthI i = sl->begin(); i != sl->end(); ++i) - (*i)->processMidi(_curTickPos, _nextTickPos, _pos.frame(), _pos.frame() + segmentSize); + (*i)->processMidi(_curTickPos, _nextTickPos, startFrame, endFrame); for (iMidiInPort i = mil->begin(); i != mil->end(); ++i) (*i)->afterProcess(); @@ -715,3 +720,14 @@ void Audio::sendMsgToGui(char c) write(sigFd, &c, 1); } +//--------------------------------------------------------- +// timestamp +// on stop we return a free running frame counter +//--------------------------------------------------------- + +unsigned Audio::timestamp() const + { + return audio->isPlaying() ? audioDriver->framePos() + : audioDriver->frameTime(); + } + diff --git a/muse/muse/audio.h b/muse/muse/audio.h index 56ce1976..56c85f05 100644 --- a/muse/muse/audio.h +++ b/muse/muse/audio.h @@ -268,6 +268,7 @@ class Audio { MidiEvent* getMidiEvent(); void popMidiEvent(); int curReadIndex() const { return _curReadIndex; } + unsigned timestamp() const; }; extern int processAudio(unsigned long, void*); diff --git a/muse/muse/driver/audiodev.h b/muse/muse/driver/audiodev.h index 0494116f..e0bf554d 100644 --- a/muse/muse/driver/audiodev.h +++ b/muse/muse/driver/audiodev.h @@ -36,12 +36,13 @@ class AudioDriver : public Driver { virtual void start(int priority) = 0; virtual bool restart() { return false; } // return true on error virtual void stop () = 0; +// virtual unsigned getCurFrame() = 0; virtual unsigned framePos() const = 0; + virtual unsigned frameTime() const = 0; virtual float* getBuffer(Port, unsigned long nframes) = 0; virtual void registerClient() = 0; virtual Port registerOutPort(const QString& name, bool midi) = 0; virtual Port registerInPort(const QString& name, bool midi) = 0; - virtual unsigned getCurFrame() = 0; virtual int realtimePriority() const = 0; // return zero if not realtime virtual void startTransport() = 0; virtual void stopTransport() = 0; diff --git a/muse/muse/driver/dummyaudio.cpp b/muse/muse/driver/dummyaudio.cpp index 796e8b58..85997824 100644 --- a/muse/muse/driver/dummyaudio.cpp +++ b/muse/muse/driver/dummyaudio.cpp @@ -57,6 +57,9 @@ class DummyAudio : public AudioDriver { virtual unsigned framePos() const { return lrint((curTime()-startTime) * AL::sampleRate); } + virtual unsigned frameTime() const { + return lrint(curTime() * AL::sampleRate); + } virtual float* getBuffer(Port /*port*/, unsigned long nframes) { diff --git a/muse/muse/driver/jackaudio.h b/muse/muse/driver/jackaudio.h index 43da338b..98d8e493 100644 --- a/muse/muse/driver/jackaudio.h +++ b/muse/muse/driver/jackaudio.h @@ -77,13 +77,14 @@ class JackAudio : public AudioDriver { void graphChanged(); virtual void putEvent(Port, const MidiEvent&); virtual void startMidiCycle(Port); - virtual unsigned int getCurFrame() { return pos.frame; } +// virtual unsigned int getCurFrame() { return pos.frame; } virtual unsigned framePos() const { return pos.frame + jack_frames_since_cycle_start(_client); } - unsigned lastFrameTime() { return jack_last_frame_time(_client); } - unsigned framesSinceCyleStart() { return jack_frames_since_cycle_start(_client); } +// unsigned lastFrameTime() { return jack_last_frame_time(_client); } +// unsigned framesSinceCyleStart() { return jack_frames_since_cycle_start(_client); } + virtual unsigned frameTime() const { return jack_frame_time(_client); } }; #endif diff --git a/muse/muse/midievent.cpp b/muse/muse/midievent.cpp index 8dbf4dc2..88539a1c 100644 --- a/muse/muse/midievent.cpp +++ b/muse/muse/midievent.cpp @@ -79,9 +79,13 @@ MidiEvent::MidiEvent(unsigned tick, int channel, const Event& e) void MidiEvent::dump() const { printf("chan:%d ", _channel+1); - if (_type == ME_NOTEON) { // NoteOn + if (_type == ME_NOTEON) { QString s = pitch2string(_a); - printf("NoteOn %3s(0x%02x) %3d\n", s.toLatin1().data(), _a, _b); + printf("NoteOn %3s(0x%02x) %3d\n", s.toLatin1().data(), _a, _b); + } + else if (_type == ME_NOTEOFF) { + QString s = pitch2string(_a); + printf("NoteOff %3s(0x%02x) %3d\n", s.toLatin1().data(), _a, _b); } else if (_type == ME_SYSEX) { printf("SysEx len %d ", len()); diff --git a/muse/muse/midififo.cpp b/muse/muse/midififo.cpp index 4bb43346..dbf16942 100644 --- a/muse/muse/midififo.cpp +++ b/muse/muse/midififo.cpp @@ -48,6 +48,25 @@ MidiEvent MidiFifo::get() return event; } +//--------------------------------------------------------- +// peek +//--------------------------------------------------------- + +MidiEvent MidiFifo::peek() + { + return fifo[rIndex]; + } + +//--------------------------------------------------------- +// remove +//--------------------------------------------------------- + +void MidiFifo::remove() + { + rIndex = (rIndex + 1) % MIDI_FIFO_SIZE; + q_atomic_decrement(&size); + } + //--------------------------------------------------------- // put // return true on fifo overflow diff --git a/muse/muse/midififo.h b/muse/muse/midififo.h index e5964e99..d8b95bcc 100644 --- a/muse/muse/midififo.h +++ b/muse/muse/midififo.h @@ -40,6 +40,8 @@ class MidiFifo { MidiFifo() { clear(); } bool put(const MidiEvent& event); // returns true on fifo overflow MidiEvent get(); + MidiEvent peek(); + void remove(); bool isEmpty() const { return size == 0; } void clear() { size = 0, wIndex = 0, rIndex = 0; } }; diff --git a/muse/muse/midiinport.cpp b/muse/muse/midiinport.cpp index 42ceff2c..878a5797 100644 --- a/muse/muse/midiinport.cpp +++ b/muse/muse/midiinport.cpp @@ -102,7 +102,7 @@ void MidiInPort::eventReceived(snd_seq_event_t* ev) { MidiEvent event; event.setB(0); - event.setTime(audioDriver->framePos()); + event.setTime(audio->timestamp()); switch(ev->type) { case SND_SEQ_EVENT_NOTEON: @@ -211,6 +211,7 @@ void MidiInPort::afterProcess() //--------------------------------------------------------- // beforeProcess +// "freeze" fifo for this process cycle //--------------------------------------------------------- void MidiInPort::beforeProcess() @@ -221,6 +222,9 @@ void MidiInPort::beforeProcess() //--------------------------------------------------------- // getEvents // called from jack process context +// This method can be called multiple times in a process +// cycle so we have to empty the fifo at +// "afterProcess()". //--------------------------------------------------------- void MidiInPort::getEvents(unsigned, unsigned, int ch, MidiEventList* dst) diff --git a/muse/muse/synth.cpp b/muse/muse/synth.cpp index 7c6de9f1..14610669 100644 --- a/muse/muse/synth.cpp +++ b/muse/muse/synth.cpp @@ -529,14 +529,14 @@ void MessSynthIF::getData(MidiEventList* el, unsigned pos, int ports, unsigned n for (int port = 0; port < ports; ++port) memset(buffer[port], 0, n * sizeof(float)); - // seems to be negative when sequencer not running, still - // working when entering notes from editor though. weird :-) (ml) - int curPos = pos; int endPos = pos + n; - while (!synti->putFifo.isEmpty()) - putEvent(synti->putFifo.get()); + while (!synti->putFifo.isEmpty()) { + if (putEvent(synti->putFifo.peek())) + break; + synti->putFifo.remove(); + } if (ports >= channels()) { iMidiEvent i = el->begin(); @@ -577,9 +577,11 @@ bool MessSynthIF::putEvent(const MidiEvent& ev) if (_mess) { rv = _mess->processEvent(ev); if (midiOutputTrace && !rv) { - printf("<%s>", synti->name().toLatin1().data()); + printf("MidiOut<%s>", synti->name().toLatin1().data()); ev.dump(); } +if (rv) + printf("SYNT BUSY\n"); } return rv; } @@ -591,7 +593,8 @@ bool MessSynthIF::putEvent(const MidiEvent& ev) void SynthI::collectInputData() { bufferEmpty = false; - unsigned pos = audio->pos().frame(); + unsigned pos = audio->isPlaying() ? audio->pos().frame() + : audio->timestamp(); _sif->getData(&_schedEvents, pos, channels(), segmentSize, buffer); } -- cgit v1.2.3