在 Mathematica 和 MIDI 踏板事件中叠加音乐曲目

Posted

技术标签:

【中文标题】在 Mathematica 和 MIDI 踏板事件中叠加音乐曲目【英文标题】:Superposing music tracks in Mathematica & MIDI pedal events 【发布时间】:2011-11-06 21:21:01 【问题描述】:

以下所有内容均指音乐/MIDI(SoundNote 对象),而不是采样声音。

不幸的是,Mathematica 似乎无法导入 MIDI。我正在尝试基于MIDI <-> CSV 为单乐器文件(专注于钢琴)制作一个简单的 MIDI 导入器。

在 Mathematica 中叠加两个 Sound 对象的最简单方法是什么?

Show 将它们连接起来,它不会叠加。

一个不太简单的方法是将Sound拆解成SoundNotes,将每个SoundNotes时间规范转换成Tstart, Tend格式,再将它们组合成一个新的声音。有没有简单的方法?

第二个问题:

是否有一种简单的方法来处理 Mathematica 中的踏板事件,同时仍然使用内部声音表示和 MIDI 播放器,而不是通过其他方式播放 MIDI?

【问题讨论】:

【参考方案1】:

1。叠加

为了能够叠加两个Sound 对象,应该有一个共同的时间原点。一个简单的SoundNote 对象有自己的时间来源,因此在这些列表上使用Sound 只会将它们连接起来并连续播放它们。您必须为每个使用绝对时间才能叠加它们。这样,您可以在同时演奏多种乐器的情况下创作 MIDI 音乐。

这是一个叠加的简短示例(未经过修饰)。低音由钢琴演奏,高音由单簧管演奏。

tempo = 110;
eighthNoteDuration = 60/tempo/2;

trebleNotes = "E5", "D#5", "E5", "D#5", "E5", "B", "D5", "C5", "A", 
   None, "C", "E", "A", "B", None, "E", "G#", "B", "C5", None, "E", 
   "E5", "D#5", "E5", "D#5", "E5", "B", "D5", "C5", "A", None, "C", 
   "E", "A", "B", None, "E", "C5", "B", "A";
trebleNoteDurations = 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1,
     1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1,
     1, 4 eighthNoteDuration;
trebleTimings = 
  Partition[
   Accumulate@Flatten@Transpose@ConstantArray[0, Length@#], # &@
    trebleNoteDurations, 2];

bassNotes = None, None, "A2", "E3", "A3", None, None, "E3", "G#3", 
   "B3", None, None, "A2", "E3", "A3", None, None, None, "A2", "E3", 
   "A3", None, None, "E3", "G#3", "B3", None, None, "A2", "E3", "A3", 
   None;
bassNoteDurations = 2, 6, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 
    2, 6, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1 eighthNoteDuration;
bassTimings = 
  Partition[
   Accumulate@Flatten@Transpose@ConstantArray[0, Length@#], # &@
    bassNoteDurations, 2];

Sound[Join[
  SoundNote[#1, #2, 
     "Piano"] & @@@ (bassNotes, bassTimings\[Transpose]), 
  SoundNote[#1, #2, 
     "Clarinet"] & @@@ (trebleNotes, trebleTimings\[Transpose])]]

2。踏板效果

至于你的第二个问题,我认为你不能使用 MIDI 再现踏板效果。 MIDI 格式非常简单,实际上并不传输任何声音。它携带的所有信息都是

    正在播放的音符(音高) 音符的持续时间(速度) 触发事件以开始和停止笔记

您选择再现声音的乐器完全取决于您的系统,并且在不同系统上再现声音的方式可能不同。现在,如果您想重现踏板效果,您将必须编写一个函数将其分解为与踏板实际效果非常相似的单个 MIDI 事件。

例如,您可以修改SoundNote 或创建一个新函数,当传递选项Sustain -&gt; t 时,将注释延长t 秒。您可以使这更加现实,并将t 秒分成更小的段,SoundVolume -&gt; v 作为附加选项,v 随每个段线性/对数递减。

【讨论】:

谢谢!我正在考虑类似的事情,似乎没有更简单的方法。关于踏板,它实际上是 MIDI 的一部分。在 CSV 表示中,踩下或松开踏板显示为Control_c, 0, 64, 127,表示将控制器 64 的值设置为 127(踩下踏板)或 0(松开踏板)。当然,这取决于使用的 MIDI 乐器是否会对这个事件做些什么,但通常任何钢琴风格的乐器都应该响应它。 我想我将在 Mathematica 中使用我自己的 MIDI 表示,并为 Sound 对象和 MIDI 文件编写一个转换器。使用Sound 对象,您可以通过扩展每个音符直到踏板被释放来模拟延音踏板。 我很确定 MIDI 可以传输踏板信息。它通过 CC #64 传输,我只是不知道您将如何在 Mathematica 上实现它。 Source,另外,yoda 对 MIDI 的评论非常不完整 - yoda,您是指 MIDI 协议本身还是 Mathematica 上的 MIDI?【参考方案2】:

关于你的第二个问题:

之前我 reported 谈到 Mathematica 连接到 Nintendo Wiimote 和 Balanceboard 的能力,使用程序 GlovePie 和 PPJoy,这是一个虚拟操纵杆驱动程序,它可以让 Mathematica 通过模拟操纵杆与您的设备交互(MMA 可以使用ControllerStateControllerInformation)。据我所知,GlovePie 也支持 MIDI。你可以试试看。

【讨论】:

Mac 版 Mathematica 通过 ControllerState[] 函数原生支持 MIDI 设备。无需任何虚拟操纵杆驱动程序。 @ragfield 我猜 Windows 没有,对吧?当我将钢琴连接到计算机时,我从ControllerInformation[] 收到“未检测到控制器设备”。 其实我一直在寻找一种输出声音的方法,同时也考虑到延音踏板的效果(我现在只对钢琴风格的乐器感兴趣),但这似乎并不在 Mathematica 中是可能的。 GlovePie 让我做的是使用外部 MIDI 键盘(可能也使用踏板)控制 Mathematica。 @szabolcs 正确,ControllerState 中的内置 MIDI 支持仅限 Mac。 @szabolcs 我认为这里的时间可能是个问题。耳朵对声音产生的延迟非常敏感。这就是音乐家总是使用 ASIO 驱动程序的原因。在将 MIDI 数据提供给 Mathematica(也不能保证实时处理)之前通过两个程序路由 MIDI 数据在这个意义上可能远非最佳。【参考方案3】:

您可以使用卷积组合或叠加声波,如本页上的 Mathematica 代码所示:

http://www.copperthoughts.com/projects/convolution/

【讨论】:

OP 已经明确表示他在谈论 MIDI 对象而不是采样声音。您不能将 MIDI 对象与任何东西进行卷积... @yoda,但 MIDI 对象在某种意义上是声音的表示。因此,除了转换为声音,卷积可能是有效的。这只会使他的解决方案不完整。 @rcollyer MIDI 对象是一组指令。如何渲染输出取决于系统。从理论上讲,您可以将其转换为采样声音,进行卷积,然后返回一组 MIDI 指令(如果结果甚至可以由 MIDI 表示)。但是 MIDI 文件并不那么容易操作、采样和导出,正如我在尝试为this question 提出解决方案时发现的那样。

以上是关于在 Mathematica 和 MIDI 踏板事件中叠加音乐曲目的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 发送midi程序更改并根据按下的脚踏板控制更改消息

Overture 钢琴插件延音问题

.Net 中的 Midi 实现

python mido MIDI包中使用MultiPort的问题

Android上的Midi事件路由

编辑 midi 事件