미디 피아노 롤 편집기를 만들고 있습니다. Note 클래스는 노트의 피치, 타이밍 및 지속 시간을 조작하기 위해 사용자가 화면에서 조작하는 사각형뿐만 아니라 NOTE_ON 오브젝트 및 연관된 NOTE_OFF 오브젝트를 생성하여 포함합니다. 다음은이 클래스의 코드에서 사각형의 코드를 뺀 코드입니다. 왜 제대로 작동하지 않는지 알 수 없습니다. 테스트 프로그램은이 Note 오브젝트 중 다섯 개를 생성하여 피아노 롤 그리드에 표시하고 제대로 재생합니다. 직사각형을 위로 또는 아래로 끌 때 피치를 변경하는 방법이 제대로 작동합니다. 그러나 타이밍이나 지속 시간을 변경하는 메소드를 호출 할 때 노트가 잘못 작동하기 시작합니다. 우선, 그들은 움직일 때 말한 곳에서 연주하지 않으며, 그 위에 노트가 드래그되거나 서로 위로 뻗어 있다면, 움직이는 노트는 그 아래의 노트가 연주되는 것을 막을 것입니다. arg가 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);
}
미디 시퀀서와 신디사이저 :
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();
}
}
시퀀스를 재생하는 데 사용하는 코드를 게시 하시겠습니까? 또한 몇 가지 노트로 트랙을 만들고 노트 중 하나의 시간/지속 시간을 변경 한 다음 시퀀스를 재생하는 간단한 테스트 케이스로 먼저 물건을 격리 할 수 있습니까? –
신디와 시퀀서 엔진을 추가했습니다. 나는 조금 떠나야 만한다. 내가 돌아 왔을 때 코드를 단순화하고 간단한 코드를 추출하려고 노력할 것이다. –