Java midi程序选择奇怪的行为

时间:2015-10-18 19:44:53

标签: java midi

我试图找到有关此问题的任何信息,但我找不到任何有用的信息。

我试图制作一个程序来生成一个midi文件,其中包含两个乐器,它们使用不同的乐器(程序)同时播放。我一直在使用示例程序: http://www.cs.cornell.edu/courses/cs211/2008sp/examples/MidiSynth.java.txt 作为一个模板但是当我尝试人工创建midi事件时(而不是在示例程序中使用合成器动态生成它们),生成的midi文件似乎并不关心我已切换程序,使用最后一个改变的程序为文件中的每个音符组成,包括两个midi-tracks,即使我已将程序更改数据保存到两个音轨。我已经粘贴了我的程序beneith的代码:

import java.io.File;
import java.io.IOException;

import javax.sound.midi.Sequence;
import javax.sound.midi.Soundbank;
import javax.sound.midi.Sequencer;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.Instrument;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;
import javax.sound.midi.InvalidMidiDataException;    

public class MidiTest2
{
    /*  This velocity is used for all notes.
     */
    private static final int    VELOCITY = 64;
        final int PROGRAM = 192;
        final int NOTEON = 144;
        final int NOTEOFF = 128;

        long startTime;
        Sequence sequence;
        Synthesizer synthesizer;
        Sequencer sequencer;
        Instrument instruments[];
        ChannelData channels[];
        ChannelData cc;
        //int instrumentCounter = 0;

        Track track;

        MidiTest2(){
            try{
               if(synthesizer == null){
                   if((synthesizer = MidiSystem.getSynthesizer()) == null){
                       System.out.println("getSynthesizer() failed");
                       return;
                   }
               }
               synthesizer.open();
               sequencer = MidiSystem.getSequencer();
               sequence = new Sequence(Sequence.PPQ, 10);

            }catch(Exception e){
                e.printStackTrace();
                return;
            }

            Soundbank sb = synthesizer.getDefaultSoundbank();
            if(sb != null){
                instruments = synthesizer.getDefaultSoundbank().getInstruments();
                synthesizer.loadInstrument(instruments[0]);
            }

            MidiChannel midiChannels[] = synthesizer.getChannels();
            channels = new ChannelData[midiChannels.length];

            for(int i = 0; i < channels.length;++i){
                channels[i] = new ChannelData(midiChannels[i], i);
            }

            cc = channels[0];

        }

        public void createShortEvent(int type, int num){
            ShortMessage message = new ShortMessage();
            try{
                long millis = System.currentTimeMillis() - startTime;
                long tick = millis * sequence.getResolution() / 500;
                message.setMessage(type+cc.num, num, cc.velocity);
                System.out.println("Type: " + message.getCommand() + ", Data1: " + message.getData1() + ", Data2: " + message.getData2() + ", Tick: " + tick);

                MidiEvent event = new MidiEvent(message, tick);
                track.add(event);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        public void createShortEvent(int type, int num, int eventTime){
            ShortMessage message = new ShortMessage();
            try{
                //long millis = System.currentTimeMillis() - startTime;
                long tick = eventTime * sequence.getResolution();
                    message.setMessage(type+cc.num, num, cc.velocity);

                System.out.println("Type: " + message.getCommand() + ", Data1: " + message.getData1() + ", Data2: " + message.getData2() + ", Tick: " + tick);

                MidiEvent event = new MidiEvent(message, tick);
                track.add(event);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        public void saveMidiFile(){
            try {
                int[] fileTypes = MidiSystem.getMidiFileTypes(sequence);
                if (fileTypes.length == 0) {
                    System.out.println("Can't save sequence");
                } else {
                    if (MidiSystem.write(sequence, fileTypes[0], new File("testmidi.mid")) == -1) {
                        throw new IOException("Problems writing to file");
                    } 
                }
            } catch (SecurityException ex) { 

            } catch (Exception ex) { 
                ex.printStackTrace(); 
            }
        }

        void run(){
            //System.out.println("sequence: " + sequence.getTracks().length);
            createNewTrack(0);
            createShortEvent(NOTEON, 60, 2);
            createShortEvent(NOTEOFF, 60, 3);
            createShortEvent(NOTEON, 61, 3);
            createShortEvent(NOTEOFF, 61, 4);
            createShortEvent(NOTEON, 62, 4);
            createShortEvent(NOTEOFF, 62, 5);
            createShortEvent(NOTEON, 63, 5);
            createShortEvent(NOTEOFF, 63, 6);

            createNewTrack(5);

            createShortEvent(NOTEON, 50, 1);
            createShortEvent(NOTEOFF, 50, 5);

            playMidiFile();
            saveMidiFile();
        }

        void printTrack(int num){
            Track tempTrack = sequence.getTracks()[num];
            System.out.println(tempTrack.get(0).getTick());
        }

        void playMidiFile(){
            try{
                sequencer.open();
                sequencer.setSequence(sequence);
            }catch (Exception e){
                e.printStackTrace();
            }
            sequencer.start();
        }

        void createNewTrack(int program){
            track = sequence.createTrack();
            programChange(program);
        }

        void programChange(int program){

            cc.channel.programChange(program);
            System.out.println("program: " + program);
            startTime = System.currentTimeMillis();
            createShortEvent(PROGRAM, program);
        }

    public static void main(String[] args)
    {
            MidiTest2 mt = new MidiTest2();
            mt.run();                
    }

}

ChannelData类(除了我认为我为了完整起见而发布它之外什么都不做):

public class ChannelData {
    MidiChannel channel;
    boolean solo, mono, mute, sustain;
    int velocity, pressure, bend, reverb;
    int row, col, num;

    public ChannelData(MidiChannel channel, int num) {
        this.channel = channel;
        this.num = num;
        velocity = pressure = bend = reverb = 64;
    }

    public void setComponentStates() {

    }

}

在程序中,我尝试使用原声钢琴声音创建5个音符,使用电子钢琴声音创建一个音符。然而,即使我在切换乐器之前创建了新的音轨,所有音符都会以电钢琴音色播放。

我一直在努力解决这个问题,现在已经有5个小时或者其他什么了,而且我完全没有想法。

1 个答案:

答案 0 :(得分:0)

曲目可以帮助您自己的程序组织事件,但它们不会以任何方式影响合成器。

为了能够进行不同的设置,您必须使用不同的频道。