[Sv1-commits] SF.net SVN: sv1:[1468] sonic-visualiser/trunk
Brought to you by:
cannam
From: <ca...@us...> - 2009-02-25 11:15:25
|
Revision: 1468 http://sv1.svn.sourceforge.net/sv1/?rev=1468&view=rev Author: cannam Date: 2009-02-25 11:15:22 +0000 (Wed, 25 Feb 2009) Log Message: ----------- * Somewhat better MIDI-based time instant timing Modified Paths: -------------- sonic-visualiser/trunk/data/midi/MIDIInput.cpp sonic-visualiser/trunk/data/midi/MIDIInput.h sonic-visualiser/trunk/framework/MainWindowBase.cpp sonic-visualiser/trunk/framework/MainWindowBase.h sonic-visualiser/trunk/sv/main/MainWindow.cpp sonic-visualiser/trunk/sv/main/MainWindow.h Added Paths: ----------- sonic-visualiser/trunk/base/FrameTimer.h Added: sonic-visualiser/trunk/base/FrameTimer.h =================================================================== --- sonic-visualiser/trunk/base/FrameTimer.h (rev 0) +++ sonic-visualiser/trunk/base/FrameTimer.h 2009-02-25 11:15:22 UTC (rev 1468) @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2009 QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _FRAME_TIMER_H_ +#define _FRAME_TIMER_H_ + +/** + * A trivial interface for things that permit retrieving "the current + * frame". Implementations of this interface are used, for example, + * for timestamping incoming MIDI events when tapping to MIDI. + */ + +class FrameTimer +{ +public: + virtual unsigned long getFrame() const = 0; +}; + +#endif Modified: sonic-visualiser/trunk/data/midi/MIDIInput.cpp =================================================================== --- sonic-visualiser/trunk/data/midi/MIDIInput.cpp 2009-02-24 17:53:01 UTC (rev 1467) +++ sonic-visualiser/trunk/data/midi/MIDIInput.cpp 2009-02-25 11:15:22 UTC (rev 1468) @@ -17,8 +17,9 @@ #include "rtmidi/RtMidi.h" -MIDIInput::MIDIInput(QString name) : +MIDIInput::MIDIInput(QString name, FrameTimer *timer) : m_rtmidi(), + m_frameTimer(timer), m_buffer(1023) { try { @@ -48,10 +49,13 @@ MIDIInput::callback(double timestamp, std::vector<unsigned char> *message) { std::cerr << "MIDIInput::callback(" << timestamp << ")" << std::endl; - unsigned long deltaTime = 0; - if (timestamp > 0) deltaTime = (unsigned long)(timestamp * 100000); //!!! for now! + // In my experience so far, the timings passed to this function + // are not reliable enough to use. We request instead an audio + // frame time from whatever FrameTimer we have been given, and use + // that as the event time. if (!message || message->empty()) return; - MIDIEvent ev(deltaTime, + unsigned long t = m_frameTimer->getFrame(); + MIDIEvent ev(t, (*message)[0], message->size() > 1 ? (*message)[1] : 0, message->size() > 2 ? (*message)[2] : 0); Modified: sonic-visualiser/trunk/data/midi/MIDIInput.h =================================================================== --- sonic-visualiser/trunk/data/midi/MIDIInput.h 2009-02-24 17:53:01 UTC (rev 1467) +++ sonic-visualiser/trunk/data/midi/MIDIInput.h 2009-02-25 11:15:22 UTC (rev 1468) @@ -21,6 +21,7 @@ #include <vector> #include "base/RingBuffer.h" +#include "base/FrameTimer.h" class RtMidiIn; @@ -29,7 +30,7 @@ Q_OBJECT public: - MIDIInput(QString name); + MIDIInput(QString name, FrameTimer *timer); virtual ~MIDIInput(); bool isOK() const { return m_rtmidi != 0; } @@ -43,6 +44,7 @@ protected: RtMidiIn *m_rtmidi; + FrameTimer *m_frameTimer; static void staticCallback(double, std::vector<unsigned char> *, void *); void callback(double, std::vector<unsigned char> *); Modified: sonic-visualiser/trunk/framework/MainWindowBase.cpp =================================================================== --- sonic-visualiser/trunk/framework/MainWindowBase.cpp 2009-02-24 17:53:01 UTC (rev 1467) +++ sonic-visualiser/trunk/framework/MainWindowBase.cpp 2009-02-25 11:15:22 UTC (rev 1468) @@ -103,7 +103,9 @@ using std::set; -MainWindowBase::MainWindowBase(bool withAudioOutput, bool withOSCSupport) : +MainWindowBase::MainWindowBase(bool withAudioOutput, + bool withOSCSupport, + bool withMIDIInput) : m_document(0), m_paneStack(0), m_viewManager(0), @@ -214,7 +216,9 @@ m_labeller = new Labeller(labellerType); m_labeller->setCounterCycleSize(cycle); - m_midiInput = new MIDIInput(QApplication::applicationName()); + if (withMIDIInput) { + m_midiInput = new MIDIInput(QApplication::applicationName(), this); + } if (withOSCSupport) { m_oscQueueStarter = new OSCQueueStarter(this); @@ -710,14 +714,22 @@ } } -void -MainWindowBase::insertInstant() +// FrameTimer method + +unsigned long +MainWindowBase::getFrame() const { if (m_playSource && m_playSource->isPlaying()) { - insertInstantAt(m_playSource->getCurrentPlayingFrame()); + return m_playSource->getCurrentPlayingFrame(); } else { - insertInstantAt(m_viewManager->getPlaybackFrame()); + return m_viewManager->getPlaybackFrame(); } +} + +void +MainWindowBase::insertInstant() +{ + insertInstantAt(getFrame()); } void Modified: sonic-visualiser/trunk/framework/MainWindowBase.h =================================================================== --- sonic-visualiser/trunk/framework/MainWindowBase.h 2009-02-24 17:53:01 UTC (rev 1467) +++ sonic-visualiser/trunk/framework/MainWindowBase.h 2009-02-25 11:15:22 UTC (rev 1468) @@ -27,6 +27,7 @@ #include "view/ViewManager.h" #include "base/PropertyContainer.h" #include "base/RecentFiles.h" +#include "base/FrameTimer.h" #include "layer/LayerFactory.h" #include "transform/Transform.h" #include "SVFileReader.h" @@ -69,12 +70,12 @@ * to use different subclasses retaining the same general structure. */ -class MainWindowBase : public QMainWindow +class MainWindowBase : public QMainWindow, public FrameTimer { Q_OBJECT public: - MainWindowBase(bool withAudioOutput, bool withOSCSupport); + MainWindowBase(bool withAudioOutput, bool withOSCSupport, bool withMIDIInput); virtual ~MainWindowBase(); enum AudioFileOpenMode { @@ -104,6 +105,9 @@ virtual bool saveSessionFile(QString path); + /// Implementation of FrameTimer interface method + virtual unsigned long getFrame() const; + signals: // Used to toggle the availability of menu actions void canAddPane(bool); Modified: sonic-visualiser/trunk/sv/main/MainWindow.cpp =================================================================== --- sonic-visualiser/trunk/sv/main/MainWindow.cpp 2009-02-24 17:53:01 UTC (rev 1467) +++ sonic-visualiser/trunk/sv/main/MainWindow.cpp 2009-02-25 11:15:22 UTC (rev 1468) @@ -119,7 +119,7 @@ MainWindow::MainWindow(bool withAudioOutput, bool withOSCSupport) : - MainWindowBase(withAudioOutput, withOSCSupport), + MainWindowBase(withAudioOutput, withOSCSupport, true), m_overview(0), m_mainMenusCreated(false), m_paneMenu(0), @@ -137,6 +137,7 @@ m_soloAction(0), m_soloModified(false), m_prevSolo(false), + m_lastInsertedMIDITime(0), m_rwdStartAction(0), m_rwdAction(0), m_ffwdAction(0), @@ -1666,6 +1667,8 @@ connect(m_playAction, SIGNAL(triggered()), this, SLOT(play())); connect(m_playSource, SIGNAL(playStatusChanged(bool)), m_playAction, SLOT(setChecked(bool))); + connect(m_playSource, SIGNAL(playStatusChanged(bool)), + this, SLOT(playStatusChanged(bool))); connect(this, SIGNAL(canPlay(bool)), m_playAction, SLOT(setEnabled(bool))); m_ffwdAction = toolbar->addAction(il.load("ffwd"), @@ -3406,16 +3409,26 @@ void MainWindow::midiEventsAvailable() { - //!!! for now. but this won't do -- we are passing a signal/slot - //!!! connection across threads here, so timing will not be good - //!!! -- we do need to use the original midi event timestamp - MIDIEvent ev(m_midiInput->readEvent()); - if (ev.getMessageType() == MIDIConstants::MIDI_NOTE_ON) { - insertInstant(); + // This is called through a serialised signal/slot invocation + // (across threads). It could happen quite some time after the + // event was actually received, which is why event timestamping + // happens in the MIDI input class and not here. + while (m_midiInput->getEventsAvailable() > 0) { + MIDIEvent ev(m_midiInput->readEvent()); + if (ev.getMessageType() != MIDIConstants::MIDI_NOTE_ON) { + continue; + } + insertInstantAt(ev.getTime()); } } void +MainWindow::playStatusChanged(bool playing) +{ + m_lastInsertedMIDITime = -1.0; // <0 means "never during this playback" +} + +void MainWindow::layerRemoved(Layer *layer) { setupExistingLayersMenus(); Modified: sonic-visualiser/trunk/sv/main/MainWindow.h =================================================================== --- sonic-visualiser/trunk/sv/main/MainWindow.h 2009-02-24 17:53:01 UTC (rev 1467) +++ sonic-visualiser/trunk/sv/main/MainWindow.h 2009-02-25 11:15:22 UTC (rev 1468) @@ -166,6 +166,7 @@ virtual void handleOSCMessage(const OSCMessage &); virtual void midiEventsAvailable(); + virtual void playStatusChanged(bool); virtual void website(); virtual void help(); @@ -205,6 +206,8 @@ bool m_soloModified; bool m_prevSolo; + double m_lastInsertedMIDITime; + QFrame *m_playControlsSpacer; int m_playControlsWidth; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |