From 81182b5bf69e06f67b3ccbca46860ac8e6387d2f Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 8 Jun 2014 11:18:18 +0200 Subject: prepare MIDI latency measurement (backend) --- libs/ardour/mididm.cc | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 libs/ardour/mididm.cc (limited to 'libs/ardour/mididm.cc') diff --git a/libs/ardour/mididm.cc b/libs/ardour/mididm.cc new file mode 100644 index 0000000000..6549544efb --- /dev/null +++ b/libs/ardour/mididm.cc @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2013-2014 Robin Gareus + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "ardour/mididm.h" +#include "ardour/port_engine.h" + +using namespace ARDOUR; + +MIDIDM::MIDIDM (framecnt_t sample_rate) + : _sample_rate (sample_rate) + , _monotonic_cnt (sample_rate) + , _last_signal_tme (0) + , _cnt_total (0) + , _dly_total (0) + , _min_delay (INT32_MAX) + , _max_delay (0) + , _avg_delay (0) + , _var_m (0) + , _var_s (0) +{ + +} + + +int MIDIDM::process (pframes_t nframes, PortEngine &pe, void *midi_in, void *midi_out) +{ + /* send midi event */ + uint8_t obuf[3]; + obuf[0] = 0xf2; + obuf[1] = (_monotonic_cnt) & 0x7f; + obuf[2] = (_monotonic_cnt >> 7) & 0x7f; + + pe.midi_clear(midi_out); + pe.midi_event_put (midi_out, 0, obuf, 3); + + /* process incoming */ + const pframes_t nevents = pe.get_midi_event_count (midi_in); + for (pframes_t n = 0; n < nevents; ++n) { + pframes_t timestamp; + size_t size; + uint8_t* buf; + pe.midi_event_get (timestamp, size, &buf, midi_in, n); + + if (size != 3 || buf[0] != 0xf2 ) continue; + + _last_signal_tme = _monotonic_cnt; + + /* calculate time difference */ +#define MODX (16384) // 1<<(2*7) +#define MASK (0x3fff) // MODX - 1 + const int64_t tc = (_monotonic_cnt + timestamp) & MASK; + const int64_t ti = (buf[2] << 7) | buf[1]; + const int64_t tdiff = (MODX + tc - ti) % MODX; + + /* running variance */ + if (_cnt_total == 0) { + _var_m = tdiff; + } else { + const double var_m1 = _var_m; + _var_m = _var_m + ((double)tdiff - _var_m) / (double)(_cnt_total + 1); + _var_s = _var_s + ((double)tdiff - _var_m) * ((double)tdiff - var_m1); + } + /* average and mix/max */ + ++_cnt_total; + _dly_total += tdiff; + _avg_delay = _dly_total / _cnt_total; + if (tdiff < _min_delay) _min_delay = tdiff; + if (tdiff > _max_delay) _max_delay = tdiff; + } + + _monotonic_cnt += nframes; + return 0; +} -- cgit v1.2.3