0

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);}    
}
CodeMed
  • 9,527
  • 70
  • 212
  • 364

1 Answers1

1

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.

prunge
  • 22,460
  • 3
  • 73
  • 80
  • I will not be at my computer for several hours. This API is completely new to me, though I read tutorials. Can you please show working code for wjat you suggest so that your suggestions are explicit when I am at my PC again? – CodeMed Aug 05 '15 at 10:57
  • *"Have you tried a longer duration?"* It works here with a longer duration (2000), but is barely noticeable at 20 msec delay. Having said that, the error above looks like the API is having trouble even setting up the MIDI system. OP - have you successfully used other apps. on that machine that will play MIDI? – Andrew Thompson Aug 05 '15 at 11:13
  • @AndrewThompson setting `nDuration=1000` gets the note to play, but does not resolve the error message. No, I have never used midi with java before. This is why I am giving such a simple code example. What else can I set up in order to resolve the still persistent error message? – CodeMed Aug 05 '15 at 19:33
  • *"No, I have never used midi with java before."* That's not what I was asking. Forget Java for the moment.. Have you heard MIDI coming out of a **non** Java app. on that machine? – Andrew Thompson Aug 05 '15 at 21:13