从 C# 中的 MIDI 端口获取信号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1991159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 22:28:27  来源:igfitidea点击:

Getting signals from a MIDI port in C#

c#midi

提问by gideonrv

I bought a MIDI keyboard for my birthday. I found a program (MidiPiano) that gets signals from the MIDI input and translates it into music, but I'd rather like to write one myself.

我为我的生日买了一个 MIDI 键盘。我找到了一个程序 (MidiPiano),它可以从 MIDI 输入中获取信号并将其转换为音乐,但我更愿意自己编写一个程序。

Where can I find documentation for doing such a task? The MIDI protocol is well documented, but not the MIDI ports.

我在哪里可以找到执行此类任务的文档?MIDI 协议有据可查,但 MIDI 端口没有。

I checked two projects from CodeProject (Project MIDI and C# MIDI Toolkit), but spent many hours without getting close to my goal.

我检查了 CodeProject 中的两个项目(Project MIDI 和 C# MIDI Toolkit),但花了很多时间没有接近我的目标。

A reference to a project will be fine, but please, only C#.

对项目的引用没问题,但请仅使用 C#。

回答by Mark Pearl

I couldn't find much either, but like Josh says, Carl has definitely done quite a bit of work on MIDI, so maybe give him an email... he may even reply, but he is typically a VB.Net guy so unless someone has ported his stuff to C#?

我也找不到太多东西,但就像 Josh 说的,Carl 肯定在 MIDI 方面做了很多工作,所以也许给他一封电子邮件……他甚至可能会回复,但他通常是一个 VB.Net 人,所以除非有人将他的东西移植到 C# 吗?

For some other references that looked promising...

对于其他一些看起来很有希望的参考...

If you are looking for a pure C# solution... have a look at Alvas.Audio. It does look a bit high end for what you are asking, but may be of some help.

如果您正在寻找纯 C# 解决方案...请查看Alvas.Audio。对于您的要求,它看起来确实有点高端,但可能会有所帮助。

Also maybe project midi

也可能是项目midi

回答by Mark Pearl

You need to wrap all the needed functions listed at http://msdn.microsoft.com/en-us/library/dd757277(VS.85).aspx

您需要包装http://msdn.microsoft.com/en-us/library/dd757277(VS.85).aspx 中列出的所有需要​​的功能

It's not too difficult if you're just using short messages, things get a little more complicated if you want to do SysEx or output streaming.

如果你只是使用短消息,这并不太难,如果你想做 SysEx 或输出流,事情会变得更复杂一些。

All you need for a basic input Port is to get the valid input IDs (InputCount -1), pass a valid ID to Open, Start the input, receive the messages via a delegate... Stop the input and then finally close it. This is a very rough example of how this could be acheived - you will need to do some checking and be careful that the Port isn't collected before it's closed and the closed callback has happened or you will freeze your system!

基本输入端口所需的只是获取有效的输入 ID (InputCount -1),将有效 ID 传递给 Open,启动输入,通过委托接收消息...停止输入,最后关闭它。这是一个非常粗略的示例,说明如何实现这一点 - 您需要进行一些检查并注意端口在关闭和关闭回调发生之前未被收集,否则您将冻结系统!

Good luck!

祝你好运!

namespace MIDI
{
    public class InputPort
    {
        private NativeMethods.MidiInProc midiInProc;
        private IntPtr handle;

        public InputPort()
        {
            midiInProc = new NativeMethods.MidiInProc(MidiProc);
            handle = IntPtr.Zero;
        }

        public static int InputCount
        {
            get { return NativeMethods.midiInGetNumDevs(); }
        }

        public bool Close()
        {
            bool result = NativeMethods.midiInClose(handle) 
                == NativeMethods.MMSYSERR_NOERROR;
            handle = IntPtr.Zero;
            return result;
        }

        public bool Open(int id)
        {
            return NativeMethods.midiInOpen(
                out handle,
                id,
                midiInProc,
                IntPtr.Zero,
                NativeMethods.CALLBACK_FUNCTION)
                    == NativeMethods.MMSYSERR_NOERROR;
        }

        public bool Start()
        {
            return NativeMethods.midiInStart(handle)
                == NativeMethods.MMSYSERR_NOERROR;
        }

        public bool Stop()
        {
            return NativeMethods.midiInStop(handle)
                == NativeMethods.MMSYSERR_NOERROR;
        }

        private void MidiProc(IntPtr hMidiIn,
            int wMsg,
            IntPtr dwInstance,
            int dwParam1,
            int dwParam2)
        {
            // Receive messages here
        }
    }

    internal static class NativeMethods
    {
        internal const int MMSYSERR_NOERROR = 0;
        internal const int CALLBACK_FUNCTION = 0x00030000;

        internal delegate void MidiInProc(
            IntPtr hMidiIn,
            int wMsg,
            IntPtr dwInstance,
            int dwParam1,
            int dwParam2);

        [DllImport("winmm.dll")]
        internal static extern int midiInGetNumDevs();

        [DllImport("winmm.dll")]
        internal static extern int midiInClose(
            IntPtr hMidiIn);

        [DllImport("winmm.dll")]
        internal static extern int midiInOpen(
            out IntPtr lphMidiIn,
            int uDeviceID,
            MidiInProc dwCallback,
            IntPtr dwCallbackInstance,
            int dwFlags);

        [DllImport("winmm.dll")]
        internal static extern int midiInStart(
            IntPtr hMidiIn);

        [DllImport("winmm.dll")]
        internal static extern int midiInStop(
            IntPtr hMidiIn);
    }
}

回答by obiwanjacobi

Use the C# Midi Toolkit to receive the midi information from your keyboard (connected to the midi in-port of you audio card). To create audio (music or tones) you need to generate a continues stream of digital audio data. You could start with the C# Synth Toolkit (same author as the midi toolkit) to write your own synth.

使用 C# Midi Toolkit 从键盘(连接到声卡的 MIDI 输入端口)接收 MIDI 信息。要创建音频(音乐或音调),您需要生成连续的数字音频数据流。您可以从 C# Synth Toolkit(与 midi 工具包相同的作者)开始编写您自己的合成器。

But you could also download a free (open source) sequencer program (audacity for instance) and use VST instrument plugins to do the job for you. There are a lot of free plugins available on the web.

但您也可以下载免费(开源)音序器程序(例如audacity)并使用VST 乐器插件为您完成这项工作。网络上有很多免费插件可用。

回答by silenter

I'm just in developing process of c# midi communication system. Sanford's midi toolkit is good but Leslie implementation has many improvement which makes code less readable. My code is as simple as possible. If you want you can join me. In a few days I publish fully working midi monitor. Just look at http://puremidi.codeplex.com/

我刚刚在开发c#midi通信系统。Sanford 的 midi 工具包很好,但 Leslie 的实现有很多改进,这使得代码可读性降低。我的代码尽可能简单。如果你愿意,你可以加入我。几天后,我发布了完全可用的 MIDI 监视器。看看http://puremidi.codeplex.com/

回答by P i

I have solved this in a roundabout way by writing a Python script to transmit a UDP packet every time a note ON/OFF occurs on the MIDI keyboard.

我通过编写一个 Python 脚本来在每次 MIDI 键盘上发生音符 ON/OFF 时传输 UDP 数据包,以一种迂回的方式解决了这个问题。

MIDI over TCP/IP/UDP to be received inUnity3D with C#/.NET

使用 C#/.NET 在 Unity3D 中通过 TCP/IP/UDP 接收 MIDI

That way the platform specific MIDI stuff is wrapped, and I can write platform agnostic C# code to pick up the UDP packet.

这样,特定于平台的 MIDI 内容就被包装了,我可以编写与平台无关的 C# 代码来获取 UDP 数据包。