在 MIDI 上播放连续的类似 theremin 的声音

Posted

技术标签:

【中文标题】在 MIDI 上播放连续的类似 theremin 的声音【英文标题】:Play a continuous theremin-like sound on MIDI 【发布时间】:2011-06-24 06:09:06 【问题描述】:

我正在尝试创建一个类似theremin 的程序,该程序根据鼠标光标位置播放连续音符。我正在使用 Carl Franklin 的 MIDI Tools 库来执行此操作。

这是我用来演奏音符的代码 sn-p。

byte pitch = 0;
while (exit == false)

    byte newpitch = (byte)(32 + ((float)Cursor.Position.X / (float)SystemParameters.PrimaryScreenWidth) * 64);

    if (newpitch != pitch)
    
        instrument.StopNote(pitch,0);
        instrument.PlayNote(newpitch, 53);
        pitch = newpitch;
    
;

问题在于以这种方式演奏的音符听起来很明显;从一个音符到另一个音符有明显的过渡。

如何播放像连续改变音高的连续 theremin 声音?

【问题讨论】:

我想最好的人是卡尔富兰克林。你在问一个关于一个相对晦涩的图书馆的具体问题;为什么不咨询他们? 很多人推荐 Carl 的库,用于使用 C# 进行 MIDI 编程。所以我想真正做 MIDI 编程的人都熟悉它。此外,这个问题特定于 MIDI,而不是特定于 API。 API 只是 WinMM.dll 方法的包装器。熟悉 WinMM.dll 的人可以在这里为我提供帮助。 【参考方案1】:

这个问题与 MIDI 关系不大,更多的是与生成声音的合成器有关。

如果您想在当前的实现中顺利地从一个音符切换到下一个音符,您需要一个具有大量滑音的合成器补丁。您可以通过在初始化时将 CC37 设置为 127 来使其适用于许多补丁。

理想情况下,为了完全平滑,您需要一个合成器补丁来解释弯音,而不仅仅是向上和向下一个步骤。同样,这与您发送的值无关。无论如何,这些都是 14 位的。由合成器决定这些值的上升/下降幅度。

根据合成器的不同,您可以使用 RPN 调整其弯音范围以获得弯音灵敏度。你可以在这里阅读:http://www.hoofjaw.com/forums/Topic946-32-1.aspx#bm1254

或在这里:http://www.philrees.co.uk/nrpnq.htm

【讨论】:

【参考方案2】:

您应该能够通过 MIDI 音高轮更改事件来执行此操作。

第一个字节是 0xE0 + MIDI 通道号(0 表示通道 1) 第二个和第三个字节是俯仰轮变化值。 0x2000 表示在中间,0x4000 是最大值(通常解释为 +2 个半音,但音序器可以对这条消息做任何事情)。

在幕后,Carl 很可能只是使用midiOutShortMsg 发送消息,该消息将三个字节转换为 DWORD。可能是他公开了一个方法让你直接发送DWORD,如果他没有变桨发送功能的话。

您需要记住,每个音高移位值字节中都没有使用最高位,所以如果您将音高值作为整数,它会变成这样的短消息:

 int pitch = 0x2000; // no pitch change
 byte byte2 = (byte)(pitch & 0x7f));
 byte byte3 = (byte)((pitch >> 7)& 0x7f));
 int shortMessage = 0xE0 + (channelNumber - 1) + (byte2 << 8) + (byte3 << 16);

【讨论】:

【参考方案3】:

已经很久了,但我确实记得 MIDI 能够表示音高变化,例如在 MIDI 控制器(合成器或键盘)上滚动弯音轮通过 MIDI 传输。您可以考虑使用这种类型的消息来改变连续播放音符的音高。

【讨论】:

以上是关于在 MIDI 上播放连续的类似 theremin 的声音的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 上播放单个 MIDI 木版音符?

将 MIDI 歌曲事件与初始设置事件分开

有没有人在 iPhone 上通过 midi->wav 转换等播放 .midi 文件的经验?

Flutter mobile,播放midi文件

在播放时捕捉 MIDI 音符?

将 MIDI 转换为 mp3