Итак, я пытаюсь играть в одну ноту в C#, используя midiOutShortMsg(). Проблема в том, что звук не воспроизводится. Единственный способ, которым я решил сыграть эту заметку, - это установить midiOutShortMsg() в цикле for от i = 0 до 10000. Но я не верю, что именно так должен работать API.C# midioutshortmsg no sound
Позже в проекте я хочу реализовать MIDI в проекте Kinect, а цикл for задерживает обратную связь Kinect в реальном времени. Таким образом, метод for loop - это не-go.
Ниже приведен код, который я использую для воспроизведения заметок, если вы прокомментируете цикл 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, беспокоясь о порядке байтов и тому подобное? Это сэкономит вам массу времени и будет иметь универсальную поддержку приложений из коробки. Вы можете легко [nuget it в свой проект] (https://www.nuget.org/packages/NAudio/). – spender
Привет, спендер, большое вам спасибо за ваш ответ! Сегодня я работал с naudio весь день, но я обнаружил, что для воспроизведения отдельных заметок требуется также использование System.Threading.Thread.Sleep(). И я получаю ту же проблему, когда воспроизведение одной заметки остановит всю программу, и звук не воспроизводится. Не могли бы вы найти какие-нибудь обходные пути? – Shinsuke