Java by API/javax.sound.midi/Sequence

Материал из Java эксперт
Перейти к: навигация, поиск

new Sequence(float divisionType, int resolution)

   <source lang="java">
 

/*

* Copyright (c) 2004 David Flanagan.  All rights reserved.
* This code is from the book Java Examples in a Nutshell, 3nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose,
* including teaching and use in open-source projects.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book, 
* please visit http://www.davidflanagan.ru/javaexamples3.
*/

import java.io.File; import java.io.IOException; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MetaEventListener; import javax.sound.midi.MetaMessage; import javax.sound.midi.MidiEvent; import javax.sound.midi.MidiSystem; import javax.sound.midi.MidiUnavailableException; import javax.sound.midi.Sequence; import javax.sound.midi.Sequencer; import javax.sound.midi.ShortMessage; import javax.sound.midi.Synthesizer; import javax.sound.midi.Track; public class Main {

 // These are some MIDI constants from the spec. They aren"t defined
 // for us in javax.sound.midi.
 public static final int DAMPER_PEDAL = 64;
 public static final int DAMPER_ON = 127;
 public static final int DAMPER_OFF = 0;
 public static final int END_OF_TRACK = 47;
 public static void main(String[] args) throws MidiUnavailableException, InvalidMidiDataException,
     IOException {
   int instrument = 0;
   int tempo = 120;
   String filename = null;
   // Parse the options
   // -i <instrument number> default 0, a piano. Allowed values: 0-127
   // -t <beats per minute> default tempo is 120 quarter notes per minute
   // -o <filename> save to a midi file instead of playing
   int a = 0;
   while (a < args.length) {
     if (args[a].equals("-i")) {
       instrument = Integer.parseInt(args[a + 1]);
       a += 2;
     } else if (args[a].equals("-t")) {
       tempo = Integer.parseInt(args[a + 1]);
       a += 2;
     } else if (args[a].equals("-o")) {
       filename = args[a + 1];
       a += 2;
     } else
       break;
   }
   char[] notes = args[a].toCharArray();
   // 16 ticks per quarter note.
   Sequence sequence = new Sequence(Sequence.PPQ, 16);
   // Add the specified notes to the track
   addTrack(sequence, instrument, tempo, notes);
   if (filename == null) { // no filename, so play the notes
     // Set up the Sequencer and Synthesizer objects
     Sequencer sequencer = MidiSystem.getSequencer();
     sequencer.open();
     Synthesizer synthesizer = MidiSystem.getSynthesizer();
     synthesizer.open();
     sequencer.getTransmitter().setReceiver(synthesizer.getReceiver());
     // Specify the sequence to play, and the tempo to play it at
     sequencer.setSequence(sequence);
     sequencer.setTempoInBPM(tempo);
     // Let us know when it is done playing
     sequencer.addMetaEventListener(new MetaEventListener() {
       public void meta(MetaMessage m) {
         // A message of this type is automatically sent
         // when we reach the end of the track
         if (m.getType() == END_OF_TRACK)
           System.exit(0);
       }
     });
     // And start playing now.
     sequencer.start();
   } else { // A file name was specified, so save the notes
     int[] allowedTypes = MidiSystem.getMidiFileTypes(sequence);
     if (allowedTypes.length == 0) {
       System.err.println("No supported MIDI file types.");
     } else {
       MidiSystem.write(sequence, allowedTypes[0], new File(filename));
       System.exit(0);
     }
   }
 }
 static final int[] offsets = { // add these amounts to the base value
 // A B C D E F G
     -4, -2, 0, 1, 3, 5, 7 };
 /*
  * This method parses the specified char[] of notes into a Track. The musical
  * notation is the following: A-G: A named note; Add b for flat and # for
  * sharp. +: Move up one octave. Persists. -: Move down one octave. Persists.
  * /1: Notes are whole notes. Persists "till changed /2: Half notes /4:
  * Quarter notes /n: N can also be, 8, 16, 32, 64. s: Toggle sustain pedal on
  * or off (initially off)
  *  >: Louder. Persists <: Softer. Persists .: Rest. Length depends on current
  * length setting Space: Play the previous note or notes; notes not separated
  * by spaces are played at the same time
  */
 public static void addTrack(Sequence s, int instrument, int tempo, char[] notes)
     throws InvalidMidiDataException {
   Track track = s.createTrack(); // Begin with a new track
   // Set the instrument on channel 0
   ShortMessage sm = new ShortMessage();
   sm.setMessage(ShortMessage.PROGRAM_CHANGE, 0, instrument, 0);
   track.add(new MidiEvent(sm, 0));
   int n = 0; // current character in notes[] array
   int t = 0; // time in ticks for the composition
   // These values persist and apply to all notes "till changed
   int notelength = 16; // default to quarter notes
   int velocity = 64; // default to middle volume
   int basekey = 60; // 60 is middle C. Adjusted up and down by octave
   boolean sustain = false; // is the sustain pedal depressed?
   int numnotes = 0; // How many notes in current chord?
   while (n < notes.length) {
     char c = notes[n++];
     if (c == "+")
       basekey += 12; // increase octave
     else if (c == "-")
       basekey -= 12; // decrease octave
     else if (c == ">")
       velocity += 16; // increase volume;
     else if (c == "<")
       velocity -= 16; // decrease volume;
     else if (c == "/") {
       char d = notes[n++];
       if (d == "2")
         notelength = 32; // half note
       else if (d == "4")
         notelength = 16; // quarter note
       else if (d == "8")
         notelength = 8; // eighth note
       else if (d == "3" && notes[n++] == "2")
         notelength = 2;
       else if (d == "6" && notes[n++] == "4")
         notelength = 1;
       else if (d == "1") {
         if (n < notes.length && notes[n] == "6")
           notelength = 4; // 1/16th note
         else
           notelength = 64; // whole note
       }
     } else if (c == "s") {
       sustain = !sustain;
       // Change the sustain setting for channel 0
       ShortMessage m = new ShortMessage();
       m
           .setMessage(ShortMessage.CONTROL_CHANGE, 0, DAMPER_PEDAL, sustain ? DAMPER_ON
               : DAMPER_OFF);
       track.add(new MidiEvent(m, t));
     } else if (c >= "A" && c <= "G") {
       int key = basekey + offsets[c - "A"];
       if (n < notes.length) {
         if (notes[n] == "b") { // flat
           key--;
           n++;
         } else if (notes[n] == "#") { // sharp
           key++;
           n++;
         }
       }
       addNote(track, t, notelength, key, velocity);
       numnotes++;
     } else if (c == " ") {
       // Spaces separate groups of notes played at the same time.
       // But we ignore them unless they follow a note or notes.
       if (numnotes > 0) {
         t += notelength;
         numnotes = 0;
       }
     } else if (c == ".") {
       // Rests are like spaces in that they force any previous
       // note to be output (since they are never part of chords)
       if (numnotes > 0) {
         t += notelength;
         numnotes = 0;
       }
       // Now add additional rest time
       t += notelength;
     }
   }
 }
 // A convenience method to add a note to the track on channel 0
 public static void addNote(Track track, int startTick, int tickLength, int key, int velocity)
     throws InvalidMidiDataException {
   ShortMessage on = new ShortMessage();
   on.setMessage(ShortMessage.NOTE_ON, 0, key, velocity);
   ShortMessage off = new ShortMessage();
   off.setMessage(ShortMessage.NOTE_OFF, 0, key, velocity);
   track.add(new MidiEvent(on, startTick));
   track.add(new MidiEvent(off, startTick + tickLength));
 }

}


 </source>