我用的是Delphi 10.2。
我希望我的一个小音乐程序能够播放MIDI文件。我想使用MCI (媒体控制接口),因为它应该比更低级别的MIDI API更简单。我找到了下面的代码,只要我只选择一次给定的MIDI文件,它就能正常运行。
我的表单上有一个TFileListBox,只要不重复,我就可以选择和播放任意数量的MIDI文件。一旦我第二次选择了一个MIDI文件,它就会停止播放。
这可能是一个问题,我没有用mciSendCommand()调用MCI_CLOSE,但是如果我尝试这样做,我就会得到一个错误,例如:
无法将类型(NULL)的变量转换为类型(Int64)
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;发布于 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文件。然后,我尝试将我的wDeviceID在Form.Create中初始化为一个虚拟值(999),并像这样启动代码:if wDeviceID <> 999 then mciSendCommand(wDeviceID, MCI_CLOSE, 0, 0)。现在,代码函数OK和相同的midi文件可以一次又一次地播放。
是的,如果设备是打开的,您应该在PlayMidiFile()开头停止并关闭该设备。
https://stackoverflow.com/questions/72999516
复制相似问题