JMSL Tutorial: Instruments and Interpreters

MIDI

JMSL supports JavaSound MIDI. With Java 7 onwards, JavaSound's "Gervill" implementation supports high quality SoundFonts!

Here's how to set up Midi:
	JMSL.midi = new MidiIOFactory().getMidiIO(MidiIOFactory.MidiIO_JAVASOUND);
	((MidiIO_JavaSound) JMSL.midi).setSoundbankFile(new File(LOCATION_OF_SOUNDFONT));
	JMSL.midi.setOutDevice("Gervill");
	JMSL.midi.open();
You do not have to specify the location of a Soundfont file. JavaSound will use a default if none is specified or if the file is not found.

JMSL's MIDI Init editor

JMSL's Midi device editor will let you browse for a soundfont. Download the FluidR3 GM2-2.SF2 here.
JMSL's MIDI Instrument Editor

JMSL's Midi Instrument Editor allows you to interactively choose Midi channel, program change, transposition, and instrument name. A dropdown list of General Midi instruments is generated from the loaded SoundFont, which sets the Program Change.


Below is complete source for a simple application that uses JavaSound MIDI, opens the Midi Device editor, then starts playing a MusicShape with a Midi Instrument. While it is playing, a Midi Instrument editor is displayed. You can hear different voices while it is performing by choosing from the drop-down list. This sets the instrument's MIDI Program Change.


package jmslexamples.simple;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JLabel;

import com.softsynth.jmsl.*;
import com.softsynth.jmsl.midi.*;
import com.softsynth.jmsl.view.MidiInstrumentEditDialog;

/**
 * Just play a MusicShape with a Midi instrument. 
 * 
 * This demo opens a Midi Device Editor.
 * It also opens Midi Instrument Editor which you can play with while the MusicShape is performing;
 * 
 * SoundFont support! As of Java 1.7 uses Gervill JavaSound. This demo uses FluidR3 soundfont. If
 * you don't have it, it will use Java's default sounds. You can download the FluidR3 SoundFont at
 * http://www.algomusic.com/SoundFonts/
 * 
 * @author Nick Didkovsky, (c) 2016 All rights reserved
 * 
 */
public class MIDISimple extends JFrame {

    // change this if you have a preferred MIDI sound font!
    // If this file is not found, MidiIO_JavaSound will try to load a default soundbank.
    // You can download the FluidR3 SoundFont at http://www.algomusic.com/SoundFonts/
    String LOCATION_OF_SOUNDFONT = "F:/jwork/SoundFonts/FluidR3/FluidR3 GM2-2.SF2";

    JMSLMixerContainer mixer;
    MidiInstrument instrument;
    MusicShape musicShape;
  
    public void go() {
        initJavaSoundMidi(); 
        buildMixer();
        buildInstrument();
        buildSong();
        launchSong();
        openMidiInstrumentEditor();
    }
  
    

    private void openMidiInstrumentEditor() {
        MidiInstrumentEditDialog d = new MidiInstrumentEditDialog(instrument);
        d.setVisible(true);
    }

    private void initJavaSoundMidi() {
        try {
            JMSL.midi = new MidiIOFactory().getMidiIO(MidiIOFactory.MidiIO_JAVASOUND);
            ((MidiIO_JavaSound) JMSL.midi).setSoundbankFile(new File(LOCATION_OF_SOUNDFONT));
            JMSL.midi.setOutDevice("Gervill");
            JMSL.midi.edit(this);
            JMSL.midi.open();
        } catch (IOException e2) {
            e2.printStackTrace();
        }
    }

    private void buildMixer() {
        mixer = new JMSLMixerContainer();
        mixer.start();
    }

    /** create a Midi instrument that sends on channel 1 and uses program change */
    private void buildInstrument() {
        instrument = new MidiInstrument(1); // midi channel 1
        instrument.setProgram(10);   // midi program change 
        mixer.addInstrument(instrument);
    }

    void buildSong() {
        musicShape = new MusicShape(instrument.getDimensionNameSpace());       
        musicShape.setInstrument(instrument);
        musicShape.add(0.5,  60,  64,  1.5);
        musicShape.add(0.5,  62,  64,  1.5);
        musicShape.add(0.5,  64,  64,  1.5);
        musicShape.add(0.5,  66,  64,  1.5);
        musicShape.add(0.5,  68,  64,  1.5);
        musicShape.setRepeats(1000);
    }

    private void launchSong() {
        musicShape.launch(JMSL.now() + 3); // 3 sec in future, give soundfont time to load.
    }
   
    public static void main(String[] args) {
        MIDISimple midiSimple = new MIDISimple();
        

        midiSimple.setTitle("Play MIDI with a MusicShape using JavaSound MIDI Gervill and a SoundFont");
        midiSimple.setSize(400, 200);
        midiSimple.setVisible(true);
        midiSimple.add(new JLabel("You can edit the Midi instrument while MusicShape is playing"));
        midiSimple.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {                
                System.exit(0);
            }
        });

        midiSimple.go();
        
    }
}
A few words on MidiInstrument...
MidiInstrument assumes MusicShape data looks like this:
dimension 0 = duration
dimension 1 = pitch
dimension 2 = velocity
dimension 3 = sustain time


MusicShape data that plays a staccato chromatic melody would look like this, for example:
dur  pitch  vel   sustain
1.0 65.0 120.0 0.25
1.0 66.0 120.0 0.25
1.0 67.0 120.0 0.25
1.0 68.0 120.0 0.25


Overlapping pitches could be achieved like this:
dur  pitch  vel   sustain
1.0 65.0 120.0 1.5
1.0 66.0 120.0 1.5
1.0 67.0 120.0 1.5
1.0 68.0 120.0 1.5


A big fat 4-note chord sustained for 10 seconds would look like this:
dur  pitch  vel   sustain
0.0 65.0 120.0 10.0
0.0 66.0 120.0 10.0
0.0 67.0 120.0 10.0
1.0 68.0 120.0 10.0



Next, we will see how to create a custom Instrument that plays a JSyn UnitVoice.



  (C) 1997 Phil Burk and Nick Didkovsky, All Rights Reserved
JMSL is based upon HMSL (C) Phil Burk, Larry Polansky and David Rosenboom.