// Path: src/main/java/com/sun/media/sound/AudioSynthesizer.java
// public interface AudioSynthesizer extends Synthesizer {
// 
//     /**
//      * Obtains the current format (encoding, sample rate, number of channels,
//      * etc.) of the synthesizer audio data.
//      *
//      * <p>If the synthesizer is not open and has never been opened, it returns
//      * the default format.
//      *
//      * @return current audio data format
//      * @see AudioFormat
//      */
//     public AudioFormat getFormat();
// 
//     /**
//      * Gets information about the possible properties for the synthesizer.
//      *
//      * @param info a proposed list of tag/value pairs that will be sent on open.
//      * @return an array of <code>AudioSynthesizerPropertyInfo</code> objects
//      * describing possible properties. This array may be an empty array if
//      * no properties are required.
//      */
//     public AudioSynthesizerPropertyInfo[] getPropertyInfo(
//             Map<String, Object> info);
// 
//     /**
//      * Opens the synthesizer and starts rendering audio into
//      * <code>SourceDataLine</code>.
//      *
//      * <p>An application opening a synthesizer explicitly with this call
//      * has to close the synthesizer by calling {@link #close}. This is
//      * necessary to release system resources and allow applications to
//      * exit cleanly.
//      *
//      * <p>Note that some synthesizers, once closed, cannot be reopened.
//      * Attempts to reopen such a synthesizer will always result in
//      * a <code>MidiUnavailableException</code>.
//      *
//      * @param line which <code>AudioSynthesizer</code> writes output audio into.
//      * If <code>line</code> is null, then line from system default mixer is used.
//      * @param info a <code>Map<String,Object></code> object containing
//      * properties for additional configuration supported by synthesizer.
//      * If <code>info</code> is null then default settings are used.
//      *
//      * @throws MidiUnavailableException thrown if the synthesizer cannot be
//      * opened due to resource restrictions.
//      * @throws SecurityException thrown if the synthesizer cannot be
//      * opened due to security restrictions.
//      *
//      * @see #close
//      * @see #isOpen
//      */
//     public void open(SourceDataLine line, Map<String, Object> info)
//             throws MidiUnavailableException;
// 
//     /**
//      * Opens the synthesizer and renders audio into returned
//      * <code>AudioInputStream</code>.
//      *
//      * <p>An application opening a synthesizer explicitly with this call
//      * has to close the synthesizer by calling {@link #close}. This is
//      * necessary to release system resources and allow applications to
//      * exit cleanly.
//      *
//      * <p>Note that some synthesizers, once closed, cannot be reopened.
//      * Attempts to reopen such a synthesizer will always result in
//      * a <code>MidiUnavailableException<code>.
//      *
//      * @param targetFormat specifies the <code>AudioFormat</code>
//      * used in returned <code>AudioInputStream</code>.
//      * @param info a <code>Map<String,Object></code> object containing
//      * properties for additional configuration supported by synthesizer.
//      * If <code>info</code> is null then default settings are used.
//      *
//      * @throws MidiUnavailableException thrown if the synthesizer cannot be
//      * opened due to resource restrictions.
//      * @throws SecurityException thrown if the synthesizer cannot be
//      * opened due to security restrictions.
//      *
//      * @see #close
//      * @see #isOpen
//      */
//     public AudioInputStream openStream(AudioFormat targetFormat,
//             Map<String, Object> info) throws MidiUnavailableException;
// }


import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Soundbank;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.Track;
import javax.sound.midi.MidiDevice.Info;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import com.sun.media.sound.AudioSynthesizer;
import java.io.File;
import java.io.FileNotFoundException;
import javax.sound.midi.MetaMessage;
				Soundbank defsbk = synth.getDefaultSoundbank();
				if (defsbk != null)
					synth.unloadAllInstruments(defsbk);
				synth.loadAllInstruments(soundbank);
			}

			// Play Sequence into AudioSynthesizer Receiver.
			double total = send(sequence, synth.getReceiver());

			// Calculate how long the WAVE file needs to be.
			long len = (long) (stream.getFormat().getFrameRate() * (total + 4));
			stream = new AudioInputStream(stream, stream.getFormat(), len);

			// Write WAVE file to disk.
			AudioSystem.write(stream, AudioFileFormat.Type.WAVE, audio_file);

			// We are finished, close synthesizer.
			synth.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * Find available AudioSynthesizer.
	 */
	public static AudioSynthesizer findAudioSynthesizer()
			throws MidiUnavailableException {
		// First check if default synthesizer is AudioSynthesizer.
		Synthesizer synth = MidiSystem.getSynthesizer();
// Path: src/main/java/com/sun/media/sound/AudioSynthesizer.java
// public interface AudioSynthesizer extends Synthesizer {
// 
//     /**
//      * Obtains the current format (encoding, sample rate, number of channels,
//      * etc.) of the synthesizer audio data.
//      *
//      * <p>If the synthesizer is not open and has never been opened, it returns
//      * the default format.
//      *
//      * @return current audio data format
//      * @see AudioFormat
//      */
//     public AudioFormat getFormat();
// 
//     /**
//      * Gets information about the possible properties for the synthesizer.
//      *
//      * @param info a proposed list of tag/value pairs that will be sent on open.
//      * @return an array of <code>AudioSynthesizerPropertyInfo</code> objects
//      * describing possible properties. This array may be an empty array if
//      * no properties are required.
//      */
//     public AudioSynthesizerPropertyInfo[] getPropertyInfo(
//             Map<String, Object> info);
// 
//     /**
//      * Opens the synthesizer and starts rendering audio into
//      * <code>SourceDataLine</code>.
//      *
//      * <p>An application opening a synthesizer explicitly with this call
//      * has to close the synthesizer by calling {@link #close}. This is
//      * necessary to release system resources and allow applications to
//      * exit cleanly.
//      *
//      * <p>Note that some synthesizers, once closed, cannot be reopened.
//      * Attempts to reopen such a synthesizer will always result in
//      * a <code>MidiUnavailableException</code>.
//      *
//      * @param line which <code>AudioSynthesizer</code> writes output audio into.
//      * If <code>line</code> is null, then line from system default mixer is used.
//      * @param info a <code>Map<String,Object></code> object containing
//      * properties for additional configuration supported by synthesizer.
//      * If <code>info</code> is null then default settings are used.
//      *
//      * @throws MidiUnavailableException thrown if the synthesizer cannot be
//      * opened due to resource restrictions.
//      * @throws SecurityException thrown if the synthesizer cannot be
//      * opened due to security restrictions.
//      *
//      * @see #close
//      * @see #isOpen
//      */
//     public void open(SourceDataLine line, Map<String, Object> info)
//             throws MidiUnavailableException;
// 
//     /**
//      * Opens the synthesizer and renders audio into returned
//      * <code>AudioInputStream</code>.
//      *
//      * <p>An application opening a synthesizer explicitly with this call
//      * has to close the synthesizer by calling {@link #close}. This is
//      * necessary to release system resources and allow applications to
//      * exit cleanly.
//      *
//      * <p>Note that some synthesizers, once closed, cannot be reopened.
//      * Attempts to reopen such a synthesizer will always result in
//      * a <code>MidiUnavailableException<code>.
//      *
//      * @param targetFormat specifies the <code>AudioFormat</code>
//      * used in returned <code>AudioInputStream</code>.
//      * @param info a <code>Map<String,Object></code> object containing
//      * properties for additional configuration supported by synthesizer.
//      * If <code>info</code> is null then default settings are used.
//      *
//      * @throws MidiUnavailableException thrown if the synthesizer cannot be
//      * opened due to resource restrictions.
//      * @throws SecurityException thrown if the synthesizer cannot be
//      * opened due to security restrictions.
//      *
//      * @see #close
//      * @see #isOpen
//      */
//     public AudioInputStream openStream(AudioFormat targetFormat,
//             Map<String, Object> info) throws MidiUnavailableException;
// }


// Path: src/main/java/Midi2WavRender.java
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Soundbank;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.Track;
import javax.sound.midi.MidiDevice.Info;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import com.sun.media.sound.AudioSynthesizer;
import java.io.File;
import java.io.FileNotFoundException;
import javax.sound.midi.MetaMessage;

				Soundbank defsbk = synth.getDefaultSoundbank();
				if (defsbk != null)
					synth.unloadAllInstruments(defsbk);
				synth.loadAllInstruments(soundbank);
			}

			// Play Sequence into AudioSynthesizer Receiver.
			double total = send(sequence, synth.getReceiver());

			// Calculate how long the WAVE file needs to be.
			long len = (long) (stream.getFormat().getFrameRate() * (total + 4));
			stream = new AudioInputStream(stream, stream.getFormat(), len);

			// Write WAVE file to disk.
			AudioSystem.write(stream, AudioFileFormat.Type.WAVE, audio_file);

			// We are finished, close synthesizer.
			synth.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * Find available AudioSynthesizer.
	 */
	public static AudioSynthesizer findAudioSynthesizer()
			throws MidiUnavailableException {
		// First check if default synthesizer is AudioSynthesizer.
		Synthesizer synth = MidiSystem.getSynthesizer();
		if (synth instanceof AudioSynthesizer)