MIDI.js 音符持续时间不会改变

Posted

技术标签:

【中文标题】MIDI.js 音符持续时间不会改变【英文标题】:MIDI.js note duration does not change 【发布时间】:2014-01-22 23:40:01 【问题描述】:

由于 mudcube MIDI.js 的文档在这方面似乎缺乏,我希望有人能够为我指明正确的方向。说白了,使用midi.js,如何调整midi音符的时长和结尾?

对于某些背景,我创建了一个带有可拖放音符 (jQuery-ui) 的乐谱小部件,可以添加或删除该小部件,以形成可以调用来播放 MIDI 的序列。到目前为止,一切正常,但是,当我试图用更复杂的时间扩展这个小部件的功能时,我遇到了一些问题。

似乎我只能在设定的时长内弹奏音符,而且,尽管我付出了所有努力,但仍无法实现可以改变该时长的更改,例如二分音符、四分音符、八分音符等。此外,这可能是原因之一,MIDI.noteOff 对输出没有明显的影响。人们会认为给定的音符会无限期地播放,直到调用 MIDI.noteOff 为止,但是,无论是否调用 noteOff,所述音符都会播放然后逐渐消失。

让我在这里说一下,我已经对 SO 和整个网络进行了广泛的研究,以弄清这一点。我找到了有类似问题的人并应用了他们的修复程序,但他们的答案对我不起作用。见how do I play arbitrary notes in Midi with javascript和MIDI.noteOff does not seem to work reliably

我有一个名为 noteSequence 的音符序列,其中每个音符都是一个具有 noteValue(即“C4”)和 noteDuration 属性的对象,这些属性在函数 convertToMidiSequence 中转换为 midiSequence。一切都适用于旋律序列和和弦,我只想添加持续时间功能。我还应该说,调整“延迟”变量或 noteDuration 属性只会增加播放序列之前的时间。然后在初始延迟之后,序列以与之前相同的时间播放。

感谢您抽出一些时间来查看此内容并希望能提供帮助。将不胜感激。

这是运行我的 MIDI 的适用代码:

$(document).ready(function() 
  MIDI.loadPlugin(
    soundfontUrl: GLOBALS.SOUNDFONT_URL,
    instrument: 'acoustic_grand_piano',
    callback: function() 
      var channel = 0,
          instrument = 0,
          velocity = 127,
          delay = 1;
      MIDI.programChange(0, instrument);
    
  );
);

function playCurrentSequence() 
  playSequence(noteSequence);


function playSequence(sequence) 
  var midiSequence = convertToMidiSequence(sequence);
  for (var i = 0; i < midiSequence.length; i++) 
    if (!(midiSequence[i] instanceof Array)) 
      playNote(midiSequence[i], i);
    
    else 
      playChord(midiSequence[i], i);
    
  


function playNote(midiNote, notePositionInMeasure) 
  var channel = 0,
      velocity = 127,
      delay = 1;
  MIDI.noteOn(channel, midiNote, velocity, delay + notePositionInMeasure + 1);
  MIDI.noteOff(channel, midiNote,
    delay + midiNote.noteDuration + notePositionInMeasure + 1);
  MIDI.Player.stop();


function playChord(midiChord, notePositionInMeasure) 
  var channel = 0,
      velocity = 127,
      delay = 1;
  for (var i = 0; i < midiChord.length; i++) 
    MIDI.noteOn(channel, midiChord[i], velocity, delay + notePositionInMeasure + 1);
    MIDI.noteOff(channel, midiChord[i],
      delay + midiChord[i].noteDuration + notePositionInMeasure + 1);
    MIDI.Player.stop();
  

【问题讨论】:

你如何衡量noteDuration?为什么+1 @CL。我已将 noteDuration 设置为 4 以表示整个音符(我尝试了许多其他值),但这可能会根据时间的正确实现而改变。 +1 是早期修复程序的保留(notePositionInMeasure 是给定音符在零索引数组中的位置,这是为了确保始终添加至少 1),但它目前似乎没有改变它是否有没有。感谢您指出这一点,我会删除它。 noteOff 的implementation 被注释掉。我还没有找到任何关于 delay 实际含义的文档。 @CL。非常有趣...我拥有的 Plugin.js 似乎包含我发布的链接中建议的修复。 MIDI.noteOff does not seem to work reliably 也许他们还没有更新他们的网站以反映这一变化? 【参考方案1】:

有必要指出 MIDI NoteOff 的实际含义——通常是之前收到 NoteOn 的音符进入其ADSR envelope 的释放状态,并最终消失。它直到一段时间后才会释放频道。

现在,对于大多数打击乐声音而言,本身并没有 NoteOff 的概念 - 它们只是在延音阶段的初始攻击之后衰减到零(有点用词不当)。钢琴上的 Note-off 应用了制音器,但此时声音可能已经消失得无影无踪了。

其他声音可能是没有 NoteOff 概念的直接样本触发器。

因此行为并不一致,很大程度上取决于您选择的声音。您是否验证过 NoteOffs 确实对它有意义?

【讨论】:

感谢您澄清这一点,我不知道。我正在调查noteOff 现在是否真的适用。但是,我是否应该发现它没有,是否有可以将钢琴声音延长或静音预定长度的解决方法? 是的。制音器(又名延音)踏板应该起到延长音符的作用 - 尽管不是无限期地 - 音符。将通道音量设置为零可能会起到阻止音符消失的作用。 这是一个很好的观点,然而,据我所知,MIDI.js 似乎没有阻尼或延音选项来增强音符。不过我可能弄错了。 阻尼踏板 - 又名。维持 - 是 CC64。我猜有什么方法可以在 MIDI.js 中发送控制器消息?这是list of controllers

以上是关于MIDI.js 音符持续时间不会改变的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 实现页面播放特定音符(如:C4)

神经网络错误率不会进展

如何播放具有确定持续时间的 MIDI 音符

声音不会一直播放! - Pygame,Python

LSTM 多特征、多类、多输出

从 MIDI 中提取音符开始