嗨:我试图将MIDI音序器的实例同步到外部时钟。我做了:
S_p = MidiSystem.getSequencer(false);
D2 = MidiSystem.getMidiDevice(MidiSystem.getMidiDeviceInfo()[1]);
S_p.open();
D2.open();
R2=S_p.getReceiver();
T2=D2.getTransmitter();
T2.setReceiver(R2);
但
for(int i=0;i<S_p.getMasterSyncModes().length;i++)
{System.out.println("Available modes are "+i+ " "+S_p.getMasterSyncModes()[i].toString());}
返回
Available modes are 0 Internal Clock
这意味着这将毫无用处。
S_p.setMasterSyncMode(Sequencer.SyncMode.MIDI_SYNC);
我做错了什么? 当然我确认消息从D2流出并进入另一个自定义写入的接收器以通知system.out,并且音序器正常播放,它似乎不支持SyncModes文档说应该。特别是这个短语使我感到困惑(来自MIDI_SYNC:&#34;此模式仅适用于也是MIDI接收器的音序器的主同步模式。&#34;
接收器的定序器含义是什么?我认为用getReceiver()
的方法就足够了问候并感谢!
答案 0 :(得分:0)
一次有很多问题!
1)最重要的信息是Java Sound中的Sequenrs是插件(服务提供者,SPI)。 Java附带至少一个Sequencer,但没有提到它确实支持所有可以想象的功能。特别是,getMasterSyncModes()
查询的存在表明并非每个Sequencer实现都支持所有同步模式。正如您所知,Oracle Java中的默认Sequencer恰好不支持除Internal之外的任何同步模式。要明确它:Java规范并未说明Sequencer必须支持任何特定的同步模式。
2)但是,可以通过插件的形式添加自己的Sequencer实现和外部同步。
作为接收者的音序器的含义是什么?
3)我假设的意思是,为了同步到另一个主同步提供者,Sequencer必须能够接收MIDI同步消息,即也接收MIDI消息。我同意接收器和发送器的术语在Java Sound中确实令人困惑。
4)你没有做错任何事。您可以查询同步模式,如果序列发生器支持您之后的同步模式,它将起作用。但是很有可能,你不会找到这样的Sequencer实现......我做错了什么?
S_p = MidiSystem.getSequencer(false);
5)如上所述,在Java Sound中,Sequencers就像MIDI设备和Synthesizer一样是插件。因此,您的系统可能会提供多个排序器。您可以查询MidiSystem.getMidiDeviceInfo()
,获取各种设备,并查看它们是否instanceof Sequencer
以查找所有可用的排序器。
但我认为主要答案是:可能没有公开的Sequencer实现支持外部同步。 可以激活并在OpenJDK的RealTimeSequencer中修复它......
答案 1 :(得分:0)
对于后代:
Homebrew,for-for-me,MIDI-clocked-sequencer。 (猜猜它现在清楚它对音序器BEING接收器的说法):(假设接收器在不同的MIDI通道上听,并且相应地创建音轨。在关闭时发送所有音符.Track_Master来自我的实现,跟踪频道接收者在听)
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
/**
* @author claudio
*
*/
public class MIDI_Clocked_Sequencer implements Receiver {
private Sequence S;
private int[] playheads;
private long counter=0;
private Receiver[] receivers;
private long counter_reset;
/**
* @throws MidiUnavailableException
*
*/
public MIDI_Clocked_Sequencer(Sequence S,long counter_reset,int[] where_to_get_receivers) throws MidiUnavailableException {
this.setSequence(S);
this.counter_reset=counter_reset;
playheads=new int[S.getTracks().length];
receivers=new Receiver[where_to_get_receivers.length];
for(int i=0;i<where_to_get_receivers.length;i++){
this.receivers[i]=MidiSystem.getMidiDevice(MidiSystem.getMidiDeviceInfo()[where_to_get_receivers[i]]).getReceiver();
MidiSystem.getMidiDevice(MidiSystem.getMidiDeviceInfo()[where_to_get_receivers[i]]).open();
}
}
@Override
public void close() {
for(int j=0;j<receivers.length;j++){
try {
receivers[j].send(new ShortMessage(ShortMessage.CONTROL_CHANGE+Track_Master.channel_map.get(Track_Master.gui_map.get(j)),123,0), 0);
} catch (InvalidMidiDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
receivers[j].close();}
}
@Override
public void send(MidiMessage msg, long arg1) {
Set<MidiMessage> message_buffer = new HashSet<MidiMessage>();
if(msg.getMessage()[0]==-8){
if(counter==counter_reset){counter=0;}
for(int j=0;j<S.getTracks().length;j++){
if(playheads[j]==S.getTracks()[j].size()){playheads[j]=0;};
while(playheads[j]<S.getTracks()[j].size() && S.getTracks()[j].get(playheads[j]).getTick()==counter){
message_buffer.add(S.getTracks()[j].get(playheads[j]).getMessage());
playheads[j]=playheads[j]+1;
}
}
for(Iterator<MidiMessage> it=message_buffer.iterator();it.hasNext();){
MidiMessage f=it.next();
for(int j=0;j<receivers.length;j++)
{
receivers[j].send(f, -1);}
}
counter=counter+1;
}
}
public Sequence getSequence() {
return S;
}
public void setSequence(Sequence s) {
this.S = s;
}
}