ALSA 音序器:使用高速 MIDI 避免输入缓冲区溢出

Posted

技术标签:

【中文标题】ALSA 音序器:使用高速 MIDI 避免输入缓冲区溢出【英文标题】:ALSA sequencer: Avoid input buffer overrun with High-Speed MIDI 【发布时间】:2020-07-11 23:38:13 【问题描述】:

我想通过 ALSA 定序器发送大型 SysEx 消息(可能是几兆字节): 目前我将它们分成几个 ALSA 事件,并像这样循环发送它们:

    while (1) 
      result = snd_seq_event_output_direct( seq, const_cast<snd_seq_event_t*>(&ev) );
      if (result != -EAGAIN && result != -EWOULDBLOCK)
        break;
      snd_seq_sync_output_queue( seq );
      //std::this_thread::sleep_for(sleeptime);
    

此循环确保所有事件都从发送客户端/端口发送。但是一旦 snd_seq_event_output_direct 返回 -EAGAIN,接收客户端的输入池就会被清空,无条件地丢弃大约 70 个事件,而不仅仅是被拒绝的数据包。由于发送客户端没有关于发送到接收客户端的事件的信息,它无法知道有多少数据包丢失并重新传输。

有人建议将传输速率限制为 MIDI 1.0 硬件规范定义的 31.25 kbit/s。但这不一定是一个好主意,因为 MIDI 协议和传输速度实际上已经被更快的以太网、蓝牙和 USB 硬件层的支持所分割。 MIDI 2.0 规范明确独立于传输速率,并建议开发/使用具有更高传输速率的硬件层。

所以我的问题是:如何在不人为限制传输的情况下可靠地将大量 MIDI 数据至少传输到软件客户端?

我想偷看接收客户端的输入池,但我不知道该怎么做。目前可以找到接收端口的输入队列的信息,但是不知道怎么处理。

【问题讨论】:

【参考方案1】:

ALSA 定序器专为实时发送消息而设计。无法根据接收器的缓冲区状态来限制传输。

如果您不想将速度限制为 MIDI 1.0,那么您唯一的选择就是改用 ALSA RawMIDI 接口。

【讨论】:

对不起,这不是我想要的答案。 My Library 是 RtMidi 的一个分支,专为实时 MIDI 而设计,不支持 RawMIDI 接口。此外,最近修复了 RtMidi 的 CoreMIDI 和 WindowsMM,以支持大型 SysEx 消息。在这里,Linux 支持不好。 其实实时并不意味着立即。如果我必须将我的应用程序限制为我什至无法检测到的东西,这不是实时证明。 正如我所读到的,现在 RawMIDI 完全打开设备,这是我极力避免的事情。

以上是关于ALSA 音序器:使用高速 MIDI 避免输入缓冲区溢出的主要内容,如果未能解决你的问题,请参考以下文章

什么是MIDI设备

为啥 MIDI 音序器无法在 Windows 10 上第二次播放

如何获取对非默认 MIDI 音序器的引用?

大跌眼镜:macOS 和 iOS 的 MIDI 音序精确性和稳定性远超 MIDI 音序器硬件

Java MIDI 音序器永无止境

如果连接到外部 Midi 输出设备,Java 定序器会延迟循环