管理 MIDI 数据块

使用数据块传递系统独占消息 (使用 midiOutLongMsgmidiInAddBuffer 函数) 和流缓冲区 (使用 midiStreamOut 函数) 的应用程序必须持续向设备驱动程序提供数据块,直到播放或录制完成。

即使使用单个数据块,应用程序也必须能够确定设备驱动程序何时完成数据块,以便它可以释放与数据块和标头结构关联的内存。 可以使用三种方法来确定设备驱动程序何时使用数据块完成:

  • 指定一个回调函数,以在完成数据块时接收驱动程序发送的消息。 若要获取带有时间戳的 MIDI 输入数据,必须使用回调函数。
  • 将事件回调 (仅用于输出) 。
  • 使用窗口或线程回调接收驱动程序在完成数据块时发送的消息。

如果应用程序在需要时未向设备驱动程序获取数据块,则播放时可能会出现可听见的间隙或丢失传入的录制信息。 应用程序至少应使用双重缓冲方案,使至少在设备驱动程序之前保留一个数据块。

使用回调函数处理驱动程序消息

可以编写自己的回调函数来处理设备驱动程序发送的消息。 若要使用回调函数,请在 dwFlags 参数中指定CALLBACK_FUNCTION标志,并在 midiInOpenmidiOutOpen 函数的 dwCallback 参数中指定回调函数的地址。

发送到回调函数的消息类似于发送到窗口的消息,只不过它们具有两个双字参数,而不是一个无符号整数参数和一个双字参数。 有关这些消息的详细信息,请参阅发送System-Exclusive消息和管理 MIDI 记录

使用以下方法之一将实例数据从应用程序传递到回调函数:

  • 使用打开设备驱动程序的函数的 dwCallbackInstance 参数。
  • 使用 MIDIHDR 结构的 dwUser 成员,该结构标识要发送到 MIDI 设备驱动程序的数据块。

如果需要超过 32 位的实例数据,请传递包含附加信息的 结构的地址。

使用事件回调处理驱动程序消息

若要使用事件回调,请使用 CreateEvent 函数检索事件的句柄,并在调用 midiOutOpen 函数时指定CALLBACK_EVENT。

事件回调是由可能导致函数回调的任何内容设置的。 与回调函数和窗口或线程回调不同,事件回调不接收特定的关闭、完成或打开通知。 因此,应用程序可能需要在事件发生后检查它正在等待的进程的状态。

有关事件回调的详细信息,请参阅 使用事件回调管理缓冲播放

使用窗口或线程回调处理驱动程序消息

若要使用窗口回调,请在 dwFlags 参数中指定CALLBACK_WINDOW标志,并在 midiInOpenmidiOutOpen 函数的 dwCallback 参数的低序字中指定窗口句柄。 驱动程序消息将发送到 由 dwCallback 中的句柄标识的窗口的窗口过程函数。

同样,若要使用线程回调,请在调用 midiInOpenmidiOutOpen 时指定CALLBACK_THREAD标志和线程标识符。 在这种情况下,消息将发布到指定的线程,而不是发布到窗口。

发送到窗口或线程回调的消息特定于所使用的 MIDI 设备。 有关这些消息的详细信息,请参阅发送System-Exclusive消息和管理 MIDI 记录

MIDI 服务