简体   繁体   English

在Javasound中播放多个样本

[英]Playing multiple samples in Javasound

I'm looking to write a simple MIDI-driven audio sequencer using Javasound. 我正在寻找使用Javasound编写一个简单的MIDI驱动的音频音序器。

I have multiple samples (one for each MIDI pitch) that are loaded into memory as a (globally accessible) Map<MidiPitch,AudioInputStream> . 我有多个样本(每个MIDI音高一个),作为(全局可访问) Map<MidiPitch,AudioInputStream>加载到内存中。

A custom subclass of javax.sound.midi.Receiver responds to incoming MIDI events as follows: javax.sound.midi.Receiver的定制子类对传入的MIDI事件做出如下响应:

If the event is a note-on, a Clip is obtained and played as follows: 如果该事件是注解,则将按如下方式获取剪辑并播放:

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

The clip is then added to a globally accessible Map<MidiPitch,List<Clip>> , representing started clips , ie clips for which start() has been called as above, but for which a note-off event has not yet been received. 然后,将该剪辑添加到全局可访问的Map<MidiPitch,List<Clip>> ,该Map<MidiPitch,List<Clip>>表示已开始的剪辑 ,即已如上所述调用start()但尚未收到音符离开事件的剪辑。

If the event is a note-off, the corresponding list of started clips is obtained from the above map. 如果该事件是笔记,则可以从上面的地图中获取相应的开始剪辑列表。 The clip at the head of the list is removed, and stop() and close() are called on it. 列表开头的剪辑被删除,并在其上调用stop()close()

The above Receiver is connected to MidiSystem.getSequencer() in the usual way, then the following called: 上面的Receiver以通常的方式连接到MidiSystem.getSequencer() ,然后将其调用:

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

Thread.sleep(aLongTime())

sequencer.stop()
sequencer.close()

The above works when the driving MIDI sequence is at a slow tempo, but at higher tempos, notes simply hang (even for sequences containing a very small number of notes). 当驱动MIDI序列的速度较慢,但​​节奏较高时,上述方法起作用,音符只是挂起(即使对于音符数量很少的音序也是如此)。

My understanding is that clip.start() is run within a separate thread behind the scenes by the Javasound API. 我的理解是clip.start()在Javasound API的幕后独立线程中运行。

Can anyone suggest why this might be happening? 谁能说出为什么会这样吗? Is it perhaps a synchronization issue? 也许是同步问题?

EDIT: By 'hang', I mean that some notes are stuck, despite the fact that log output reports that the corresponding 'stop' method has been called. 编辑:通过“挂起”,我的意思是尽管日志输出报告已调用了相应的“停止”方法,但仍有一些记录卡住了。

EDIT2: It looks as if the hanging first happens when a given note is played for the second time. EDIT2:似乎在第二次播放给定音符时首先发生挂起。 This happens even if the MIDI sequence is monophonic, ie the previous note has stopped. 即使MIDI序列是单声道的,即前一个音符已停止,也会发生这种情况。

Your method of loading the Clip for each play is going to be a considerable source of variable latency. 您为每次播放加载剪辑的方法将成为可变延迟的重要来源。 Every time you call this, the file is read anew and will not start playing until it the entire file has finished loading. 每次您调用此文件时,都将重新读取该文件,并且直到整个文件加载完成后才开始播放。

I recommend pre-loading all the clips and holding them in memory. 我建议预加载所有剪辑并将其保存在内存中。 When the note-on is called, set the clip cursor to zero and then play: 调用note-on时,将剪辑光标设置为零,然后播放:

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

These clips should have already been opened. 这些剪辑应该已经打开。 I'm putting them in an array and using "mapIndex" as a plausible way of selecting the correct clip that might work with the mapping you've already set up. 我将它们放置在数组中,并使用“ mapIndex”作为选择与您已设置的映射一起使用的正确片段的合理方式。

You probably won't need to "stop" or "close" the clips until the entire sequence has finished, unless the clips are rather long and are designed to be stopped while in progress, or if they are being played as loops. 在整个序列完成之前,您可能不需要“停止”或“关闭”剪辑,除非剪辑很长且被设计为在进行中时停止播放,或者如果它们是作为循环播放的。

This should improve things considerably. 这应该会大大改善。 I can't say if it will fix everything. 我不能说是否能解决所有问题。 The cpu is probably doing some thread multiplexing, and it is plausible that occasionally, in your current code, the clip.close is being called on one thread before the clip has finished loading on the other. 该cpu可能正在执行一些线程多路复用,并且可能在您当前的代码中偶尔在一个线程上完成clip.close加载之前在一个线程上调用clip.close。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM