Java MIDI Sequencer SyncMode

时间:2015-10-27 02:24:16

标签: java midi javax.sound.midi

嗨:我试图将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()

的方法就足够了

问候并感谢!

2 个答案:

答案 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;
  }

}