gpt4 book ai didi

java - 在 Javasound 中播放多个样本

转载 作者:行者123 更新时间:2023-12-01 08:51:49 26 4
gpt4 key购买 nike

我希望使用 Javasound 编写一个简单的 MIDI 驱动的音频音序器。

我有多个样本(每个 MIDI 音高一个),它们作为(全局可访问)Map<MidiPitch,AudioInputStream> 加载到内存中。 。

javax.sound.midi.Receiver 的自定义子类响应传入的 MIDI 事件如下:

如果事件是音符打开,则获取并播放剪辑,如下所示:

Clip clip = AudioSystem.getClip();
clip.open(lookupAIS(pitch));
clip.start();

然后将该剪辑添加到全局可访问的 Map<MidiPitch,List<Clip>> ,代表开始的剪辑,即 start() 的剪辑已按上述方式调用,但尚未收到注释事件。

如果事件是音符结束,则从上面的 map 中获取相应的开始剪辑列表。列表头部的剪辑被删除,并且 stop()close()被召唤。

以上Receiver连接到MidiSystem.getSequencer()按照通常的方式,然后调用以下内容:

sequencer.setSequence(MidiSystem.getSequence(new File(myMidFile)))
sequencer.open()
sequencer.start()

Thread.sleep(aLongTime())

sequencer.stop()
sequencer.close()

当驱动 MIDI 序列速度较慢时,上述方法有效,但在较高速度下,音符会简单地挂起(即使对于包含很少数量音符的序列)。

我的理解是clip.start()由 Javasound API 在后台的单独线程中运行。

任何人都可以解释为什么会发生这种情况吗?可能是同步问题吗?

编辑:通过“挂起”,我的意思是一些注释被卡住,尽管日志输出报告相应的“停止”方法已被调用。

EDIT2:看起来好像当第二次播放给定音符时第一次发生挂起。即使 MIDI 序列是单音的(即前一个音符已停止),也会发生这种情况。

最佳答案

每次播放加载剪辑的方法将成为可变延迟的重要来源。每次调用此方法时,都会重新读取该文件,并且在整个文件加载完毕之前不会开始播放。

我建议预加载所有剪辑并将它们保存在内存中。当音符打开时,将剪辑光标设置为零,然后播放:

clip[mapIndex].setFramePosition(0);
clip[mapIndex].start();

这些剪辑应该已经打开。我将它们放入一个数组中,并使用“mapIndex”作为选择可能与您已经设置的映射配合使用的正确剪辑的合理方式。

在整个序列完成之前,您可能不需要“停止”或“关闭”剪辑,除非剪辑相当长并且设计为在进行时停止,或者它们作为循环播放.

这应该会大大改善事情。我不能说它是否能解决一切问题。 cpu 可能正在执行一些线程多路复用,并且有时在当前代码中,在剪辑完成在另一个线程上的加载之前在一个线程上调用 Clip.close 是合理的。

关于java - 在 Javasound 中播放多个样本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42343297/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com