I am trying to establish the ability of javax.sound.midi code to generate a simple sound, so that I can be setup to start to work on more complicated MIDI code.  But the code below is not producing a sound.  The code sample is only about 50 lines and is from a web example that is supposed to just work out of the box.  But instead it is producing the following error message in the console when I run the program:  
Synthesizer: com.sun.media.sound.SoftSynthesizer@682a0b20
Aug 04, 2015 5:03:20 PM java.util.prefs.WindowsPreferences <init>
WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
MidiChannel: com.sun.media.sound.SoftChannelProxy@6e2c9341
Also, NO SOUND IS BEING GENERATED. The OS is Windows 8.1, if that matters.
What is causing this error? How can I change the small code section below to get it to play the simple sound?
Here is the complete ~50 lines of code that is throwing the above output:
package main;
import javax.sound.midi.*;
public class MidiMain {
private static boolean  DEBUG = true;
public static void main(String[] args){
    /** The MIDI channel to use for playing the note. */
    int nChannelNumber = 1;
    int nNoteNumber = 20;   // MIDI key number
    int nVelocity = 20;
    /*  Time between note on and note off event in milliseconds. Note that on most systems, the
     *  best resolution you can expect are 10 ms.*/
    int nDuration = 20;
    nNoteNumber = Math.min(127, Math.max(0, nNoteNumber));
    nVelocity = Math.min(127, Math.max(0, nVelocity));
    nDuration = Math.max(0, nDuration);
    /*  We need a synthesizer to play the note on. Here, we simply request the default synthesizer. */
    Synthesizer synth = null;
    try { synth = MidiSystem.getSynthesizer();}
    catch (MidiUnavailableException e){
        e.printStackTrace();
        System.exit(1);
    }
    if (DEBUG) out("Synthesizer: " + synth);
    /*  Of course, we have to open the synthesizer to produce any sound for us. */
    try {synth.open();}
    catch (MidiUnavailableException e){
        e.printStackTrace();
        System.exit(1);
    }
    /* Turn the note on on MIDI channel 1.  (Index zero means MIDI channel 1) */
    MidiChannel[]   channels = synth.getChannels();
    MidiChannel channel = channels[nChannelNumber];
    if (DEBUG) out("MidiChannel: " + channel);
    channel.noteOn(nNoteNumber, nVelocity);
    /* Wait for the specified amount of time (the duration of the note). */
    try {Thread.sleep(nDuration);}
    catch (InterruptedException e){e.printStackTrace();}
    /* Turn the note off. */
    channel.noteOff(nNoteNumber);
    /* Close the synthesizer. */
    synth.close();
}
private static void out(String strMessage){ System.out.println(strMessage);}    
}
20 milliseconds is a short amount of time. Have you tried a longer duration? You might also need some more sleeping at the end before you program exits.
When you do a synth.close() you won't get any more sound output from the sound card.  You'll probably need to allow extra time before closing it for soft-synth latency and instrument echo.
The latency can be retrieved by synth.getLatency() and is in microseconds.  You might want to Thread.sleep() for this amount of time at a minimum before closing synth.  
...
Thread.sleep(TimeUnit.MICROSECONDS.toMillis(synth.getLatency()));
synth.close();
But adding some time for instrument echo would give a better sound instead of a sudden cutoff.
User contributions licensed under CC BY-SA 3.0