c# - midioutshortmsg 没有声音

标签 c# audio visual-studio-2015 midi winmm

因此,我正在尝试使用 midiOutShortMsg() 在 C# 中播放单个音符。问题是没有声音播放。我想出的一种播放音符的方法是将 midiOutShortMsg() 放在一个从 i=0 到 10000 的 for 循环中。但我不认为 API 应该是这样工作的。

项目后期想把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();
        }
    }
}

最佳答案

这是因为 midiOutShortMsg 不会停止代码的执行,这意味着 midiOutClose 在音符有时间播放之前被调用。

克服这个问题的一种方法是添加一个Sleep:

res = midiOutShortMsg(handle, (int)msg);

if (res == 0) // Check success code
{
    System.Threading.Thread.Sleep(length);
}

res = midiOutClose(handle);

其中 length 是音符完成播放所需的时间量(以毫秒为单位)。

然而,这几乎肯定不会被推荐。

关于c# - midioutshortmsg 没有声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40392382/

相关文章:

c# - Microsoft ACE OLEDB 12.0 - 无 header .CSV 的 F1 语法导致异常

c# - 如何避免浪费屏幕空间编写稀疏的 C# 代码?

javascript - 我想在用户等待时播放警报中的响铃声音

c# - 在 Visual Studio 2015 中用于符号扩展操作数的按位或运算符

c# - roslyn 分析器发出警告,后来被删除

javascript - 自定义 Sharepoint 托管加载项的 ECB 菜单

c# - 日期时间精度?

c# - 如何在不使用 excel 互操作库的情况下将 excel 工作簿转换为 pdf?

ios - Iphone IOS,从另一个 Audio Session 访问音频数据

javascript - 使用 javascript 在移动设备中播放多种音频声音