6 Replies Latest reply: Aug 6, 2010 2:52 PM by 843802 RSS

    Saving a MIDI sequence to a standard MIDI file!

    843802
      Hello.

      I'm working in an application where I'm filling a Sequence object with Tracks playing notes. Then I'm saving the Sequence to a standard MIDI file. But my problem is that I cannot choose the instrument with which to play the sequence on MIDI file. I don't have problems when using Synthesizer to play notes in runtime, I mean I can load all the instruments then choose them using programChange(int bank, int program), but I can't find a way with the Sequence object! The notes to be saved are sent as ShortMessage-s.
      If needed more details, I'll post a piece of code.

      Thanks in advance
        • 1. Re: Saving a MIDI sequence to a standard MIDI file!
          captfoss
          I'm pretty sure that instrument changes are handled as MIDI events...so you'd need to create a MidiMessage object specifying the instrument change, add it to a MidiEvent, and then send that event to the track you want to change the instrument on...

          [http://www.midi.org/techspecs/midimessages.php]

          Specifically, you'd want to generate a "Program Change" message to change the MIDI patch.

          [http://download.oracle.com/javase/6/docs/api/javax/sound/midi/ShortMessage.html]

          In Java, that would be represented as a ShortMessage object...

          So, I think it'd be like... for instance, to change it to percussion...
          ShortMessage sm = new ShortMessage();
          sm.setMessage(ShortMessage.PROGRAM_CHANGE, 10);
          • 2. Re: Saving a MIDI sequence to a standard MIDI file!
            843802
            It worked like a charm! Except that setMessage requires either one or three or four parameters, I used setMessage(int status, int data1, int data2). Thank you very much for your time.

            All the best.
            • 3. Re: Saving a MIDI sequence to a standard MIDI file!
              captfoss
              Eh, no one's perfect.. ;-)

              Glad you got it working.
              • 4. Re: Saving a MIDI sequence to a standard MIDI file!
                843802
                Ok I ran into another problem on the same issue.
                When I send ShortMessage-s to change the instrument, it seems it is only caring about the data1, it's ignoring data2, which doesn't fit my needs because I'm loading instruments and saving their 'bank' and 'program' indexes. On my PC it loads up to 411 instruments. Here are the loaded instruments using "synthesizer.getAvailableInstruments();"

                Instrument 1, Bank=0, Program=0
                Instrument 2, Bank=0, Program=1
                .........................................................
                Instrument 127, Bank=0, Program=126
                Instrument 128, Bank=0, Program=127
                Instrument 129, Bank=1, Program=27
                .........................................................
                Instrument 191, Bank=1, Program=95
                Instrument 192, Bank=2, Program=0
                .........................................................
                Instrument 319, Bank=2, Program=127
                Instrument 320, Bank=3, Program=0
                .........................................................
                Instrument 411, Bank=3, Program=91

                So I tried like this

                ShortMessage message = new ShortMessage();
                message.setMessage(ShortMessage.PROGRAM_CHANGE, 0, bank, program); //on channel 0

                This calling takes into consideration only the data1 parameter. Since data1 and data2 of setMessage can't be greater than 127, that means I can change only the first 128 instruments of the first bank, setting data1 from 0...127(That is Bank=0, Program=0...127). These instruments work great.

                My point is that indexes are not corresponding with the loaded instruments from Synthesizer. In my above code
                I thought to use data1 as bank, and data2 as program of the instrument.

                Any idea?
                I tried changing MIDI channel but it's not working, since I used channel 0 for Synthesizer. Internet seems to be poor at this point, also I admit am a beginner on java sound programming.

                Thanks in advance.
                • 5. Re: Saving a MIDI sequence to a standard MIDI file!
                  captfoss
                  Again, not a MIDI expert, but...

                  Bank selection appears to be handled via a "Control Change" message.

                  [http://www.midi.org/techspecs/midimessages.php]

                  Based on table 3, coupled with what I understand from the previous stuff in this thread...
                  public static void setInstrument(Track track, int tick, int bank, int instrument) {
                  
                    // First, issue the bank change
                    ShortMessage sm = new ShortMessage();
                    sm.setMessage(ShortMessage.CONTROL_CHANGE, 0, bank);
                  
                    track.add(new MidiEvent(sm, tick));
                  
                    // Now, issue the intrument change
                    ShortMessage sm2 = new ShortMessage();
                    sm2.setMEssage(ShortMessage.PROGRAM_CHANGE, instrument, 0);
                  
                    track.add(new MidiEvent(sm2, tick));
                  }
                  • 6. Re: Saving a MIDI sequence to a standard MIDI file!
                    843802
                    Ah okay, thanks a bunch. Now i can choose any of the loaded instruments.
                    I'm a little unsatisfied with the sound on file, it sounds just a little different each instrument(diff from runtime) but it's ok.

                    Thanks again.