【问题标题】:Java MIDI - ControllerEventListener (How to change the instrument)Java MIDI - ControllerEventListener(如何更改乐器)
【发布时间】:2019-03-18 18:53:41
【问题描述】:

我正在开发一个生成和播放 MIDI 事件的程序。我已经实现了 ControllerEventListener 接口,因为我想在每次播放 15 个音符中的一个时打印消息。

问题是,我不能再改变演奏音符的乐器(我不得不说我的电脑不使用默认钢琴,但如果我添加了鼓或类似的东西ControllerEvent to the track)我已经在 J​​ava API 规范中查找了涉及的方法,但是我没有找到可以解决我的问题的方法,就像我在这个站点上或通过谷歌搜索找到的一样少。 我也做了,是尝试改变整个频道的乐器(通过添加一个 Program Change 消息),但它和以前一样。

代码如下:

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

我现在的问题是:如何在不更改事件处理程序的情况下更改仪器?

【问题讨论】:

    标签: java event-handling javax.sound.midi


    【解决方案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);
      }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多