2015-06-19 111 views
0

首先我不是PRO程序员,但只是一名学生,他对一个优秀的图书馆Midi-Dot-Net有点小问题。Midi-dot-net声音播放两次

我使用一个Midi-Dot-Net库在C#语言的Visual Studio中编写一个简单的应用程序。但我坚持一个非常混乱的问题。

我把一些代码到Form1.cs的

public void NoteOn(NoteOnMessage msg) { 
    if (InvokeRequired) { 
     BeginInvoke(noteOnHandler, msg); 
     return; 
    } 

    inputStatusLabel.Text = String.Format("{0}", msg.Pitch); 
    String nutka = inputStatusLabel.Text; 

    if (nutka == "A0") { 
     clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Pitch.A0, 80, 2)); 
    } 
} 

所以,我把新的String,并把它称为nutka,并nutka将收到我的USB MIDI键盘按下的音符名。然后,我放置IF声明,并将nutka与“A0”(键盘上的第一个音符)进行比较。

然后如果是“A0”,我按下我的outputDevice播放特定的音符。它播放,但它播放两次,一次 - 当我按下键盘(注意A0)键盘和第二次 - 当我释放该键。

我在public void NoteOn(NoteOnMessage msg)上做了一个断点,并注意到应用程序在这里返回两次并播放两次该音符,但仍不知道为什么。

还有一件事,有一种方法public void NoteOff(NoteOffMessage message),但它似乎不工作。

我真的不知道,我正在寻找任何帮助。

UPDATE ...... UPDATE ... UPDATE

出现的另一个问题(第一部分就解决了由于CL克里斯·达纳韦建议和步进一步一步贾斯汀解释)。

谢谢贾斯汀:)我看到生活没有任何问题是不可能的:)

随着clock.Schedule我只能发挥将MIDI声音,但我要玩例如钢琴音符(WAV文件格式)和4- 5 星期我的大学会帮助我为每个音符录制自己的钢琴声音。我也想同时玩。

我认为一切都会好起来,现在......同时玩的问题。我试图检查三种可能性:

1)我是想弹钢琴,从基本的笔记库中的声音,我有和使用声音播放它:

SoundPlayer noteA0 = new SoundPlayer(Properties.Resources.A0); 
noteA0.Play(); 

我用它的每一个音符语句不同的SoundPlayer名称(取决于音符名称),我注意到的是 - 我无法同时播放音符。

2)所以我用下一个WMP库和WindowsMediaPlayer中:

例如:

var noteA0 = new WMPLib.WindowsMediaPlayer(); 
noteA0.URL = @"c:\sounds\piano\A0.wav"; 

好吧......它起着同时,但它看起来更笔记我玩或者我只是播放歌曲我得到的更大的延迟,finnaly我的程序卡住玩什么...

3)我试图使用Microsoft.DirectX.AudioVideoPlayback:

Audio noteA1 = new Audio(@"C:\sounds\piano\A1.wav"); 
noteA1.Play(); 

我开始了我的程序,按下了键和繁荣!一个错误消息崩溃:

An unhandled exception of type 'System.BadImageFormatException' occurred in Midi.dll 
Additional information: Could not load file or assembly 'Microsoft.DirectX.AudioVideoPlayback.dll' or one of its dependencies. 
It is not a valid Win32 application. (Exception from HRESULT: 0x800700C1) 

我当然没忘了用:

using System.Media; 
using Microsoft.DirectX.AudioVideoPlayback; 
using Microsoft.DirectX; 

现在,我不知道我能做些什么更多的,并再次 - 我需要的帮助经验的人:)

+0

一个Velocity“音符关闭”的测试中,我不明白'Invoke'一部分,你不应该调用'NoteOn'?什么是'noteOnHandler'?你怎么称呼'NoteOn'?来自哪里? – Sinatr

+0

我有一个完整的源使用:[链接](https://code.google.com/p/midi-dot-net/source/browse/trunk#trunk%2FGUIDemo)我eddited form1.cs和项目取决于在Midi文件夹中也放置在上面的链接中。 – Martin

+0

您正在编辑的程序需要用户按窗口窗体上的播放按钮。通过使用MIDI键盘,您可以有效地演奏音符,但也可以将事件发送到“NoteOn”方法,然后在您调用clock.Schedule时触发第二个音符。总之,您正在编辑的程序可能不是您尝试实现的正确起点。 – Paul

回答

1

CL.'s answer扩大,这里是事件发生的顺序可能发生:

  1. 你MIDI键盘,它发送了Note On message, with a Pitch of A0, and a velocity(确切的速度,每次可能会有所不同推送的关键)。
  2. 您的代码收到此代码,并且因为它符合您的if声明,所以会发送Note On message, with a pitch of A0, and a velocity of 80

这里是棘手的地方。某些MIDI设备在释放密钥时会使用相同的音高发送相应的Note Off消息。其他设备将发送第二个Note On消息,其中包含相同的音高,但速度为0.这两种类型的消息在功能上相当(并且应该是),并且每个设备都可以停止播放音符(或甚至两者) 。所以,

  1. 你松开键盘上的键,发出一个Note On message, with a Pitch of A0, and a Velocity of 0
  2. 您的代码收到此代码,并且由于它也与您的if声明相匹配,所以发出Note On message, with a pich of A0, and a velocity of 80

由于Note on的速度为0也是一个Note Off,所以会发生的是您的代码将键盘的“Note Off”重新转换为Note On,从而播放声音两次。

由于Chris Dunaway suggested,你需要确定是否注意在实际上是一个为0

if (nutka == "A0" && msg.Velocity != 0) { 
     clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Pitch.A0, 80, 2)); 
    } 
+0

是否可以使用clock.Schedule从资源播放声音? – Martin

+0

@Martin对不起,我不太明白你的意思。请随时发布另一个问题,提供新问题的所有详细信息,并将其标记为[midi]。 –

1

的MIDI 1.0详细规格说:

MIDI提供关闭音符的两个大致等同装置(VO冰)。可以通过发送关于相同音符编号和频道的音符关闭消息,或通过为速度值为零的音符和频道发送音符开启消息来关闭音符。使用“速度零注意”的好处在于,它可以避免在运行状态被使用时发送额外的状态字节。

由于这种效率,发送速度值为零的Note-On消息是最常用的方法。但是,某些键盘乐器在使用带有“速度关闭”字节的注释码(8nH)的情况下执行释放速度。接收器必须能够识别关闭音符的任何方法,并且应该对它们进行相同的处理。

+0

仍然无法弄清楚,不幸的是我不是一个合乎逻辑的头脑:(需要任何帮助:) – Martin

+2

@Martin - 我想你需要检查' msg.Velocity'在你的'NoteOn'方法中,如果Velocity是0,那么这是一个注释(如果我理解什么CL发布)。 –