首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MCI play功能只能播放一次MIDI文件。

MCI play功能只能播放一次MIDI文件。
EN

Stack Overflow用户
提问于 2022-07-15 20:55:48
回答 1查看 121关注 0票数 1

我用的是Delphi 10.2。

我希望我的一个小音乐程序能够播放MIDI文件。我想使用MCI (媒体控制接口),因为它应该比更低级别的MIDI API更简单。我找到了下面的代码,只要我只选择一次给定的MIDI文件,它就能正常运行。

我的表单上有一个TFileListBox,只要不重复,我就可以选择和播放任意数量的MIDI文件。一旦我第二次选择了一个MIDI文件,它就会停止播放。

这可能是一个问题,我没有用mciSendCommand()调用MCI_CLOSE,但是如果我尝试这样做,我就会得到一个错误,例如:

无法将类型(NULL)的变量转换为类型(Int64)

代码语言:javascript
复制
Function TForm1.PlayMidiFile(FileName: string): Word;
// http://www.delphigroups.info/2/3e/176031.html
// You need to add the MMSYSTEM unit in your USES clause.
var
  wDeviceID: Integer;
  dwReturn : Word;
  mciOpen  : TMCI_Open_Parms;
  mciPlay  : TMCI_Play_Parms;
  mciStat  : TMCI_Status_Parms;
  mciSeq   : TMCI_Seq_Set_Parms;
begin
  // Open the device by specifying the device and filename.
  // MCI will attempt to choose the MIDI mapper as the output port.
  mciOpen.lpstrDeviceType := 'sequencer';
  mciOpen.lpstrElementName := PChar(FileName);
  dwReturn := mciSendCommand($0, MCI_OPEN, MCI_OPEN_TYPE or MCI_OPEN_ELEMENT, LongInt(@mciOpen));
  if dwReturn <> 0 then
    Result := dwReturn
  else begin
    // The device opened successfully; get the device ID.
    wDeviceID := mciOpen.wDeviceID;
    // Check if the output port is the MIDI mapper.
    mciStat.dwItem := MCI_SEQ_STATUS_PORT;
    dwReturn := mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, LongInt(@mciStat));
    if dwReturn <> 0 then begin
      { close if not succeeding }
      mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
      Result := dwReturn;
    end else begin
      // Begin playback. The window procedure function for the parent
      // window will be notified with an MM_MCINOTIFY message when
      // playback is complete. At this time, the window procedure closes
      // the device.
      mciPlay.dwCallback := Application.Handle;
      dwReturn := mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY, LongInt(@mciPlay));
      if dwReturn <> 0 then begin
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        Result := dwReturn;
      end;
    end;
  end;
end;
EN

回答 1

Stack Overflow用户

发布于 2022-07-16 08:27:54

当打开设备时代码失败..。dwReturn值为265

MCI错误265为MCIERR_DEVICE_OPEN (“此应用程序已将设备名称用作别名。请使用唯一别名”)。当您使用完MCI设备时,始终关闭它。

我尝试在代码的末尾放置一个MCI_CLOSE命令,比如mciSendCommand(wDeviceID, MCI_CLOSE, 0, 0)。结果是midifile没有播放。就像在程序到达播放文件之前设备已经关闭一样。

是的,这正是正在发生的事情。您没有在MCI_WAIT命令上使用MCI_PLAY标志,因此回放是异步的。在MCI_CLOSE结束时调用PlayMidiFile()将终止播放。

由于您使用的是MCI_NOTIFY,所以可以在播放结束时关闭MM_MCINOTIFY处理程序中的设备。

另一方面,如果我将

放在单独的按钮上(并使wDeviceID成为全局变体),我就能够按我想要的方式播放相同的midi文件。然后,我尝试将我的wDeviceIDForm.Create中初始化为一个虚拟值(999),并像这样启动代码:if wDeviceID <> 999 then mciSendCommand(wDeviceID, MCI_CLOSE, 0, 0)。现在,代码函数OK和相同的midi文件可以一次又一次地播放。

是的,如果设备是打开的,您应该在PlayMidiFile()开头停止并关闭该设备。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72999516

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档