所以我試圖在C#中使用midiOutShortMsg()播放單個音符。問題是沒有聲音播放。我已經想出了一個方法來演奏音符,將midiOutShortMsg()放在從i = 0到10000的for循環中。但是我不相信API是如何工作的。C#midioutshortmsg沒有聲音
在後面的項目中,我想將MIDI實現爲Kinect項目,並讓for循環延遲Kinect的實時反饋。所以for循環方法是不行的。
下面是我用來播放音符的代碼,如果您註釋掉for循環,則不會播放聲音。任何幫助,將不勝感激。
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace MIDITest
{
[StructLayout(LayoutKind.Sequential)]
public struct MidiOutCaps
{
public UInt16 wMid;
public UInt16 wPid;
public UInt32 vDriverVersion;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst = 32)]
public String szPname;
public UInt16 wTechnology;
public UInt16 wVoices;
public UInt16 wNotes;
public UInt16 wChannelMask;
public UInt32 dwSupport;
}
class Program
{
// MCI INterface
[DllImport("winmm.dll")]
private static extern long mciSendString(string command,
StringBuilder returnValue, int returnLength,
IntPtr winHandle);
// Midi API
[DllImport("winmm.dll")]
private static extern int midiOutGetNumDevs();
[DllImport("winmm.dll")]
private static extern int midiOutGetDevCaps(Int32 uDeviceID,
ref MidiOutCaps lpMidiOutCaps, UInt32 cbMidiOutCaps);
[DllImport("winmm.dll")]
private static extern int midiOutOpen(ref int handle,
int deviceID, MidiCallBack proc, int instance, int flags);
[DllImport("winmm.dll")]
private static extern int midiOutShortMsg(int handle,
int message);
[DllImport("winmm.dll")]
private static extern int midiOutClose(int handle);
private delegate void MidiCallBack(int handle, int msg,
int instance, int param1, int param2);
static void Main()
{
int handle = 0;
var numDevs = midiOutGetNumDevs();
Console.WriteLine("You have {0} midi output devices", numDevs);
MidiOutCaps myCaps = new MidiOutCaps();
var res = midiOutGetDevCaps(0, ref myCaps,
(UInt32)Marshal.SizeOf(myCaps));
res = midiOutOpen(ref handle, 0, null, 0, 0);
byte[] data = new byte[4];
data[0] = 0x90;
data[1] = 50;
data[2] = 111;
uint msg = BitConverter.ToUInt32(data, 0);
for (int i = 0; i < 10000; i++)
{
// both hard coding the message and creating it with byte doesn't work
//res = midiOutShortMsg(handle, 0x007F4A90);
res = midiOutShortMsg(handle, (int)msg);
}
res = midiOutClose(handle);
Console.ReadLine();
}
}
}
我認爲這種方法是錯誤的。使用現有的MIDI庫來做到這一點。我非常尊重[naudio](https://github.com/naudio/NAudio)。它已經包含了一個MIDI IO管理包裝,應該經過充分測試。爲什麼不使用它,而不是浪費大量的時間來編寫一個midi包裝,擔心字節排序等?它可以爲您節省大量時間,並提供開箱即用的全面應用支持。您可以輕鬆地將它嵌入您的項目中(https://www.nuget.org/packages/NAudio/)。 – spender
嗨斯佩爾德,非常感謝你的迴應!我今天一直在用naudio工作,但是我發現播放單音符也需要使用System.Threading.Thread.Sleep()。而且我也遇到了同樣的問題,播放單個音符會停止整個節目並且沒有播放聲音。你會碰巧知道任何解決方法嗎? – Shinsuke