Sunday, 26 February 2012

Getting started with Java MIDI

This post is about getting started with the Java MIDI Api.

I'll try and step through creating a simple class that will let you add notes to a track, then let you play that track. This will allow most

If you want in depth information about everything, this site is great:

http://docs.oracle.com/javase/tutorial/sound/MIDI-synth.html

First things first, create a MusicPlayer class:


import javax.sound.midi.Track;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;

public class MusicPlayer {

        public Sequence currentSong;
        public Track currentTrack;
        public Sequencer player;

        public MusicPlayer()
        {
                currentSong = null;
                currentTrack = null;
                player = null;
        }
}



The second thing is learn how to write code on blogger....

No, the second thing is to add a method to create the sequencer we will use to play the music.
If you're looking for more information about the sequencer timing thing:
http://docs.oracle.com/javase/1.4.2/docs/api/javax/sound/midi/Sequence.html


    public Sequencer createPlayer()
    {
            Sequencer cPlayer = null;
           try
           {
                   cPlayer = MidiSystem.getSequencer();
                   cPlayer.open();
                    // 16 counts per quarter note, so 4/4 = 64 counts;
                   Sequence seq = new Sequence(Sequence.PPQ, 16);
                   currentSong = seq;
                   currentTrack = currentSong.createTrack();
           }
           catch (Exception e)
           {
                   e.printStackTrace();
            }
           return cPlayer;
    }



import javax.sound.midi.InvalidMidiDataException;
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.Track;

public class MusicPlayer {
   
    public Sequence currentSong;
    public Track currentTrack;
    public Sequencer player;

    public MusicPlayer()
    {
            currentSong = null;
            currentTrack = null;
            player = createPlayer();
    }
   
    public void play()
    {
            if(currentSong != null)
            {
                   try
                    {
                            player.setSequence(currentSong);
                            player.start();
                    }
                    catch (Exception e) {
                            e.printStackTrace();
                    }
            }
    }
   
    public void addNote(int pitch, int volume, int time, int duration)
    {
            try {
                    if(duration < 1)
                    {
                            duration = 1;
                    }
                    ShortMessage a = new ShortMessage();
                    // First part is what you want to happen, the 4 is channel (instrument pretty much)
                    // Pitch is which note (60 for middle C, 61 C#, 62 D etc)
                    // Volume is how loud (relatively) the note should be played.
                    a.setMessage(ShortMessage.NOTE_ON, 4, pitch, volume);
                    MidiEvent noteOn = new MidiEvent (a, time);
                    currentTrack.add(noteOn);
                    ShortMessage b = new ShortMessage();
                    b.setMessage(ShortMessage.NOTE_OFF, 4, pitch, volume);
                    MidiEvent noteOff = new MidiEvent (b, time + duration);
                    currentTrack.add(noteOff);
           } catch (InvalidMidiDataException e) {
                    e.printStackTrace();
            }
    }
   
    // If I was smart this would be an actual song rather than bad noise!
    public void createDemoSong()
    {
            // Pitch, Volume, StartTime, Duration
            // StartTime is in the same time scheme as the sequencer
            // So 0 starts beginning first bar, 64 seconds, 128 third etc
            // Because our sequencer is set to 64 counts a bar
            this.addNote(60, 60, 0, 16);
            this.addNote(50, 60, 16, 16);
            this.addNote(62, 60, 32, 32);
            this.addNote(54, 60, 64, 16);
            this.addNote(56, 60, 80, 16);
            this.addNote(44, 60, 96, 16);
            this.addNote(76, 60, 112, 16);
            this.addNote(47, 60, 128, 16);
            this.addNote(48, 60, 144, 32);
    }
   
    public Sequencer createPlayer()
    {
            Sequencer cPlayer = null;
            try
            {
                    cPlayer = MidiSystem.getSequencer();
                    cPlayer.open();
                    // 16 counts per quarter note, so 4/4 = 64 counts;
                    Sequence seq = new Sequence(Sequence.PPQ, 16);
                    currentSong = seq;
                    currentTrack = currentSong.createTrack();
            }
            catch (Exception e)
            {
                    e.printStackTrace();
            }
            return cPlayer;
    }
}

No comments:

Post a Comment