Задержки MIDI

я, например, барабанщик, но внутри меня живет диджей, который ненавидит звук акустических барабанов
 
Уже давно как многие устройства поддерживают Running Status. Даже если нажать (ИЛИ отпустить) 10 нот, то передастся всего навсего 21 байт: 9к nn vv nn vv … nn vv (к - MIDI канал, nn - нота, vv - динамика). Ну или же 31 байт (9к nn vv 00 nn vv 00 … nn vv 00 — не знаю, может ли быть так?). Если Running Status не поддерживает, то 9к nn vv 9к nn vv… или 9к nn vv 00 9к nn vv 00… — итого 30 или 40 байт). Получается, в теории, при скорости 32 байта в миллисекунду, т.е. 31,25 киБ/сек, минимальная задержка между первым и последним событиями может доходить до 2 мсек… Но вот про размер пакета в 8 байт… хм… А что мешает устройству объединить пару таких событий в один пакет?
Кстати, мне приходилось вручную шестнадцатеричным редактором править MIDI-файлы (SMF). Там между MIDI-событиями может вставляться от одного до нескольких байт — время между событиями в "tick`ах" (00 - нет расстояния, т.е. в секвенсоре они отображаются одновременно). Если в процессе такой правки меняется итоговый размер файла, то тогда ещё нужно и в MTrk-заголовке поправить это число.
Ещё нужно учесть, что некоторые устройства отправляют Active Sensing (FE) и Timing Clock (F8), вот тут-то при живой игре, помимо того, что пальцами трудно столько клавиш в одном tick`е нажать (не говоря уже о том, чтоб воткнуть в один пакет), так ещё и эти System Realtime сообщения могут совсем незначительно сдвинуть сообщения нот/CC/пр.… А вот что касается tick`ов и темпа – О – вот это интересно рассчитать:
при 320 BPM одна доля (один удар) или, проще говоря, четверть должна быть равной 187,5 мсек.;
Если TPQN (PPQ) = 1680, то между tick`ами должно выходить около 0,1116 мсек.
Теперь вот думаем в один ли tick разместит одно/два/три события, когда за один пакет из 8 байт проходит 0,25 мсек, или же оно в одно время может на tick`и разделить, а в другое время - вместить?…
 
Последнее редактирование:
Получается, в теории, при скорости 32 байта в миллисекунду,
31.25 кбит в сек. Байт = 8 бит + стартовый и стоповый биты в аппаратном протоколе. Итого примерно три байта в мс. При 6-мсек асиобуфере через миди аппаратно можно пропихнуть не больше 19 байт. Хватит на сложный аккорд двумя руками.
 
  • Like
Реакции: «G~Li†ch»
Разбирайтесь!!!
Код:
struct VstMidiEvent
{
VstInt32 type;///< #kVstMidiType
VstInt32 byteSize;///< sizeof (VstMidiEvent)
VstInt32 deltaFrames;///< sample frames related to the current block start sample position
VstInt32 flags;///< @see VstMidiEventFlags
VstInt32 noteLength;///< (in sample frames) of entire note, if available, else 0
VstInt32 noteOffset;///< offset (in sample frames) into note from note start if available, else 0
char midiData[4];///< 1 to 3 MIDI bytes; midiData[3] is reserved (zero)
char detune;///< -64 to +63 cents; for scales other than 'well-tempered' ('microtuning')
char noteOffVelocity;///< Note Off Velocity [0, 127]
char reserved1;///< zero (Reserved for future use)
char reserved2;///< zero (Reserved for future use)
};
PS: буффер наполняется мидисобытиями, при считывании плагином буффер запрашивает по 3 bytes на сэмпл. Отсюда и считайте)))
 
  • Like
Реакции: Trasher и PianoIst
Оу, точно, килобит же… значит один восьмибайтовый пакет не за 0,25, а за 2 мсек. Если учесть, что это считали не в кибибитах, а в килобитах, то вообще за 2,56 мсек. Если уж последнее "синхронизировать" с аудиопериодами (audiosamples), то при 44100 Гц один пакет MIDI-данных (8 байт) будет ползти 112,896 периода, а при 48000 Гц — 122,88 периода. Если надо только 3 байта, то вообще выходит 42,336 и 46,08 периода соответственно…
Надо было вводить частоту дискретизации полностью синхронизирующейся с MIDI-протоколом (62,5кГц), чтоб было меньше этих дробей (и было бы ровно 160 периодов за пакет из 8 байт, или 20 за байт), вот только 1 период при такой ч.д. = 3 квинты; 27 секст; 21 септима; 36 октав. Но тут теперь MIDI 2.0 и уже другие скорости и надо другая ч.д.…
 
Последнее редактирование:
@PianoIst, извиняюсь, я тему быстренько прошуршал и видать недопонял сути вопроса.
Я только с vst работаю, и тут мидисобытия просто накапливаются из потока и при проходе в диспетчере сообщений заполняется только эта структура. Потоковый мидисигнал контролируется периодически событием времени для синхронизации потока с нужным хосту временем, но как это в коде работает неприходилось вникать.
Если сильно надо могу литературу поискать, у меня что-то такое было, но чисто программерское.
 
@Alex Longard, Интересно, я напрямую с VST_SDK никогда не работал. А, что в KONTAKT, что в JUSE, что в JSFX такого понятия как эвент вообще нет. Скорее всё-таки, сообщение.
А эвент уже формируется не хостом, а плагином самостоятельно, отводя, условно, объект под 0x9X > 0x8X цикл.
Вообще, конечно, интересно, как там с миди на стороне хоста, но это надо курить не VST_SDK, а ASIO_SDK. Оно, кстати, кажется, куда менее объемно. Но закапываться лень...
 
это надо курить не VST_SDK, а ASIO_SDK

В ASIO про миди ничего нет. Оно к нему отношения не имеет. Это все отдельная епархия, в винде - специальный WDM-драйвер, на Mac'е - CoreMIDI или как-то так.
 
@PianoIst, в juce наследуется класс audioeffect из vst sdk в котором инкапсулируется структура которую я скидывал выше, в самом juce есть методы для управления буферами и отдельно миди сообщений.
Там целая куча наследований и переопределений через виртуальные методы, меня на этом тормознуло изучение juce, я больше знаю внутрености vst sdk.
Asio это прямой доступ к звуковой карте, к миди неимеет никакого отношения, про это выше написал Rst7, он по звуковухам знает в сто раз больше меня)))
 

Вложения

  • Like
Реакции: Trasher
-- А можно встрять? :)
С какой такой радости тут всё ограничено NoteOn-NoteOFF ?
А динамика, афтертач, и прочие прелести?
 
  • Like
Реакции: Trasher
С какой такой радости тут всё ограничено NoteOn-NoteOFF ?
Мне кажется, что это просто визуально удобнее. А какая разница, какие там сообщения? главное — сколько их поступает с одного устройства. Или вы как раз про количество сообщений?
 
-- Так этих дополнительных может быть во много раз больше, чем NoteOn-NoteOFF.
А уж если полифоник афтерточ...
 
  • Like
Реакции: Trasher
за один пакет из 8 байт проходит 0,25
31.25 кбит в сек. Байт = 8 бит + стартовый и стоповый биты в аппаратном протоколе. Итого примерно три байта в мс. При 6-мсек асиобуфере через миди аппаратно можно пропихнуть не больше 19 байт.
Оу, точно, килобит же… значит один восьмибайтовый пакет не за 0,25, а за 2 мсек. Если учесть, что это считали не в кибибитах, а в килобитах, то вообще за 2,56 мсек
Опять неверные расчёты…

31248 бит/сек. ÷ 8 = 3906 байт/сек.;
за миллисекунду почти 4 байта, а пакет из 8 байт ≈ 2,048131 мсек. и за 6 мсек тогда должно вмещаться 23 полных байта. Если же выходит 19, значит сами MIDI-сообщения (включая значения — нот / Poly A.T. / CC / PC / Channel A.T / PB / System Common / System Realtime) идут со скоростью ≈ 26кбит/сек, что вводит в заблуждение!
Я вот точно тоже не знаю, как разрываются длинные SysEx`ы на восьмибайтовые пакеты — вставляется ли 0xF5 (SysEx continue) куда-нибудь в пакете?
[ F0 41 10 6A hh mm ll vv
] vv vv vv CS F7 … … … …
- или -
[ F0 41 10 6A hh mm ll vv
] F5 vv vv vv CS F7 … … …
- или -
[ F0 41 10 6A hh mm ll ??
] F5 vv vv vv vv CS F7 … …
- или -
[ F0 41 10 6A hh mm ll кс
] vv vv vv vv CS F7 … … кс
- или -
[ F0 41 10 6A hh mm ll кс
] F5 vv vv vv vv CS F7 …кс
CS – контрольная сумма (вернее, разность) у роландов; кс — контрольная сумма пакета, содержащего SysEx?
Так как же шлются SysEx`ы по MIDI-протоколу? Что-то мне вот подсказывает, что всё-таки первый вариант – чтоб не тратило лишние байты на передачу и так уже на столь малой скорости…
 
Последнее редактирование:
ну да, если ещё учесть лишний бит "старт" и бит "стоп", значит один байт MIDI-данных занимает 10 бит этой всей скорости. 3125 байт в секунду = 0,32 мсек за байт, то тогда да, 18,75 байт за 6 мсек.
+ время на реакцию на прерывание
Так, стоп, итоговая же скорость уже "стандартизирована". От неё и расчитываем. Фактически, внутри устройства оно должно предусматривать это так, чтоб в потоке скорость достигала 31250 бит/сек, иначе устройство нарушит "стандарт"…
При "старт … байт … стоп … старт … байт … стоп…" внутри устройства сами биты идут уж точно не 31250 бит в сек, а выше, это из-за этой задержки (…) между битом-старт/стоп и байтом по идее тормозится при передаче до 31250 бит/сек… Если в проводе (после передачи одного устройства / до приёма другим устройством) биты проходят с другой скоростью, то что же тогда значит "скорость потока" / "скорость передачи/приёма"? Как тогда назвать скорость данных в MIDI-кабеле?
 
Последнее редактирование:
«G~Li†ch»

Нет. Аппаратно мидиинтерфейс требует дополнительных два бита, чтобы понять когда началась-закончилась передача данных миди (собственно, байта информации). Потому делить не на 8 - а на 10. Получается ближе к 3-м байтам...
 
  • Like
Реакции: «G~Li†ch»
... раньше меня написали.
Реакция на прерывание - на ноге микросхемы приемника миди указывается, что буфер приема заполнем 8-мью информационными битами. Дальше это прерывание уже обрабатывается софтом драйвера миди. К 31.25 - к аппаратной прием-передаче -оно отношения не имеет.
 
Последнее редактирование:
  • Like
Реакции: «G~Li†ch»
НУ - ОК! В итоге подтверждены те самые 3 байта на ОДНО миди сообщение (не важно какое, но нас в первую очередь интересует Note On конечно, хотя @Long прав и последняя нота в аккорде из 10 нот может долететь значительно позже, чем просто 10х3 байта из-за того, что в это время можно ещё и ногами на две педали пару раз успеть нажать, что добавит ещё приличное кол-во данных в очереди).
Написано много, но ПО СУТИ 10-ая нота в аккорде может прозвучать быстрее чем через 10 мс после её нажатия - ИЛИ НЕТ?
10 мс - это ОЙ КАК далеко от обще принятой информации, что миди по входу даёт задержку НОЛЬ!
И самое то печальное в том, что с AD/DA мы задержку можем уменьшать с увеличением частоты дискретизации, а с миди сообщениями - НЕ МОЖЕМ!
 
И самое то печальное в том, что с AD/DA мы задержку можем уменьшать с увеличением частоты дискретизации, а с миди сообщениями - НЕ МОЖЕМ!

Это если MIDI продолжает ходить через последовательный интерфейс 31250. Если в цепочке этого интерфейса нет, то можно считать, что задержка равна нулю (все остальные способы сильно быстрее).
 
  • Like
Реакции: PianoIst
Хах, а ведь в этом "определяющем документе" USB-MIDI 1.0 сказано, что скорость USB в сотню раз выше MIDI, и к тому же допускает множество портов и виртуальных MIDI кабелей, а вот какая именно – не сказано! Может в действительности скорость USB-MIDI может быть не ограничена 38 килобитами, как COM Mode в ямахах…
Зато теперь стало понятно, как SysEx`ы передаются. Значит каждые 4 байта (32 бита) повторяется 0x4, до тех пор, пока в определённом месте не будет определён конец, и тогда передастся 0x5/0x6/0x7 в зависимости от положения F7… И ещё можно "недослав" его до конца воткнуть другое MIDI-событие (не только сообщениями System Realtime и Timing Clock), затем снова байт "продолжения SysEx`а" - 0x4 (?) и дальше слать пакеты с остальным содержимым SysEx`а — вставляются 4 байта вместо одного — 3F F8 xx xx.
А так же ли это сделано в простом не-USB-шном MIDI? Помню, что простой MIDI как-то позволял пропускать System Realtime (Start/Continue/Stop/Active Sensing) и Timing Clock, даже если SysEx ещё не дошёл, но вот каким образом? Может втупую пропускал байт за байтом через старт-стоп биты, типа:
¯F0_¯41_¯00_¯00_¯00_¯3A_¯FE_¯11_¯20_¯00_¯02_¯FA_¯15_¯00_¯00_¯00_¯04_¯34F7_ (¯ / _ = биты старт / стоп, FE — Active Sensing, FA - Start)?
 
Последнее редактирование:
Это если MIDI продолжает ходить через последовательный интерфейс 31250. Если в цепочке этого интерфейса нет, то можно считать, что задержка равна нулю (все остальные способы сильно быстрее).
Не понимаю как?
Как, если сам миди протокол подразумевает передачу миди сообщений ПОСЛЕДОВАТЕЛЬНО?
Какая разница с каой скоростью они долетят, если до и/или после выстроятся в очередь?
 

Сейчас просматривают