Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么赢了';midi音符计时是否有效?_Java_Midi_Javax.sound.midi - Fatal编程技术网

Java 为什么赢了';midi音符计时是否有效?

Java 为什么赢了';midi音符计时是否有效?,java,midi,javax.sound.midi,Java,Midi,Javax.sound.midi,我正在创建一个midi钢琴卷编辑器。Note类创建并包含一个Note_ON对象和一个关联的Note_OFF对象以及一个矩形,用户可以在屏幕上操纵该矩形来操纵音符的音高、计时和持续时间。下面是这个类的代码减去矩形的代码。我不明白为什么它不能正常工作。测试程序创建了其中五个音符对象,并将它们显示在钢琴滚动网格上,它们可以正常播放。当上下拖动矩形时,更改间距的方法也能正常工作。但是当我调用这些方法来更改时间或持续时间时,这些注释开始出现错误。首先,它们不会在移动时被告知的位置播放,然后,如果音符相互重

我正在创建一个midi钢琴卷编辑器。Note类创建并包含一个Note_ON对象和一个关联的Note_OFF对象以及一个矩形,用户可以在屏幕上操纵该矩形来操纵音符的音高、计时和持续时间。下面是这个类的代码减去矩形的代码。我不明白为什么它不能正常工作。测试程序创建了其中五个音符对象,并将它们显示在钢琴滚动网格上,它们可以正常播放。当上下拖动矩形时,更改间距的方法也能正常工作。但是当我调用这些方法来更改时间或持续时间时,这些注释开始出现错误。首先,它们不会在移动时被告知的位置播放,然后,如果音符相互重叠或延伸,移动的音符将阻止其下方的音符播放。我发送给这些方法的移动单位作为参数设置为16,因此音符将始终捕捉到第16拍位置。有人能发现我的代码有什么错误吗

public class Note {
MidiEvent noteOn;
MidiEvent noteOff;

private int channel;
private int pitch;
private int vel;

// Constructor calls methods to create NOTE_ON, NOTE_OFF, and graphical rectangle
public Note(MidiMessage on, long tickPos) {
    noteOn = createNoteOn(on, tickPos);
    ShortMessage shortMessage = (ShortMessage) on;
    noteOff = createNoteOff(shortMessage.getChannel(), shortMessage.getData1(), tickPos);
}

public MidiEvent createNoteOn(MidiMessage on, long tickPos) {
    noteOn = new MidiEvent(on, tickPos);
    return noteOn;
}

public MidiEvent createNoteOff(int chan, int pitch, long tickPos) {
    try {
        noteOff = new MidiEvent(new ShortMessage(ShortMessage.NOTE_OFF, chan, pitch, 0), tickPos + 2);
    } catch (InvalidMidiDataException e) {
            e.printStackTrace();
    }
    return noteOff;
}

// Method for moving musical pitch of this note up or down for both NOTE_ON and NOTE_OFF
public void setPitch(int pitchUpOrDown) {
    MidiMessage message = noteOn.getMessage();
    ShortMessage shortMessage = (ShortMessage) message;
        channel = shortMessage.getChannel();
        pitch = shortMessage.getData1();
        vel = shortMessage.getData2();
        try {
            shortMessage.setMessage(ShortMessage.NOTE_ON, channel, pitch + pitchUpOrDown, vel);
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
        }
        message = noteOff.getMessage();
        shortMessage = (ShortMessage) message;
        try {
            shortMessage.setMessage(ShortMessage.NOTE_OFF, channel, pitch + pitchUpOrDown, 0);
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
        }
}

// Moves entire note without changing duration of note
public void shiftLocation(int diff) {
    noteOn.setTick(noteOn.getTick() + diff);
    noteOff.setTick(noteOff.getTick() + diff);
}

// Moves start time of note while leaving end time in place, changes duration of note
public void setStartTime(long start) {
    noteOn.setTick(start);
}

// Moves end time of note while leaving start time in place, changes duration of note
public void setDuration(int duration) {
    noteOff.setTick(noteOff.getTick() + duration);
}
MIDI音序器和合成器:

import javax.sound.midi.*;

public class MusicEngine {
Sequencer sequencer;
Sequence sequence;
Synthesizer synthesizer;
Track track;
MidiEvent event;
// PPQ, or ticks per beat
int ticksPerBeat = 16;
int tempoBPM = 120;

// Constructor
public MusicEngine() {      
    createMidi();
}

// Get sequencer and sequence and track
public void createMidi() {
    try {
        sequencer =  MidiSystem.getSequencer();
        if (sequencer == null) {
            System.out.println("Cannot get a sequencer");
            System.exit(0);
        }
        sequencer.open();

        // If sequencer is not the same as synthesizer, link the two 
        // (required in J2SE 5.0)
        if (!(sequencer instanceof Synthesizer)) {
            System.out.println("Linking the sequencer to the synthesizer");
            synthesizer = MidiSystem.getSynthesizer();
            synthesizer.open();
            Receiver synthReceiver = synthesizer.getReceiver();
            Transmitter seqTransmitter = sequencer.getTransmitter();
            seqTransmitter.setReceiver(synthReceiver);
        } else 
            synthesizer = (Synthesizer)sequencer;
        sequence = new Sequence(Sequence.PPQ, ticksPerBeat);
        track = sequence.createTrack();
        sequencer.setTempoInBPM(tempoBPM);
    } catch(MidiUnavailableException e) {
        System.out.println("No sequencer available");
        System.exit(0);
    } catch(Exception e) {
        e.printStackTrace();
        System.exit(0);
    }

}

// Create an individual MIDI event
public MidiEvent createEvent(int command, int channel, int one, int two, int tick) {
    event = null;
    try {
        ShortMessage a = new ShortMessage();
        a.setMessage(command, channel, one, two);
        event = new MidiEvent(a, tick);
    } catch(InvalidMidiDataException e) {
        e.printStackTrace();
    }
    return event;
}

public void add(MidiEvent event) {
    track.add(event);
}

public void playSong(int tempo) {
    try {
        sequencer.setSequence(sequence);
    }
    catch (InvalidMidiDataException e) {
        e.printStackTrace();
    }

    sequencer.start();
}

public void stopSong() {
    sequencer.stop();
}
}

我可能误解了这里的代码,但似乎您只是在增加
setDuration()
方法中注释的长度。它不应该看起来像这样吗

public void setDuration(int duration) {
    noteOff.setTick(noteOn.getTick() + duration);
}

可能有助于发布您用于播放序列的代码?另外,你能先把事情隔离到一个简单的测试用例中吗?在这个测试用例中,你用几个音符创建一个曲目,改变其中一个音符的时间/持续时间,然后播放序列?我添加了synth和sequencer引擎。我得离开一会儿。当我回来的时候,我会尝试简化代码,并从我的更复杂的代码中提取一个简单的测试代码。是的,这就是这种方法的目的:增加注释的长度。上面是一个单独的方法,用于实际移动音符(setStartTime)。我仍在致力于提供一种简洁的代码形式,但在使代码正常工作时遇到了问题。这是我的第一个真正的项目,所以我恳求你耐心等待我想出如何做这些事情。