#java #event-handling #javax.sound.midi
#java #обработка событий #javax.sound.midi
Вопрос:
Я работаю над программой, которая генерирует и воспроизводит MIDI-события. Я реализовал интерфейс ControllerEventListener для того, чтобы печатать сообщения каждый раз, когда воспроизводится одна из 15 нот.
Проблема в том, что я больше не могу изменить инструмент, на котором воспроизводятся ноты (этим я должен сказать, что мой компьютер использует не пианино по умолчанию, а барабан или что-то подобное, если я добавлю ControllerEvent к дорожке) Я уже просмотрел задействованные методы в спецификациях Java API, но я не нашел ничего, что могло бы решить мою проблему, так же мало я нашел на этом сайте или в Google. Что я также сделал, так это попытался изменить инструмент всего канала (добавив сообщение об изменении программы), но это было точно так же, как и раньше.
Код следующий:
import javax.sound.midi.*;
public class MusikPlayer implements ControllerEventListener {
public static void main(String[] args) {
MusikPlayer mini = new MusikPlayer();
mini.go();
}
public void go() {
try {
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
int[] wishedEvents = {127};
sequencer.addControllerEventListener(this, wishedEvents);
Sequence seq = new Sequence(Sequence.PPQ, 4);
Track track = seq.createTrack();
for (int i = 5; i < 61; i =4) {
track.add(generateEvent(144, 1, i, 100, i));
track.add(generateEvent(128, 1, i, 100, i 2));
track.add(generateEvent(176, 1, 127, 0, i));
}
sequencer.setSequence(seq);
sequencer.setTempoInBPM(220);
sequencer.start();
Thread.sleep(5000);
sequencer.close();
} catch (Exception e) {e.printStackTrace();}
}
public void controlChange(ShortMessage event) {
System.out.println("la");
}
public MidiEvent generateEvent(int comd, int chan, int one, int two, int tick) {
MidiEvent event = null;
try {
ShortMessage a = new ShortMessage();
a.setMessage(comd, chan, one, two);
event = new MidiEvent(a, tick);
} catch (Exception e) {}
return event;
}
}
Теперь мой вопрос: как я могу изменить инструмент без изменения моей процедуры обработки событий?
Ответ №1:
Проверьте этот код
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.sound.midi.*;
public class TestMidi {
private static final int TYPE_SINGLE_TRACK = 0;
private static final int TYPE_PARALLEL_TRACKS = 1;
private static final int TYPE_SERIAL_TRACKS = 2;
public static void main(String[] args) {
String filename = TestMidi.class.getName() "_" new SimpleDateFormat("yyyyMMdd-HHmmss.SSSS").format(new Date()) ".mid";
System.out.println("filename:" filename);
File midiOutputFile = new File(filename);
System.out.println("midiOutputFile.getAbsolutePath():" midiOutputFile.getAbsolutePath());
Sequence sequence = null;
Synthesizer synthesizer = null;
final Sequencer sequencer;
List<Instrument> listInstrument;
List<MidiChannel> listMidiChannel;
Track trackPiano;
Track trackViolin;
try {
synthesizer = MidiSystem.getSynthesizer();
synthesizer.open();
synthesizer.loadAllInstruments(synthesizer.getDefaultSoundbank());
listInstrument = Arrays.asList(synthesizer.getLoadedInstruments());
listMidiChannel = Arrays.asList(synthesizer.getChannels());
listInstrument
.stream()
.map(instrument -> instrument.getPatch())
.forEach(patch -> System.out.println("patch.getBank():" patch.getBank()
"tpatch.getProgram():" patch.getProgram()
"tlistInstrument.get(patch.getProgram()).getName():" listInstrument.get(patch.getProgram()).getName()));
Instrument instrumentPiano = listInstrument
.stream()
.filter(instrument -> instrument.getName().equals("Acoustic Grand Piano"))
.findFirst()
.get();
Instrument instrumentViolin = listInstrument
.stream()
.filter(instrument -> instrument.getName().equals("Violin"))
.findFirst()
.get();
int channelPiano = 0;
int channelViolin = 1;
listMidiChannel.get(channelPiano).programChange(instrumentPiano.getPatch().getProgram());
listMidiChannel.get(channelViolin).programChange(instrumentViolin.getPatch().getProgram());
sequence = new Sequence(Sequence.PPQ, 10); //10 pulses per quarter note
trackPiano = sequence.createTrack();
trackViolin = sequence.createTrack();
long instant = 0L;
trackPiano.add(createMidiEvent(ShortMessage.PROGRAM_CHANGE, channelPiano, instrumentPiano.getPatch().getProgram(), 0, instant * sequence.getResolution() / 500));
trackViolin.add(createMidiEvent(ShortMessage.PROGRAM_CHANGE, channelViolin, instrumentViolin.getPatch().getProgram(), 0, instant * sequence.getResolution() / 500));
instant = 250L; //250milliSeconds -> 1/4 Second
int pitchViolin = 63;
int valueViolin = 127;
trackViolin.add(createMidiEvent(ShortMessage.NOTE_ON, channelViolin, pitchViolin, valueViolin, instant * sequence.getResolution() / 500));
instant = 500L; //500milliSeconds -> 1/2 Second
int pitchPiano = 60;
int valuePiano = 64;
trackPiano.add(createMidiEvent(ShortMessage.NOTE_ON, channelPiano, pitchPiano, valuePiano, instant * sequence.getResolution() / 500));
instant = 1000L; //1000milliSeconds -> 1 Second
trackPiano.add(createMidiEvent(ShortMessage.NOTE_OFF, channelPiano, pitchPiano, valuePiano, instant * sequence.getResolution() / 500));
instant = 1250L; //1250milliSeconds
trackViolin.add(createMidiEvent(ShortMessage.NOTE_OFF, channelViolin, pitchViolin, valueViolin, instant * sequence.getResolution() / 500));
instant = 1500L; //1500milliSeconds
pitchPiano = 66;
trackPiano.add(createMidiEvent(ShortMessage.NOTE_ON, channelPiano, pitchPiano, valuePiano, instant * sequence.getResolution() / 500));
instant = 1000L; //500milliSeconds
trackPiano.add(createMidiEvent(ShortMessage.NOTE_OFF, channelPiano, pitchPiano, valuePiano, instant * sequence.getResolution() / 500));
sequencer = MidiSystem.getSequencer();
try {
sequencer.open();
sequencer.setSequence(sequence);
} catch (Exception ex) {
Logger.getLogger(TestMidi.class.getName()).log(Level.SEVERE, null, ex);
}
sequencer.start();
Integer midiFileType;
if (sequence.getTracks().length == 1) {
midiFileType = TYPE_SINGLE_TRACK;
} else {
midiFileType = TYPE_PARALLEL_TRACKS;
}
int[] arrayMidiFileTypes = MidiSystem.getMidiFileTypes(sequence);
if (arrayMidiFileTypes.length > 0) {
MidiSystem.write(sequence, arrayMidiFileTypes[0], midiOutputFile);
}
sequencer.addMetaEventListener(new MetaEventListener() {
@Override
public void meta(MetaMessage metaMsg) {
if (metaMsg.getType() == 0x2F) {
sequencer.close();
}
}
});
/*
while (sequencer.isRunning()) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(TestMidi.class.getName()).log(Level.SEVERE, null, ex);
}
}
sequencer.close();
*/
} catch (InvalidMidiDataException e) {
Logger.getLogger(TestMidi.class.getName()).log(Level.SEVERE, null, e);
} catch (MidiUnavailableException ex) {
Logger.getLogger(TestMidi.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(TestMidi.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static MidiEvent createMidiEvent(int command, int channel, int data1, int data2, long instant) {
ShortMessage shortMessage = new ShortMessage();
try {
shortMessage.setMessage(
command,
channel,
data1,
data2);
} catch (InvalidMidiDataException e) {
}
return new MidiEvent(shortMessage, instant);
}
}