changeset 843:bcba163568ac

Integrate Gervill. 2008-04-30 Mark Wielaard <mark@klomp.org> * Makefile.am (ICEDTEA_PATCHES): Add patches/icedtea-gervill.patch. * Makefile.in: Regenerated. * patches/icedtea-gervill.patch: New patch. * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/*: New Gervill files.
author Mark Wielaard <mark@klomp.org>
date Wed, 30 Apr 2008 22:09:08 +0200
parents 1b845dd20b86
children 7b560b84e143
files ChangeLog Makefile.am Makefile.in overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatInputStream.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSInfo.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSInstrument.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSModulator.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSRegion.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSample.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSampleLoop.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSampleOptions.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbankReader.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/EmergencySoundbank.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/FFT.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/InvalidDataException.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/InvalidFormatException.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/JARSoundbankReader.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/LICENSE overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelAbstractChannelMixer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelAbstractOscillator.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelChannelMixer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelConnectionBlock.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDestination.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDirectedPlayer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDirector.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelIdentifier.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrumentComparator.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelMappedInstrument.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelOscillator.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelOscillatorStream.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelPatch.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelPerformer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelSource.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelStandardDirector.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelStandardTransform.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelTransform.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelWavetable.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATInstrument.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSample.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSoundbankReader.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/README.txt overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidDataException.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidFormatException.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFReader.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFWriter.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2GlobalRegion.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Instrument.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2InstrumentRegion.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Layer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2LayerRegion.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Modulator.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Region.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Sample.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2SoundbankReader.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SimpleInstrument.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SimpleSoundbank.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAbstractResampler.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioBuffer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioProcessor.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannelProxy.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChorus.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftControl.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftInstrument.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLanczosResampler.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLimiter.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler2.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftPerformer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftPointResampler.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftProcess.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftProvider.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReceiver.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftResampler.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftResamplerStreamer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftShortMessage.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSincResampler.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftTuning.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java patches/icedtea-gervill.patch
diffstat 101 files changed, 26224 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Apr 29 12:47:53 2008 -0400
+++ b/ChangeLog	Wed Apr 30 22:09:08 2008 +0200
@@ -1,3 +1,11 @@
+2008-04-30  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (ICEDTEA_PATCHES): Add patches/icedtea-gervill.patch.
+	* Makefile.in: Regenerated.
+	* patches/icedtea-gervill.patch: New patch.
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/*:
+	New Gervill files.
+
 2008-04-29  Lillian Angel  <langel@redhat.com>
 
 	* Makefile.am
--- a/Makefile.am	Tue Apr 29 12:47:53 2008 -0400
+++ b/Makefile.am	Wed Apr 30 22:09:08 2008 +0200
@@ -309,6 +309,7 @@
 	patches/icedtea-color-createcontext.patch \
 	patches/icedtea-color-profiles.patch \
 	patches/icedtea-fonts.patch \
+	patches/icedtea-gervill.patch \
 	$(GCC_PATCH) \
 	$(DISTRIBUTION_PATCHES)
 
--- a/Makefile.in	Tue Apr 29 12:47:53 2008 -0400
+++ b/Makefile.in	Wed Apr 30 22:09:08 2008 +0200
@@ -412,8 +412,8 @@
 	patches/icedtea-LCMS-setTagData.patch \
 	patches/icedtea-color-createcontext.patch \
 	patches/icedtea-color-profiles.patch \
-	patches/icedtea-fonts.patch $(GCC_PATCH) \
-	$(DISTRIBUTION_PATCHES) $(am__append_7)
+	patches/icedtea-fonts.patch patches/icedtea-gervill.patch \
+	$(GCC_PATCH) $(DISTRIBUTION_PATCHES) $(am__append_7)
 
 # Patch OpenJDK for plug replacements and ecj.
 ICEDTEA_ECJ_PATCH = patches/icedtea-ecj.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.spi.SoundbankReader;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.UnsupportedAudioFileException;
+
+/**
+ * Soundbank reader that uses audio files as soundbanks.
+ * 
+ * @version %I%, %E% 
+ * @author Karl Helgason
+ * 
+ */
+public class AudioFileSoundbankReader extends SoundbankReader {
+
+	public Soundbank getSoundbank(URL url) throws InvalidMidiDataException,
+			IOException {
+		try {
+			AudioInputStream ais = AudioSystem.getAudioInputStream(url);
+			Soundbank sbk = getSoundbank(ais);
+			ais.close();
+			return sbk;
+		} catch (UnsupportedAudioFileException e) {
+			return null;
+		} catch (IOException e) {
+			return null;
+		}
+	}
+
+	public Soundbank getSoundbank(InputStream stream)
+			throws InvalidMidiDataException, IOException {
+
+		stream.mark(512);
+		try {
+			AudioInputStream ais = AudioSystem.getAudioInputStream(stream);
+			Soundbank sbk = getSoundbank(ais);
+			if (sbk != null)
+				return sbk;
+		} catch (UnsupportedAudioFileException e) {
+		} catch (IOException e) {
+		}
+		stream.reset();
+		return null;
+	}
+
+	public Soundbank getSoundbank(AudioInputStream ais)
+			throws InvalidMidiDataException, IOException {
+
+		try {
+			try {
+				byte[] buffer;
+				if (ais.getFrameLength() == -1) {
+					ByteArrayOutputStream baos = new ByteArrayOutputStream();
+					byte[] buff = new byte[1024 - (1024 % ais.getFormat().getFrameSize())];
+					int ret;
+					while ((ret = ais.read(buff)) != -1)
+						baos.write(buff, 0, ret);
+					ais.close();
+					buffer = baos.toByteArray();
+				} else {
+					buffer = new byte[(int) (ais.getFrameLength() * ais
+							.getFormat().getFrameSize())];
+					ais.read(buffer);
+				}
+				ModelByteBufferWavetable osc = new ModelByteBufferWavetable(
+						new ModelByteBuffer(buffer), ais.getFormat(), -4800);
+				ModelPerformer performer = new ModelPerformer();
+				;
+				performer.getOscillators().add(osc);
+
+				SimpleSoundbank sbk = new SimpleSoundbank();
+				SimpleInstrument ins = new SimpleInstrument();
+				ins.add(performer);
+				sbk.addInstrument(ins);
+				return sbk;
+			} finally {
+			}
+		} catch (Exception e) {
+			return null;
+		}
+	}
+
+	public Soundbank getSoundbank(File file) throws InvalidMidiDataException,
+			IOException {
+
+		try {									
+				AudioInputStream ais = AudioSystem.getAudioInputStream(file);
+				ais.close();
+				ModelByteBufferWavetable osc = new ModelByteBufferWavetable(
+					new ModelByteBuffer(file, 0, file.length()), -4800);
+				ModelPerformer performer = new ModelPerformer();				
+				performer.getOscillators().add(osc);
+				SimpleSoundbank sbk = new SimpleSoundbank();
+				SimpleInstrument ins = new SimpleInstrument();
+				ins.add(performer);
+				sbk.addInstrument(ins);
+				return sbk;							
+		} catch (UnsupportedAudioFileException e1) {
+			return null;
+		} catch (IOException e) {
+			return null;
+		}
+
+	}
+	
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,670 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
+
+/**
+ * This class is used to convert between 8,16,24,32 bit signed/unsigned
+ * big/litle endian fixed/floating point byte buffers and float buffers.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public abstract class AudioFloatConverter {
+
+	public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");
+
+	/***************************************************************************
+	 * 
+	 * 32 bit float, little/big-endian
+	 * 
+	 **************************************************************************/
+
+	// PCM 32 bit float, little-endian
+	private static class AudioFloatConversion32L extends AudioFloatConverter {
+		ByteBuffer bytebuffer = null;
+
+		FloatBuffer floatbuffer = null;
+
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int in_len = out_len * 4;
+			if (bytebuffer == null || bytebuffer.capacity() < in_len) {
+				bytebuffer = ByteBuffer.allocate(in_len).order(
+						ByteOrder.LITTLE_ENDIAN);
+				floatbuffer = bytebuffer.asFloatBuffer();
+			}
+			bytebuffer.position(0);
+			floatbuffer.position(0);
+			bytebuffer.put(in_buff, in_offset, in_len);
+			floatbuffer.get(out_buff, out_offset, out_len);
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int out_len = in_len * 4;
+			if (bytebuffer == null || bytebuffer.capacity() < out_len) {
+				bytebuffer = ByteBuffer.allocate(out_len).order(
+						ByteOrder.LITTLE_ENDIAN);
+				floatbuffer = bytebuffer.asFloatBuffer();
+			}
+			floatbuffer.position(0);
+			bytebuffer.position(0);
+			floatbuffer.put(in_buff, in_offset, in_len);
+			bytebuffer.get(out_buff, out_offset, out_len);
+			return out_buff;
+		}
+	}
+
+	// PCM 32 bit float, big-endian
+	private static class AudioFloatConversion32B extends AudioFloatConverter {
+		ByteBuffer bytebuffer = null;
+
+		FloatBuffer floatbuffer = null;
+
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int in_len = out_len * 4;
+			if (bytebuffer == null || bytebuffer.capacity() < in_len) {
+				bytebuffer = ByteBuffer.allocate(in_len).order(
+						ByteOrder.BIG_ENDIAN);
+				floatbuffer = bytebuffer.asFloatBuffer();
+			}
+			bytebuffer.position(0);
+			floatbuffer.position(0);
+			bytebuffer.put(in_buff, in_offset, in_len);
+			floatbuffer.get(out_buff, out_offset, out_len);
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int out_len = in_len * 4;
+			if (bytebuffer == null || bytebuffer.capacity() < out_len) {
+				bytebuffer = ByteBuffer.allocate(out_len).order(
+						ByteOrder.BIG_ENDIAN);
+				floatbuffer = bytebuffer.asFloatBuffer();
+			}
+			floatbuffer.position(0);
+			bytebuffer.position(0);
+			floatbuffer.put(in_buff, in_offset, in_len);
+			bytebuffer.get(out_buff, out_offset, out_len);
+			return out_buff;
+		}
+	}
+
+	/***************************************************************************
+	 * 
+	 * 8 bit signed/unsigned
+	 * 
+	 **************************************************************************/
+
+	// PCM 8 bit, signed
+	private static class AudioFloatConversion8S extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++)
+				out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f);
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++)
+				out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f);
+			return out_buff;
+		}
+	}
+
+	// PCM 8 bit, unsigned
+	private static class AudioFloatConversion8U extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++)
+				out_buff[ox++] = ((in_buff[ix++]&0xFF) - 127) * (1.0f / 127.0f);
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++)
+				out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f);
+			return out_buff;
+		}
+	}
+
+	/***************************************************************************
+	 * 
+	 * 16 bit signed/unsigned, little/big-endian
+	 * 
+	 **************************************************************************/
+
+	// PCM 16 bit, signed, little-endian
+	private static class AudioFloatConversion16SL extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			/*
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++)
+				out_buff[ox++] = ((short) ((in_buff[ix++] & 0xFF) | (in_buff[ix++] << 8)))
+						* (1.0f / 32767.0f);
+			*/			
+			int len = out_offset + out_len;
+			for (int ox = out_offset; ox < len; ox++)
+				out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) | (in_buff[ix++] << 8)))
+						* (1.0f / 32767.0f);
+			
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ox = out_offset;
+			int len = in_offset + in_len;
+			for (int ix = in_offset; ix < len; ix++) {
+				int x = (int) (in_buff[ix] * 32767.0);
+				out_buff[ox++] = (byte) x;
+				out_buff[ox++] = (byte) (x >>> 8);
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 16 bit, signed, big-endian
+	private static class AudioFloatConversion16SB extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++)
+				out_buff[ox++] = ((short) ((in_buff[ix++] << 8) | (in_buff[ix++] & 0xFF)))
+						* (1.0f / 32767.0f);
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = (int) (in_buff[ix++] * 32767.0);
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) x;
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 16 bit, unsigned, little-endian
+	private static class AudioFloatConversion16UL extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++)
+				out_buff[ox++] = (( ((in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8))) - 32767)
+						* (1.0f / 32767.0f);
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = 32767 + (int) (in_buff[ix++] * 32767.0);
+				out_buff[ox++] = (byte) x;
+				out_buff[ox++] = (byte) (x >>> 8);
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 16 bit, unsigned, big-endian
+	private static class AudioFloatConversion16UB extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++)
+				out_buff[ox++] = (( (((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF))) - 32767)
+						* (1.0f / 32767.0f);
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = 32767 + (int) (in_buff[ix++] * 32767.0);
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) x;
+			}
+			return out_buff;
+		}
+	}
+
+	/***************************************************************************
+	 * 
+	 * 24 bit signed/unsigned, little/big-endian
+	 * 
+	 **************************************************************************/
+
+	// PCM 24 bit, signed, little-endian
+	private static class AudioFloatConversion24SL extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++) {
+				int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
+						| ((in_buff[ix++] & 0xFF) << 16);
+				if (x > 8388607)
+					x -= 16777216;
+				out_buff[ox++] = x * (1.0f / 8388607.0f);
+			}
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = (int) (in_buff[ix++] * 8388607.0);
+				if (x < 0)
+					x += 16777216;
+				out_buff[ox++] = (byte) x;
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) (x >>> 16);
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 24 bit, signed, big-endian
+	private static class AudioFloatConversion24SB extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++) {
+				int x = ((in_buff[ix++] & 0xFF) << 16)
+						| ((in_buff[ix++] & 0xFF) << 8)
+						| (in_buff[ix++] & 0xFF);
+				if (x > 8388607)
+					x -= 16777216;
+				out_buff[ox++] = x * (1.0f / 8388607.0f);
+			}
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = (int) (in_buff[ix++] * 8388607.0);
+				if (x < 0)
+					x += 16777216;
+				out_buff[ox++] = (byte) (x >>> 16);
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) x;
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 24 bit, unsigned, little-endian
+	private static class AudioFloatConversion24UL extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++) {
+				int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
+						| ((in_buff[ix++] & 0xFF) << 16);
+				x -= 8388607;
+				out_buff[ox++] = x * (1.0f / 8388607.0f);
+			}
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = (int) (in_buff[ix++] * 8388607.0);
+				x += 8388607;
+				out_buff[ox++] = (byte) x;
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) (x >>> 16);
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 24 bit, unsigned, big-endian
+	private static class AudioFloatConversion24UB extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++) {
+				int x = ((in_buff[ix++] & 0xFF) << 16)
+						| ((in_buff[ix++] & 0xFF) << 8)
+						| (in_buff[ix++] & 0xFF);
+				x -= 8388607;
+				out_buff[ox++] = x * (1.0f / 8388607.0f);
+			}
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = (int) (in_buff[ix++] * 8388607.0);
+				x += 8388607;
+				out_buff[ox++] = (byte) (x >>> 16);
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) x;
+			}
+			return out_buff;
+		}
+	}
+
+	/***************************************************************************
+	 * 
+	 * 32 bit signed/unsigned, little/big-endian
+	 * 
+	 **************************************************************************/
+
+	// PCM 32 bit, signed, little-endian
+	private static class AudioFloatConversion32SL extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++) {
+				int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
+						| ((in_buff[ix++] & 0xFF) << 16)
+						| ((in_buff[ix++] & 0xFF) << 24);
+				out_buff[ox++] = x * (1.0f / 2147483647.0f);
+			}
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = (int) (in_buff[ix++] * 2147483647.0);
+				out_buff[ox++] = (byte) x;
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) (x >>> 16);
+				out_buff[ox++] = (byte) (x >>> 24);
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 32 bit, signed, big-endian
+	private static class AudioFloatConversion32SB extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++) {
+				int x = ((in_buff[ix++] & 0xFF) << 24)
+						| ((in_buff[ix++] & 0xFF) << 16)
+						| ((in_buff[ix++] & 0xFF) << 8)
+						| (in_buff[ix++] & 0xFF);
+				out_buff[ox++] = x * (1.0f / 2147483647.0f);
+			}
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = (int) (in_buff[ix++] * 2147483647.0);
+				out_buff[ox++] = (byte) (x >>> 24);
+				out_buff[ox++] = (byte) (x >>> 16);
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) x;
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 32 bit, unsigned, little-endian
+	private static class AudioFloatConversion32UL extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++) {
+				int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8)
+						| ((in_buff[ix++] & 0xFF) << 16)
+						| ((in_buff[ix++] & 0xFF) << 24);
+				x -= 2147483647;
+				out_buff[ox++] = x * (1.0f / 2147483647.0f);
+			}
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = (int) (in_buff[ix++] * 2147483647.0);
+				x += 2147483647;
+				out_buff[ox++] = (byte) x;
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) (x >>> 16);
+				out_buff[ox++] = (byte) (x >>> 24);
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 32 bit, unsigned, big-endian
+	private static class AudioFloatConversion32UB extends AudioFloatConverter {
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < out_len; i++) {
+				int x = ((in_buff[ix++] & 0xFF) << 24)
+						| ((in_buff[ix++] & 0xFF) << 16)
+						| ((in_buff[ix++] & 0xFF) << 8)
+						| (in_buff[ix++] & 0xFF);
+				x -= 2147483647;
+				out_buff[ox++] = x * (1.0f / 2147483647.0f);
+			}
+			return out_buff;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+				byte[] out_buff, int out_offset) {
+			int ix = in_offset;
+			int ox = out_offset;
+			for (int i = 0; i < in_len; i++) {
+				int x = (int) (in_buff[ix++] * 2147483647.0);
+				x += 2147483647;
+				out_buff[ox++] = (byte) (x >>> 24);
+				out_buff[ox++] = (byte) (x >>> 16);
+				out_buff[ox++] = (byte) (x >>> 8);
+				out_buff[ox++] = (byte) x;
+			}
+			return out_buff;
+		}
+	}
+
+	public static AudioFloatConverter getConverter(AudioFormat format) {
+		AudioFloatConverter conv = null;
+		if (format.getFrameSize() != (format.getSampleSizeInBits() / 8)
+				* format.getChannels())
+			return null;
+		if (format.getEncoding().equals(Encoding.PCM_SIGNED)) {
+			if (format.isBigEndian()) {
+				if (format.getSampleSizeInBits() == 8)
+					conv = new AudioFloatConversion8S();
+				else if (format.getSampleSizeInBits() > 8
+						&& format.getSampleSizeInBits() <= 16)
+					conv = new AudioFloatConversion16SB();
+				else if (format.getSampleSizeInBits() > 16
+						&& format.getSampleSizeInBits() <= 24)
+					conv = new AudioFloatConversion24SB();
+				else if (format.getSampleSizeInBits() > 24
+						&& format.getSampleSizeInBits() <= 32)
+					conv = new AudioFloatConversion32SB();
+			} else {
+				if (format.getSampleSizeInBits() == 8)
+					conv = new AudioFloatConversion8S();
+				else if (format.getSampleSizeInBits() > 8
+						& format.getSampleSizeInBits() <= 16)
+					conv = new AudioFloatConversion16SL();
+				else if (format.getSampleSizeInBits() > 16
+						&& format.getSampleSizeInBits() <= 24)
+					conv = new AudioFloatConversion24SL();
+				else if (format.getSampleSizeInBits() > 24
+						&& format.getSampleSizeInBits() <= 32)
+					conv = new AudioFloatConversion32SL();
+			}
+		} else if (format.getEncoding().equals(Encoding.PCM_UNSIGNED)) {
+			if (format.isBigEndian()) {
+				if (format.getSampleSizeInBits() == 8)
+					conv = new AudioFloatConversion8U();
+				else if (format.getSampleSizeInBits() > 8
+						&& format.getSampleSizeInBits() <= 16)
+					conv = new AudioFloatConversion16UB();
+				else if (format.getSampleSizeInBits() > 16
+						&& format.getSampleSizeInBits() <= 24)
+					conv = new AudioFloatConversion24UB();
+				else if (format.getSampleSizeInBits() > 24
+						&& format.getSampleSizeInBits() <= 32)
+					conv = new AudioFloatConversion32UB();
+			} else {
+				if (format.getSampleSizeInBits() == 8)
+					conv = new AudioFloatConversion8U();
+				else if (format.getSampleSizeInBits() > 8
+						&& format.getSampleSizeInBits() <= 16)
+					conv = new AudioFloatConversion16UL();
+				else if (format.getSampleSizeInBits() > 16
+						&& format.getSampleSizeInBits() <= 24)
+					conv = new AudioFloatConversion24UL();
+				else if (format.getSampleSizeInBits() > 24
+						&& format.getSampleSizeInBits() <= 32)
+					conv = new AudioFloatConversion32UL();
+			}
+		} else if (format.getEncoding().equals(PCM_FLOAT)) {
+			if (format.getSampleSizeInBits() == 32) {
+				if (format.isBigEndian())
+					conv = new AudioFloatConversion32B();
+				else
+					conv = new AudioFloatConversion32L();
+			}
+		}
+
+		if (conv != null)
+			conv.format = format;
+		return conv;
+	}
+
+	private AudioFormat format;
+
+	public AudioFormat getFormat() {
+		return format;
+	}
+
+	public abstract float[] toFloatArray(byte[] in_buff, int in_offset,
+			float[] out_buff, int out_offset, int out_len);
+
+	public float[] toFloatArray(byte[] in_buff, float[] out_buff,
+			int out_offset, int out_len) {
+		return toFloatArray(in_buff, 0, out_buff, out_offset, out_len);
+	}
+
+	public float[] toFloatArray(byte[] in_buff, int in_offset,
+			float[] out_buff, int out_len) {
+		return toFloatArray(in_buff, in_offset, out_buff, 0, out_len);
+	}
+
+	public float[] toFloatArray(byte[] in_buff, float[] out_buff, int out_len) {
+		return toFloatArray(in_buff, 0, out_buff, 0, out_len);
+	}
+
+	public float[] toFloatArray(byte[] in_buff, float[] out_buff) {
+		return toFloatArray(in_buff, 0, out_buff, 0, out_buff.length);
+	}
+
+	public abstract byte[] toByteArray(float[] in_buff, int in_offset,
+			int in_len, byte[] out_buff, int out_offset);
+
+	public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff,
+			int out_offset) {
+		return toByteArray(in_buff, 0, in_len, out_buff, out_offset);
+	}
+
+	public byte[] toByteArray(float[] in_buff, int in_offset, int in_len,
+			byte[] out_buff) {
+		return toByteArray(in_buff, in_offset, in_len, out_buff, 0);
+	}
+
+	public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff) {
+		return toByteArray(in_buff, 0, in_len, out_buff, 0);
+	}
+
+	public byte[] toByteArray(float[] in_buff, byte[] out_buff) {
+		return toByteArray(in_buff, 0, in_buff.length, out_buff, 0);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatInputStream.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.UnsupportedAudioFileException;
+
+/**
+ * This class is used to create AudioFloatInputStream from AudioInputStream and
+ * byte buffers.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public abstract class AudioFloatInputStream {
+
+	private static class BytaArrayAudioFloatInputStream extends
+			AudioFloatInputStream {
+
+		private int pos = 0;
+
+		private int markpos = 0;
+
+		private AudioFloatConverter converter;
+
+		private AudioFormat format;
+
+		private byte[] buffer;
+
+		private int buffer_offset;
+
+		private int buffer_len;
+
+		private int framesize_pc;
+
+		public BytaArrayAudioFloatInputStream(AudioFloatConverter converter,
+				byte[] buffer, int offset, int len) {
+			this.converter = converter;
+			this.format = converter.getFormat();
+			this.buffer = buffer;
+			this.buffer_offset = offset;
+			framesize_pc = format.getFrameSize() / format.getChannels();
+			this.buffer_len = len / framesize_pc;
+
+		}
+
+		public AudioFormat getFormat() {
+			return format;
+		}
+
+		public long getFrameLength() {
+			return buffer_len;// / format.getFrameSize();
+		}
+
+		public int read(float[] b, int off, int len) throws IOException {
+			if (b == null)
+				throw new NullPointerException();
+			if (off < 0 || len < 0 || len > b.length - off)
+				throw new IndexOutOfBoundsException();
+			if (pos >= buffer_len)
+				return -1;
+			if (len == 0)
+				return 0;
+			if (pos + len > buffer_len)
+				len = buffer_len - pos;
+			converter.toFloatArray(buffer, buffer_offset + pos * framesize_pc,
+					b, off, len);
+			pos += len;
+			return len;
+		}
+
+		public long skip(long len) throws IOException {
+			if (pos >= buffer_len)
+				return -1;
+			if (len <= 0)
+				return 0;
+			if (pos + len > buffer_len)
+				len = buffer_len - pos;
+			pos += len;
+			return len;
+		}
+
+		public int available() throws IOException {
+			return buffer_len - pos;
+		}
+
+		public void close() throws IOException {
+		}
+
+		public void mark(int readlimit) {
+			markpos = pos;
+		}
+
+		public boolean markSupported() {
+			return true;
+		}
+
+		public void reset() throws IOException {
+			pos = markpos;
+		}
+
+	}
+
+	private static class DirectAudioFloatInputStream extends
+			AudioFloatInputStream {
+		private AudioInputStream stream;
+
+		private AudioFloatConverter converter;
+
+		private int framesize_pc; // framesize / channels
+
+		private byte[] buffer;
+
+		public DirectAudioFloatInputStream(AudioInputStream stream) {
+			converter = AudioFloatConverter.getConverter(stream
+					.getFormat());
+			if (converter == null) {
+				AudioFormat format = stream.getFormat();
+				AudioFormat newformat;
+
+				AudioFormat[] formats = AudioSystem.getTargetFormats(
+						AudioFormat.Encoding.PCM_SIGNED, format);
+				if (formats.length != 0) {
+					newformat = formats[0];
+				} else {
+
+					float samplerate = format.getSampleRate();
+					int samplesizeinbits = format.getSampleSizeInBits();
+					int framesize = format.getFrameSize();
+					float framerate = format.getFrameRate();
+					samplesizeinbits = 16;
+					framesize = format.getChannels() * (samplesizeinbits / 8);
+					framerate = samplerate;
+
+					newformat = new AudioFormat(
+							AudioFormat.Encoding.PCM_SIGNED, samplerate,
+							samplesizeinbits, format.getChannels(), framesize,
+							framerate, false);
+				}
+
+				stream = AudioSystem.getAudioInputStream(newformat, stream);
+				converter = AudioFloatConverter.getConverter(stream
+						.getFormat());
+			}
+			framesize_pc = stream.getFormat().getFrameSize()
+					/ stream.getFormat().getChannels();
+			this.stream = stream;
+		}
+
+		public AudioFormat getFormat() {
+			return stream.getFormat();
+		}
+
+		public long getFrameLength() {
+			return stream.getFrameLength();
+		}
+
+		public int read(float[] b, int off, int len) throws IOException {
+			int b_len = len * framesize_pc;
+			if (buffer == null || buffer.length < b_len)
+				buffer = new byte[b_len];
+			int ret = stream.read(buffer, 0, b_len);
+			if (ret == -1)
+				return -1;
+			converter.toFloatArray(buffer, b, off, ret / framesize_pc);
+			return ret / framesize_pc;
+		}
+
+		public long skip(long len) throws IOException {
+			long b_len = len * framesize_pc;
+			long ret = stream.skip(b_len);
+			if (ret == -1)
+				return -1;
+			return ret / framesize_pc;
+		}
+
+		public int available() throws IOException {
+			return stream.available() / framesize_pc;
+		}
+
+		public void close() throws IOException {
+			stream.close();
+		}
+
+		public void mark(int readlimit) {
+			stream.mark(readlimit * framesize_pc);
+		}
+
+		public boolean markSupported() {
+			return stream.markSupported();
+		}
+
+		public void reset() throws IOException {
+			stream.reset();
+		}
+
+	}
+
+	public static AudioFloatInputStream getInputStream(URL url)
+			throws UnsupportedAudioFileException, IOException {
+		return new DirectAudioFloatInputStream(AudioSystem
+				.getAudioInputStream(url));
+	}
+
+	public static AudioFloatInputStream getInputStream(File file)
+			throws UnsupportedAudioFileException, IOException {
+		return new DirectAudioFloatInputStream(AudioSystem
+				.getAudioInputStream(file));
+	}
+
+	public static AudioFloatInputStream getInputStream(InputStream stream)
+			throws UnsupportedAudioFileException, IOException {
+		return new DirectAudioFloatInputStream(AudioSystem
+				.getAudioInputStream(stream));
+	}
+
+	public static AudioFloatInputStream getInputStream(
+			AudioInputStream stream) {
+		return new DirectAudioFloatInputStream(stream);
+	}
+
+	public static AudioFloatInputStream getInputStream(AudioFormat format,
+			byte[] buffer, int offset, int len) {
+		AudioFloatConverter converter = AudioFloatConverter
+				.getConverter(format);
+		if (converter != null)
+			return new BytaArrayAudioFloatInputStream(converter, buffer,
+					offset, len);
+
+		InputStream stream = new ByteArrayInputStream(buffer, offset, len);
+		AudioInputStream astream = new AudioInputStream(stream, format, format
+				.getFrameSize() == -1 ? -1 : (len / format.getFrameSize()));
+		return getInputStream(astream);
+	}
+
+	public abstract AudioFormat getFormat();
+
+	public abstract long getFrameLength();
+
+	public abstract int read(float[] b, int off, int len) throws IOException;
+
+	public int read(float[] b) throws IOException {
+		return read(b, 0, b.length);
+	}
+
+	public float read() throws IOException {
+		float[] b = new float[1];
+		int ret = read(b, 0, 1);
+		if (ret == -1 || ret == 0)
+			return 0;
+		return b[0];
+	}
+
+	public abstract long skip(long len) throws IOException;
+
+	public abstract int available() throws IOException;
+
+	public abstract void close() throws IOException;
+
+	public abstract void mark(int readlimit);
+
+	public abstract boolean markSupported();
+
+	public abstract void reset() throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,132 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.util.Map;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Synthesizer;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * 
+ * <code>AudioSynthesizer</code> is a <code>Synthesizer</code>
+ * which renders it's output audio into <code>SourceDataLine</code>
+ * or <code>AudioInputStream</code>.
+ * 
+ * @see MidiSystem#getSynthesizer
+ * @see Synthesizer
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+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 this 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 MidiUnavailableException.
+     * 
+     * @param line which <code>AudioSynthesizer</code> writes output audio into.
+     * If line is null, then line from system default mixer is used.
+     * 
+     * @param info is a Map<String,Object> object containing properties
+     * for additional configuration supported by synthesizer.
+     * If info 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 MidiUnavailableException.
+     * 
+     * @param targetFormat specifies the <code>AudioFormat</code> 
+     * used in returned <code>AudioInputStream</code>.
+     * 
+     * @param info is a Map<String,Object> object containing properties
+     * for additional configuration supported by synthesizer.
+     * If info 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;
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,85 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * <p>Information about property used in 
+ * opening <code>AudioSynthesizer</code>.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class AudioSynthesizerPropertyInfo {
+
+    /**
+     * Constructs a <code>AudioSynthesizerPropertyInfo</code> object with a  given
+     * name and value.  The <code>description</code> and <code>choices</code>
+     * are intialized to <code>null</code>.
+     *
+     * @param name the name of the property
+     * @param value the current value or class used for values.
+     * 
+     */	
+    public AudioSynthesizerPropertyInfo(String name, Object value) {
+        this.name = name;
+        this.value = value;
+        if(value instanceof Class)
+        	valueClass = (Class)value;
+        else
+        	if(value != null) valueClass = value.getClass();
+    }
+
+    /**
+     * The name of the property.
+     */
+    public String name;
+
+    /**
+     * A brief description of the property, which may be null.
+     */
+    public String description = null;
+
+    /**
+     * The <code>value</code> field specifies the current value of 
+	 * the property.
+     */    
+    public Object value = null;
+    
+    /**
+     * The <code>valueClass</code> field specifies class
+     * used in  <code>value</code> field.
+     */    
+    public Class valueClass = null;
+
+    /**
+     * An array of possible values if the value for the field 
+	 * <code>AudioSynthesizerPropertyInfo.value</code> may be selected
+	 * from a particular set of values; otherwise null.
+     */    
+    public Object[] choices = null;
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,179 @@
+  - Fix: Default tempo in SoftMidiFileReader was supposed to be 500000 mpq or 120 bpm
+  - Fix: Change type of info variable in SoftSynthesize into MidiDevice.Info
+  - Fix: Fix instanceof check of p1 variable in ModelInstrumentComparator
+  - Fix: Remove redundant constant variable in ModelByteBufferWaveTable
+
+Version 0.9
+  - Fix: JTreg SoftSynthesizer\ImplicitOpenClose.java
+         did not test correctly.
+  - Fix: SoftSynthesizer.isSoundbankSupported
+         now only returns false if
+         there is any instrument which is not supported.
+  - Fix: SoftSynthesizer.remapInstrument
+         did not work correctly.
+  - Fix: SoftSynthesizer.loadInstrument
+         SoftSynthesizer.loadInstruments
+         SoftSynthesizer.loadAllInstruments
+         SoftSynthesizer.unloadInstrument
+         SoftSynthesizer.unloadInstruments
+         SoftSynthesizer.unloadAllInstruments
+         SoftSynthesizer.getAvailableInstruments
+         SoftSynthesizer.getLoadedInstruments
+         now throws IllegalArgumentException
+         if instrument is not supported
+         and false if instrument can't be loaded
+         for some other reason.
+  - Fix: SoftSynthesizer.getReceivers()
+         SoftSynthesizer.getMicrosecondPosition()
+         SoftSynthesizer.getVoiceStatus()
+         SoftSynthesizer.getChannels()
+         SoftMidiAudioFileReader.getAudioInputStream(Sequence seq)
+         now no longer throw IllegalStateException.
+  - Fix: SoftSynthesizer.getChannels() and
+         SoftSynthesizer.getVoiceStatus()
+         now no longer return internal array. 
+  - Fix: CPU spiking caused by denormal floats in SoftReverb.
+  - Fix: Calling getReceiver before opening the synthesizer results in NullPointerException.
+    JTreg test added: SoftSynthesizer/GetReceiver2
+  - Fix: Removed checksum check on
+           BULK TUNING DUMP (NON-REAL-TIME)
+         Because MIDI Tuning Spec was ambigous about
+         how to calculate the checksum
+         and different programs tested calculated 
+         different checksum.       
+         JTreg test SoftTuning/Load1 fixed.
+
+VERSION 0.8
+  - Fix: Active Sense Messages where incorrectly handled.
+    JTreg test: SoftReceiver/Send_ActiveSense.java
+  - Fix: SoftAudioPusher doesn't longer try to prevent blocking.
+  - Added: SoftJitterCorrector added to fix jitter on long buffers.
+
+VERSION 0.7
+  - Fix: General MIDI mode,
+    and voice_allocation_mode flag wasn't reseted on open/close cycle.     
+  - Fix: Added support for implicit open/close    
+    (as described in http://java.sun.com/javase/6/docs/api/javax/sound/midi/MidiDevice.html)
+    (JTreg test also added)
+    This done by implementing com.sun.media.sound.ReferenceCountingDevice interface.
+  - Fix: SoftReceiver.close doesn't throw exception if closed.
+    (now behaves like SoftSynthesizer.close)
+  - Fix: Close variable wasn't accessed in Thread safe way in: 
+    SoftReceiver, SoftSynthesizer.
+  - Fix: Hang in SoftSynthesizer.close.
+	SoftAudioPusher must not be closed synchronized against control_mutex			
+	this may result in synchronized conflict between pusher and caller thread.
+  - Fix: Bad handling of mono output in SoftVoice.processAudioLogic,
+    this error was found running the new SoftSynthesizer/TestRender1 jtreg test.
+  - Added: ModelDirector to support conditional layers/performers.   
+  - Added: ReleaseTrigger property to ModelPerformer.
+  - Added: ModelAbstractOscillator to simplify creation custom oscillators.
+  - Added: ModelChannelMixer to support for example non-voice oriented instruments.
+  - Added: Support for more than 16 midi channels.
+  - Added: JARSoundBankReader.
+  - Change default latency from 400 to 200 mec.
+  
+VERSION 0.6
+  - Added RIFFWriter(OutputStream) constructor.
+  - Added save(OutputStream out) to DLSSoundbank and SF2Soundbank.
+  - Renamed :  isAddDefaultConnections   to  setDefaultConnectionsEnabled
+  - Renamed :  getAddDefaultConnections  to  isDefaultConnectionsEnabled
+  - Created JTreg Unit Tests   
+  - Fixed error found in Unit Tests
+      * AudioFloatConversion8U.toFloatArray, did not convert correctly
+      * SoftSynthesizer.remapInstrument did not work
+          The error was in ModelMappedInstrument
+      * SoftSynthesizer.getMaxReceivers did not return -1
+      * SoftTuning.checksumOK calculated incorrect checksums.
+      * RIFFReader.close didn't work
+      * AudioFloatInputStream.getFrameLength returned incorrect value.
+      * ModelByteBuffer.writeTo didn't work when ModelByteBuffer uses file pointer.
+      * ModelIdentifier.equals, didn't compare the variable "instance".
+      * SimpleSoundbank.removeResource did not remove resource.
+      * RIFFWriter.close never closed underlying stream.
+
+VERSION 0.5
+  - New instruments in Emergency Soundbank:
+	  * Acoustic Grand Piano
+  	  * Bright Acoustic Piano
+	  * Honky-tonk Piano
+	  * Guitar 
+	  * Distortion Guitar
+   	  * Trumpet
+   	  * Trombone
+	  * Brass Section
+  	  * Horn
+  	  * Sax
+  	  * Oboe
+  	  * Bassoon
+	  * Clarinet
+	  * Flute
+	  * Timpani
+	  * Melodic Toms
+	  * Reverse Cymbal
+	  * Orch Hit
+  - Faster Linear Interpolation
+    with no float to int casting.
+      Thanks to Bruno Schoedlbauer for
+      pointing out that float to int casting
+      can be costly.
+  - LargeSoundBankReader removed,
+    Loading soundbank in large mode using urls removed.
+  - Soundbank aren't loaded into memory
+    until loadInstrument/loadAllInstrument
+    is called in SoftSynthesizer.
+    This enable loading only single instrument
+    from soundbank collection into memory.
+  - New "large mode" property added to SoftSynthesizer.    
+  - "getInstrument" method in DLS/SF2/SimpleSoundbank
+    now returns ordered list by program,bank,percussion.
+  - Fix AccessControlException in "SoftSynthesizer.getDefaultSoundbank",
+    which occurred when using SoftSynthesizer in Applets.
+     
+VERSION 0.4
+  - Fixed ArrayOutOfBoundsException in SoftAbstractResmpler.
+  - Fixed NullPointerException in SoundFont.save(File).
+    Saving global zone for layers resulted in NullPointerException.
+  - Fixed PATSoundbankReader.getInputStream
+    so it doesn't throw InvalidFormatException.
+    This prevented use of MidiSystem.getSoundBank(InputStream).
+  - Fix: Delay wasn't implemented in AHDSR envelopes.
+  - Loading soundbank in large mode supported using
+    MidiSystem.getSoundBank(URL)
+    Where url is on the form:
+    file:/C:/soundbank.sf2?largemode=true
+  - Reverb,Chorus,AGC can be turned on/off.
+  - MIDI files can be opened as audio streams
+    thru javax.sound.sampled.spi.AudioFileReader.
+  - Optimizations, rendering is up to 50 percent faster.
+  - Emergency SoundBank.
+
+VERSION 0.3
+  - SoftSynthesizer doesn't implement mixer interface anymore,
+    instead the method "openStream" has been added.    
+  - New AudioSynthesizer interface.
+  - SoftSynthesizer.getVoiceStatus() is now thread-safe.
+  - SoftAudioFeeder renamed to SoftAudioPusher
+    and made more generic.
+  - Support for multi-receiver in SoftSynthesizer.
+  - More cleanup in SoftSynthesizer.
+  - Fixed loops in large soundbanks.
+  - WaveFloatFileReader added to META-INF/services
+
+VERSION 0.2
+  - Large format support see: LargeSoundbankReader
+  - Fix soundfont modulator mapping
+    direction mapping was wrong
+  - Fix handling of unsigned 16 bit streams
+  - Improved GUS patch support
+  - Add support for ping-pong/bi-directional and reverse loops
+
+VERSION 0.1 
+  - Downloadable Sound Level 2.2.
+  - SoundFont 2.04 (24 bit)
+  - Gravis Ultrasound-compatible patches
+  - Use Audio files (AIFF, AU and WAV) as SoundBanks
+  - General Midi Level 2
+  - MIDI Tuning Standard
+  - Drumkits can be used on any channel
+  - Sinc interpolation with anti-aliasing
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSInfo.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,115 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * This class is used to store information 
+ * to describe soundbanks, instruments and samples.
+ * It is stored inside a "INFO" List Chunk inside DLS files.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class DLSInfo {
+
+	/**
+	 * (INAM) Title or subject.
+	 */
+	public String name = "untitled";						
+	/**
+	 * (ICRD) Date of creation, the format is: YYYY-MM-DD. 
+	 *        For example 2007-01-01 for 1. januar of year 2007. 
+	 */
+	public String creationDate = null;
+	/**
+	 * (IENG) Name of engineer who created the object. 
+	 */
+	public String engineers = null;
+	/**
+	 * (IPRD) Name of the product which the object is 
+	 *        intended for.
+	 */
+	public String product = null;
+	/**
+	 * (ICOP) Copyright information. 
+	 */
+	public String copyright = null;
+	/**
+	 * (ICMT) General comments. Doesn't contain newline characters.
+	 */
+	public String comments = null;
+	/**
+	 * (ISFT) Name of software package used to create the file.
+	 */
+	public String tools = null;		
+	/**
+	 * (IARL) Where content is archived.
+	 */	
+	public String archival_location = null;
+	/**
+	 * (IART) Artists of original content.
+	 */	
+	public String artist = null;
+	/**
+	 * (ICMS) Names of persons or orginizations who
+	 *        commissioned the file.
+	 */	
+	public String commissioned = null;
+	/**
+	 * (IGNR) Genre of the work.
+	 *        Example: jazz, classical, rock, etc.
+	 */	
+	public String genre = null;
+	/**
+	 * (IKEY) List of keyword that describe the content.
+	 *        Examples: FX, bird, piano, etc.
+	 */	
+	public String keywords = null;
+	/**
+	 * (IMED) Describes original medium of the data, 
+	 *        for example: record, CD, etc.
+	 */	
+	public String medium = null;
+	/**
+	 * (ISBJ) Description of the content.
+	 */	
+	public String subject = null;
+	/**
+	 * (ISRC) Name of person or orginization who supplied 
+	 *        orginal material for the file.
+	 */	
+	public String source = null;
+	/**
+	 * (ISRF) Source media for sample data is from.
+	 *        For example: CD, TV, etc.
+	 */
+	public String source_form = null;
+	/**
+	 * (ITCH) Technician who sample the file/object.
+	 */
+	public String technician = null;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSInstrument.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,384 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.sound.midi.Patch;
+
+/**
+ * This class is used to store information 
+ * to describe instrument. I contains list of regions and modulators.
+ * It is stored inside a "ins " List Chunk inside DLS files.
+ * In the DLS documentation a modulator is called articulator.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class DLSInstrument extends ModelInstrument {
+	
+	protected int preset = 0;
+	protected int bank = 0;
+	
+	protected boolean druminstrument = false;	
+	protected byte[] guid = null;
+	
+	protected DLSInfo info = new DLSInfo();
+	
+	protected List<DLSRegion> regions = new ArrayList<DLSRegion>();
+	protected List<DLSModulator> modulators = new ArrayList<DLSModulator>();
+
+	public DLSInstrument() {
+		super(null, null, null, null);
+	}
+	
+	public DLSInstrument(DLSSoundbank soundbank) {
+		super(soundbank, null, null, null);
+	}
+	
+	public DLSInfo getInfo() {
+		return info;
+	}	
+	
+	public String getName() {
+		return info.name;
+	}
+	
+	public void setName(String name)
+	{
+		info.name = name;
+	}
+		
+	public ModelPatch getPatch() {
+		return new ModelPatch(bank, preset, druminstrument);
+	}
+	
+	public void setPatch(Patch patch)
+	{
+		if(patch instanceof ModelPatch && ((ModelPatch)patch).isPercussion())
+		{
+			druminstrument = true;
+			bank = patch.getBank();
+			preset = patch.getProgram();			
+		}
+		else
+		{
+			druminstrument = false;
+			bank = patch.getBank();
+			preset = patch.getProgram();
+		}
+	}
+
+	public Object getData() {
+		return null;
+	}
+	
+	public List<DLSRegion> getRegions() {
+		return regions;
+	}
+	
+	public List<DLSModulator> getModulators() {
+		return modulators;
+	}	
+	
+	public String toString()
+	{	
+		if(druminstrument)
+			return "Drumkit: " + info.name + " bank #" + bank + " preset #" + preset;
+		else
+			return "Instrument: " + info.name + " bank #" + bank + " preset #" + preset; 
+	}
+	
+	private ModelIdentifier convertToModelDest(int dest)
+	{
+		if(dest == DLSModulator.CONN_DST_NONE) return null;
+		if(dest == DLSModulator.CONN_DST_GAIN) return ModelDestination.DESTINATION_GAIN;
+		if(dest == DLSModulator.CONN_DST_PITCH) return ModelDestination.DESTINATION_PITCH;
+		if(dest == DLSModulator.CONN_DST_PAN) return ModelDestination.DESTINATION_PAN;
+		
+		if(dest == DLSModulator.CONN_DST_LFO_FREQUENCY) return ModelDestination.DESTINATION_LFO1_FREQ;
+		if(dest == DLSModulator.CONN_DST_LFO_STARTDELAY) return ModelDestination.DESTINATION_LFO1_DELAY;
+
+		if(dest == DLSModulator.CONN_DST_EG1_ATTACKTIME) return ModelDestination.DESTINATION_EG1_ATTACK;
+		if(dest == DLSModulator.CONN_DST_EG1_DECAYTIME) return ModelDestination.DESTINATION_EG1_DECAY;
+		if(dest == DLSModulator.CONN_DST_EG1_RELEASETIME) return ModelDestination.DESTINATION_EG1_RELEASE;
+		if(dest == DLSModulator.CONN_DST_EG1_SUSTAINLEVEL) return ModelDestination.DESTINATION_EG1_SUSTAIN;
+		
+		if(dest == DLSModulator.CONN_DST_EG2_ATTACKTIME) return ModelDestination.DESTINATION_EG2_ATTACK;
+		if(dest == DLSModulator.CONN_DST_EG2_DECAYTIME) return ModelDestination.DESTINATION_EG2_DECAY;
+		if(dest == DLSModulator.CONN_DST_EG2_RELEASETIME) return ModelDestination.DESTINATION_EG2_RELEASE;
+		if(dest == DLSModulator.CONN_DST_EG2_SUSTAINLEVEL) return ModelDestination.DESTINATION_EG2_SUSTAIN;				
+
+		// DLS2 Destinations
+		if(dest == DLSModulator.CONN_DST_KEYNUMBER) return ModelDestination.DESTINATION_KEYNUMBER;				
+		
+		if(dest == DLSModulator.CONN_DST_CHORUS) return ModelDestination.DESTINATION_CHORUS;				
+		if(dest == DLSModulator.CONN_DST_REVERB) return ModelDestination.DESTINATION_REVERB;				
+
+		if(dest == DLSModulator.CONN_DST_VIB_FREQUENCY) return ModelDestination.DESTINATION_LFO2_FREQ;				
+		if(dest == DLSModulator.CONN_DST_VIB_STARTDELAY) return ModelDestination.DESTINATION_LFO2_DELAY;				
+
+		if(dest == DLSModulator.CONN_DST_EG1_DELAYTIME) return ModelDestination.DESTINATION_EG1_DELAY;				
+		if(dest == DLSModulator.CONN_DST_EG1_HOLDTIME) return ModelDestination.DESTINATION_EG1_HOLD;				
+		if(dest == DLSModulator.CONN_DST_EG1_SHUTDOWNTIME) return ModelDestination.DESTINATION_EG1_SHUTDOWN;				
+
+		if(dest == DLSModulator.CONN_DST_EG2_DELAYTIME) return ModelDestination.DESTINATION_EG2_DELAY;				
+		if(dest == DLSModulator.CONN_DST_EG2_HOLDTIME) return ModelDestination.DESTINATION_EG2_HOLD;				
+
+		if(dest == DLSModulator.CONN_DST_FILTER_CUTOFF) return ModelDestination.DESTINATION_FILTER_FREQ;				
+		if(dest == DLSModulator.CONN_DST_FILTER_Q) return ModelDestination.DESTINATION_FILTER_Q;				
+		
+		return null;
+	}
+	
+	private ModelIdentifier convertToModelSrc(int src)
+	{
+		if(src == DLSModulator.CONN_SRC_NONE) return null;
+
+		if(src == DLSModulator.CONN_SRC_LFO) return ModelSource.SOURCE_LFO1;
+		if(src == DLSModulator.CONN_SRC_KEYONVELOCITY) return ModelSource.SOURCE_NOTEON_VELOCITY;
+		if(src == DLSModulator.CONN_SRC_KEYNUMBER) return ModelSource.SOURCE_NOTEON_KEYNUMBER;
+		if(src == DLSModulator.CONN_SRC_EG1) return ModelSource.SOURCE_EG1;
+		if(src == DLSModulator.CONN_SRC_EG2) return ModelSource.SOURCE_EG2;
+		if(src == DLSModulator.CONN_SRC_PITCHWHEEL) return ModelSource.SOURCE_MIDI_PITCH;
+		if(src == DLSModulator.CONN_SRC_CC1) return new ModelIdentifier("midi_cc","1",0);
+		if(src == DLSModulator.CONN_SRC_CC7) return new ModelIdentifier("midi_cc","7",0);
+		if(src == DLSModulator.CONN_SRC_CC10) return new ModelIdentifier("midi_cc","10",0);
+		if(src == DLSModulator.CONN_SRC_CC11) return new ModelIdentifier("midi_cc","11",0);
+		if(src == DLSModulator.CONN_SRC_RPN0) return new ModelIdentifier("midi_rpn","0",0);
+		if(src == DLSModulator.CONN_SRC_RPN1) return new ModelIdentifier("midi_rpn","1",0);
+
+		if(src == DLSModulator.CONN_SRC_POLYPRESSURE) return ModelSource.SOURCE_MIDI_POLY_PRESSURE;
+		if(src == DLSModulator.CONN_SRC_CHANNELPRESSURE) return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE;
+		if(src == DLSModulator.CONN_SRC_VIBRATO) return ModelSource.SOURCE_LFO2;
+		if(src == DLSModulator.CONN_SRC_MONOPRESSURE) return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE;
+
+		if(src == DLSModulator.CONN_SRC_CC91) return new ModelIdentifier("midi_cc","91",0);
+		if(src == DLSModulator.CONN_SRC_CC93) return new ModelIdentifier("midi_cc","93",0);
+		
+		return null;
+	}	
+	
+	private ModelConnectionBlock convertToModel(DLSModulator mod)
+	{
+		ModelIdentifier source = convertToModelSrc(mod.getSource());
+		ModelIdentifier control = convertToModelSrc(mod.getControl());
+		ModelIdentifier destination_id = convertToModelDest(mod.getDestination());
+		
+		int scale = mod.getScale();
+		double f_scale;
+		if(scale == Integer.MIN_VALUE)
+			f_scale = Double.NEGATIVE_INFINITY; 
+		else
+			f_scale = scale / 65536.0;
+		
+		if(destination_id != null)
+		{
+			ModelSource src = null;
+			ModelSource ctrl = null;
+			ModelConnectionBlock block = new ModelConnectionBlock();
+			if(control != null)
+			{
+				ModelSource s = new ModelSource();
+				if(control == ModelSource.SOURCE_MIDI_PITCH)
+					((ModelStandardTransform)s.getTransform()).setPolarity(ModelStandardTransform.POLARITY_BIPOLAR);
+				else if(control == ModelSource.SOURCE_LFO1 || control == ModelSource.SOURCE_LFO2)
+					((ModelStandardTransform)s.getTransform()).setPolarity(ModelStandardTransform.POLARITY_BIPOLAR);				
+				s.setIdentifier(control);
+				block.addSource(s);
+				ctrl = s;
+			}
+			if(source != null)
+			{
+				ModelSource s = new ModelSource();
+				if(source == ModelSource.SOURCE_MIDI_PITCH)
+					((ModelStandardTransform)s.getTransform()).setPolarity(ModelStandardTransform.POLARITY_BIPOLAR);
+				else if(source == ModelSource.SOURCE_LFO1 || source == ModelSource.SOURCE_LFO2)
+					((ModelStandardTransform)s.getTransform()).setPolarity(ModelStandardTransform.POLARITY_BIPOLAR);
+				s.setIdentifier(source);
+				block.addSource(s);
+				src = s;
+			}			
+			ModelDestination destination = new ModelDestination();
+			destination.setIdentifier(destination_id);
+			block.setDestination(destination);
+			
+			if(mod.getVersion() == 1)
+			{				
+				//if(mod.getTransform() ==  DLSModulator.CONN_TRN_CONCAVE) 
+				//	((ModelStandardTransform)destination.getTransform()).setTransform(ModelStandardTransform.TRANSFORM_CONCAVE);				
+				if(mod.getTransform() ==  DLSModulator.CONN_TRN_CONCAVE)
+				{
+					if(src != null)
+					{		
+						((ModelStandardTransform)src.getTransform()).setTransform(ModelStandardTransform.TRANSFORM_CONCAVE);
+						((ModelStandardTransform)src.getTransform()).setDirection(ModelStandardTransform.DIRECTION_MAX2MIN);
+					}
+					if(ctrl != null)
+					{		
+						((ModelStandardTransform)ctrl.getTransform()).setTransform(ModelStandardTransform.TRANSFORM_CONCAVE);
+						((ModelStandardTransform)ctrl.getTransform()).setDirection(ModelStandardTransform.DIRECTION_MAX2MIN);
+					}					
+				}
+				
+			}
+			else if(mod.getVersion() == 2)
+			{
+				int transform = mod.getTransform();
+				int src_transform_invert  = (transform >> 15) & 1;
+				int src_transform_bipolar = (transform >> 14) & 1;
+				int src_transform         = (transform >> 10) & 8;
+				int ctr_transform_invert  = (transform >> 9) & 1;
+				int ctr_transform_bipolar = (transform >> 8) & 1;
+				int ctr_transform         = (transform >> 4) & 8;				
+
+
+				if(src != null)
+				{				
+					int trans =  ModelStandardTransform.TRANSFORM_LINEAR;				
+					if(src_transform ==  DLSModulator.CONN_TRN_SWITCH) trans = ModelStandardTransform.TRANSFORM_SWITCH; 
+					if(src_transform ==  DLSModulator.CONN_TRN_CONCAVE) trans = ModelStandardTransform.TRANSFORM_CONCAVE; 
+					if(src_transform ==  DLSModulator.CONN_TRN_CONVEX) trans = ModelStandardTransform.TRANSFORM_CONVEX; 
+					((ModelStandardTransform)src.getTransform()).setTransform(trans);
+					((ModelStandardTransform)src.getTransform()).setPolarity(src_transform_bipolar==1);
+					((ModelStandardTransform)src.getTransform()).setDirection(src_transform_invert==1);
+					
+				}
+
+				if(ctrl != null)
+				{				
+					int trans =  ModelStandardTransform.TRANSFORM_LINEAR;				
+					if(ctr_transform ==  DLSModulator.CONN_TRN_SWITCH) trans = ModelStandardTransform.TRANSFORM_SWITCH; 
+					if(ctr_transform ==  DLSModulator.CONN_TRN_CONCAVE) trans = ModelStandardTransform.TRANSFORM_CONCAVE; 
+					if(ctr_transform ==  DLSModulator.CONN_TRN_CONVEX) trans = ModelStandardTransform.TRANSFORM_CONVEX; 
+					((ModelStandardTransform)ctrl.getTransform()).setTransform(trans);
+					((ModelStandardTransform)ctrl.getTransform()).setPolarity(ctr_transform_bipolar==1);
+					((ModelStandardTransform)ctrl.getTransform()).setDirection(ctr_transform_invert==1);
+				}
+				
+				/*
+				 No output transforms are defined the DLS Level 2
+				 
+				 int out_transform         = transform % 8;
+
+				int trans =  ModelStandardTransform.TRANSFORM_LINEAR;				
+				if(out_transform ==  DLSModulator.CONN_TRN_SWITCH) trans = ModelStandardTransform.TRANSFORM_SWITCH; 
+				if(out_transform ==  DLSModulator.CONN_TRN_CONCAVE) trans = ModelStandardTransform.TRANSFORM_CONCAVE; 
+				if(out_transform ==  DLSModulator.CONN_TRN_CONVEX) trans = ModelStandardTransform.TRANSFORM_CONVEX; 
+				if(ctrl != null) ((ModelStandardTransform)destination.getTransform()).setTransform(trans);
+				*/
+									
+				
+			}			
+			
+			block.setScale(f_scale);
+			
+			return block;
+		}
+		
+		return null;
+	}
+	
+	public ModelPerformer[] getPerformers()
+	{
+		List<ModelPerformer> performers = new ArrayList<ModelPerformer>();
+		
+		Map<String, DLSModulator> modmap = new HashMap<String, DLSModulator> ();
+		for(DLSModulator mod : getModulators())
+			modmap.put(mod.getSource()+"x"+mod.getControl()+"="+mod.getDestination(), mod);
+			
+		Map<String, DLSModulator> insmodmap = new HashMap<String, DLSModulator> ();
+		
+		for(DLSRegion zone : regions)
+		{
+			ModelPerformer performer = new ModelPerformer();
+			performer.setName(zone.getSample().getName());
+			performer.setSelfNonExclusive((zone.getFusoptions() & DLSRegion.OPTION_SELFNONEXCLUSIVE) != 0);
+			performer.setExclusiveClass(zone.getExclusiveClass());
+			performer.setKeyFrom(zone.getKeyfrom());
+			performer.setKeyTo(zone.getKeyto());
+			performer.setVelFrom(zone.getVelfrom());
+			performer.setVelTo(zone.getVelto());		
+			
+			insmodmap.clear();
+			insmodmap.putAll(modmap);
+			for(DLSModulator mod : zone.getModulators())
+				insmodmap.put(mod.getSource()+"x"+mod.getControl()+"="+mod.getDestination(), mod);
+			
+			List<ModelConnectionBlock> blocks = performer.getConnectionBlocks();
+			for(DLSModulator mod : insmodmap.values())
+			{
+				ModelConnectionBlock p = convertToModel(mod);			
+				if(p != null) blocks.add(p);
+			}
+
+			
+			DLSSample sample = zone.getSample();			
+			DLSSampleOptions sampleopt = zone.getSampleoptions();
+			if(sampleopt == null) sampleopt = sample.getSampleoptions();
+			
+			ModelByteBuffer buff = sample.getDataBuffer();
+			
+			float pitchcorrection = (-sampleopt.unitynote*100) + sampleopt.finetune;			
+			
+			ModelByteBufferWavetable osc = new ModelByteBufferWavetable(buff, sample.getFormat(),pitchcorrection);
+			osc.setAttenuation(osc.getAttenuation() / 65536f);
+			if(sampleopt.getLoops().size() != 0)
+			{
+				DLSSampleLoop loop = sampleopt.getLoops().get(0);
+				osc.setLoopStart((int)loop.getStart());
+				osc.setLoopLength((int)loop.getLength());				
+				if(loop.getType() == DLSSampleLoop.LOOP_TYPE_FORWARD)
+					osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD);
+				if(loop.getType() == DLSSampleLoop.LOOP_TYPE_RELEASE)
+					osc.setLoopType(ModelWavetable.LOOP_TYPE_RELEASE);
+				else
+					osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD);
+			}
+			
+			performer.getConnectionBlocks().add(new ModelConnectionBlock(SoftFilter.FILTERTYPE_LP12,new ModelDestination(new ModelIdentifier("filter", "type", 1))));
+			
+			performer.getOscillators().add(osc);
+			
+			performers.add(performer);
+			
+		}			
+		
+		return performers.toArray(new ModelPerformer[performers.size()]);
+	}
+
+	public byte[] getGuid() {
+		return guid;
+	}
+
+	public void setGuid(byte[] guid) {
+		this.guid = guid;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSModulator.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,284 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * This class is used to store modulator/artiuclation data.
+ * A modulator connects one synthesizer source to
+ * a destination. For example a note on velocity
+ * can be mapped to the gain of the synthesized voice.
+ * It is stored as a "art1" or "art2" chunk inside DLS files.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class DLSModulator {
+
+	// DLS1 Destinations
+	public static final int CONN_DST_NONE             = 0x000; // 0
+	public static final int CONN_DST_GAIN             = 0x001; // cB
+	public static final int CONN_DST_PITCH            = 0x003; // 3     cent 
+	public static final int CONN_DST_PAN              = 0x004; // 4     0.1%
+
+	public static final int CONN_DST_LFO_FREQUENCY    = 0x104; // 260   cent   (default 5 Hz)
+	public static final int CONN_DST_LFO_STARTDELAY   = 0x105; // 261   timecent
+
+	public static final int CONN_DST_EG1_ATTACKTIME   = 0x206; // 518   timecent
+	public static final int CONN_DST_EG1_DECAYTIME    = 0x207; // 519   timecent
+	public static final int CONN_DST_EG1_RELEASETIME  = 0x209; // 521   timecent
+	public static final int CONN_DST_EG1_SUSTAINLEVEL = 0x20A; // 522   0.1%
+
+	public static final int CONN_DST_EG2_ATTACKTIME   = 0x30A; // 778   timecent
+	public static final int CONN_DST_EG2_DECAYTIME    = 0x30B; // 779   timecent
+	public static final int CONN_DST_EG2_RELEASETIME  = 0x30D; // 781   timecent
+	public static final int CONN_DST_EG2_SUSTAINLEVEL = 0x30E; // 782   0.1%
+		
+	// DLS2 Destinations
+	public static final int CONN_DST_KEYNUMBER        = 0x005;
+
+	public static final int CONN_DST_LEFT             = 0x010; // 0.1%
+	public static final int CONN_DST_RIGHT            = 0x011; // 0.1%
+	public static final int CONN_DST_CENTER           = 0x012; // 0.1%
+	public static final int CONN_DST_LEFTREAR         = 0x013; // 0.1%
+	public static final int CONN_DST_RIGHTREAR        = 0x014; // 0.1%
+	public static final int CONN_DST_LFE_CHANNEL      = 0x015; // 0.1%
+	public static final int CONN_DST_CHORUS           = 0x080; // 0.1%
+	public static final int CONN_DST_REVERB           = 0x081; // 0.1%
+
+	public static final int CONN_DST_VIB_FREQUENCY    = 0x114; // cent
+	public static final int CONN_DST_VIB_STARTDELAY   = 0x115; // dB
+
+	public static final int CONN_DST_EG1_DELAYTIME    = 0x20B; // timecent
+	public static final int CONN_DST_EG1_HOLDTIME     = 0x20C; // timecent
+	public static final int CONN_DST_EG1_SHUTDOWNTIME = 0x20D; // timecent
+
+	public static final int CONN_DST_EG2_DELAYTIME    = 0x30F; // timecent
+	public static final int CONN_DST_EG2_HOLDTIME     = 0x310; // timecent
+
+	public static final int CONN_DST_FILTER_CUTOFF    = 0x500; // cent
+	public static final int CONN_DST_FILTER_Q         = 0x501; // dB
+
+	// DLS1 Sources	
+	public static final int CONN_SRC_NONE             = 0x000; // 1
+	public static final int CONN_SRC_LFO              = 0x001; // linear (sine wave) 
+	public static final int CONN_SRC_KEYONVELOCITY    = 0x002; //   ?? db or velocity ?? 
+	public static final int CONN_SRC_KEYNUMBER        = 0x003; //   ?? cent or keynumber ??
+	public static final int CONN_SRC_EG1              = 0x004; // linear direct from eg
+	public static final int CONN_SRC_EG2              = 0x005; // linear direct from eg
+	public static final int CONN_SRC_PITCHWHEEL       = 0x006; // linear -1..1
+
+	public static final int CONN_SRC_CC1              = 0x081; // linear 0..1
+	public static final int CONN_SRC_CC7              = 0x087; // linear 0..1
+	public static final int CONN_SRC_CC10             = 0x08A; // linear 0..1
+	public static final int CONN_SRC_CC11             = 0x08B; // linear 0..1
+	
+	public static final int CONN_SRC_RPN0             = 0x100; //   ??  // Pitch Bend Range
+	public static final int CONN_SRC_RPN1             = 0x101; //   ??  // Fine Tune
+	public static final int CONN_SRC_RPN2             = 0x102; //   ??  // Course Tune
+	
+	// DLS2 Sources
+	public static final int CONN_SRC_POLYPRESSURE     = 0x007; // linear 0..1
+	public static final int CONN_SRC_CHANNELPRESSURE  = 0x008; // linear 0..1
+	public static final int CONN_SRC_VIBRATO          = 0x009; // linear 0..1
+	public static final int CONN_SRC_MONOPRESSURE     = 0x00A; // linear 0..1
+
+	public static final int CONN_SRC_CC91             = 0x0DB; // linear 0..1
+	public static final int CONN_SRC_CC93             = 0x0DD; // linear 0..1
+
+	
+	// DLS1 Transforms
+	public static final int CONN_TRN_NONE             = 0x000;
+	public static final int CONN_TRN_CONCAVE          = 0x001;
+	
+	// DLS2 Transforms
+	public static final int CONN_TRN_CONVEX           = 0x002;
+	public static final int CONN_TRN_SWITCH           = 0x003;
+
+	
+	public static final int DST_FORMAT_CB       = 1;
+	public static final int DST_FORMAT_CENT     = 1;
+	public static final int DST_FORMAT_TIMECENT = 2; 
+	public static final int DST_FORMAT_PERCENT  = 3; 
+	
+	protected int source;
+	protected int control;
+	protected int destination;
+	protected int transform;
+	protected int scale;
+	protected int version = 1;
+	
+	public int getControl() {
+		return control;
+	}
+	public void setControl(int control) {
+		this.control = control;
+	}
+	public static int getDestinationFormat(int destination) {
+		
+		if(destination == CONN_DST_GAIN) return DST_FORMAT_CB;
+		if(destination == CONN_DST_PITCH) return DST_FORMAT_CENT;
+		if(destination == CONN_DST_PAN) return DST_FORMAT_PERCENT;
+
+		if(destination == CONN_DST_LFO_FREQUENCY) return DST_FORMAT_CENT;
+		if(destination == CONN_DST_LFO_STARTDELAY) return DST_FORMAT_TIMECENT;
+
+		if(destination == CONN_DST_EG1_ATTACKTIME) return DST_FORMAT_TIMECENT;
+		if(destination == CONN_DST_EG1_DECAYTIME) return DST_FORMAT_TIMECENT;
+		if(destination == CONN_DST_EG1_RELEASETIME) return DST_FORMAT_TIMECENT;
+		if(destination == CONN_DST_EG1_SUSTAINLEVEL) return DST_FORMAT_PERCENT;
+
+		if(destination == CONN_DST_EG2_ATTACKTIME) return DST_FORMAT_TIMECENT;
+		if(destination == CONN_DST_EG2_DECAYTIME) return DST_FORMAT_TIMECENT;
+		if(destination == CONN_DST_EG2_RELEASETIME) return DST_FORMAT_TIMECENT;
+		if(destination == CONN_DST_EG2_SUSTAINLEVEL) return DST_FORMAT_PERCENT;	
+		
+		if(destination == CONN_DST_KEYNUMBER) return DST_FORMAT_CENT; // NOT SURE WITHOUT DLS 2 SPEC
+		if(destination == CONN_DST_LEFT) return DST_FORMAT_CB;
+		if(destination == CONN_DST_RIGHT) return DST_FORMAT_CB;
+		if(destination == CONN_DST_CENTER) return DST_FORMAT_CB;
+		if(destination == CONN_DST_LEFTREAR) return DST_FORMAT_CB;
+		if(destination == CONN_DST_RIGHTREAR) return DST_FORMAT_CB;
+		if(destination == CONN_DST_LFE_CHANNEL) return DST_FORMAT_CB;
+		if(destination == CONN_DST_CHORUS) return DST_FORMAT_PERCENT;
+		if(destination == CONN_DST_REVERB) return DST_FORMAT_PERCENT;
+
+		if(destination == CONN_DST_VIB_FREQUENCY) return DST_FORMAT_CENT;
+		if(destination == CONN_DST_VIB_STARTDELAY) return DST_FORMAT_TIMECENT;
+
+		if(destination == CONN_DST_EG1_DELAYTIME) return DST_FORMAT_TIMECENT;
+		if(destination == CONN_DST_EG1_HOLDTIME) return DST_FORMAT_TIMECENT;
+		if(destination == CONN_DST_EG1_SHUTDOWNTIME) return DST_FORMAT_TIMECENT;
+
+		if(destination == CONN_DST_EG2_DELAYTIME) return DST_FORMAT_TIMECENT;
+		if(destination == CONN_DST_EG2_HOLDTIME) return DST_FORMAT_TIMECENT;
+
+		if(destination == CONN_DST_FILTER_CUTOFF) return DST_FORMAT_CENT;
+		if(destination == CONN_DST_FILTER_Q) return DST_FORMAT_CB;
+	
+		return -1;
+	}	
+	
+	public static String getDestinationName(int destination) {
+		
+		if(destination == CONN_DST_GAIN) return "gain";
+		if(destination == CONN_DST_PITCH) return "pitch";
+		if(destination == CONN_DST_PAN) return "pan";
+
+		if(destination == CONN_DST_LFO_FREQUENCY) return "lfo1.freq";
+		if(destination == CONN_DST_LFO_STARTDELAY) return "lfo1.delay";
+
+		if(destination == CONN_DST_EG1_ATTACKTIME) return "eg1.attack";
+		if(destination == CONN_DST_EG1_DECAYTIME) return "eg1.decay";
+		if(destination == CONN_DST_EG1_RELEASETIME) return "eg1.release";
+		if(destination == CONN_DST_EG1_SUSTAINLEVEL) return "eg1.sustain";
+
+		if(destination == CONN_DST_EG2_ATTACKTIME) return "eg2.attack";
+		if(destination == CONN_DST_EG2_DECAYTIME) return "eg2.decay";
+		if(destination == CONN_DST_EG2_RELEASETIME) return "eg2.release";
+		if(destination == CONN_DST_EG2_SUSTAINLEVEL) return "eg2.sustain";
+		
+		if(destination == CONN_DST_KEYNUMBER) return "keynumber";
+		if(destination == CONN_DST_LEFT) return "left";
+		if(destination == CONN_DST_RIGHT) return "right";
+		if(destination == CONN_DST_CENTER) return "center";
+		if(destination == CONN_DST_LEFTREAR) return "leftrear";
+		if(destination == CONN_DST_RIGHTREAR) return "rightrear";
+		if(destination == CONN_DST_LFE_CHANNEL) return "lfe_channel";
+		if(destination == CONN_DST_CHORUS) return "chorus";
+		if(destination == CONN_DST_REVERB) return "reverb";
+
+		if(destination == CONN_DST_VIB_FREQUENCY) return "vib.freq";
+		if(destination == CONN_DST_VIB_STARTDELAY) return "vib.delay";
+
+		if(destination == CONN_DST_EG1_DELAYTIME) return "eg1.delay";
+		if(destination == CONN_DST_EG1_HOLDTIME) return "eg1.hold";
+		if(destination == CONN_DST_EG1_SHUTDOWNTIME) return "eg1.shutdown";
+
+		if(destination == CONN_DST_EG2_DELAYTIME) return "eg2.delay";
+		if(destination == CONN_DST_EG2_HOLDTIME) return "eg.2hold";
+
+		if(destination == CONN_DST_FILTER_CUTOFF) return "filter.cutoff"; // NOT SURE WITHOUT DLS 2 SPEC
+		if(destination == CONN_DST_FILTER_Q) return "filter.q"; // NOT SURE WITHOUT DLS 2 SPEC		
+		
+		return null;
+	}
+	
+	public static String getSourceName(int source) {
+		
+		if(source == CONN_SRC_NONE) return "none";
+		if(source == CONN_SRC_LFO) return "lfo";
+		if(source == CONN_SRC_KEYONVELOCITY) return "keyonvelocity";
+		if(source == CONN_SRC_KEYNUMBER) return "keynumber";
+		if(source == CONN_SRC_EG1) return "eg1";
+		if(source == CONN_SRC_EG2) return "eg2";
+		if(source == CONN_SRC_PITCHWHEEL) return "pitchweel";
+		if(source == CONN_SRC_CC1) return "cc1";
+		if(source == CONN_SRC_CC7) return "cc7";
+		if(source == CONN_SRC_CC10) return "c10";
+		if(source == CONN_SRC_CC11) return "cc11";
+		
+		if(source == CONN_SRC_POLYPRESSURE) return "polypressure";
+		if(source == CONN_SRC_CHANNELPRESSURE) return "channelpressure";
+		if(source == CONN_SRC_VIBRATO) return "vibrato";
+		if(source == CONN_SRC_MONOPRESSURE) return "monopressure";
+		if(source == CONN_SRC_CC91) return "cc91";
+		if(source == CONN_SRC_CC93) return "cc93";	
+		return null;
+	}			
+	
+	
+	public int getDestination() {
+		return destination;
+	}
+	public void setDestination(int destination) {
+		this.destination = destination;
+	}
+	public int getScale() {
+		return scale;
+	}
+	public void setScale(int scale) {
+		this.scale = scale;
+	}
+	public int getSource() {
+		return source;
+	}
+	public void setSource(int source) {
+		this.source = source;
+	}
+	public int getVersion() {
+		return version;
+	}
+	public void setVersion(int version) {
+		this.version = version;
+	}
+	public int getTransform() {
+		return transform;
+	}
+	public void setTransform(int transform) {
+		this.transform = transform;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSRegion.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,162 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+/**
+ * This class is used to store region parts for instrument.
+ * A region has a velocity and key range which it response to.
+ * And it has a list of modulators/articulators which 
+ * is used how to synthesize a single voice.
+ * It is stored inside a "rgn " List Chunk inside DLS files.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is used for storing DLS regions.
+ * It is stored inside a "rgn " List Chunk inside DLS files.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class DLSRegion {
+	
+	public final static int OPTION_SELFNONEXCLUSIVE = 0x0001;
+
+	protected List<DLSModulator> modulators = new ArrayList<DLSModulator>();
+	
+	protected int keyfrom;
+	protected int keyto;
+	protected int velfrom;
+	protected int velto;
+	protected int options;
+	protected int exclusiveClass;
+	
+	protected int fusoptions;
+	protected int phasegroup;
+	protected long channel;
+	protected DLSSample sample = null;	
+	protected DLSSampleOptions sampleoptions;
+	
+	public List<DLSModulator> getModulators() {
+		return modulators;
+	}
+
+	public long getChannel() {
+		return channel;
+	}
+
+	public void setChannel(long channel) {
+		this.channel = channel;
+	}
+
+	public int getExclusiveClass() {
+		return exclusiveClass;
+	}
+
+	public void setExclusiveClass(int exclusiveClass) {
+		this.exclusiveClass = exclusiveClass;
+	}
+
+	public int getFusoptions() {
+		return fusoptions;
+	}
+
+	public void setFusoptions(int fusoptions) {
+		this.fusoptions = fusoptions;
+	}
+
+	public int getKeyfrom() {
+		return keyfrom;
+	}
+
+	public void setKeyfrom(int keyfrom) {
+		this.keyfrom = keyfrom;
+	}
+
+	public int getKeyto() {
+		return keyto;
+	}
+
+	public void setKeyto(int keyto) {
+		this.keyto = keyto;
+	}
+
+	public int getOptions() {
+		return options;
+	}
+
+	public void setOptions(int options) {
+		this.options = options;
+	}
+
+	public int getPhasegroup() {
+		return phasegroup;
+	}
+
+	public void setPhasegroup(int phasegroup) {
+		this.phasegroup = phasegroup;
+	}
+
+	public DLSSample getSample() {
+		return sample;
+	}
+
+	public void setSample(DLSSample sample) {
+		this.sample = sample;
+	}
+
+	public int getVelfrom() {
+		return velfrom;
+	}
+
+	public void setVelfrom(int velfrom) {
+		this.velfrom = velfrom;
+	}
+
+	public int getVelto() {
+		return velto;
+	}
+
+	public void setVelto(int velto) {
+		this.velto = velto;
+	}
+
+	public void setModulators(List<DLSModulator> modulators) {
+		this.modulators = modulators;
+	}
+
+	public DLSSampleOptions getSampleoptions() {
+		return sampleoptions;
+	}
+
+	public void setSampleoptions(DLSSampleOptions sampleOptions) {
+		this.sampleoptions = sampleOptions;
+	}	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSample.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,131 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.InputStream;
+
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.SoundbankResource;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+
+/**
+ * This class is used to store the sample data itself.
+ * A sample is encoded as PCM audio stream
+ * and in DLS Level 1 files it is always a mono 8/16 bit stream.
+ * They are stored just like RIFF WAVE files are stored.
+ * It is stored inside a "wave" List Chunk inside DLS files.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class DLSSample extends SoundbankResource {
+
+	protected byte[] guid = null;
+	
+	protected DLSInfo info = new DLSInfo();
+	
+	protected DLSSampleOptions sampleoptions;
+	protected ModelByteBuffer data;
+	protected AudioFormat format;
+	
+	public DLSSample(Soundbank soundBank) {
+		super(soundBank, null, AudioInputStream.class);
+	}
+	
+	public DLSSample() {
+		super(null, null, AudioInputStream.class);
+	}
+	
+	public DLSInfo getInfo() {
+		return info;
+	}	
+
+	public Object getData() {		
+		
+		AudioFormat format = getFormat();		
+		
+		InputStream is = data.getInputStream();
+		if(is == null) return null;
+		return new AudioInputStream(is, format, data.capacity());
+	}
+	
+	public ModelByteBuffer getDataBuffer()
+	{
+		return data;
+	}
+
+	public AudioFormat getFormat()
+	{
+		return format;
+	}
+
+	public void setFormat(AudioFormat format) {
+		this.format = format;
+	}
+	
+	public void setData(ModelByteBuffer data) {
+		this.data = data;
+	}	
+	
+	public void setData(byte[] data) {
+		this.data = new ModelByteBuffer(data);
+	}
+	
+	public void setData(byte[] data, int offset, int length) {
+		this.data = new ModelByteBuffer(data, offset, length);
+	}		
+	
+	public String getName() {
+		return info.name;
+	}
+
+	public void setName(String name) {
+		info.name = name;
+	}	
+
+	public DLSSampleOptions getSampleoptions() {
+		return sampleoptions;
+	}
+
+	public void setSampleoptions(DLSSampleOptions sampleOptions) {
+		this.sampleoptions = sampleOptions;
+	}	
+	
+	public String toString()
+	{
+		return "Sample: " + info.name;
+	}
+
+	public byte[] getGuid() {
+		return guid;
+	}
+
+	public void setGuid(byte[] guid) {
+		this.guid = guid;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSampleLoop.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,62 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * This class is used to store loop points inside DLSSampleOptions class.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class DLSSampleLoop {
+
+	public final static int LOOP_TYPE_FORWARD = 0;
+	public final static int LOOP_TYPE_RELEASE = 1;
+
+	protected long type;
+	protected long start;
+	protected long length;
+	
+	public long getLength() {
+		return length;
+	}
+	public void setLength(long length) {
+		this.length = length;
+	}
+	public long getStart() {
+		return start;
+	}
+	public void setStart(long start) {
+		this.start = start;
+	}
+	public long getType() {
+		return type;
+	}
+	public void setType(long type) {
+		this.type = type;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSampleOptions.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,85 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+/**
+ * This class is used to store information
+ * how samples are rendered inside software synthesizer.
+ * It includes information on MIDI root note, loop points
+ * attenuation and tuning.
+ * It is stored inside a "wsmp" Chunk inside DLS files.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class stores options how to 
+ * playback sampled data like pitch/tuning, attenuation and loops.
+ * It is stored as a "wsmp" chunk inside DLS files.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class DLSSampleOptions {
+	
+	protected int unitynote;
+	protected short finetune;
+	protected int attenuation;
+	protected long options;
+	protected List<DLSSampleLoop> loops = new ArrayList<DLSSampleLoop>();
+	
+	public int getAttenuation() {
+		return attenuation;
+	}
+	public void setAttenuation(int attenuation) {
+		this.attenuation = attenuation;
+	}
+	public short getFinetune() {
+		return finetune;
+	}
+	public void setFinetune(short finetune) {
+		this.finetune = finetune;
+	}
+	public List<DLSSampleLoop> getLoops() {
+		return loops;
+	}
+	public long getOptions() {
+		return options;
+	}
+	public void setOptions(long options) {
+		this.options = options;
+	}
+	public int getUnitynote() {
+		return unitynote;
+	}
+	public void setUnitynote(int unitynote) {
+		this.unitynote = unitynote;
+	}	
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,1333 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+/**
+ * This class reads DLS (Downloadable Sounds) from files/url/streams. 
+ * It can both read Level 1 and Level 2 DLS files.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+package com.sun.media.sound;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.SoundbankResource;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.AudioFormat.Encoding;
+
+/**
+ * A DLS Level 1 and Level 2 soundbank reader.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class DLSSoundbank implements Soundbank {
+	
+	static private class DLSID
+	{
+		long i1;
+		int s1;
+		int s2;
+		int x1;
+		int x2;
+		int x3;
+		int x4;
+		int x5;
+		int x6;
+		int x7;
+		int x8;
+		
+		private DLSID()
+		{			
+		}
+		public DLSID(long i1, int s1, int s2, int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8)
+		{
+			this.i1 = i1;
+			this.s1 = s1;
+			this.s2 = s2;
+			this.x1 = x1;
+			this.x2 = x2;
+			this.x3 = x3;
+			this.x4 = x4;
+			this.x5 = x5;
+			this.x6 = x6;
+			this.x7 = x7;
+			this.x8 = x8;
+		}
+		
+		public static DLSID read(RIFFReader riff) throws IOException
+		{
+			DLSID d = new DLSID();
+			d.i1 = riff.readUnsignedInt();
+			d.s1 = riff.readUnsignedShort();
+			d.s2 = riff.readUnsignedShort();
+			d.x1 = riff.readByte();
+			d.x2 = riff.readByte();
+			d.x3 = riff.readByte();
+			d.x4 = riff.readByte();
+			d.x5 = riff.readByte();
+			d.x6 = riff.readByte();
+			d.x7 = riff.readByte();
+			d.x8 = riff.readByte();
+			return d;
+		}
+		
+		public boolean equals(Object obj) {
+			if(!(obj instanceof DLSID)) return false;
+			DLSID t = (DLSID)obj;
+			if(i1 != t.i1) return false;
+			if(s1 != t.s1) return false;
+			if(s2 != t.s2) return false;
+			if(x1 != t.x1) return false;
+			if(x2 != t.x2) return false;
+			if(x3 != t.x3) return false;
+			if(x4 != t.x4) return false;
+			if(x5 != t.x5) return false;
+			if(x6 != t.x6) return false;
+			if(x7 != t.x7) return false;
+			if(x8 != t.x8) return false;
+			return true;
+		}
+		
+		
+	}
+	
+	private static final int DLS_CDL_AND			= 0x0001;	/* X = X & Y */
+	private static final int DLS_CDL_OR			    = 0x0002;	/* X = X | Y */
+	private static final int DLS_CDL_XOR			= 0x0003;	/* X = X ^ Y */
+	private static final int DLS_CDL_ADD			= 0x0004;	/* X = X + Y */
+	private static final int DLS_CDL_SUBTRACT		= 0x0005;	/* X = X - Y */
+	private static final int DLS_CDL_MULTIPLY		= 0x0006;	/* X = X * Y */
+	private static final int DLS_CDL_DIVIDE		    = 0x0007;	/* X = X / Y */
+	private static final int DLS_CDL_LOGICAL_AND	= 0x0008;	/* X = X && Y */
+	private static final int DLS_CDL_LOGICAL_OR		= 0x0009;	/* X = X || Y */
+	private static final int DLS_CDL_LT			    = 0x000A;	/* X = (X < Y) */
+	private static final int DLS_CDL_LE			    = 0x000B;	/* X = (X <= Y) */
+	private static final int DLS_CDL_GT			    = 0x000C;	/* X = (X > Y) */
+	private static final int DLS_CDL_GE			    = 0x000D;	/* X = (X >= Y) */
+	private static final int DLS_CDL_EQ			    = 0x000E;	/* X = (X == Y) */
+	private static final int DLS_CDL_NOT			= 0x000F;	/* X = !X */
+	private static final int DLS_CDL_CONST		    = 0x0010;	/* 32-bit constant */
+	private static final int DLS_CDL_QUERY		    = 0x0011;	/* 32-bit value returned from query */
+	private static final int DLS_CDL_QUERYSUPPORTED	= 0x0012;	/* 32-bit value returned from query */
+	
+	private static final DLSID DLSID_GMInHardware       = new DLSID(0x178f2f24, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+	private static final DLSID DLSID_GSInHardware       = new DLSID(0x178f2f25, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+	private static final DLSID DLSID_XGInHardware       = new DLSID(0x178f2f26, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+	private static final DLSID DLSID_SupportsDLS1       = new DLSID(0x178f2f27, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+	private static final DLSID DLSID_SupportsDLS2       = new DLSID(0xf14599e5, 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
+	private static final DLSID DLSID_SampleMemorySize   = new DLSID(0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
+	private static final DLSID DLSID_ManufacturersID    = new DLSID(0xb03e1181, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+	private static final DLSID DLSID_ProductID          = new DLSID(0xb03e1182, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+	private static final DLSID DLSID_SamplePlaybackRate = new DLSID(0x2a91f713, 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
+	
+	private long major = -1;
+	private long minor = -1;
+	
+	private DLSInfo info = new DLSInfo();
+	
+	private List<DLSInstrument> instruments = new ArrayList<DLSInstrument>();
+	private List<DLSSample> samples = new ArrayList<DLSSample>();
+	
+	private boolean largeFormat = false;
+	private File sampleFile;	
+	
+	public DLSSoundbank()
+	{
+	}
+	
+	public DLSSoundbank(URL url) throws IOException {
+		
+		InputStream is = url.openStream();
+		try
+		{
+			readSoundbank(is);
+		}
+		finally
+		{
+			is.close();
+		}
+	}	
+	
+	public DLSSoundbank(File file) throws IOException {
+		largeFormat = true;
+		sampleFile = file;
+		InputStream is = new FileInputStream(file);
+		try
+		{
+			readSoundbank(is);
+		}
+		finally
+		{
+			is.close();
+		}
+	}		
+
+	public DLSSoundbank(InputStream inputstream) throws IOException {
+		readSoundbank(inputstream);
+	}		
+		
+	private void readSoundbank(InputStream inputstream) throws IOException {
+		
+		RIFFReader riff = new RIFFReader(inputstream);
+		if (!riff.getFormat().equals("RIFF"))
+			throw new RIFFInvalidFormatException("Input stream is not a valid RIFF stream!");
+		if (!riff.getType().equals("DLS "))
+			throw new RIFFInvalidFormatException("Input stream is not a valid DLS soundbank!");
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			if (chunk.getFormat().equals("LIST")) {
+				if (chunk.getType().equals("INFO"))
+					readInfoChunk(chunk);
+				if (chunk.getType().equals("lins"))
+					readLinsChunk(chunk);
+				if (chunk.getType().equals("wvpl"))
+					readWvplChunk(chunk);
+			}
+			else
+			{
+				if (chunk.getFormat().equals("cdl "))
+				{
+					if(!readCdlChunk(chunk))
+						throw new RIFFInvalidFormatException("DLS file isn't supported!");
+				}
+				if (chunk.getFormat().equals("colh")) {
+					// - skipped because we will load the entire bank into memory
+					// long instrumentcount = chunk.readUnsignedInt();
+					// System.out.println("instrumentcount = "+ instrumentcount);					
+				}
+				if (chunk.getFormat().equals("ptbl")) {
+					// Pool Table Chunk
+					// - skipped because we will load the entire bank into memory
+				}	
+				if (chunk.getFormat().equals("vers")) {
+					major = chunk.readUnsignedInt();
+					minor = chunk.readUnsignedInt();
+				}						
+			}
+		}	
+		
+		for(Map.Entry<DLSRegion,Long> entry : temp_rgnassign.entrySet())
+		{
+			entry.getKey().sample = samples.get((int)entry.getValue().longValue());
+		}
+		
+		temp_rgnassign = null;
+	}
+	
+	
+	
+	private boolean cdlIsQuerySupported(DLSID uuid)
+	{
+		if(uuid.equals(DLSID_GMInHardware)) return true;
+		if(uuid.equals(DLSID_GSInHardware)) return true;
+		if(uuid.equals(DLSID_XGInHardware)) return true;
+		if(uuid.equals(DLSID_SupportsDLS1)) return true;
+		if(uuid.equals(DLSID_SupportsDLS2)) return true;
+		if(uuid.equals(DLSID_SampleMemorySize)) return true;
+		if(uuid.equals(DLSID_ManufacturersID)) return true;
+		if(uuid.equals(DLSID_ProductID)) return true;
+		if(uuid.equals(DLSID_SamplePlaybackRate)) return true;
+		return false;
+	}
+	private long cdlQuery(DLSID uuid)
+	{
+		if(uuid.equals(DLSID_GMInHardware)) return 1;
+		if(uuid.equals(DLSID_GSInHardware)) return 0;
+		if(uuid.equals(DLSID_XGInHardware)) return 0;
+		if(uuid.equals(DLSID_SupportsDLS1)) return 1;
+		if(uuid.equals(DLSID_SupportsDLS2)) return 1;
+		if(uuid.equals(DLSID_SampleMemorySize)) return Runtime.getRuntime().totalMemory();
+		if(uuid.equals(DLSID_ManufacturersID)) return 0;
+		if(uuid.equals(DLSID_ProductID)) return 0;
+		if(uuid.equals(DLSID_SamplePlaybackRate)) return 44100;		
+		return 0;
+	}
+	
+
+	// Reading cdl-ck Chunk
+	// "cdl " chunk can only appear inside : DLS,lart,lar2,rgn,rgn2
+	private boolean readCdlChunk(RIFFReader riff) throws IOException {
+
+		DLSID uuid;
+		long x;
+	    long y;		
+		Stack<Long> stack = new Stack<Long>();
+		
+		while(riff.available() != 0)
+		{
+			int opcode = riff.readUnsignedShort();
+			switch (opcode) {
+			case DLS_CDL_AND:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( ((x!=0) & (y!=0)) ?1:0));
+				break;
+			case DLS_CDL_OR:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( ((x!=0) | (y!=0)) ?1:0));
+				break;
+			case DLS_CDL_XOR:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( ((x!=0) ^ (y!=0)) ?1:0));
+				break;
+			case DLS_CDL_ADD:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( x+y ));
+				break;
+			case DLS_CDL_SUBTRACT:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( x-y ));
+				break;
+			case DLS_CDL_MULTIPLY:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( x*y ));
+				break;
+			case DLS_CDL_DIVIDE:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( x/y ));
+				break;
+			case DLS_CDL_LOGICAL_AND:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( ((x!=0) & (y!=0)) ?1:0));
+				break;
+			case DLS_CDL_LOGICAL_OR:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( ((x!=0) | (y!=0)) ?1:0));
+				break;
+			case DLS_CDL_LT:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( (x < y) ?1:0));
+				break;				
+			case DLS_CDL_LE:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( (x <= y) ?1:0));
+				break;				
+			case DLS_CDL_GT:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( (x > y) ?1:0));
+				break;				
+			case DLS_CDL_GE:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( (x >= y) ?1:0));
+				break;				
+			case DLS_CDL_EQ:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long( (x == y) ?1:0));
+				break;		
+			case DLS_CDL_NOT:
+				x = stack.pop();
+				y = stack.pop();
+				stack.push(new Long((x==0)?1:0));
+				break;
+			case DLS_CDL_CONST:
+				stack.push(new Long(riff.readUnsignedInt()));
+				break;
+			case DLS_CDL_QUERY:
+				uuid = DLSID.read(riff);
+				stack.push(cdlQuery(uuid));
+				break;				
+			case DLS_CDL_QUERYSUPPORTED:
+				uuid = DLSID.read(riff);
+				stack.push(new Long(cdlIsQuerySupported(uuid)?1:0));
+				break;				
+			default:
+				break;
+			}
+		}
+		if(stack.isEmpty()) return false;
+		return stack.pop() == 1;
+		                          
+	}
+			
+	private void readInfoChunk(RIFFReader riff) throws IOException {
+		info.name = null;
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			String format = chunk.getFormat();			
+			if(format.equals("INAM"))
+				info.name = chunk.readString(chunk.available());						
+			else if(format.equals("ICRD"))
+				info.creationDate = chunk.readString(chunk.available());
+			else if(format.equals("IENG"))
+				info.engineers = chunk.readString(chunk.available());
+			else if(format.equals("IPRD"))
+				info.product = chunk.readString(chunk.available());
+			else if(format.equals("ICOP"))
+				info.copyright = chunk.readString(chunk.available());
+			else if(format.equals("ICMT"))
+				info.comments = chunk.readString(chunk.available());
+			else if(format.equals("ISFT"))
+				info.tools = chunk.readString(chunk.available());
+			else if(format.equals("IARL"))
+				info.archival_location = chunk.readString(chunk.available());
+			else if(format.equals("IART"))
+				info.artist = chunk.readString(chunk.available());
+			else if(format.equals("ICMS"))
+				info.commissioned = chunk.readString(chunk.available());
+			else if(format.equals("IGNR"))
+				info.genre = chunk.readString(chunk.available());
+			else if(format.equals("IKEY"))
+				info.keywords = chunk.readString(chunk.available());
+			else if(format.equals("IMED"))
+				info.medium = chunk.readString(chunk.available());
+			else if(format.equals("ISBJ"))
+				info.subject = chunk.readString(chunk.available());
+			else if(format.equals("ISRC"))
+				info.source = chunk.readString(chunk.available());
+			else if(format.equals("ISRF"))
+				info.source_form = chunk.readString(chunk.available());
+			else if(format.equals("ITCH"))
+				info.technician = chunk.readString(chunk.available());						
+		}
+	}
+	
+	private void readLinsChunk(RIFFReader riff) throws IOException {			
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			if (chunk.getFormat().equals("LIST")) {
+				if(chunk.getType().equals("ins "))
+				{
+					readInsChunk(chunk);				
+				}
+				
+			}
+		}
+	}
+	
+	private void readInsChunk(RIFFReader riff) throws IOException {
+		DLSInstrument instrument = new DLSInstrument(this);
+		
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			String format = chunk.getFormat();
+			if(format.equals("LIST"))
+			{
+				if(chunk.getType().equals("INFO"))
+				{
+					readInsInfoChunk(instrument, chunk);
+				}
+				if(chunk.getType().equals("lrgn"))
+				{
+					while(chunk.hasNextChunk())
+					{
+						RIFFReader subchunk = chunk.nextChunk();
+						if(subchunk.getFormat().equals("LIST"))
+						{
+							if(subchunk.getType().equals("rgn "))
+							{
+								DLSRegion split = new DLSRegion();
+								if(readRgnChunk(split, subchunk))
+									instrument.getRegions().add(split);
+								
+							}
+							if(subchunk.getType().equals("rgn2")) // support for DLS level 2 regions
+							{
+								DLSRegion split = new DLSRegion();
+								if(readRgnChunk(split, subchunk))
+									instrument.getRegions().add(split);
+								
+							}							
+						}
+					}
+				}
+				if(chunk.getType().equals("lart"))
+				{
+					List<DLSModulator> modlist = new ArrayList<DLSModulator>();  
+					while(chunk.hasNextChunk())
+					{
+						RIFFReader subchunk = chunk.nextChunk();
+						if (chunk.getFormat().equals("cdl "))
+						{
+							if(!readCdlChunk(chunk))
+							{
+								modlist.clear();
+								break;
+							}
+						}								
+						if(subchunk.getFormat().equals("art1"))
+							readArt1Chunk(modlist, subchunk);
+					}					
+					instrument.getModulators().addAll(modlist);
+				}
+				if(chunk.getType().equals("lar2")) // support for DLS level 2 ART
+				{
+					List<DLSModulator> modlist = new ArrayList<DLSModulator>();
+					while(chunk.hasNextChunk())
+					{
+						RIFFReader subchunk = chunk.nextChunk();
+						if (chunk.getFormat().equals("cdl "))
+						{
+							if(!readCdlChunk(chunk))
+							{
+								modlist.clear();
+								break;
+							}
+						}									
+						if(subchunk.getFormat().equals("art2"))
+							readArt2Chunk(modlist, subchunk);
+					}				
+					instrument.getModulators().addAll(modlist);
+				}				
+			}
+			else
+			{
+				if(format.equals("dlid"))
+				{
+					instrument.guid = new byte[16];
+					chunk.read(instrument.guid);	
+				}
+				if(format.equals("insh"))
+				{
+					chunk.readUnsignedInt(); // Read Region Count - ignored
+					
+					int bank = chunk.read();             // LSB					
+					bank += (chunk.read() & 127) << 7;   // MSB
+					chunk.read(); // Read Reserved byte
+					int drumins = chunk.read();          // Drum Instrument
+					
+					int id = chunk.read() & 127; // Read only first 7 bits
+					chunk.read(); // Read Reserved byte
+					chunk.read(); // Read Reserved byte
+					chunk.read(); // Read Reserved byte
+					
+					instrument.bank = bank;
+					instrument.preset = (int)id;
+					instrument.druminstrument = (drumins & 128) > 0;
+					//System.out.println("bank="+bank+" drumkit="+drumkit+" id="+id);
+				}				
+				
+			}
+		}						
+		instruments.add(instrument);		
+	}
+	
+	private void readArt1Chunk(List<DLSModulator> modulators, RIFFReader riff) throws IOException {
+
+		long size = riff.readUnsignedInt();
+		long count = riff.readUnsignedInt();
+		
+		if(size - 8 != 0) riff.skip(size - 8);
+
+		for (int i = 0; i < count; i++) {
+			
+			DLSModulator modulator = new DLSModulator();
+			modulator.version = 1;
+			modulator.source = riff.readUnsignedShort();
+			modulator.control = riff.readUnsignedShort();
+			modulator.destination = riff.readUnsignedShort();
+			modulator.transform = riff.readUnsignedShort();
+			modulator.scale = riff.readInt();			
+			modulators.add(modulator);
+		}		
+	}
+
+	private void readArt2Chunk(List<DLSModulator> modulators, RIFFReader riff) throws IOException {
+
+		long size = riff.readUnsignedInt();
+		long count = riff.readUnsignedInt();
+		
+		if(size - 8 != 0) riff.skip(size - 8);
+
+		for (int i = 0; i < count; i++) {
+			
+			DLSModulator modulator = new DLSModulator();
+			modulator.version = 2;
+			modulator.source = riff.readUnsignedShort();
+			modulator.control = riff.readUnsignedShort();
+			modulator.destination = riff.readUnsignedShort();
+			modulator.transform = riff.readUnsignedShort();
+			modulator.scale = riff.readInt();			
+			modulators.add(modulator);
+		}		
+	}	
+	private Map<DLSRegion,Long> temp_rgnassign = new HashMap<DLSRegion,Long>();
+	private boolean readRgnChunk(DLSRegion split, RIFFReader riff) throws IOException {
+		
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			String format = chunk.getFormat();
+			if(format.equals("LIST"))
+			{
+				if(chunk.getType().equals("lart"))
+				{
+					List<DLSModulator> modlist = new ArrayList<DLSModulator>();
+					while(chunk.hasNextChunk())
+					{
+						RIFFReader subchunk = chunk.nextChunk();
+						if (chunk.getFormat().equals("cdl "))
+						{
+							if(!readCdlChunk(chunk))
+							{
+								modlist.clear();
+								break;
+							}
+						}									
+						if(subchunk.getFormat().equals("art1"))
+							readArt1Chunk(modlist, subchunk);
+					}				
+					split.getModulators().addAll(modlist);							
+				}
+				if(chunk.getType().equals("lar2")) // support for DLS level 2 ART
+				{
+					List<DLSModulator> modlist = new ArrayList<DLSModulator>();
+					while(chunk.hasNextChunk())
+					{
+						RIFFReader subchunk = chunk.nextChunk();
+						if (chunk.getFormat().equals("cdl "))
+						{
+							if(!readCdlChunk(chunk))
+							{
+								modlist.clear();
+								break;
+							}
+						}									
+						if(subchunk.getFormat().equals("art2"))
+							readArt2Chunk(modlist, subchunk);
+					}				
+					split.getModulators().addAll(modlist);					
+				}						
+			}
+			else
+			{	
+				
+				if (format.equals("cdl "))
+				{
+					if(!readCdlChunk(chunk))
+						return false;
+				}				
+				if(format.equals("rgnh"))
+				{
+					split.keyfrom = chunk.readUnsignedShort();
+					split.keyto = chunk.readUnsignedShort();
+					split.velfrom = chunk.readUnsignedShort();
+					split.velto = chunk.readUnsignedShort();
+					split.options = chunk.readUnsignedShort();
+					split.exclusiveClass = chunk.readUnsignedShort();
+				}
+				if(format.equals("wlnk"))
+				{
+					split.fusoptions = chunk.readUnsignedShort();
+					split.phasegroup = chunk.readUnsignedShort();
+					split.channel    = chunk.readUnsignedInt();					
+					long sampleid = chunk.readUnsignedInt();
+					temp_rgnassign.put(split, sampleid);
+				}
+				if(format.equals("wsmp"))
+				{
+					split.sampleoptions = new DLSSampleOptions();
+					readWsmpChunk(split.sampleoptions, chunk);
+				}
+			}
+		}
+		return true;
+	}	
+	
+	private void readWsmpChunk(DLSSampleOptions sampleOptions, RIFFReader riff) throws IOException {
+	
+		long size = riff.readUnsignedInt(); 
+		sampleOptions.unitynote = riff.readUnsignedShort(); 
+		sampleOptions.finetune = riff.readShort();  
+		sampleOptions.attenuation = riff.readInt();
+		sampleOptions.options = riff.readUnsignedInt();
+		long loops = riff.readInt();
+		
+		if(size > 20)
+		{
+			riff.skip(size - 20);
+		}
+		
+		for (int i = 0; i < loops; i++) {
+			DLSSampleLoop loop = new DLSSampleLoop();
+			long size2 = riff.readUnsignedInt();
+			loop.type = riff.readUnsignedInt();
+			loop.start = riff.readUnsignedInt();
+			loop.length = riff.readUnsignedInt();
+			sampleOptions.loops.add(loop);
+			if(size2 > 16)
+			{
+				riff.skip(size2 - 16);
+			}			
+		}
+	}
+		
+	private void readInsInfoChunk(DLSInstrument dlsinstrument, RIFFReader riff) throws IOException {
+		dlsinstrument.info.name = null;
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			String format = chunk.getFormat();			
+			if(format.equals("INAM"))
+				dlsinstrument.info.name = chunk.readString(chunk.available());						
+			else if(format.equals("ICRD"))
+				dlsinstrument.info.creationDate = chunk.readString(chunk.available());
+			else if(format.equals("IENG"))
+				dlsinstrument.info.engineers = chunk.readString(chunk.available());
+			else if(format.equals("IPRD"))
+				dlsinstrument.info.product = chunk.readString(chunk.available());
+			else if(format.equals("ICOP"))
+				dlsinstrument.info.copyright = chunk.readString(chunk.available());
+			else if(format.equals("ICMT"))
+				dlsinstrument.info.comments = chunk.readString(chunk.available());
+			else if(format.equals("ISFT"))
+				dlsinstrument.info.tools = chunk.readString(chunk.available());
+			else if(format.equals("IARL"))
+				dlsinstrument.info.archival_location = chunk.readString(chunk.available());
+			else if(format.equals("IART"))
+				dlsinstrument.info.artist = chunk.readString(chunk.available());
+			else if(format.equals("ICMS"))
+				dlsinstrument.info.commissioned = chunk.readString(chunk.available());
+			else if(format.equals("IGNR"))
+				dlsinstrument.info.genre = chunk.readString(chunk.available());
+			else if(format.equals("IKEY"))
+				dlsinstrument.info.keywords = chunk.readString(chunk.available());
+			else if(format.equals("IMED"))
+				dlsinstrument.info.medium = chunk.readString(chunk.available());
+			else if(format.equals("ISBJ"))
+				dlsinstrument.info.subject = chunk.readString(chunk.available());
+			else if(format.equals("ISRC"))
+				dlsinstrument.info.source = chunk.readString(chunk.available());
+			else if(format.equals("ISRF"))
+				dlsinstrument.info.source_form = chunk.readString(chunk.available());
+			else if(format.equals("ITCH"))
+				dlsinstrument.info.technician = chunk.readString(chunk.available());						
+		}
+	}	
+	
+	private void readWvplChunk(RIFFReader riff) throws IOException {
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			if (chunk.getFormat().equals("LIST")) {
+				if(chunk.getType().equals("wave"))
+				{
+					readWaveChunk(chunk);				
+				}				
+			}
+		}
+	}
+	
+	private void readWaveChunk(RIFFReader riff) throws IOException {
+		
+		DLSSample sample = new DLSSample(this);
+		
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			String format = chunk.getFormat();
+			if(format.equals("LIST"))
+			{
+				if(chunk.getType().equals("INFO"))
+				{
+					readWaveInfoChunk(sample, chunk);
+				}
+			}
+			else
+			{
+				if(format.equals("dlid"))
+				{
+					sample.guid = new byte[16];
+					chunk.read(sample.guid);	
+				}	
+
+				if(format.equals("fmt "))
+				{
+					
+					int sampleformat = chunk.readUnsignedShort();
+					if(sampleformat != 1 && sampleformat != 3)
+						throw new RIFFInvalidDataException("Only PCM samples are supported!");
+					int channels = chunk.readUnsignedShort();
+					long samplerate = chunk.readUnsignedInt();
+					/* long framerate = */ chunk.readUnsignedInt(); // bytes per sec
+					int framesize = chunk.readUnsignedShort(); // block align, framesize
+					int bits = chunk.readUnsignedShort();
+					AudioFormat audioformat = null;
+					if(sampleformat == 1)						
+					if(bits == 8)
+						audioformat = new AudioFormat(
+								Encoding.PCM_UNSIGNED, samplerate, bits, 
+								channels, framesize, samplerate, false);
+						
+					else
+						audioformat = new AudioFormat(
+							Encoding.PCM_SIGNED, samplerate, bits, 
+							channels, framesize, samplerate, false);					
+					if(sampleformat == 3)
+						audioformat = new AudioFormat
+							(AudioFloatConverter.PCM_FLOAT, samplerate, bits, 
+							channels, framesize, samplerate, false);						
+					
+					sample.format = audioformat;
+				}
+					
+				if(format.equals("data"))
+				{
+					if(largeFormat)
+					{
+						sample.setData(new ModelByteBuffer(sampleFile, chunk.getFilePointer(), chunk.available()));
+					}
+					else
+					{
+					
+						byte[] buffer = new byte[chunk.available()];
+						//	chunk.read(buffer);
+						sample.setData(buffer);
+					
+						int read = 0;
+						int avail = chunk.available();
+						while(read != avail)
+						{
+							if(avail - read > 65536)
+							{
+								chunk.read(buffer, read, 65536);
+								read += 65536;
+							}
+							else
+							{
+								chunk.read(buffer, read, avail - read);
+								read = avail;
+							}
+						
+						}	
+					}
+				}
+
+				if(format.equals("wsmp"))
+				{
+					sample.sampleoptions = new DLSSampleOptions();
+					readWsmpChunk(sample.sampleoptions, chunk);
+				}
+			}
+		}				
+		
+		samples.add(sample);
+				
+	}
+	
+	private void readWaveInfoChunk(DLSSample dlssample, RIFFReader riff) throws IOException {
+		dlssample.info.name = null;
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			String format = chunk.getFormat();				
+			if(format.equals("INAM"))
+				dlssample.info.name = chunk.readString(chunk.available());						
+			else if(format.equals("ICRD"))
+				dlssample.info.creationDate = chunk.readString(chunk.available());
+			else if(format.equals("IENG"))
+				dlssample.info.engineers = chunk.readString(chunk.available());
+			else if(format.equals("IPRD"))
+				dlssample.info.product = chunk.readString(chunk.available());
+			else if(format.equals("ICOP"))
+				dlssample.info.copyright = chunk.readString(chunk.available());
+			else if(format.equals("ICMT"))
+				dlssample.info.comments = chunk.readString(chunk.available());
+			else if(format.equals("ISFT"))
+				dlssample.info.tools = chunk.readString(chunk.available());
+			else if(format.equals("IARL"))
+				dlssample.info.archival_location = chunk.readString(chunk.available());
+			else if(format.equals("IART"))
+				dlssample.info.artist = chunk.readString(chunk.available());
+			else if(format.equals("ICMS"))
+				dlssample.info.commissioned = chunk.readString(chunk.available());
+			else if(format.equals("IGNR"))
+				dlssample.info.genre = chunk.readString(chunk.available());
+			else if(format.equals("IKEY"))
+				dlssample.info.keywords = chunk.readString(chunk.available());
+			else if(format.equals("IMED"))
+				dlssample.info.medium = chunk.readString(chunk.available());
+			else if(format.equals("ISBJ"))
+				dlssample.info.subject = chunk.readString(chunk.available());
+			else if(format.equals("ISRC"))
+				dlssample.info.source = chunk.readString(chunk.available());
+			else if(format.equals("ISRF"))
+				dlssample.info.source_form = chunk.readString(chunk.available());
+			else if(format.equals("ITCH"))
+				dlssample.info.technician = chunk.readString(chunk.available());						
+		}
+	}
+	
+	public void save(String name) throws IOException
+	{
+		writeSoundbank(new RIFFWriter(name, "DLS "));
+	}
+	
+	public void save(File file) throws IOException
+	{
+		writeSoundbank(new RIFFWriter(file, "DLS "));
+	}	
+	
+	public void save(OutputStream out) throws IOException
+	{
+		writeSoundbank(new RIFFWriter(out, "DLS "));
+	}	
+	
+	private void writeSoundbank(RIFFWriter writer) throws IOException
+	{		
+		RIFFWriter colh_chunk = writer.writeChunk("colh");
+		colh_chunk.writeUnsignedInt(instruments.size());	
+		
+		if(major != -1 && minor != -1)
+		{
+			RIFFWriter vers_chunk = writer.writeChunk("vers");
+			vers_chunk.writeUnsignedInt(major);
+			vers_chunk.writeUnsignedInt(minor);			
+		}
+		
+		writeInstruments(writer.writeList("lins"));
+				
+		RIFFWriter ptbl = writer.writeChunk("ptbl");
+		ptbl.writeUnsignedInt(8);
+		ptbl.writeUnsignedInt(samples.size());
+		long ptbl_offset = writer.getFilePointer();
+		for (int i = 0; i < samples.size(); i++) 
+			ptbl.writeUnsignedInt(0);
+		
+		RIFFWriter wvpl = writer.writeList("wvpl");
+		long off = wvpl.getFilePointer();
+		List<Long> offsettable = new ArrayList<Long>(); 
+		for (DLSSample sample : samples) 
+		{
+			offsettable.add(new Long(wvpl.getFilePointer() - off));
+			writeSample(wvpl.writeList("wave"), sample);
+		}
+		
+		// small cheat, we are going to rewrite data back in wvpl
+		long bak = writer.getFilePointer();
+		writer.seek(ptbl_offset);
+		writer.setWriteOverride(true);
+		for(Long offset : offsettable)
+			writer.writeUnsignedInt(offset.longValue());
+		writer.setWriteOverride(false);
+		writer.seek(bak);
+		
+		writeInfo(writer.writeList("INFO"), info);
+		
+		writer.close();
+	}
+	
+	private void writeSample(RIFFWriter writer, DLSSample sample) throws IOException
+	{
+
+		AudioFormat audioformat = sample.getFormat();
+
+	    Encoding encoding = audioformat.getEncoding();
+	    float sampleRate = audioformat.getSampleRate();
+	    int sampleSizeInBits = audioformat.getSampleSizeInBits();
+	    int channels = audioformat.getChannels();
+	    int frameSize = audioformat.getFrameSize();
+	    float frameRate = audioformat.getFrameRate();
+	    boolean bigEndian = audioformat.isBigEndian();
+	    
+	    boolean convert_needed = false;
+		
+		if(audioformat.getSampleSizeInBits() == 8)
+		{
+			if(!encoding.equals(Encoding.PCM_UNSIGNED))
+			{
+				encoding = Encoding.PCM_UNSIGNED;
+				convert_needed = true;
+			}
+		}
+		else
+		{
+			if(!encoding.equals(Encoding.PCM_SIGNED))
+			{
+				encoding = Encoding.PCM_SIGNED;
+				convert_needed = true;
+			}			
+			if(bigEndian)
+			{
+				bigEndian = false;
+				convert_needed = true;
+			}					
+		}
+		
+		if(convert_needed)
+		{
+			audioformat = new AudioFormat(encoding, sampleRate, 
+					sampleSizeInBits, channels, frameSize, frameRate, bigEndian);
+		}
+		
+		// fmt		
+		RIFFWriter fmt_chunk = writer.writeChunk("fmt ");
+		int sampleformat = 0;
+		if(audioformat.getEncoding().equals(Encoding.PCM_UNSIGNED)) sampleformat = 1;
+		if(audioformat.getEncoding().equals(Encoding.PCM_SIGNED)) sampleformat = 1;
+		if(audioformat.getEncoding().equals(AudioFloatConverter.PCM_FLOAT)) sampleformat = 3;
+		fmt_chunk.writeUnsignedShort(sampleformat);		
+		fmt_chunk.writeUnsignedShort(audioformat.getChannels());
+		fmt_chunk.writeUnsignedInt((long)audioformat.getSampleRate());
+		long srate = (long)audioformat.getSampleRate();
+		srate *= audioformat.getChannels();
+		srate *= audioformat.getSampleSizeInBits() / 8;
+		//fmt_chunk.writeUnsignedInt((long)audioformat.getFrameRate());
+		fmt_chunk.writeUnsignedInt(srate);
+		fmt_chunk.writeUnsignedShort(audioformat.getFrameSize());
+		fmt_chunk.writeUnsignedShort(audioformat.getSampleSizeInBits());
+		fmt_chunk.write(0);
+		fmt_chunk.write(0);
+
+		writeSampleOptions(writer.writeChunk("wsmp"), sample.sampleoptions);
+		
+		if(convert_needed)
+		{
+			RIFFWriter data_chunk = writer.writeChunk("data");
+			AudioInputStream stream = AudioSystem.getAudioInputStream(audioformat, (AudioInputStream)sample.getData());
+			byte[] buff = new byte[1024];
+			int ret;
+			while( (ret = stream.read(buff)) != -1)
+			{
+				data_chunk.write(buff, 0, ret);
+			}
+		}
+		else
+		{
+		
+			RIFFWriter data_chunk = writer.writeChunk("data");
+			ModelByteBuffer databuff = sample.getDataBuffer();
+			databuff.writeTo(data_chunk);
+			/*
+			data_chunk.write(databuff.array(),
+				databuff.arrayOffset(),
+				databuff.capacity());
+				*/
+		
+		}
+				
+		writeInfo(writer.writeList("INFO"), sample.info);
+	}
+	
+	private void writeInstruments(RIFFWriter writer) throws IOException
+	{
+		for(DLSInstrument instrument : instruments)
+		{
+			writeInstrument(writer.writeList("ins "), instrument);
+		}
+	}
+	
+	private void writeInstrument(RIFFWriter writer, DLSInstrument instrument) throws IOException
+	{		
+
+		int art1_count = 0;
+		int art2_count = 0;
+		for(DLSModulator modulator : instrument.getModulators())
+		{
+			if(modulator.version == 1) art1_count++;
+			if(modulator.version == 2) art2_count++;
+		}
+		for(DLSRegion region : instrument.regions)
+		for(DLSModulator modulator : region.getModulators())
+		{
+			if(modulator.version == 1) art1_count++;
+			if(modulator.version == 2) art2_count++;
+		}
+		
+		int version = 1;
+		if(art2_count > 0) version = 2;
+		
+		RIFFWriter insh_chunk = writer.writeChunk("insh");		
+		insh_chunk.writeUnsignedInt(instrument.getRegions().size());		
+		insh_chunk.writeUnsignedInt(instrument.bank + 
+				(instrument.druminstrument?2147483648L:0));
+		insh_chunk.writeUnsignedInt(instrument.preset);
+		
+		RIFFWriter lrgn = writer.writeList("lrgn");
+		for(DLSRegion region : instrument.regions)
+			writeRegion(lrgn, region, version);		
+
+		writeArticulators(writer, instrument.getModulators());
+
+		writeInfo(writer.writeList("INFO"), instrument.info);
+		
+	}
+	
+	private void writeArticulators(RIFFWriter writer, List<DLSModulator> modulators) throws IOException
+	{
+		int art1_count = 0;
+		int art2_count = 0;
+		for(DLSModulator modulator : modulators)
+		{
+			if(modulator.version == 1) art1_count++;
+			if(modulator.version == 2) art2_count++;
+		}	
+		if(art1_count > 0)
+		{
+			RIFFWriter lar1 = writer.writeList("lart");
+			RIFFWriter art1 = lar1.writeChunk("art1");						
+			art1.writeUnsignedInt(8);
+			art1.writeUnsignedInt(art1_count);			
+			for(DLSModulator modulator : modulators)
+			if(modulator.version == 1)
+			{
+				
+				art1.writeUnsignedShort(modulator.source);
+				art1.writeUnsignedShort(modulator.control);
+				art1.writeUnsignedShort(modulator.destination);
+				art1.writeUnsignedShort(modulator.transform);
+				art1.writeInt(modulator.scale);					
+			}						
+		}		
+		if(art2_count > 0)
+		{
+			RIFFWriter lar2 = writer.writeList("lar2");
+			RIFFWriter art2 = lar2.writeChunk("art2");
+			art2.writeUnsignedInt(8);
+			art2.writeUnsignedInt(art2_count);			
+			for(DLSModulator modulator : modulators)
+			if(modulator.version == 2)
+			{
+				
+				art2.writeUnsignedShort(modulator.source);
+				art2.writeUnsignedShort(modulator.control);
+				art2.writeUnsignedShort(modulator.destination);
+				art2.writeUnsignedShort(modulator.transform);
+				art2.writeInt(modulator.scale);					
+			}									
+		}				
+	}
+
+	private void writeRegion(RIFFWriter writer, DLSRegion region, int version) throws IOException
+	{
+
+		RIFFWriter rgns = null;
+		if(version == 1)
+			rgns = writer.writeList("rgn ");
+		if(version == 2)
+			rgns = writer.writeList("rgn2");		
+		if(rgns == null)
+			return;
+		
+		RIFFWriter rgnh = rgns.writeChunk("rgnh");
+		rgnh.writeUnsignedShort(region.keyfrom);
+		rgnh.writeUnsignedShort(region.keyto);
+		rgnh.writeUnsignedShort(region.velfrom);
+		rgnh.writeUnsignedShort(region.velto);
+		rgnh.writeUnsignedShort(region.options);
+		rgnh.writeUnsignedShort(region.exclusiveClass);
+		
+		if(region.sampleoptions != null)
+			writeSampleOptions(rgns.writeChunk("wsmp"), region.sampleoptions);
+		
+		if(region.sample != null)
+		if(samples.indexOf(region.sample) != -1)
+		{
+			RIFFWriter wlnk = rgns.writeChunk("wlnk");
+			wlnk.writeUnsignedShort(region.fusoptions);
+			wlnk.writeUnsignedShort(region.phasegroup);
+			wlnk.writeUnsignedInt(region.channel);		
+			wlnk.writeUnsignedInt(samples.indexOf(region.sample));
+		}		
+		writeArticulators(rgns, region.getModulators());
+		rgns.close();
+	}
+	
+	private void writeSampleOptions(RIFFWriter wsmp, DLSSampleOptions sampleoptions) throws IOException
+	{
+		wsmp.writeUnsignedInt(20);		
+		wsmp.writeUnsignedShort(sampleoptions.unitynote);
+		wsmp.writeShort(sampleoptions.finetune);
+		wsmp.writeInt(sampleoptions.attenuation);
+		wsmp.writeUnsignedInt(sampleoptions.options);
+		wsmp.writeInt(sampleoptions.loops.size());			
+		
+		for(DLSSampleLoop loop : sampleoptions.loops)
+		{
+			wsmp.writeUnsignedInt(16);
+			wsmp.writeUnsignedInt(loop.type);
+			wsmp.writeUnsignedInt(loop.start);
+			wsmp.writeUnsignedInt(loop.length);
+		}			
+	}
+	
+	private void writeInfoStringChunk(RIFFWriter writer, String name, String value) throws IOException
+	{
+		if(value == null) return;
+		RIFFWriter chunk = writer.writeChunk(name);
+		chunk.writeString(value);
+		int len = value.getBytes("ascii").length;
+		chunk.write(0);
+		len++;
+		if(len % 2 != 0) chunk.write(0);
+	}
+	
+	private void writeInfo(RIFFWriter writer, DLSInfo info) throws IOException
+	{
+		writeInfoStringChunk(writer, "INAM", info.name);						
+		writeInfoStringChunk(writer, "ICRD", info.creationDate);
+		writeInfoStringChunk(writer, "IENG", info.engineers);
+		writeInfoStringChunk(writer, "IPRD", info.product);
+		writeInfoStringChunk(writer, "ICOP", info.copyright);
+		writeInfoStringChunk(writer, "ICMT", info.comments);
+		writeInfoStringChunk(writer, "ISFT", info.tools);
+		writeInfoStringChunk(writer, "IARL", info.archival_location);
+		writeInfoStringChunk(writer, "IART", info.artist);
+		writeInfoStringChunk(writer, "ICMS", info.commissioned);
+		writeInfoStringChunk(writer, "IGNR", info.genre);
+		writeInfoStringChunk(writer, "IKEY", info.keywords);
+		writeInfoStringChunk(writer, "IMED", info.medium);
+		writeInfoStringChunk(writer, "ISBJ", info.subject);
+		writeInfoStringChunk(writer, "ISRC", info.source);
+		writeInfoStringChunk(writer, "ISRF", info.source_form);
+		writeInfoStringChunk(writer, "ITCH", info.technician);		
+	}
+	
+	public DLSInfo getInfo() {
+		return info;
+	}
+	
+	public String getName() {
+		return info.name;
+	}
+
+	public String getVersion() {
+		return major + "." + minor;
+	}
+
+	public String getVendor() {
+		return info.engineers;
+	}
+
+	public String getDescription() {
+		return info.comments;
+	}
+	
+	public void setName(String s) {
+		info.name = s;
+	}
+
+	public void setVendor(String s) {
+		info.engineers = s;
+	}
+
+	public void setDescription(String s) {
+		info.comments = s;
+	}	
+	
+	public SoundbankResource[] getResources() {
+		SoundbankResource[] resources = new SoundbankResource[samples.size()];
+		int j = 0;
+		for (int i = 0; i < samples.size(); i++) 
+			resources[j++] = samples.get(i);		
+		return resources;
+	}
+
+	public DLSInstrument[] getInstruments() {
+		DLSInstrument[] inslist_array = instruments.toArray(new DLSInstrument[instruments.size()]);
+		Arrays.sort(inslist_array, new ModelInstrumentComparator());
+		return inslist_array;
+	}
+	
+	public DLSSample[] getSamples() {
+		return samples.toArray(new DLSSample[samples.size()]);
+	}
+
+	public Instrument getInstrument(Patch patch) {
+		int program = patch.getProgram();
+		int bank = patch.getBank();
+		boolean percussion = false;
+		if (patch instanceof ModelPatch)
+			percussion = ((ModelPatch) patch).isPercussion();
+		for (Instrument instrument : instruments) {
+			Patch patch2 = instrument.getPatch();
+			int program2 = patch2.getProgram();
+			int bank2 = patch2.getBank();
+			if (program == program2 && bank == bank2) {
+				boolean percussion2 = false;
+				if (patch2 instanceof ModelPatch)
+					percussion2 = ((ModelPatch) patch2).isPercussion();
+				if (percussion == percussion2)
+					return instrument;
+			}
+		}
+		return null;
+	}
+
+	public void addResource(SoundbankResource resource)
+	{
+		if(resource instanceof DLSInstrument) instruments.add((DLSInstrument)resource);
+		if(resource instanceof DLSSample) samples.add((DLSSample)resource);
+	}
+	
+	public void removeResource(SoundbankResource resource)
+	{
+		if(resource instanceof DLSInstrument) instruments.remove((DLSInstrument)resource);
+		if(resource instanceof DLSSample) samples.remove((DLSSample)resource);
+	}		
+	
+	public void addInstrument(DLSInstrument resource)
+	{
+		instruments.add(resource);
+	}
+	
+	public void removeInstrument(DLSInstrument resource)
+	{
+		instruments.remove(resource);
+	}
+
+	public long getMajor() {
+		return major;
+	}
+
+	public void setMajor(long major) {
+		this.major = major;
+	}
+
+	public long getMinor() {
+		return minor;
+	}
+
+	public void setMinor(long minor) {
+		this.minor = minor;
+	}		
+	
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbankReader.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,82 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.spi.SoundbankReader;
+
+/**
+ * This class is used to connect the DLSSoundBank class
+ * to the SoundbankReader SPI interface.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class DLSSoundbankReader extends SoundbankReader {
+
+	public Soundbank getSoundbank(URL url) throws InvalidMidiDataException, IOException {
+		try
+		{
+			return new DLSSoundbank(url);
+		}
+		catch(RIFFInvalidFormatException e)
+		{
+			return null;
+		}		
+	}
+
+	public Soundbank getSoundbank(InputStream stream) throws InvalidMidiDataException, IOException {
+		try
+		{
+			stream.mark(512);
+			return new DLSSoundbank(stream);
+		}
+		catch(RIFFInvalidFormatException e)
+		{
+			stream.reset();
+			return null;
+		}
+	}
+	
+	public Soundbank getSoundbank(File file) throws InvalidMidiDataException, IOException {
+		if(!file.getPath().toLowerCase().endsWith(".dls")) return null;		
+		try
+		{
+			return new DLSSoundbank(file);
+		}
+		catch(RIFFInvalidFormatException e)
+		{
+			return null;
+		}			
+	}	
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/EmergencySoundbank.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,2795 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.util.Random;
+
+import javax.sound.midi.Patch;
+import javax.sound.sampled.AudioFormat;
+
+import com.sun.media.sound.ModelPatch;
+import com.sun.media.sound.SF2GlobalRegion;
+import com.sun.media.sound.SF2Instrument;
+import com.sun.media.sound.SF2InstrumentRegion;
+import com.sun.media.sound.SF2Layer;
+import com.sun.media.sound.SF2LayerRegion;
+import com.sun.media.sound.SF2Region;
+import com.sun.media.sound.SF2Sample;
+import com.sun.media.sound.SF2Soundbank;
+
+/**
+ * Emergency Soundbank generator.
+ * Used when no other default soundbank can be found.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class EmergencySoundbank {
+	
+	public static String[] general_midi_instruments = { 
+	"Acoustic Grand Piano",
+	"Bright Acoustic Piano",
+	"Electric Grand Piano",
+	"Honky-tonk Piano",
+	"Electric Piano 1",
+	"Electric Piano 2",
+	"Harpsichord",
+	"Clavi",
+	"Celesta",
+	"Glockenspiel",
+	"Music Box",
+	"Vibraphone",
+	"Marimba",
+	"Xylophone",
+	"Tubular Bells",
+	"Dulcimer",
+	"Drawbar Organ",
+	"Percussive Organ",
+	"Rock Organ",
+	"Church Organ",
+	"Reed Organ",
+	"Accordion",
+	"Harmonica",
+	"Tango Accordion",
+	"Acoustic Guitar (nylon)",
+	"Acoustic Guitar (steel)",
+	"Electric Guitar (jazz)",
+	"Electric Guitar (clean)",
+	"Electric Guitar (muted)",
+	"Overdriven Guitar",
+	"Distortion Guitar",
+	"Guitar harmonics",
+	"Acoustic Bass",
+	"Electric Bass (finger)",
+	"Electric Bass (pick)",
+	"Fretless Bass",
+	"Slap Bass 1",
+	"Slap Bass 2",
+	"Synth Bass 1",
+	"Synth Bass 2",
+	"Violin",
+	"Viola",
+	"Cello",
+	"Contrabass",
+	"Tremolo Strings",
+	"Pizzicato Strings",
+	"Orchestral Harp",
+	"Timpani",
+	"String Ensemble 1",
+	"String Ensemble 2",
+	"SynthStrings 1",
+	"SynthStrings 2",
+	"Choir Aahs",
+	"Voice Oohs",
+	"Synth Voice",
+	"Orchestra Hit",
+	"Trumpet",
+	"Trombone",
+	"Tuba",
+	"Muted Trumpet",
+	"French Horn",
+	"Brass Section",
+	"SynthBrass 1",
+	"SynthBrass 2",
+	"Soprano Sax",
+	"Alto Sax",
+	"Tenor Sax",
+	"Baritone Sax",
+	"Oboe",
+	"English Horn",
+	"Bassoon",
+	"Clarinet",
+	"Piccolo",
+	"Flute",
+	"Recorder",
+	"Pan Flute",
+	"Blown Bottle",
+	"Shakuhachi",
+	"Whistle",
+	"Ocarina",
+	"Lead 1 (square)",
+	"Lead 2 (sawtooth)",
+	"Lead 3 (calliope)",
+	"Lead 4 (chiff)",
+	"Lead 5 (charang)",
+	"Lead 6 (voice)",
+	"Lead 7 (fifths)",
+	"Lead 8 (bass + lead)",
+	"Pad 1 (new age)",
+	"Pad 2 (warm)",
+	"Pad 3 (polysynth)",
+	"Pad 4 (choir)",
+	"Pad 5 (bowed)",
+	"Pad 6 (metallic)",
+	"Pad 7 (halo)",
+	"Pad 8 (sweep)",
+	"FX 1 (rain)",
+	"FX 2 (soundtrack)",
+	"FX 3 (crystal)",
+	"FX 4 (atmosphere)",
+	"FX 5 (brightness)",
+	"FX 6 (goblins)",
+	"FX 7 (echoes)",
+	"FX 8 (sci-fi)",
+	"Sitar",
+	"Banjo",
+	"Shamisen",
+	"Koto",
+	"Kalimba",
+	"Bag pipe",
+	"Fiddle",
+	"Shanai",
+	"Tinkle Bell",
+	"Agogo",
+	"Steel Drums",
+	"Woodblock",
+	"Taiko Drum",
+	"Melodic Tom",
+	"Synth Drum",
+	"Reverse Cymbal",
+	"Guitar Fret Noise",
+	"Breath Noise",
+	"Seashore",
+	"Bird Tweet",
+	"Telephone Ring",
+	"Helicopter",
+	"Applause",
+	"Gunshot"};
+
+	public static SF2Soundbank createSoundbank() throws Exception
+	{
+		SF2Soundbank sf2 = new SF2Soundbank();
+		sf2.setName("Emergency GM sound set");
+		sf2.setVendor("Generated");
+		sf2.setDescription("Emergency generated soundbank");
+		
+		/*
+		 *  percussion instruments
+		 */
+		
+		SF2Layer bass_drum = new_bass_drum(sf2);
+		SF2Layer snare_drum = new_snare_drum(sf2);
+		SF2Layer tom = new_tom(sf2);
+		SF2Layer open_hihat = new_open_hihat(sf2);
+		SF2Layer closed_hihat = new_closed_hihat(sf2);
+		SF2Layer crash_cymbal = new_crash_cymbal(sf2);
+		SF2Layer side_stick = new_side_stick(sf2);
+		
+		SF2Layer[] drums = new SF2Layer[128];
+		drums[35] = bass_drum;
+		drums[36] = bass_drum;
+		drums[38] = snare_drum;
+		drums[40] = snare_drum;
+		drums[41] = tom;
+		drums[43] = tom;
+		drums[45] = tom;
+		drums[47] = tom;
+		drums[48] = tom;
+		drums[50] = tom;
+		drums[42] = closed_hihat;
+		drums[44] = closed_hihat;
+		drums[46] = open_hihat;	
+		drums[49] = crash_cymbal;
+		drums[51] = crash_cymbal;
+		drums[52] = crash_cymbal;
+		drums[55] = crash_cymbal;
+		drums[57] = crash_cymbal;
+		drums[59] = crash_cymbal;
+		
+		// Use side_stick for missing drums:
+		drums[37] = side_stick;
+		drums[39] = side_stick;
+		drums[53] = side_stick;
+		drums[54] = side_stick;
+		drums[56] = side_stick;
+		drums[58] = side_stick;
+		drums[69] = side_stick;
+		drums[70] = side_stick;
+		drums[75] = side_stick;
+		drums[60] = side_stick;
+		drums[61] = side_stick;
+		drums[62] = side_stick;
+		drums[63] = side_stick;
+		drums[64] = side_stick;
+		drums[65] = side_stick;
+		drums[66] = side_stick;
+		drums[67] = side_stick;
+		drums[68] = side_stick;
+		drums[71] = side_stick;
+		drums[72] = side_stick;
+		drums[73] = side_stick;
+		drums[74] = side_stick;
+		drums[76] = side_stick;
+		drums[77] = side_stick;
+		drums[78] = side_stick;
+		drums[79] = side_stick;
+		drums[80] = side_stick;
+		drums[81] = side_stick;
+		
+		
+		SF2Instrument drum_instrument = new SF2Instrument(sf2);
+		drum_instrument.setName("Standard Kit");
+		drum_instrument.setPatch(new ModelPatch(0,0,true));
+		sf2.addInstrument(drum_instrument);
+		for (int i = 0; i < drums.length; i++) {
+			if(drums[i] != null)
+			{
+				SF2InstrumentRegion region = new SF2InstrumentRegion();
+				region.setLayer(drums[i]);
+				region.putBytes(SF2InstrumentRegion.GENERATOR_KEYRANGE, new byte[] {(byte)i, (byte)i});
+				drum_instrument.getRegions().add(region);
+			}
+		}
+		
+		
+		/*
+		 *  melodic instruments
+		 */
+		
+		SF2Layer gpiano = new_gpiano(sf2);
+		SF2Layer gpiano2 = new_gpiano2(sf2);
+		SF2Layer gpiano_hammer = new_piano_hammer(sf2);
+		SF2Layer piano1 = new_piano1(sf2);
+		SF2Layer epiano1 = new_epiano1(sf2);
+		SF2Layer epiano2 = new_epiano2(sf2);		
+		
+		SF2Layer guitar = new_guitar1(sf2);
+		SF2Layer guitar_pick = new_guitar_pick(sf2);
+		SF2Layer guitar_dist = new_guitar_dist(sf2);
+		SF2Layer bass1 = new_bass1(sf2);
+		SF2Layer bass2 = new_bass2(sf2);
+		SF2Layer synthbass = new_synthbass(sf2);
+		SF2Layer string2 = new_string2(sf2);
+		SF2Layer orchhit = new_orchhit(sf2);
+		SF2Layer choir = new_choir(sf2);
+		SF2Layer solostring = new_solostring(sf2);
+		SF2Layer organ = new_organ(sf2);
+		SF2Layer ch_organ = new_ch_organ(sf2);		
+		SF2Layer bell = new_bell(sf2);		
+		SF2Layer flute = new_flute(sf2);
+		
+		SF2Layer timpani = new_timpani(sf2);
+		SF2Layer melodic_toms = new_melodic_toms(sf2);
+		SF2Layer trumpet = new_trumpet(sf2);
+		SF2Layer trombone = new_trombone(sf2);
+		SF2Layer brass_section = new_brass_section(sf2);
+		SF2Layer horn = new_horn(sf2);
+		SF2Layer sax = new_sax(sf2);
+		SF2Layer oboe = new_oboe(sf2);
+		SF2Layer bassoon = new_bassoon(sf2);
+		SF2Layer clarinet = new_clarinet(sf2);
+		SF2Layer reverse_cymbal = new_reverse_cymbal(sf2);
+		
+		SF2Layer defaultsound = piano1;
+				
+	    newInstrument(sf2, "Piano", new Patch(0, 0), gpiano, gpiano_hammer);		
+		newInstrument(sf2, "Piano", new Patch(0, 1), gpiano2, gpiano_hammer);		
+		newInstrument(sf2, "Piano", new Patch(0, 2), piano1);
+		{
+			SF2Instrument ins = newInstrument(sf2, "Honky-tonk Piano", new Patch(0, 3), piano1, piano1);
+			SF2InstrumentRegion region = ins.getRegions().get(0);
+			region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 80);
+			region.putInteger(SF2Region.GENERATOR_FINETUNE, 30);
+			region = ins.getRegions().get(1);
+			region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 30);
+		}
+		newInstrument(sf2, "Rhodes", new Patch(0, 4), epiano2);
+		newInstrument(sf2, "Rhodes", new Patch(0, 5), epiano2);
+		newInstrument(sf2, "Clavinet", new Patch(0, 6), epiano1);
+		newInstrument(sf2, "Clavinet", new Patch(0, 7), epiano1);
+		newInstrument(sf2, "Rhodes", new Patch(0, 8), epiano2);
+		newInstrument(sf2, "Bell", new Patch(0, 9), bell);
+		newInstrument(sf2, "Bell", new Patch(0, 10), bell);
+		newInstrument(sf2, "Vibraphone", new Patch(0, 11), bell);
+		newInstrument(sf2, "Marimba", new Patch(0, 12), bell);
+		newInstrument(sf2, "Marimba", new Patch(0, 13), bell);
+		newInstrument(sf2, "Bell", new Patch(0, 14), bell);		
+		newInstrument(sf2, "Rock Organ", new Patch(0, 15), organ);
+		newInstrument(sf2, "Rock Organ", new Patch(0, 16), organ);
+		newInstrument(sf2, "Perc Organ", new Patch(0, 17), organ);
+		newInstrument(sf2, "Rock Organ", new Patch(0, 18), organ);
+		newInstrument(sf2, "Church Organ", new Patch(0, 19), ch_organ);
+		newInstrument(sf2, "Accordion", new Patch(0, 20), organ);
+		newInstrument(sf2, "Accordion", new Patch(0, 21), organ);
+		newInstrument(sf2, "Accordion", new Patch(0, 22), organ);
+		newInstrument(sf2, "Accordion", new Patch(0, 23), organ);
+		newInstrument(sf2, "Guitar", new Patch(0, 24), guitar, guitar_pick);
+		newInstrument(sf2, "Guitar", new Patch(0, 25), guitar, guitar_pick);
+		newInstrument(sf2, "Guitar", new Patch(0, 26), guitar, guitar_pick);
+		newInstrument(sf2, "Guitar", new Patch(0, 27), guitar, guitar_pick);
+		newInstrument(sf2, "Guitar", new Patch(0, 28), guitar, guitar_pick);
+		newInstrument(sf2, "Distorted Guitar", new Patch(0, 29), guitar_dist);
+		newInstrument(sf2, "Distorted Guitar", new Patch(0, 30), guitar_dist);
+		newInstrument(sf2, "Guitar", new Patch(0, 31), guitar, guitar_pick);
+		newInstrument(sf2, "Finger Bass", new Patch(0, 32), bass1);
+		newInstrument(sf2, "Finger Bass", new Patch(0, 33), bass1);
+		newInstrument(sf2, "Finger Bass", new Patch(0, 34), bass1);
+		newInstrument(sf2, "Frettless Bass", new Patch(0, 35), bass2);
+		newInstrument(sf2, "Frettless Bass", new Patch(0, 36), bass2);
+		newInstrument(sf2, "Frettless Bass", new Patch(0, 37), bass2);
+		newInstrument(sf2, "Synth Bass1", new Patch(0, 38), synthbass);
+		newInstrument(sf2, "Synth Bass2", new Patch(0, 39), synthbass);
+		newInstrument(sf2, "Solo String", new Patch(0, 40), string2, solostring);
+		newInstrument(sf2, "Solo String", new Patch(0, 41), string2, solostring);
+		newInstrument(sf2, "Solo String", new Patch(0, 42), string2, solostring);
+		newInstrument(sf2, "Solo String", new Patch(0, 43), string2, solostring);
+		newInstrument(sf2, "Solo String", new Patch(0, 44), string2, solostring);
+		newInstrument(sf2, "Def", new Patch(0, 45), defaultsound);
+		newInstrument(sf2, "Harp", new Patch(0, 46), bell);
+		newInstrument(sf2, "Timpani", new Patch(0, 47), timpani);
+		newInstrument(sf2, "Strings", new Patch(0, 48), string2);
+		SF2Instrument slow_strings = newInstrument(sf2, "Slow Strings", new Patch(0, 49), string2);
+		SF2InstrumentRegion region = slow_strings.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, 2500);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 2000);
+		newInstrument(sf2, "Synth Strings", new Patch(0, 50), string2);
+		newInstrument(sf2, "Synth Strings", new Patch(0, 51), string2);
+
+		
+		newInstrument(sf2, "Choir", new Patch(0, 52), choir);
+		newInstrument(sf2, "Choir", new Patch(0, 53), choir);
+		newInstrument(sf2, "Choir", new Patch(0, 54), choir);
+		{
+			SF2Instrument ins = newInstrument(sf2, "Orch Hit", new Patch(0, 55), orchhit,orchhit,timpani);
+			region = ins.getRegions().get(0);
+			region.putInteger(SF2Region.GENERATOR_COARSETUNE, -12);
+			region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);
+		}
+		newInstrument(sf2, "Trumpet", new Patch(0, 56), trumpet);
+		newInstrument(sf2, "Trombone", new Patch(0, 57), trombone);
+		newInstrument(sf2, "Trombone", new Patch(0, 58), trombone);
+		newInstrument(sf2, "Trumpet", new Patch(0, 59), trumpet);
+		newInstrument(sf2, "Horn", new Patch(0, 60), horn);
+		newInstrument(sf2, "Brass Section", new Patch(0, 61), brass_section);
+		newInstrument(sf2, "Brass Section", new Patch(0, 62), brass_section);
+		newInstrument(sf2, "Brass Section", new Patch(0, 63), brass_section);
+		newInstrument(sf2, "Sax", new Patch(0, 64), sax);
+		newInstrument(sf2, "Sax", new Patch(0, 65), sax);
+		newInstrument(sf2, "Sax", new Patch(0, 66), sax);
+		newInstrument(sf2, "Sax", new Patch(0, 67), sax);
+		newInstrument(sf2, "Oboe", new Patch(0, 68), oboe);
+		newInstrument(sf2, "Horn", new Patch(0, 69), horn);
+		newInstrument(sf2, "Bassoon", new Patch(0, 70), bassoon);
+		newInstrument(sf2, "Clarinet", new Patch(0, 71), clarinet);
+		newInstrument(sf2, "Flute", new Patch(0, 72), flute);
+		newInstrument(sf2, "Flute", new Patch(0, 73), flute);
+		newInstrument(sf2, "Flute", new Patch(0, 74), flute);
+		newInstrument(sf2, "Flute", new Patch(0, 75), flute);
+		newInstrument(sf2, "Flute", new Patch(0, 76), flute);
+		newInstrument(sf2, "Flute", new Patch(0, 77), flute);
+		newInstrument(sf2, "Flute", new Patch(0, 78), flute);
+		newInstrument(sf2, "Flute", new Patch(0, 79), flute);
+		newInstrument(sf2, "Organ", new Patch(0, 80), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 81), organ);
+		newInstrument(sf2, "Flute", new Patch(0, 82), flute);
+		newInstrument(sf2, "Organ", new Patch(0, 83), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 84), organ);
+		newInstrument(sf2, "Choir", new Patch(0, 85), choir);
+		newInstrument(sf2, "Organ", new Patch(0, 86), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 87), organ);
+		newInstrument(sf2, "Synth Strings", new Patch(0, 88), string2);
+		newInstrument(sf2, "Organ", new Patch(0, 89), organ);
+		newInstrument(sf2, "Def", new Patch(0, 90), defaultsound);
+		newInstrument(sf2, "Choir", new Patch(0, 91), choir);		
+		newInstrument(sf2, "Organ", new Patch(0, 92), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 93), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 94), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 95), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 96), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 97), organ);
+		newInstrument(sf2, "Bell", new Patch(0, 98), bell);
+		newInstrument(sf2, "Organ", new Patch(0, 99), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 100), organ);
+		newInstrument(sf2, "Organ", new Patch(0, 101), organ);
+		newInstrument(sf2, "Def", new Patch(0, 102), defaultsound);
+		newInstrument(sf2, "Synth Strings", new Patch(0, 103), string2);
+		newInstrument(sf2, "Def", new Patch(0, 104), defaultsound);
+		newInstrument(sf2, "Def", new Patch(0, 105), defaultsound);
+		newInstrument(sf2, "Def", new Patch(0, 106), defaultsound);
+		newInstrument(sf2, "Def", new Patch(0, 107), defaultsound);
+		newInstrument(sf2, "Marimba", new Patch(0, 108), bell);
+		newInstrument(sf2, "Sax", new Patch(0, 109), sax);		
+		newInstrument(sf2, "Solo String", new Patch(0, 110), string2, solostring);
+		newInstrument(sf2, "Oboe", new Patch(0, 111), oboe);
+		newInstrument(sf2, "Bell", new Patch(0, 112), bell);
+		newInstrument(sf2, "Melodic Toms", new Patch(0, 113), melodic_toms);
+		newInstrument(sf2, "Marimba", new Patch(0, 114), bell);
+		newInstrument(sf2, "Melodic Toms", new Patch(0, 115), melodic_toms);
+		newInstrument(sf2, "Melodic Toms", new Patch(0, 116), melodic_toms);
+		newInstrument(sf2, "Melodic Toms", new Patch(0, 117), melodic_toms);
+		newInstrument(sf2, "Reverse Cymbal", new Patch(0, 118), reverse_cymbal);
+		newInstrument(sf2, "Reverse Cymbal", new Patch(0, 119), reverse_cymbal);
+		newInstrument(sf2, "Guitar", new Patch(0, 120), guitar);
+		newInstrument(sf2, "Def", new Patch(0, 121), defaultsound);		
+		{
+			SF2Instrument ins = newInstrument(sf2, "Seashore/Reverse Cymbal", new Patch(0, 122), reverse_cymbal);
+			region = ins.getRegions().get(0);
+			region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);
+			region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 18500);
+			region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 4500);
+			region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, -4500);
+		}		
+		{
+			SF2Instrument ins = newInstrument(sf2, "Bird/Flute", new Patch(0, 123), flute);
+			region = ins.getRegions().get(0);
+			region.putInteger(SF2Region.GENERATOR_COARSETUNE, 24);
+			region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, -3000);
+			region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);
+		}		
+		newInstrument(sf2, "Def", new Patch(0, 124), side_stick);
+		{
+			SF2Instrument ins = newInstrument(sf2, "Seashore/Reverse Cymbal", new Patch(0, 125), reverse_cymbal);
+			region = ins.getRegions().get(0);
+			region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);
+			region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 18500);
+			region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 4500);
+			region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, -4500);
+		}				
+		newInstrument(sf2, "Applause/crash_cymbal", new Patch(0, 126), crash_cymbal);
+		newInstrument(sf2, "Gunshot/side_stick", new Patch(0, 127), side_stick);
+		
+		for(SF2Instrument instrument : sf2.getInstruments())
+		{
+			Patch patch = instrument.getPatch();
+			if(patch instanceof ModelPatch)
+			if(((ModelPatch)patch).isPercussion()) continue;
+			instrument.setName(general_midi_instruments[patch.getProgram()]);			
+		}
+		
+		return sf2;		
+		
+	}
+	
+	public static SF2Layer new_bell(SF2Soundbank sf2)
+	{
+		Random random = new Random(102030201);
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_w = 0.01;
+		double end_w   = 0.05;
+		double start_a = 0.2;
+		double end_a   = 0.00001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0); 
+		for (int i = 0; i < 40; i++) {			
+			double detune = 1 + (random.nextDouble()*2 - 1)*0.01;
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1)*detune, w, a);
+			a *= a_step;
+		}
+		SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base);
+		SF2Layer layer = newLayer(sf2, "EPiano", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 1200);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -9000);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000);
+		return layer;
+	}
+	
+	public static SF2Layer new_guitar1(SF2Soundbank sf2)
+	{
+
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_w = 0.01;
+		double end_w   = 0.01;
+		double start_a = 2;
+		double end_a   = 0.01;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0);
+		
+		double[] aa = new double[40];
+		for (int i = 0; i < 40; i++)
+		{
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] = 2;
+		aa[1] = 0.5;
+		aa[2] = 0.45;
+		aa[3] = 0.2;
+		aa[4] = 1;
+		aa[5] = 0.5;
+		aa[6] = 2;
+		aa[7] = 1;
+		aa[8] = 0.5;
+		aa[9] = 1;
+		aa[9] = 0.5;
+		aa[10] = 0.2;
+		aa[11] = 1;
+		aa[12] = 0.7;
+		aa[13] = 0.5;
+		aa[14] = 1;
+		
+		for (int i = 0; i < 40; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, aa[i]);			
+		}		
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Guitar", data, base);
+		SF2Layer layer = newLayer(sf2, "Guitar", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 2400);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);	
+		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -100);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -6000);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -20);		
+		return layer;
+	}	
+	
+	
+	public static SF2Layer new_guitar_dist(SF2Soundbank sf2)
+	{
+
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_w = 0.01;
+		double end_w   = 0.01;
+		double start_a = 2;
+		double end_a   = 0.01;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0);
+		
+		double[] aa = new double[40];
+		for (int i = 0; i < 40; i++)
+		{
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] = 5;
+		aa[1] = 2;
+		aa[2] = 0.45;
+		aa[3] = 0.2;
+		aa[4] = 1;
+		aa[5] = 0.5;
+		aa[6] = 2;
+		aa[7] = 1;
+		aa[8] = 0.5;
+		aa[9] = 1;
+		aa[9] = 0.5;
+		aa[10] = 0.2;
+		aa[11] = 1;
+		aa[12] = 0.7;
+		aa[13] = 0.5;
+		aa[14] = 1;
+		
+		for (int i = 0; i < 40; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, aa[i]);			
+		}		
+		
+		
+		
+		SF2Sample sample = newSimpleFFTSample_dist(sf2, "Distorted Guitar", data, base, 10000.0);
+		
+		
+		
+		SF2Layer layer = newLayer(sf2, "Distorted Guitar", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		//region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 2400);
+		//region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 200);	
+		
+		//region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -100);
+		//region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		//region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -1000);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 8000);
+		//region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -20);		
+		return layer;
+	}	
+	
+	
+	public static SF2Layer new_guitar_pick(SF2Soundbank sf2)
+	{
+
+		double datab[];
+				
+		// Make treble part
+		{
+			int m = 2;
+			int fftlen = 4096*m;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5));		
+			fft(data);	
+			// Remove all negative frequency
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;			
+			for (int i = 0; i < 2048*m; i++)
+				data[i] *= Math.exp(-Math.abs((i-23)/((double)m))*1.2)
+				         +Math.exp(-Math.abs((i-40)/((double)m))*0.9);
+			randomPhase(data, new Random(3049912));						
+			ifft(data);		
+			normalize(data, 0.8);		
+			data = realPart(data);	
+			double gain = 1.0;
+			for (int i = 0; i < data.length; i++) {
+				data[i] *= gain;
+				gain *= 0.9994;
+			}				
+			datab = data;	
+			
+			fadeUp(data, 80);
+		}
+			
+		SF2Sample sample = newSimpleDrumSample(sf2, "Guitar Noise", datab);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Guitar Noise");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();	
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);
+		//region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+//		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);
+/*
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 0);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINMODENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -11000);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 12000);
+		*/
+		
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}
+	
+	
+	public static SF2Layer new_gpiano(SF2Soundbank sf2)
+	{
+		//Random random = new Random(302030201);
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_a = 0.2;
+		double end_a   = 0.001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/15.0);
+	
+		double[] aa = new double[30];
+		for (int i = 0; i < 30; i++)
+		{
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] *= 2;
+		//aa[2] *= 0.1;
+		aa[4] *= 2;
+		
+		
+		aa[12] *= 0.9;
+		aa[13] *= 0.7;
+		for (int i = 14; i < 30; i++)
+		{
+			aa[i] *= 0.5;
+		}
+	
+		
+		for (int i = 0; i < 30; i++) {			
+			//double detune = 1 + (random.nextDouble()*2 - 1)*0.0001;
+			double w = 0.2;
+			double ai = aa[i];
+			if(i > 10)
+			{
+				w = 5;
+				ai *= 10;
+			}
+			int adjust = 0;
+			if(i > 5)
+			{
+				adjust = (i - 5)*7;
+			}
+			complexGaussianDist(data, base*(i+1)+adjust, w, ai);			
+		}
+				
+		SF2Sample sample = newSimpleFFTSample(sf2, "Grand Piano", data, base, 200);
+		SF2Layer layer = newLayer(sf2, "Grand Piano", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -7000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5500);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 18000);
+		return layer;
+	}
+	
+	public static SF2Layer new_gpiano2(SF2Soundbank sf2)
+	{
+		//Random random = new Random(302030201);
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_a = 0.2;
+		double end_a   = 0.001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/20.0);
+	
+		double[] aa = new double[30];
+		for (int i = 0; i < 30; i++)
+		{
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] *= 1;
+		//aa[2] *= 0.1;
+		aa[4] *= 2;
+		
+		
+		aa[12] *= 0.9;
+		aa[13] *= 0.7;
+		for (int i = 14; i < 30; i++)
+		{
+			aa[i] *= 0.5;
+		}
+	
+		
+		for (int i = 0; i < 30; i++) {			
+			//double detune = 1 + (random.nextDouble()*2 - 1)*0.0001;
+			double w = 0.2;
+			double ai = aa[i];
+			if(i > 10)
+			{
+				w = 5;
+				ai *= 10;
+			}
+			int adjust = 0;
+			if(i > 5)
+			{
+				adjust = (i - 5)*7;
+			}
+			complexGaussianDist(data, base*(i+1)+adjust, w, ai);			
+		}
+				
+		SF2Sample sample = newSimpleFFTSample(sf2, "Grand Piano", data, base, 200);
+		SF2Layer layer = newLayer(sf2, "Grand Piano", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -7000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5500);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 18000);
+		return layer;
+	}		
+	
+	
+	public static SF2Layer new_piano_hammer(SF2Soundbank sf2)
+	{
+
+		double datab[];
+				
+		// Make treble part
+		{
+			int m = 2;
+			int fftlen = 4096*m;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5));		
+			fft(data);	
+			// Remove all negative frequency
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;			
+			for (int i = 0; i < 2048*m; i++)
+				data[i] *= Math.exp(-Math.abs((i-37)/((double)m))*0.05);
+			randomPhase(data, new Random(3049912));						
+			ifft(data);		
+			normalize(data, 0.6);		
+			data = realPart(data);	
+			double gain = 1.0;
+			for (int i = 0; i < data.length; i++) {
+				data[i] *= gain;
+				gain *= 0.9997;
+			}				
+			datab = data;	
+			
+			fadeUp(data, 80);
+		}
+			
+		SF2Sample sample = newSimpleDrumSample(sf2, "Piano Hammer", datab);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Piano Hammer");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();	
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);
+		//region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+/*
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 0);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINMODENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -11000);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 12000);
+		*/
+		
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}
+		
+	
+
+	public static SF2Layer new_piano1(SF2Soundbank sf2)
+	{
+		//Random random = new Random(302030201);
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_a = 0.2;
+		double end_a   = 0.0001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0);
+	
+		double[] aa = new double[30];
+		for (int i = 0; i < 30; i++)
+		{
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] *= 5;
+		aa[2] *= 0.1;
+		aa[7] *= 5;
+	
+		
+		for (int i = 0; i < 30; i++) {			
+			//double detune = 1 + (random.nextDouble()*2 - 1)*0.0001;
+			double w = 0.2;
+			double ai = aa[i];
+			if(i > 12)
+			{
+				w = 5;
+				ai *= 10;
+			}
+			int adjust = 0;
+			if(i > 5)
+			{
+				adjust = (i - 5)*7;
+			}
+			complexGaussianDist(data, base*(i+1)+adjust, w, ai);			
+		}
+		
+		complexGaussianDist(data, base*(15.5), 1, 0.1);
+		complexGaussianDist(data, base*(17.5), 1, 0.01);
+				
+		SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base, 200);
+		SF2Layer layer = newLayer(sf2, "EPiano", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -1200);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5500);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000);
+		return layer;
+	}	
+
+	public static SF2Layer new_epiano1(SF2Soundbank sf2)
+	{
+		Random random = new Random(302030201);
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_w = 0.05;
+		double end_w   = 0.05;
+		double start_a = 0.2;
+		double end_a   = 0.0001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0); 
+		for (int i = 0; i < 40; i++) {			
+			double detune = 1 + (random.nextDouble()*2 - 1)*0.0001;
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1)*detune, w, a);
+			a *= a_step;
+		}
+		
+
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base);
+		SF2Layer layer = newLayer(sf2, "EPiano", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 1200);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -9000);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000);
+		return layer;
+	}
+	
+	
+
+	public static SF2Layer new_epiano2(SF2Soundbank sf2)
+	{
+		Random random = new Random(302030201);
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_w = 0.01;
+		double end_w   = 0.05;
+		double start_a = 0.2;
+		double end_a   = 0.00001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0); 
+		for (int i = 0; i < 40; i++) {			
+			double detune = 1 + (random.nextDouble()*2 - 1)*0.0001;
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1)*detune, w, a);
+			a *= a_step;
+		}		
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base);
+		SF2Layer layer = newLayer(sf2, "EPiano", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 8000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 2400);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -9000);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);		
+		return layer;
+	}
+	
+	public static SF2Layer new_bass1(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_w = 0.05;
+		double end_w   = 0.05;
+		double start_a = 0.2;
+		double end_a   = 0.02;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/25.0);
+		
+		double[] aa = new double[25];
+		for (int i = 0; i < 25; i++) {
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] *= 8;
+		aa[1] *= 4;
+		aa[3] *= 8;
+		aa[5] *= 8;
+		
+		for (int i = 0; i < 25; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, aa[i]);			
+		}
+		
+		
+
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Bass", data, base);
+		SF2Layer layer = newLayer(sf2, "Bass", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5000);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 11000);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);		
+		return layer;
+	}
+	
+	public static SF2Layer new_synthbass(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_w = 0.05;
+		double end_w   = 0.05;
+		double start_a = 0.2;
+		double end_a   = 0.02;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/25.0);
+		
+		double[] aa = new double[25];
+		for (int i = 0; i < 25; i++) {
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] *= 16;
+		aa[1] *= 4;
+		aa[3] *= 16;
+		aa[5] *= 8;
+		
+		for (int i = 0; i < 25; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, aa[i]);			
+		}
+		
+
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Bass", data, base);
+		SF2Layer layer = newLayer(sf2, "Bass", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -3000);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERQ, 100);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 8000);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);		
+		return layer;
+	}	
+	
+	public static SF2Layer new_bass2(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;
+		double[] data = new double[fftsize*2];
+		double base = x * 25;
+		double start_w = 0.05;
+		double end_w   = 0.05;
+		double start_a = 0.2;
+		double end_a   = 0.002;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/25.0);
+		
+		double[] aa = new double[25];
+		for (int i = 0; i < 25; i++) {
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] *= 8;
+		aa[1] *= 4;
+		aa[3] *= 8;
+		aa[5] *= 8;
+		
+		for (int i = 0; i < 25; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, aa[i]);			
+		}
+		
+
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Bass2", data, base);
+		SF2Layer layer = newLayer(sf2, "Bass2", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -8000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 5000);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);		
+		return layer;
+	}
+			
+		
+		
+	public static SF2Layer new_solostring(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];
+		double base = x * 25; 
+		double start_w = 2;
+		double end_w   = 2;
+		double start_a = 0.2;
+		double end_a   = 0.01;
+		
+		double[] aa = new double[18];
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0);
+		for (int i = 0; i < aa.length; i++) {
+			a *= a_step;
+			aa[i] = a;
+		}		
+		
+		aa[0] *= 5;
+		aa[1] *= 5;
+		aa[2] *= 5;
+		aa[3] *= 4;
+		aa[4] *= 4;
+		aa[5] *= 3;
+		aa[6] *= 3;
+		aa[7] *= 2;
+		 
+		for (int i = 0; i < aa.length; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, a);			
+		}
+		SF2Sample sample = newSimpleFFTSample(sf2, "Strings", data, base);
+		SF2Layer layer = newLayer(sf2, "Strings", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500);
+		region.putInteger(SF2Region.GENERATOR_FREQVIBLFO, -1000);
+		region.putInteger(SF2Region.GENERATOR_VIBLFOTOPITCH, 15);
+		return layer;
+
+	}		
+	
+	public static SF2Layer new_orchhit(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];
+		double base = x * 25; 
+		double start_w = 2;
+		double end_w   = 80;
+		double start_a = 0.2;
+		double end_a   = 0.001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0); 
+		for (int i = 0; i < 40; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, a);
+			a *= a_step;
+		}
+		complexGaussianDist(data, base*4, 300, 1);
+
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Och Strings", data, base);
+		SF2Layer layer = newLayer(sf2, "Och Strings", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 200);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 200);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500);
+		return layer;
+
+	}
+	
+	
+	public static SF2Layer new_string2(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];
+		double base = x * 25; 
+		double start_w = 2;
+		double end_w   = 80;
+		double start_a = 0.2;
+		double end_a   = 0.001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0); 
+		for (int i = 0; i < 40; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, a);
+			a *= a_step;
+		}
+		SF2Sample sample = newSimpleFFTSample(sf2, "Strings", data, base);
+		SF2Layer layer = newLayer(sf2, "Strings", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500);
+		return layer;
+
+	}
+	
+	
+	public static SF2Layer new_choir(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];
+		double base = x * 25; 
+		double start_w = 2;
+		double end_w   = 80;
+		double start_a = 0.2;
+		double end_a   = 0.001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0);
+		double[] aa = new double[40]; 
+		for (int i = 0; i < aa.length; i++) {
+			a *= a_step;
+			aa[i] = a;
+		}		
+		
+		aa[5] *= 0.1;
+		aa[6] *= 0.01;
+		aa[7] *= 0.1;
+		aa[8] *= 0.1;
+		
+		for (int i = 0; i < aa.length; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, aa[i]);		
+		}
+		SF2Sample sample = newSimpleFFTSample(sf2, "Strings", data, base);
+		SF2Layer layer = newLayer(sf2, "Strings", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500);
+		return layer;
+
+	}
+		
+	
+	public static SF2Layer new_organ(SF2Soundbank sf2)
+	{
+		Random random = new Random(102030201);
+		int x = 1;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15; 
+		double start_w = 0.01;
+		double end_w   = 0.01;
+		double start_a = 0.2;
+		double end_a   = 0.001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0);
+			
+		for (int i = 0; i < 12; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, a*(0.5 + 3*(random.nextDouble())));
+			a *= a_step;
+		}
+		SF2Sample sample = newSimpleFFTSample(sf2, "Organ", data, base);
+		SF2Layer layer = newLayer(sf2, "Organ", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500);
+		return layer;
+
+	}	
+	
+	
+	
+	public static SF2Layer new_ch_organ(SF2Soundbank sf2)
+	{
+		int x = 1;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15; 
+		double start_w = 0.01;
+		double end_w   = 0.01;
+		double start_a = 0.2;
+		double end_a   = 0.001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/60.0);
+		
+		double[] aa = new double[60]; 
+		for (int i = 0; i < aa.length; i++) {
+			a *= a_step;
+			aa[i] = a;
+		}
+		
+		aa[0] *= 5;
+		aa[1] *= 2;
+		aa[2] = 0;
+		aa[4] = 0;
+		aa[5] = 0;
+		aa[7] *= 7;
+		aa[9] = 0;
+		aa[10] = 0;
+		aa[12] = 0;
+		aa[15] *= 7;
+		aa[18] = 0;
+		aa[20] = 0;
+		aa[24] = 0;
+		aa[27] *= 5;
+		aa[29] = 0;
+		aa[30] = 0;
+		aa[33] = 0;
+		aa[36] *= 4;
+		aa[37] = 0;
+		aa[39] = 0;
+		aa[42] = 0;
+		aa[43] = 0;
+		aa[47] = 0;
+		aa[50] *= 4;
+		aa[52] = 0;
+		aa[55] = 0;
+		aa[57] = 0;
+		
+		
+		aa[10] *= 0.1;
+		aa[11] *= 0.1;
+		aa[12] *= 0.1;
+		aa[13] *= 0.1;	
+
+		aa[17] *= 0.1;
+		aa[18] *= 0.1;
+		aa[19] *= 0.1;
+		aa[20] *= 0.1;
+
+		for (int i = 0; i < 60; i++) {			
+			double w = start_w + (end_w - start_w)*(i/40.0);				
+			complexGaussianDist(data, base*(i+1), w, aa[i]);
+			a *= a_step;
+		}
+		SF2Sample sample = newSimpleFFTSample(sf2, "Organ", data, base);
+		SF2Layer layer = newLayer(sf2, "Organ", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -10000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		return layer;
+
+	}	
+	
+	public static SF2Layer new_flute(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15; 
+
+		complexGaussianDist(data, base*1, 0.001, 0.5);
+		complexGaussianDist(data, base*2, 0.001, 0.5);
+		complexGaussianDist(data, base*3, 0.001, 0.5);
+		complexGaussianDist(data, base*4, 0.01, 0.5);
+		
+		complexGaussianDist(data, base*4, 100, 120);
+		complexGaussianDist(data, base*6, 100, 40);
+		complexGaussianDist(data, base*8, 100, 80);
+		
+		complexGaussianDist(data, base*5, 0.001, 0.05);
+		complexGaussianDist(data, base*6, 0.001, 0.06);
+		complexGaussianDist(data, base*7, 0.001, 0.04);
+		complexGaussianDist(data, base*8, 0.005, 0.06);
+		complexGaussianDist(data, base*9, 0.005, 0.06);
+		complexGaussianDist(data, base*10, 0.01, 0.1);
+		complexGaussianDist(data, base*11, 0.08, 0.7);
+		complexGaussianDist(data, base*12, 0.08, 0.6);
+		complexGaussianDist(data, base*13, 0.08, 0.6);
+		complexGaussianDist(data, base*14, 0.08, 0.6);
+		complexGaussianDist(data, base*15, 0.08, 0.5);
+		complexGaussianDist(data, base*16, 0.08, 0.5);
+		complexGaussianDist(data, base*17, 0.08, 0.2);
+		
+
+		complexGaussianDist(data, base*1, 10, 8);
+		complexGaussianDist(data, base*2, 10, 8);
+		complexGaussianDist(data, base*3, 10, 8);
+		complexGaussianDist(data, base*4, 10, 8);
+		complexGaussianDist(data, base*5, 10, 8);
+		complexGaussianDist(data, base*6, 20, 9);
+		complexGaussianDist(data, base*7, 20, 9);
+		complexGaussianDist(data, base*8, 20, 9);
+		complexGaussianDist(data, base*9, 20, 8);
+		complexGaussianDist(data, base*10, 30, 8);
+		complexGaussianDist(data, base*11, 30, 9);
+		complexGaussianDist(data, base*12, 30, 9);
+		complexGaussianDist(data, base*13, 30, 8);
+		complexGaussianDist(data, base*14, 30, 8);
+		complexGaussianDist(data, base*15, 30, 7);
+		complexGaussianDist(data, base*16, 30, 7);
+		complexGaussianDist(data, base*17, 30, 6);
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Flute", data, base);
+		SF2Layer layer = newLayer(sf2, "Flute", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500);
+		return layer;
+
+	}
+	
+	public static SF2Layer new_horn(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15;
+		
+		double start_a = 0.5;
+		double end_a   = 0.00000000001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0); 
+		for (int i = 0; i < 40; i++) {			
+			if(i == 0)
+				complexGaussianDist(data, base*(i+1), 0.1, a*0.2);
+			else
+				complexGaussianDist(data, base*(i+1), 0.1, a);
+			a *= a_step;
+		}
+		
+		complexGaussianDist(data, base*2, 100, 	1);
+		
+						
+		SF2Sample sample = newSimpleFFTSample(sf2, "Horn", data, base);
+		SF2Layer layer = newLayer(sf2, "Horn", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);
+		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -500);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500);
+		return layer;
+
+	}			
+	
+	public static SF2Layer new_trumpet(SF2Soundbank sf2)
+	{		
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15;
+		
+		double start_a = 0.5;
+		double end_a   = 0.00001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/80.0);
+		double[] aa = new double[80];
+		for (int i = 0; i < 80; i++)
+		{
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] *= 0.05;
+		aa[1] *= 0.2;
+		aa[2] *= 0.5;
+		aa[3] *= 0.85;
+		
+		for (int i = 0; i < 80; i++) {			
+			complexGaussianDist(data, base*(i+1), 0.1, aa[i]);
+			
+		}
+		
+		complexGaussianDist(data, base*5, 300, 	3);
+		
+						
+		SF2Sample sample = newSimpleFFTSample(sf2, "Trumpet", data, base);
+		SF2Layer layer = newLayer(sf2, "Trumpet", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -10000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);
+		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -4000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, -2500);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERQ, 10);
+		return layer;
+
+	}		
+	
+	public static SF2Layer new_brass_section(SF2Soundbank sf2)
+	{		
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15;
+		
+		double start_a = 0.5;
+		double end_a   = 0.005;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/30.0);
+		double[] aa = new double[30];
+		for (int i = 0; i < 30; i++)
+		{
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] *= 0.8;
+		aa[1] *= 0.9;
+		
+		double w = 5;
+		for (int i = 0; i < 30; i++) {			
+			
+			complexGaussianDist(data, base*(i+1), 0.1*w, aa[i]*w);
+			w += 6; //*= w_step;
+		}
+		
+		complexGaussianDist(data, base*6, 300, 	2);
+		
+						
+		SF2Sample sample = newSimpleFFTSample(sf2, "Brass Section", data, base);
+		SF2Layer layer = newLayer(sf2, "Brass Section", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -9200);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);
+		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500);
+		return layer;
+
+	}		
+	
+	
+	public static SF2Layer new_trombone(SF2Soundbank sf2)
+	{		
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15;
+		
+		double start_a = 0.5;
+		double end_a   = 0.001;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/80.0);
+		double[] aa = new double[80];
+		for (int i = 0; i < 80; i++)
+		{
+			aa[i] = a;
+			a *= a_step;
+		}
+		
+		aa[0] *= 0.3;
+		aa[1] *= 0.7;
+		
+		for (int i = 0; i < 80; i++) {			
+			complexGaussianDist(data, base*(i+1), 0.1, aa[i]);
+			
+		}
+		
+		complexGaussianDist(data, base*6, 300, 	2);
+		
+						
+		SF2Sample sample = newSimpleFFTSample(sf2, "Trombone", data, base);
+		SF2Layer layer = newLayer(sf2, "Trombone", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -8000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);
+		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -2000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERQ, 10);
+		return layer;
+
+	}		
+	
+	public static SF2Layer new_sax(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15;
+		
+		double start_a = 0.5;
+		double end_a   = 0.01;
+		double a = start_a;
+		double a_step = Math.pow(end_a/start_a, 1.0/40.0); 
+		for (int i = 0; i < 40; i++) {			
+			if(i == 0 || i == 2)
+				complexGaussianDist(data, base*(i+1), 0.1, a*4);
+			else
+				complexGaussianDist(data, base*(i+1), 0.1, a);
+			a *= a_step;
+		}
+		
+		complexGaussianDist(data, base*4, 200, 	1);
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Sax", data, base);
+		SF2Layer layer = newLayer(sf2, "Sax", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);
+		
+		region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000);
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500);
+		return layer;
+
+	}	
+			
+	public static SF2Layer new_oboe(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15;
+		
+		complexGaussianDist(data, base*5, 100, 80);
+
+
+		complexGaussianDist(data, base*1, 0.01, 0.53);
+		complexGaussianDist(data, base*2, 0.01, 0.51);
+		complexGaussianDist(data, base*3, 0.01, 0.48);
+		complexGaussianDist(data, base*4, 0.01, 0.49);		
+		complexGaussianDist(data, base*5, 0.01, 5);
+		complexGaussianDist(data, base*6, 0.01, 0.51);
+		complexGaussianDist(data, base*7, 0.01, 0.50);
+		complexGaussianDist(data, base*8, 0.01, 0.59);
+		complexGaussianDist(data, base*9, 0.01, 0.61);
+		complexGaussianDist(data, base*10, 0.01, 0.52);
+		complexGaussianDist(data, base*11, 0.01, 0.49);
+		complexGaussianDist(data, base*12, 0.01, 0.51);
+		complexGaussianDist(data, base*13, 0.01, 0.48);
+		complexGaussianDist(data, base*14, 0.01, 0.51);
+		complexGaussianDist(data, base*15, 0.01, 0.46);
+		complexGaussianDist(data, base*16, 0.01, 0.35);
+		complexGaussianDist(data, base*17, 0.01, 0.20);
+		complexGaussianDist(data, base*18, 0.01, 0.10);
+		complexGaussianDist(data, base*19, 0.01, 0.5);
+		complexGaussianDist(data, base*20, 0.01, 0.1);
+		
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Oboe", data, base);
+		SF2Layer layer = newLayer(sf2, "Oboe", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500);
+		return layer;
+
+	}
+	
+	public static SF2Layer new_bassoon(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15;
+		
+		complexGaussianDist(data, base*2, 100, 40);
+		complexGaussianDist(data, base*4, 100, 20);
+
+		complexGaussianDist(data, base*1, 0.01, 0.53);
+		complexGaussianDist(data, base*2, 0.01, 5);
+		complexGaussianDist(data, base*3, 0.01, 0.51);
+		complexGaussianDist(data, base*4, 0.01, 0.48);
+		complexGaussianDist(data, base*5, 0.01, 1.49);		
+		complexGaussianDist(data, base*6, 0.01, 0.51);
+		complexGaussianDist(data, base*7, 0.01, 0.50);
+		complexGaussianDist(data, base*8, 0.01, 0.59);
+		complexGaussianDist(data, base*9, 0.01, 0.61);
+		complexGaussianDist(data, base*10, 0.01, 0.52);
+		complexGaussianDist(data, base*11, 0.01, 0.49);
+		complexGaussianDist(data, base*12, 0.01, 0.51);
+		complexGaussianDist(data, base*13, 0.01, 0.48);
+		complexGaussianDist(data, base*14, 0.01, 0.51);
+		complexGaussianDist(data, base*15, 0.01, 0.46);
+		complexGaussianDist(data, base*16, 0.01, 0.35);
+		complexGaussianDist(data, base*17, 0.01, 0.20);
+		complexGaussianDist(data, base*18, 0.01, 0.10);
+		complexGaussianDist(data, base*19, 0.01, 0.5);
+		complexGaussianDist(data, base*20, 0.01, 0.1);
+		
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Flute", data, base);
+		SF2Layer layer = newLayer(sf2, "Flute", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500);
+		return layer;
+
+	}		
+	
+	public static SF2Layer new_clarinet(SF2Soundbank sf2)
+	{
+		int x = 8;
+		int fftsize = 4096*x;		
+		double[] data = new double[fftsize*2];		
+		double base = x * 15; 
+
+		complexGaussianDist(data, base*1, 0.001, 0.5);
+		complexGaussianDist(data, base*2, 0.001, 0.02);
+		complexGaussianDist(data, base*3, 0.001, 0.2);
+		complexGaussianDist(data, base*4, 0.01, 0.1);
+		
+		complexGaussianDist(data, base*4, 100, 60);
+		complexGaussianDist(data, base*6, 100, 20);
+		complexGaussianDist(data, base*8, 100, 20);
+		
+		complexGaussianDist(data, base*5, 0.001, 0.1);
+		complexGaussianDist(data, base*6, 0.001, 0.09);
+		complexGaussianDist(data, base*7, 0.001, 0.02);
+		complexGaussianDist(data, base*8, 0.005, 0.16);
+		complexGaussianDist(data, base*9, 0.005, 0.96);
+		complexGaussianDist(data, base*10, 0.01, 0.9);
+		complexGaussianDist(data, base*11, 0.08, 1.2);
+		complexGaussianDist(data, base*12, 0.08, 1.8);
+		complexGaussianDist(data, base*13, 0.08, 1.6);
+		complexGaussianDist(data, base*14, 0.08, 1.2);
+		complexGaussianDist(data, base*15, 0.08, 0.9);
+		complexGaussianDist(data, base*16, 0.08, 0.5);
+		complexGaussianDist(data, base*17, 0.08, 0.2);
+		
+
+		complexGaussianDist(data, base*1, 10, 8);
+		complexGaussianDist(data, base*2, 10, 8);
+		complexGaussianDist(data, base*3, 10, 8);
+		complexGaussianDist(data, base*4, 10, 8);
+		complexGaussianDist(data, base*5, 10, 8);
+		complexGaussianDist(data, base*6, 20, 9);
+		complexGaussianDist(data, base*7, 20, 9);
+		complexGaussianDist(data, base*8, 20, 9);
+		complexGaussianDist(data, base*9, 20, 8);
+		complexGaussianDist(data, base*10, 30, 8);
+		complexGaussianDist(data, base*11, 30, 9);
+		complexGaussianDist(data, base*12, 30, 9);
+		complexGaussianDist(data, base*13, 30, 8);
+		complexGaussianDist(data, base*14, 30, 8);
+		complexGaussianDist(data, base*15, 30, 7);
+		complexGaussianDist(data, base*16, 30, 7);
+		complexGaussianDist(data, base*17, 30, 6);
+		
+		SF2Sample sample = newSimpleFFTSample(sf2, "Clarient", data, base);
+		SF2Layer layer = newLayer(sf2, "Clarient", sample);
+		SF2Region region = layer.getRegions().get(0);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000);
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100);		
+		region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500);
+		return layer;
+
+	}
+	
+	public static SF2Layer new_timpani(SF2Soundbank sf2)
+	{
+
+		double datab[];
+		double datah[];
+		
+		// Make Bass Part
+		{
+			int fftlen = 4096*8;
+			double[] data = new double[2*fftlen];
+			double base = 48;
+			complexGaussianDist(data, base*2, 0.2, 1);
+			complexGaussianDist(data, base*3, 0.2, 0.7);
+			complexGaussianDist(data, base*5, 10, 1);
+			complexGaussianDist(data, base*6, 9, 1);
+			complexGaussianDist(data, base*8, 15, 1);
+			complexGaussianDist(data, base*9, 18, 0.8);
+			complexGaussianDist(data, base*11, 21, 0.5);
+			complexGaussianDist(data, base*13, 28, 0.3);
+			complexGaussianDist(data, base*14, 22, 0.1);
+			randomPhase(data, new Random(3049912));				
+			ifft(data);
+			normalize(data, 0.5);
+			data = realPart(data);
+
+			double d_len = data.length;
+			for (int i = 0; i < data.length; i++)
+			{
+				double g = (1.0 - (i/d_len));
+				data[i] *= g*g;
+			}
+			fadeUp(data, 40);
+			datab = data;
+		}
+		
+		// Make treble part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5))*0.1;
+			fft(data);	
+			// Remove all negative frequency
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 1024*4; i < 2048*4; i++) 
+				data[i] = 1.0 - (i-4096)/4096.0;
+			for (int i = 0; i < 300; i++)
+			{
+				double g = (1.0 - (i / 300.0));
+				data[i] *= 1.0 + 20*g*g;
+			}		
+			for (int i = 0; i < 24; i++) 
+				data[i] = 0;					
+			randomPhase(data, new Random(3049912));						
+			ifft(data);		
+			normalize(data, 0.9);		
+			data = realPart(data);		
+			double gain = 1.0;
+			for (int i = 0; i < data.length; i++) {
+				data[i] *= gain;
+				gain *= 0.9998;
+			}				
+			datah = data;			
+		}
+			
+		for (int i = 0; i < datah.length; i++) 
+			datab[i] += datah[i]*0.02;		
+		
+		normalize(datab, 0.9);
+
+		SF2Sample sample = newSimpleDrumSample(sf2, "Timpani", datab);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Timpani");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();	
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);		
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}
+	
+	public static SF2Layer new_melodic_toms(SF2Soundbank sf2)
+	{
+
+		double datab[];
+		double datah[];
+		
+		// Make Bass Part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			complexGaussianDist(data, 30, 0.5, 1);		
+			randomPhase(data, new Random(3049912));				
+			ifft(data);
+			normalize(data, 0.8);
+			data = realPart(data);
+
+			double d_len = data.length;
+			for (int i = 0; i < data.length; i++) 
+				data[i] *= (1.0 - (i/d_len));						
+			datab = data;
+		}
+		
+		// Make treble part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5))*0.1;
+			fft(data);	
+			// Remove all negative frequency
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 1024*4; i < 2048*4; i++) 
+				data[i] = 1.0 - (i-4096)/4096.0;
+			for (int i = 0; i < 200; i++)
+			{
+				double g = (1.0 - (i / 200.0));
+				data[i] *= 1.0 + 20*g*g;
+			}		
+			for (int i = 0; i < 30; i++) 
+				data[i] = 0;					
+			randomPhase(data, new Random(3049912));						
+			ifft(data);		
+			normalize(data, 0.9);		
+			data = realPart(data);		
+			double gain = 1.0;
+			for (int i = 0; i < data.length; i++) {
+				data[i] *= gain;
+				gain *= 0.9996;
+			}				
+			datah = data;			
+		}
+			
+		for (int i = 0; i < datah.length; i++) 
+			datab[i] += datah[i]*0.5;			
+		for (int i = 0; i < 5; i++) 
+			datab[i] *= i/5.0;
+		
+		normalize(datab, 0.99);
+
+		SF2Sample sample = newSimpleDrumSample(sf2, "Melodic Toms", datab);
+		sample.setOriginalPitch(63);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Melodic Toms");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);
+		//region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);		
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}	
+	
+	public static SF2Layer new_reverse_cymbal(SF2Soundbank sf2)
+	{
+		double datah[];
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);		
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5)); 
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 0; i < 100; i++)
+				data[i] = 0;		
+			
+			for (int i = 0; i < 512*2; i++)
+			{
+				double gain = (i / (512.0*2.0));
+				data[i] = 1 - gain;
+			}					
+			datah = data;		
+		}
+			
+		SF2Sample sample = newSimpleFFTSample(sf2, "Reverse Cymbal", datah, 100, 20);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Reverse Cymbal");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();
+		region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -200);
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, -12000);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}	
+	
+	public static SF2Layer new_snare_drum(SF2Soundbank sf2)
+	{
+
+		double datab[];
+		double datah[];
+		
+		// Make Bass Part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			complexGaussianDist(data, 24, 0.5, 1);		
+			randomPhase(data, new Random(3049912));				
+			ifft(data);
+			normalize(data, 0.5);
+			data = realPart(data);
+
+			double d_len = data.length;
+			for (int i = 0; i < data.length; i++) 
+				data[i] *= (1.0 - (i/d_len));						
+			datab = data;
+		}
+		
+		// Make treble part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5))*0.1;
+			fft(data);	
+			// Remove all negative frequency
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 1024*4; i < 2048*4; i++) 
+				data[i] = 1.0 - (i-4096)/4096.0;
+			for (int i = 0; i < 300; i++)
+			{
+				double g = (1.0 - (i / 300.0));
+				data[i] *= 1.0 + 20*g*g;
+			}		
+			for (int i = 0; i < 24; i++) 
+				data[i] = 0;					
+			randomPhase(data, new Random(3049912));						
+			ifft(data);		
+			normalize(data, 0.9);		
+			data = realPart(data);		
+			double gain = 1.0;
+			for (int i = 0; i < data.length; i++) {
+				data[i] *= gain;
+				gain *= 0.9998;
+			}				
+			datah = data;			
+		}
+			
+		for (int i = 0; i < datah.length; i++) 
+			datab[i] += datah[i];		
+		for (int i = 0; i < 5; i++) 
+			datab[i] *= i/5.0;
+
+		SF2Sample sample = newSimpleDrumSample(sf2, "Snare Drum", datab);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Snare Drum");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();	
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);		
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}
+	
+	public static SF2Layer new_bass_drum(SF2Soundbank sf2)
+	{
+
+		double datab[];
+		double datah[];
+		
+		// Make Bass Part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			complexGaussianDist(data, 1.8*5+1, 2, 1);
+			complexGaussianDist(data, 1.8*9+1, 2, 1);		
+			randomPhase(data, new Random(3049912));				
+			ifft(data);
+			normalize(data, 0.9);
+			data = realPart(data);
+			double d_len = data.length;
+			for (int i = 0; i < data.length; i++) 
+				data[i] *= (1.0 - (i/d_len));				
+			datab = data;
+		}
+		
+		// Make treble part
+		{
+			int fftlen = 4096;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5))*0.1;
+			fft(data);	
+			// Remove all negative frequency
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 1024; i < 2048; i++) 
+				data[i] = 1.0 - (i-1024)/1024.0;		
+			for (int i = 0; i < 512; i++) 
+				data[i] = 10*i/512.0;
+			for (int i = 0; i < 10; i++) 
+				data[i] = 0;					
+			randomPhase(data, new Random(3049912));						
+			ifft(data);		
+			normalize(data, 0.9);		
+			data = realPart(data);		
+			double gain = 1.0;
+			for (int i = 0; i < data.length; i++) {
+				data[i] *= gain;
+				gain *= 0.999;
+			}				
+			datah = data;			
+		}
+			
+		for (int i = 0; i < datah.length; i++) 
+			datab[i] += datah[i]*0.5;			
+		for (int i = 0; i < 5; i++) 
+			datab[i] *= i/5.0;
+
+		SF2Sample sample = newSimpleDrumSample(sf2, "Bass Drum", datab);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Bass Drum");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);
+		region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);		
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}
+	
+	public static SF2Layer new_tom(SF2Soundbank sf2)
+	{
+
+		double datab[];
+		double datah[];
+		
+		// Make Bass Part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			complexGaussianDist(data, 30, 0.5, 1);		
+			randomPhase(data, new Random(3049912));				
+			ifft(data);
+			normalize(data, 0.8);
+			data = realPart(data);
+
+			double d_len = data.length;
+			for (int i = 0; i < data.length; i++) 
+				data[i] *= (1.0 - (i/d_len));						
+			datab = data;
+		}
+		
+		// Make treble part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5))*0.1;
+			fft(data);	
+			// Remove all negative frequency
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 1024*4; i < 2048*4; i++) 
+				data[i] = 1.0 - (i-4096)/4096.0;
+			for (int i = 0; i < 200; i++)
+			{
+				double g = (1.0 - (i / 200.0));
+				data[i] *= 1.0 + 20*g*g;
+			}		
+			for (int i = 0; i < 30; i++) 
+				data[i] = 0;					
+			randomPhase(data, new Random(3049912));						
+			ifft(data);		
+			normalize(data, 0.9);		
+			data = realPart(data);		
+			double gain = 1.0;
+			for (int i = 0; i < data.length; i++) {
+				data[i] *= gain;
+				gain *= 0.9996;
+			}				
+			datah = data;			
+		}
+			
+		for (int i = 0; i < datah.length; i++) 
+			datab[i] += datah[i]*0.5;			
+		for (int i = 0; i < 5; i++) 
+			datab[i] *= i/5.0;
+		
+		normalize(datab, 0.99);
+
+		SF2Sample sample = newSimpleDrumSample(sf2, "Tom", datab);
+		sample.setOriginalPitch(50);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Tom");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);
+		//region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100);		
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}
+
+	public static SF2Layer new_closed_hihat(SF2Soundbank sf2)
+	{
+		double datah[];
+
+		// Make treble part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5))*0.1;
+			fft(data);	
+			// Remove all negative frequency
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 1024*4; i < 2048*4; i++) 
+				data[i] = 1.0 - (i-4096)/4096.0;
+			for (int i = 0; i < 2048; i++) 
+				data[i] = 0.2 + 0.8*(i / 2048.0);					
+			randomPhase(data, new Random(3049912));						
+			ifft(data);		
+			normalize(data, 0.9);		
+			data = realPart(data);		
+			double gain = 1.0;
+			for (int i = 0; i < data.length; i++) {
+				data[i] *= gain;
+				gain *= 0.9996;
+			}				
+			datah = data;			
+		}
+			
+		for (int i = 0; i < 5; i++) 
+			datah[i] *= i/5.0;
+		SF2Sample sample = newSimpleDrumSample(sf2, "Closed Hi-Hat", datah);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Closed Hi-Hat");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);		
+		region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+		region.putInteger(SF2Region.GENERATOR_EXCLUSIVECLASS, 1);
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}
+
+	public static SF2Layer new_open_hihat(SF2Soundbank sf2)
+	{
+		double datah[];
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);		
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5)); 
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 0; i < 200; i++)
+				data[i] = 0;			
+			for (int i = 0; i < 2048*4; i++)
+			{
+				double gain = (i / (2048.0*4.0));
+				data[i] = gain;
+			}									
+			datah = data;		
+		}
+			
+		SF2Sample sample = newSimpleFFTSample(sf2, "Open Hi-Hat", datah, 1000, 5);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Open Hi-Hat");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 1500);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1500);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);
+		region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+		region.putInteger(SF2Region.GENERATOR_EXCLUSIVECLASS, 1);
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}
+	
+	public static SF2Layer new_crash_cymbal(SF2Soundbank sf2)
+	{
+		double datah[];
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);		
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5)); 
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 0; i < 100; i++)
+				data[i] = 0;		
+			
+			for (int i = 0; i < 512*2; i++)
+			{
+				double gain = (i / (512.0*2.0));
+				data[i] = gain;
+			}								
+			datah = data;		
+		}
+			
+		SF2Sample sample = newSimpleFFTSample(sf2, "Crash Cymbal", datah, 1000, 5);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Crash Cymbal");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();
+		region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 1800);
+		region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1);		
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1800);
+		region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000);
+		region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+		region.setSample(sample);
+		layer.getRegions().add(region);
+
+		return layer;
+	}	
+	
+	public static SF2Layer new_side_stick(SF2Soundbank sf2)
+	{
+		double datab[];
+		
+		// Make treble part
+		{
+			int fftlen = 4096*4;
+			double[] data = new double[2*fftlen];
+			Random random = new Random(3049912);
+			for (int i = 0; i < data.length; i+=2) 
+				data[i] = (2.0*(random.nextDouble()-0.5))*0.1;
+			fft(data);	
+			// Remove all negative frequency
+			for (int i = fftlen/2; i < data.length; i++) 
+				data[i] = 0;
+			for (int i = 1024*4; i < 2048*4; i++) 
+				data[i] = 1.0 - (i-4096)/4096.0;
+			for (int i = 0; i < 200; i++)
+			{
+				double g = (1.0 - (i / 200.0));
+				data[i] *= 1.0 + 20*g*g;
+			}		
+			for (int i = 0; i < 30; i++) 
+				data[i] = 0;					
+			randomPhase(data, new Random(3049912));						
+			ifft(data);		
+			normalize(data, 0.9);		
+			data = realPart(data);		
+			double gain = 1.0;
+			for (int i = 0; i < data.length; i++) {
+				data[i] *= gain;
+				gain *= 0.9996;
+			}				
+			datab = data;			
+		}
+			
+		for (int i = 0; i < 10; i++) 
+			datab[i] *= i/10.0;
+
+		SF2Sample sample = newSimpleDrumSample(sf2, "Side Stick", datab);
+		
+		SF2Layer layer = new SF2Layer(sf2);
+		layer.setName("Side Stick");
+		
+		SF2GlobalRegion global = new SF2GlobalRegion();
+		layer.setGlobalZone(global);		
+		sf2.addResource(layer);
+
+		SF2LayerRegion region = new SF2LayerRegion();
+		region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);		
+		region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0);
+		region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -50);
+		region.setSample(sample);
+		layer.getRegions().add(region);
+		
+		return layer;
+		
+	}	
+
+	
+	public static SF2Sample newSimpleFFTSample(SF2Soundbank sf2, String name, double[] data, double base)
+	{
+		return newSimpleFFTSample(sf2, name, data, base, 10);
+	}
+	
+	public static SF2Sample newSimpleFFTSample(SF2Soundbank sf2, String name, double[] data, double base, int fadeuptime)
+	{
+		
+		int fftsize = data.length/2;
+		AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
+		double basefreq = (base / fftsize) * format.getSampleRate() * 0.5;
+
+		randomPhase(data);
+		ifft(data);
+		data = realPart(data);		
+		normalize(data, 0.9);
+		float[] fdata = toFloat(data);
+		fdata = loopExtend(fdata, fdata.length+512);
+		fadeUp(fdata, fadeuptime);
+		byte[] bdata = toBytes(fdata, format); 
+		
+		/*
+		 * Create SoundFont2 sample.
+		 */
+		SF2Sample sample = new SF2Sample(sf2);
+		sample.setName(name);
+		sample.setData(bdata);
+		sample.setStartLoop(256);
+		sample.setEndLoop(fftsize+256);
+		sample.setSampleRate((long) format.getSampleRate());
+		double orgnote = (69 + 12) + (12*Math.log(basefreq/440.0)/Math.log(2));
+		sample.setOriginalPitch((int)orgnote);
+		sample.setPitchCorrection((byte)(-(orgnote - (int)orgnote)*100.0));
+		sf2.addResource(sample);		
+		
+		return sample;
+	}
+	
+	public static SF2Sample newSimpleFFTSample_dist(SF2Soundbank sf2, String name, double[] data, double base, double preamp)
+	{
+		
+		int fftsize = data.length/2;
+		AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
+		double basefreq = (base / fftsize) * format.getSampleRate() * 0.5;
+
+		randomPhase(data);
+		ifft(data);
+		data = realPart(data);
+		
+		for (int i = 0; i < data.length; i++) {
+			
+			data[i] = (1-Math.exp(-Math.abs(data[i]*preamp)))*Math.signum(data[i]);
+		}
+		
+		normalize(data, 0.9);
+		float[] fdata = toFloat(data);
+		fdata = loopExtend(fdata, fdata.length+512);
+		fadeUp(fdata, 80);
+		byte[] bdata = toBytes(fdata, format); 
+		
+		/*
+		 * Create SoundFont2 sample.
+		 */
+		SF2Sample sample = new SF2Sample(sf2);
+		sample.setName(name);
+		sample.setData(bdata);
+		sample.setStartLoop(256);
+		sample.setEndLoop(fftsize+256);
+		sample.setSampleRate((long) format.getSampleRate());
+		double orgnote = (69 + 12) + (12*Math.log(basefreq/440.0)/Math.log(2));
+		sample.setOriginalPitch((int)orgnote);
+		sample.setPitchCorrection((byte)(-(orgnote - (int)orgnote)*100.0));
+		sf2.addResource(sample);		
+		
+		return sample;
+	}
+		
+	
+	public static SF2Sample newSimpleDrumSample(SF2Soundbank sf2, String name, double[] data)
+	{
+		
+		int fftsize = data.length;
+		AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
+
+		byte[] bdata = toBytes(toFloat(realPart(data)), format);
+	
+		/*
+		 * Create SoundFont2 sample.
+		 */
+		SF2Sample sample = new SF2Sample(sf2);
+		sample.setName(name);
+		sample.setData(bdata);
+		sample.setStartLoop(256);
+		sample.setEndLoop(fftsize+256);
+		sample.setSampleRate((long) format.getSampleRate());
+		sample.setOriginalPitch(60);
+		sf2.addResource(sample);		
+		
+		return sample;
+	}
+	
+	public static SF2Layer newLayer(SF2Soundbank sf2, String name, SF2Sample sample)
+	{
+		SF2LayerRegion region = new SF2LayerRegion();		
+		region.setSample(sample);
+		
+		SF2Layer layer = new SF2Layer(sf2);		
+		layer.setName(name);
+		layer.getRegions().add(region);
+		sf2.addResource(layer);
+		
+		return layer;
+	}
+	
+	public static SF2Instrument newInstrument(SF2Soundbank sf2, String name, Patch patch, SF2Layer... layers)
+	{
+		
+		/*
+		 * Create SoundFont2 instrument.
+		 */
+		SF2Instrument ins = new SF2Instrument(sf2);
+		ins.setPatch(patch);
+		ins.setName(name);
+		sf2.addInstrument(ins);
+
+		/*
+		 * Create region for instrument.
+		 */
+		for (int i = 0; i < layers.length; i++) {
+			SF2InstrumentRegion insregion = new SF2InstrumentRegion();
+			insregion.setLayer(layers[i]);
+			ins.getRegions().add(insregion);			
+		}
+
+		return ins;
+	}	
+	
+	static public void ifft(double[] data)
+	{
+		new FFT(data.length/2, 1).transform(data);
+	}
+	
+	static public void fft(double[] data)
+	{
+		new FFT(data.length/2, -1).transform(data);
+	}	
+	
+	public static void complexGaussianDist(double[] cdata, double m, double s, double v)
+	{
+		for (int x = 0; x < cdata.length/4; x++) {
+			cdata[x*2] += v * (1.0/(s*Math.sqrt(2*Math.PI)) * Math.exp( (-1.0/2.0) * Math.pow( (x - m)/s ,2.0)) );
+		}
+	};	
+	
+	static public void randomPhase(double[] data)
+	{
+		for (int i = 0; i < data.length; i+=2) {
+			double phase = Math.random()*2*Math.PI;
+			double d = data[i];
+			data[i] = Math.sin(phase)*d;
+			data[i+1] = Math.cos(phase)*d;
+		}						
+	}
+	
+	static public void randomPhase(double[] data, Random random)
+	{
+		for (int i = 0; i < data.length; i+=2) {
+			double phase = random.nextDouble()*2*Math.PI;
+			double d = data[i];
+			data[i] = Math.sin(phase)*d;
+			data[i+1] = Math.cos(phase)*d;
+		}						
+	}	
+	
+	static public void normalize(double[] data, double target)
+	{
+		double maxvalue = 0;
+		for (int i = 0; i < data.length; i++) {
+			if(data[i] > maxvalue) maxvalue = data[i];
+			if(-data[i] > maxvalue) maxvalue = -data[i];
+		}
+		if(maxvalue == 0) return;
+		double gain = target/maxvalue;
+		for (int i = 0; i < data.length; i++) 
+			data[i] *= gain;		
+				
+	}
+	
+	static public void normalize(float[] data, double target)
+	{
+		double maxvalue = 0.5;
+		for (int i = 0; i < data.length; i++) {
+			if(data[i*2] > maxvalue) maxvalue = data[i*2];
+			if(-data[i*2] > maxvalue) maxvalue = -data[i*2];
+		}
+		double gain = target/maxvalue;
+		for (int i = 0; i < data.length; i++) 
+			data[i*2] *= gain;		
+				
+	}
+	
+	static public double[] realPart(double[] in)
+	{
+		double[] out = new double[in.length/2];
+		for (int i = 0; i < out.length; i++) {
+			out[i] = in[i*2];
+		}
+		return out;
+	}
+	
+	static public double[] imgPart(double[] in)
+	{
+		double[] out = new double[in.length/2];
+		for (int i = 0; i < out.length; i++) {
+			out[i] = in[i*2];
+		}
+		return out;
+	}	
+	
+	static public float[] toFloat(double[] in)
+	{
+		float[] out = new float[in.length];
+		for (int i = 0; i < out.length; i++) {
+			out[i] = (float)in[i];
+		}
+		return out;
+	}
+	
+	static public byte[] toBytes(float[] in, AudioFormat format)
+	{
+		byte[] out = new byte[in.length * format.getFrameSize()];
+		return AudioFloatConverter.getConverter(format).toByteArray(in, out);
+	}
+	
+	static public void fadeUp(double[] data, int samples)
+	{
+		double dsamples = samples;
+		for (int i = 0; i < samples; i++) 
+			data[i] *= i/dsamples;					
+	}
+	
+	static public void fadeUp(float[] data, int samples)
+	{
+		double dsamples = samples;
+		for (int i = 0; i < samples; i++) 
+			data[i] *= i/dsamples;					
+	}
+	
+	static public double[] loopExtend(double[] data, int newsize)
+	{
+		double[] outdata = new double[newsize];
+		int p_len = data.length;
+		int p_ps = 0;
+		for (int i = 0; i < outdata.length; i++) {
+			outdata[i] = data[p_ps];
+			p_ps++;
+			if(p_ps == p_len) p_ps = 0;
+		}
+		return outdata;
+	}
+	
+	static public float[] loopExtend(float[] data, int newsize)
+	{
+		float[] outdata = new float[newsize];
+		int p_len = data.length;
+		int p_ps = 0;
+		for (int i = 0; i < outdata.length; i++) {
+			outdata[i] = data[p_ps];
+			p_ps++;
+			if(p_ps == p_len) p_ps = 0;
+		}
+		return outdata;
+	}		
+
+	
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/FFT.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,771 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * Fast Fourier Transformer.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public final class FFT {
+
+	private double[] w;
+
+	private int fftFrameSize;
+
+	private int sign;
+
+	private int[] bitm_array;
+
+	private int fftFrameSize2;
+
+	// Sign = -1 is FFT, 1 is IFFT (inverse FFT)
+	// Data = Interlaced double array to be transformed.
+	// The order is: real (sin), complex (cos)
+	// Framesize must be power of 2
+	
+	public FFT(int fftFrameSize, int sign) {
+		w = computeTwiddleFactors(fftFrameSize, sign);
+
+		this.fftFrameSize = fftFrameSize;
+		this.sign = sign;
+		fftFrameSize2 = fftFrameSize << 1;
+
+		// Pre-process Bit-Reversal
+		bitm_array = new int[fftFrameSize2];
+		for (int i = 2; i < fftFrameSize2; i += 2) {
+			int j;
+			int bitm;
+			for (bitm = 2, j = 0; bitm < fftFrameSize2; bitm <<= 1) {
+				if ((i & bitm) != 0)
+					j++;
+				j <<= 1;
+			}
+			bitm_array[i] = j;
+		}
+
+	}
+
+	public void transform(double[] data) {
+		bitreversal(data);
+		calc(fftFrameSize, data, sign, w);
+	}
+
+	private final static double[] computeTwiddleFactors(int fftFrameSize,
+			int sign) {
+
+		int imax = (int) (Math.log(fftFrameSize) / Math.log(2.));
+
+		double[] warray = new double[(fftFrameSize - 1) * 4];
+		int w_index = 0;
+
+		for (int i = 0, nstep = 2; i < imax; i++) {
+
+			int jmax = nstep;
+			nstep <<= 1;
+
+			double wr = 1.0;
+			double wi = 0.0;
+
+			double arg = Math.PI / (jmax >> 1);
+			double wfr = Math.cos(arg);
+			double wfi = sign * Math.sin(arg);
+
+			for (int j = 0; j < jmax; j += 2) {
+
+				warray[w_index++] = wr;
+				warray[w_index++] = wi;
+
+				double tempr = wr;
+				wr = tempr * wfr - wi * wfi;
+				wi = tempr * wfi + wi * wfr;
+			}
+		}
+
+		// PRECOMPUTATION of wwr1, wwi1 for factor 4 Decomposition (3 * complex
+		// operators and 8 +/- complex operators)
+		{
+
+			w_index = 0;
+			int w_index2 = warray.length >> 1;
+			for (int i = 0, nstep = 2; i < (imax - 1); i++) {
+
+				int jmax = nstep;
+				nstep *= 2;
+
+				int ii = w_index + jmax;
+				for (int j = 0; j < jmax; j += 2) {
+
+					double wr = warray[w_index++];
+					double wi = warray[w_index++];
+					double wr1 = warray[ii++];
+					double wi1 = warray[ii++];
+					warray[w_index2++] = wr * wr1 - wi * wi1;
+					warray[w_index2++] = wr * wi1 + wi * wr1;
+
+				}
+			}
+
+		}
+
+		return warray;
+
+	}
+
+	private final static void calc(int fftFrameSize, double[] data, int sign,
+			double[] w)
+
+	{
+
+		final int fftFrameSize2 = fftFrameSize << 1;
+
+		int nstep = 2;
+
+		if (nstep >= fftFrameSize2)
+			return;
+		int i = nstep - 2;
+		if (sign == -1)
+			calcF4F(fftFrameSize, data, i, nstep, w);
+		else
+			calcF4I(fftFrameSize, data, i, nstep, w);
+
+	}
+
+	private final static void calcF2E(int fftFrameSize, double[] data, int i,
+			int nstep, double[] w) {
+		int jmax = nstep;
+		nstep <<= 1;
+		for (int n = 0; n < jmax; n += 2) {
+			double wr = w[i++];
+			double wi = w[i++];
+			int m = n + jmax;
+			double datam_r = data[m];
+			double datam_i = data[m + 1];
+			double datan_r = data[n];
+			double datan_i = data[n + 1];
+			double tempr = datam_r * wr - datam_i * wi;
+			double tempi = datam_r * wi + datam_i * wr;
+			data[m] = datan_r - tempr;
+			data[m + 1] = datan_i - tempi;
+			data[n] = datan_r + tempr;
+			data[n + 1] = datan_i + tempi;
+		}
+		return;
+
+	}
+
+	// Perform Factor-4 Decomposition with 3 * complex operators and 8 +/-
+	// complex operators
+
+	private final static void calcF4F(int fftFrameSize, double[] data, int i,
+			int nstep, double[] w) {
+		final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize;
+		// Factor-4 Decomposition
+
+		int w_len = w.length >> 1;
+		while (nstep < fftFrameSize2) {
+
+			if (nstep << 2 == fftFrameSize2) {
+				// Goto Factor-4 Final Decomposition
+				// calcF4E(data, i, nstep, -1, w);
+				calcF4FE(fftFrameSize, data, i, nstep, w);
+				return;
+			}
+			int jmax = nstep;
+			int nnstep = nstep << 1;
+			if (nnstep == fftFrameSize2) {
+				// Factor-4 Decomposition not possible
+				calcF2E(fftFrameSize, data, i, nstep, w);
+				return;
+			}
+			nstep <<= 2;
+			int ii = i + jmax;
+			int iii = i + w_len;
+
+			{
+				i += 2;
+				ii += 2;
+				iii += 2;
+
+				for (int n = 0; n < fftFrameSize2; n += nstep) {
+					int m = n + jmax;
+
+					double datam1_r = data[m];
+					double datam1_i = data[m + 1];
+					double datan1_r = data[n];
+					double datan1_i = data[n + 1];
+
+					n += nnstep;
+					m += nnstep;
+					double datam2_r = data[m];
+					double datam2_i = data[m + 1];
+					double datan2_r = data[n];
+					double datan2_i = data[n + 1];
+
+					double tempr = datam1_r;
+					double tempi = datam1_i;
+
+					datam1_r = datan1_r - tempr;
+					datam1_i = datan1_i - tempi;
+					datan1_r = datan1_r + tempr;
+					datan1_i = datan1_i + tempi;
+
+					double n2w1r = datan2_r;
+					double n2w1i = datan2_i;
+					double m2ww1r = datam2_r;
+					double m2ww1i = datam2_i;
+
+					tempr = m2ww1r - n2w1r;
+					tempi = m2ww1i - n2w1i;
+
+					datam2_r = datam1_r + tempi;
+					datam2_i = datam1_i - tempr;
+					datam1_r = datam1_r - tempi;
+					datam1_i = datam1_i + tempr;
+
+					tempr = n2w1r + m2ww1r;
+					tempi = n2w1i + m2ww1i;
+
+					datan2_r = datan1_r - tempr;
+					datan2_i = datan1_i - tempi;
+					datan1_r = datan1_r + tempr;
+					datan1_i = datan1_i + tempi;
+
+					data[m] = datam2_r;
+					data[m + 1] = datam2_i;
+					data[n] = datan2_r;
+					data[n + 1] = datan2_i;
+
+					n -= nnstep;
+					m -= nnstep;
+					data[m] = datam1_r;
+					data[m + 1] = datam1_i;
+					data[n] = datan1_r;
+					data[n + 1] = datan1_i;
+
+				}
+
+			}
+			for (int j = 2; j < jmax; j += 2) {
+				double wr = w[i++];
+				double wi = w[i++];
+				double wr1 = w[ii++];
+				double wi1 = w[ii++];
+				double wwr1 = w[iii++];
+				double wwi1 = w[iii++];
+				// double wwr1 = wr * wr1 - wi * wi1; // these numbers can be
+				// precomputed!!!
+				// double wwi1 = wr * wi1 + wi * wr1;
+
+				for (int n = j; n < fftFrameSize2; n += nstep) {
+					int m = n + jmax;
+
+					double datam1_r = data[m];
+					double datam1_i = data[m + 1];
+					double datan1_r = data[n];
+					double datan1_i = data[n + 1];
+
+					n += nnstep;
+					m += nnstep;
+					double datam2_r = data[m];
+					double datam2_i = data[m + 1];
+					double datan2_r = data[n];
+					double datan2_i = data[n + 1];
+
+					double tempr = datam1_r * wr - datam1_i * wi;
+					double tempi = datam1_r * wi + datam1_i * wr;
+
+					datam1_r = datan1_r - tempr;
+					datam1_i = datan1_i - tempi;
+					datan1_r = datan1_r + tempr;
+					datan1_i = datan1_i + tempi;
+
+					double n2w1r = datan2_r * wr1 - datan2_i * wi1;
+					double n2w1i = datan2_r * wi1 + datan2_i * wr1;
+					double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1;
+					double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1;
+
+					tempr = m2ww1r - n2w1r;
+					tempi = m2ww1i - n2w1i;
+
+					datam2_r = datam1_r + tempi;
+					datam2_i = datam1_i - tempr;
+					datam1_r = datam1_r - tempi;
+					datam1_i = datam1_i + tempr;
+
+					tempr = n2w1r + m2ww1r;
+					tempi = n2w1i + m2ww1i;
+
+					datan2_r = datan1_r - tempr;
+					datan2_i = datan1_i - tempi;
+					datan1_r = datan1_r + tempr;
+					datan1_i = datan1_i + tempi;
+
+					data[m] = datam2_r;
+					data[m + 1] = datam2_i;
+					data[n] = datan2_r;
+					data[n + 1] = datan2_i;
+
+					n -= nnstep;
+					m -= nnstep;
+					data[m] = datam1_r;
+					data[m + 1] = datam1_i;
+					data[n] = datan1_r;
+					data[n + 1] = datan1_i;
+
+				}
+			}
+
+			i += jmax << 1;
+
+		}
+
+		calcF2E(fftFrameSize, data, i, nstep, w);
+
+	}
+
+	// Perform Factor-4 Decomposition with 3 * complex operators and 8 +/-
+	// complex operators
+
+	private final static void calcF4I(int fftFrameSize, double[] data, int i,
+			int nstep, double[] w) {
+		final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize;
+		// Factor-4 Decomposition
+
+		int w_len = w.length >> 1;
+		while (nstep < fftFrameSize2) {
+
+			if (nstep << 2 == fftFrameSize2) {
+				// Goto Factor-4 Final Decomposition
+				// calcF4E(data, i, nstep, 1, w);
+				calcF4IE(fftFrameSize, data, i, nstep, w);
+				return;
+			}
+			int jmax = nstep;
+			int nnstep = nstep << 1;
+			if (nnstep == fftFrameSize2) {
+				// Factor-4 Decomposition not possible
+				calcF2E(fftFrameSize, data, i, nstep, w);
+				return;
+			}
+			nstep <<= 2;
+			int ii = i + jmax;
+			int iii = i + w_len;
+			{
+				i += 2;
+				ii += 2;
+				iii += 2;
+
+				for (int n = 0; n < fftFrameSize2; n += nstep) {
+					int m = n + jmax;
+
+					double datam1_r = data[m];
+					double datam1_i = data[m + 1];
+					double datan1_r = data[n];
+					double datan1_i = data[n + 1];
+
+					n += nnstep;
+					m += nnstep;
+					double datam2_r = data[m];
+					double datam2_i = data[m + 1];
+					double datan2_r = data[n];
+					double datan2_i = data[n + 1];
+
+					double tempr = datam1_r;
+					double tempi = datam1_i;
+
+					datam1_r = datan1_r - tempr;
+					datam1_i = datan1_i - tempi;
+					datan1_r = datan1_r + tempr;
+					datan1_i = datan1_i + tempi;
+
+					double n2w1r = datan2_r;
+					double n2w1i = datan2_i;
+					double m2ww1r = datam2_r;
+					double m2ww1i = datam2_i;
+
+					tempr = n2w1r - m2ww1r;
+					tempi = n2w1i - m2ww1i;
+
+					datam2_r = datam1_r + tempi;
+					datam2_i = datam1_i - tempr;
+					datam1_r = datam1_r - tempi;
+					datam1_i = datam1_i + tempr;
+
+					tempr = n2w1r + m2ww1r;
+					tempi = n2w1i + m2ww1i;
+
+					datan2_r = datan1_r - tempr;
+					datan2_i = datan1_i - tempi;
+					datan1_r = datan1_r + tempr;
+					datan1_i = datan1_i + tempi;
+
+					data[m] = datam2_r;
+					data[m + 1] = datam2_i;
+					data[n] = datan2_r;
+					data[n + 1] = datan2_i;
+
+					n -= nnstep;
+					m -= nnstep;
+					data[m] = datam1_r;
+					data[m + 1] = datam1_i;
+					data[n] = datan1_r;
+					data[n + 1] = datan1_i;
+
+				}
+
+			}
+			for (int j = 2; j < jmax; j += 2) {
+				double wr = w[i++];
+				double wi = w[i++];
+				double wr1 = w[ii++];
+				double wi1 = w[ii++];
+				double wwr1 = w[iii++];
+				double wwi1 = w[iii++];
+				// double wwr1 = wr * wr1 - wi * wi1; // these numbers can be
+				// precomputed!!!
+				// double wwi1 = wr * wi1 + wi * wr1;
+
+				for (int n = j; n < fftFrameSize2; n += nstep) {
+					int m = n + jmax;
+
+					double datam1_r = data[m];
+					double datam1_i = data[m + 1];
+					double datan1_r = data[n];
+					double datan1_i = data[n + 1];
+
+					n += nnstep;
+					m += nnstep;
+					double datam2_r = data[m];
+					double datam2_i = data[m + 1];
+					double datan2_r = data[n];
+					double datan2_i = data[n + 1];
+
+					double tempr = datam1_r * wr - datam1_i * wi;
+					double tempi = datam1_r * wi + datam1_i * wr;
+
+					datam1_r = datan1_r - tempr;
+					datam1_i = datan1_i - tempi;
+					datan1_r = datan1_r + tempr;
+					datan1_i = datan1_i + tempi;
+
+					double n2w1r = datan2_r * wr1 - datan2_i * wi1;
+					double n2w1i = datan2_r * wi1 + datan2_i * wr1;
+					double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1;
+					double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1;
+
+					tempr = n2w1r - m2ww1r;
+					tempi = n2w1i - m2ww1i;
+
+					datam2_r = datam1_r + tempi;
+					datam2_i = datam1_i - tempr;
+					datam1_r = datam1_r - tempi;
+					datam1_i = datam1_i + tempr;
+
+					tempr = n2w1r + m2ww1r;
+					tempi = n2w1i + m2ww1i;
+
+					datan2_r = datan1_r - tempr;
+					datan2_i = datan1_i - tempi;
+					datan1_r = datan1_r + tempr;
+					datan1_i = datan1_i + tempi;
+
+					data[m] = datam2_r;
+					data[m + 1] = datam2_i;
+					data[n] = datan2_r;
+					data[n + 1] = datan2_i;
+
+					n -= nnstep;
+					m -= nnstep;
+					data[m] = datam1_r;
+					data[m + 1] = datam1_i;
+					data[n] = datan1_r;
+					data[n + 1] = datan1_i;
+
+				}
+			}
+
+			i += jmax << 1;
+
+		}
+
+		calcF2E(fftFrameSize, data, i, nstep, w);
+
+	}
+
+	// Perform Factor-4 Decomposition with 3 * complex operators and 8 +/-
+	// complex operators
+
+	private final static void calcF4FE(int fftFrameSize, double[] data, int i,
+			int nstep, double[] w) {
+		final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize;
+		// Factor-4 Decomposition
+
+		int w_len = w.length >> 1;
+		while (nstep < fftFrameSize2) {
+
+			int jmax = nstep;
+			int nnstep = nstep << 1;
+			if (nnstep == fftFrameSize2) {
+				// Factor-4 Decomposition not possible
+				calcF2E(fftFrameSize, data, i, nstep, w);
+				return;
+			}
+			nstep <<= 2;
+			int ii = i + jmax;
+			int iii = i + w_len;
+			for (int n = 0; n < jmax; n += 2) {
+				double wr = w[i++];
+				double wi = w[i++];
+				double wr1 = w[ii++];
+				double wi1 = w[ii++];
+				double wwr1 = w[iii++];
+				double wwi1 = w[iii++];
+				// double wwr1 = wr * wr1 - wi * wi1; // these numbers can be
+				// precomputed!!!
+				// double wwi1 = wr * wi1 + wi * wr1;
+
+				int m = n + jmax;
+
+				double datam1_r = data[m];
+				double datam1_i = data[m + 1];
+				double datan1_r = data[n];
+				double datan1_i = data[n + 1];
+
+				n += nnstep;
+				m += nnstep;
+				double datam2_r = data[m];
+				double datam2_i = data[m + 1];
+				double datan2_r = data[n];
+				double datan2_i = data[n + 1];
+
+				double tempr = datam1_r * wr - datam1_i * wi;
+				double tempi = datam1_r * wi + datam1_i * wr;
+
+				datam1_r = datan1_r - tempr;
+				datam1_i = datan1_i - tempi;
+				datan1_r = datan1_r + tempr;
+				datan1_i = datan1_i + tempi;
+
+				double n2w1r = datan2_r * wr1 - datan2_i * wi1;
+				double n2w1i = datan2_r * wi1 + datan2_i * wr1;
+				double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1;
+				double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1;
+
+				tempr = m2ww1r - n2w1r;
+				tempi = m2ww1i - n2w1i;
+
+				datam2_r = datam1_r + tempi;
+				datam2_i = datam1_i - tempr;
+				datam1_r = datam1_r - tempi;
+				datam1_i = datam1_i + tempr;
+
+				tempr = n2w1r + m2ww1r;
+				tempi = n2w1i + m2ww1i;
+
+				datan2_r = datan1_r - tempr;
+				datan2_i = datan1_i - tempi;
+				datan1_r = datan1_r + tempr;
+				datan1_i = datan1_i + tempi;
+
+				data[m] = datam2_r;
+				data[m + 1] = datam2_i;
+				data[n] = datan2_r;
+				data[n + 1] = datan2_i;
+
+				n -= nnstep;
+				m -= nnstep;
+				data[m] = datam1_r;
+				data[m + 1] = datam1_i;
+				data[n] = datan1_r;
+				data[n + 1] = datan1_i;
+
+			}
+
+			i += jmax << 1;
+
+		}
+
+	}
+
+	// Perform Factor-4 Decomposition with 3 * complex operators and 8 +/-
+	// complex operators
+
+	private final static void calcF4IE(int fftFrameSize, double[] data, int i,
+			int nstep, double[] w) {
+		final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize;
+		// Factor-4 Decomposition
+
+		int w_len = w.length >> 1;
+		while (nstep < fftFrameSize2) {
+
+			int jmax = nstep;
+			int nnstep = nstep << 1;
+			if (nnstep == fftFrameSize2) {
+				// Factor-4 Decomposition not possible
+				calcF2E(fftFrameSize, data, i, nstep, w);
+				return;
+			}
+			nstep <<= 2;
+			int ii = i + jmax;
+			int iii = i + w_len;
+			for (int n = 0; n < jmax; n += 2) {
+				double wr = w[i++];
+				double wi = w[i++];
+				double wr1 = w[ii++];
+				double wi1 = w[ii++];
+				double wwr1 = w[iii++];
+				double wwi1 = w[iii++];
+				// double wwr1 = wr * wr1 - wi * wi1; // these numbers can be
+				// precomputed!!!
+				// double wwi1 = wr * wi1 + wi * wr1;
+
+				int m = n + jmax;
+
+				double datam1_r = data[m];
+				double datam1_i = data[m + 1];
+				double datan1_r = data[n];
+				double datan1_i = data[n + 1];
+
+				n += nnstep;
+				m += nnstep;
+				double datam2_r = data[m];
+				double datam2_i = data[m + 1];
+				double datan2_r = data[n];
+				double datan2_i = data[n + 1];
+
+				double tempr = datam1_r * wr - datam1_i * wi;
+				double tempi = datam1_r * wi + datam1_i * wr;
+
+				datam1_r = datan1_r - tempr;
+				datam1_i = datan1_i - tempi;
+				datan1_r = datan1_r + tempr;
+				datan1_i = datan1_i + tempi;
+
+				double n2w1r = datan2_r * wr1 - datan2_i * wi1;
+				double n2w1i = datan2_r * wi1 + datan2_i * wr1;
+				double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1;
+				double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1;
+
+				tempr = n2w1r - m2ww1r;
+				tempi = n2w1i - m2ww1i;
+
+				datam2_r = datam1_r + tempi;
+				datam2_i = datam1_i - tempr;
+				datam1_r = datam1_r - tempi;
+				datam1_i = datam1_i + tempr;
+
+				tempr = n2w1r + m2ww1r;
+				tempi = n2w1i + m2ww1i;
+
+				datan2_r = datan1_r - tempr;
+				datan2_i = datan1_i - tempi;
+				datan1_r = datan1_r + tempr;
+				datan1_i = datan1_i + tempi;
+
+				data[m] = datam2_r;
+				data[m + 1] = datam2_i;
+				data[n] = datan2_r;
+				data[n + 1] = datan2_i;
+
+				n -= nnstep;
+				m -= nnstep;
+				data[m] = datam1_r;
+				data[m + 1] = datam1_i;
+				data[n] = datan1_r;
+				data[n + 1] = datan1_i;
+
+			}
+
+			i += jmax << 1;
+
+		}
+
+	}
+
+	private final void bitreversal(double[] data) {
+		if (fftFrameSize < 4)
+			return;
+
+		int inverse = fftFrameSize2 - 2;
+		for (int i = 0; i < fftFrameSize; i += 4) {
+			int j = bitm_array[i];
+
+			// Performing Bit-Reversal, even v.s. even, O(2N)
+			if (i < j) {
+
+				int n = i;
+				int m = j;
+
+				// COMPLEX: SWAP(data[n], data[m])
+				// Real Part
+				double tempr = data[n];
+				data[n] = data[m];
+				data[m] = tempr;
+				// Imagery Part
+				n++;
+				m++;
+				double tempi = data[n];
+				data[n] = data[m];
+				data[m] = tempi;
+
+				n = inverse - i;
+				m = inverse - j;
+
+				// COMPLEX: SWAP(data[n], data[m])
+				// Real Part
+				tempr = data[n];
+				data[n] = data[m];
+				data[m] = tempr;
+				// Imagery Part
+				n++;
+				m++;
+				tempi = data[n];
+				data[n] = data[m];
+				data[m] = tempi;
+			}
+
+			// Performing Bit-Reversal, odd v.s. even, O(N)
+
+			int m = j + fftFrameSize; // bitm_array[i+2];
+			// COMPLEX: SWAP(data[n], data[m])
+			// Real Part
+			int n = i + 2;
+			double tempr = data[n];
+			data[n] = data[m];
+			data[m] = tempr;
+			// Imagery Part
+			n++;
+			m++;
+			double tempi = data[n];
+			data[n] = data[m];
+			data[m] = tempi;
+		}
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/InvalidDataException.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,49 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+
+/**
+ * This exception is used when a file
+ * contains illegal or unexpected data.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class InvalidDataException extends IOException {
+
+	private static final long serialVersionUID = 1L;
+
+	public InvalidDataException() {
+		super("Invalid Data!");
+	}
+
+	public InvalidDataException(String s) {
+		super(s);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/InvalidFormatException.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,48 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * This exception is used when a reader
+ * is used to read file of a format it doesn't unterstand
+ * or support.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class InvalidFormatException extends InvalidDataException {
+
+	private static final long serialVersionUID = 1L;
+
+	public InvalidFormatException() {
+		super("Invalid format!");
+	}
+
+	public InvalidFormatException(String s) {
+		super(s);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/JARSoundbankReader.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,118 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.spi.SoundbankReader;
+
+/**
+ * JarSoundbankReader is ued to read sounbank object from jar files.
+ *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+
+public class JARSoundbankReader extends SoundbankReader {
+
+	public boolean isZIP(URL url)
+	{
+		boolean ok = false;
+		try
+		{
+			InputStream stream = url.openStream();
+			try
+			{
+				byte[] buff = new byte[4];
+				ok = stream.read(buff) == 4;
+				if(ok)
+				{
+					ok = (buff[0] == 0x50 &&
+					buff[1] == 0x4b &&
+					buff[2] == 0x03 &&
+					buff[3] == 0x04);					
+				}
+			}
+			finally
+			{
+				stream.close();
+			}
+		}
+		catch(IOException e)
+		{
+		}
+		return ok;
+	}
+	
+	public Soundbank getSoundbank(URL url) throws InvalidMidiDataException, IOException {
+		if(!isZIP(url)) return null;
+		ArrayList<Soundbank> soundbanks = new ArrayList<Soundbank>();		
+		URLClassLoader ucl = URLClassLoader.newInstance(new URL[] {url});
+		InputStream stream = ucl.getResourceAsStream("META-INF/services/javax.sound.midi.Soundbank");
+		if(stream == null) return null;
+		BufferedReader r = new BufferedReader(new InputStreamReader(stream));
+		String line = r.readLine();
+		while (line != null) {
+			if (!line.startsWith("#")) {
+				try {
+					Class c = Class.forName(line.trim(), true, ucl);
+					Object o = c.newInstance();
+					if (o instanceof Soundbank) {
+						soundbanks.add((Soundbank)o);
+					}
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+			line = r.readLine();
+		}
+		stream.close();		
+		if(soundbanks.size() == 0) return null;
+		if(soundbanks.size() == 1) return soundbanks.get(0); 
+		SimpleSoundbank sbk = new SimpleSoundbank();
+		for (Soundbank soundbank : soundbanks) 
+			sbk.addAllInstruments(soundbank);
+		return sbk;
+	}
+
+	public Soundbank getSoundbank(InputStream stream) throws InvalidMidiDataException, IOException {
+		return null;
+	}
+
+	public Soundbank getSoundbank(File file) throws InvalidMidiDataException, IOException {
+		return getSoundbank(file.toURI().toURL());
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/LICENSE	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,347 @@
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it.  By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users.  This General Public License applies to
+most of the Free Software Foundation's software and to any other program whose
+authors commit to using it.  (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price.  Our
+General Public Licenses are designed to make sure that you have the freedom to
+distribute copies of free software (and charge for this service if you wish),
+that you receive source code or can get it if you want it, that you can change
+the software or use pieces of it in new free programs; and that you know you
+can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights.  These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for
+a fee, you must give the recipients all the rights that you have.  You must
+make sure that they, too, receive or can get the source code.  And you must
+show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software.  If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced
+by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents.  We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program proprietary.
+To prevent this, we have made it clear that any patent must be licensed for
+everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License.  The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or
+translated into another language.  (Hereinafter, translation is included
+without limitation in the term "modification".) Each licensee is addressed as
+"you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope.  The act of running the Program is
+not restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program).  Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this License
+and to the absence of any warranty; and give any other recipients of the
+Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may
+at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such modifications
+or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+    a) You must cause the modified files to carry prominent notices stating
+    that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in whole or
+    in part contains or is derived from the Program or any part thereof, to be
+    licensed as a whole at no charge to all third parties under the terms of
+    this License.
+
+    c) If the modified program normally reads commands interactively when run,
+    you must cause it, when started running for such interactive use in the
+    most ordinary way, to print or display an announcement including an
+    appropriate copyright notice and a notice that there is no warranty (or
+    else, saying that you provide a warranty) and that users may redistribute
+    the program under these conditions, and telling the user how to view a copy
+    of this License.  (Exception: if the Program itself is interactive but does
+    not normally print such an announcement, your work based on the Program is
+    not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License, and
+its terms, do not apply to those sections when you distribute them as separate
+works.  But when you distribute the same sections as part of a whole which is a
+work based on the Program, the distribution of the whole must be on the terms
+of this License, whose permissions for other licensees extend to the entire
+whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise the
+right to control the distribution of derivative or collective works based on
+the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and
+2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable source
+    code, which must be distributed under the terms of Sections 1 and 2 above
+    on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three years, to
+    give any third party, for a charge no more than your cost of physically
+    performing source distribution, a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of Sections 1
+    and 2 above on a medium customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer to
+    distribute corresponding source code.  (This alternative is allowed only
+    for noncommercial distribution and only if you received the program in
+    object code or executable form with such an offer, in accord with
+    Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it.  For an executable work, complete source code means all
+the source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and installation
+of the executable.  However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in either
+source or binary form) with the major components (compiler, kernel, and so on)
+of the operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License.  Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License.  However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so
+long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works.  These actions are prohibited by law if you do not
+accept this License.  Therefore, by modifying or distributing the Program (or
+any work based on the Program), you indicate your acceptance of this License to
+do so, and all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to
+copy, distribute or modify the Program subject to these terms and conditions.
+You may not impose any further restrictions on the recipients' exercise of the
+rights granted herein.  You are not responsible for enforcing compliance by
+third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues), conditions
+are imposed on you (whether by court order, agreement or otherwise) that
+contradict the conditions of this License, they do not excuse you from the
+conditions of this License.  If you cannot distribute so as to satisfy
+simultaneously your obligations under this License and any other pertinent
+obligations, then as a consequence you may not distribute the Program at all.
+For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through
+you, then the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply and
+the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or
+other property right claims or to contest validity of any such claims; this
+section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices.  Many
+people have made generous contributions to the wide range of software
+distributed through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing to
+distribute software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an explicit
+geographical distribution limitation excluding those countries, so that
+distribution is permitted only in or among countries not thus excluded.  In
+such case, this License incorporates the limitation as if written in the body
+of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time.  Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems
+or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any later
+version", you have the option of following the terms and conditions either of
+that version or of any later version published by the Free Software Foundation.
+If the Program does not specify a version number of this License, you may
+choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission.  For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of
+all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN OTHERWISE
+STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
+PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
+ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
+PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
+BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
+OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest possible
+use to the public, the best way to achieve this is to make it free software
+which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program.  It is safest to attach
+them to the start of each source file to most effectively convey the exclusion
+of warranty; and each file should have at least the "copyright" line and a
+pointer to where the full notice is found.
+
+    One line to give the program's name and a brief idea of what it does.
+
+    Copyright (C) <year> <name of author>
+
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the Free
+    Software Foundation; either version 2 of the License, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc., 59
+    Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when it
+starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+    with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free
+    software, and you are welcome to redistribute it under certain conditions;
+    type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may be
+called something other than 'show w' and 'show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.  Here
+is a sample; alter the names:
+
+    Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+    'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+    signature of Ty Coon, 1 April 1989
+
+    Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General Public
+License instead of this License.
+
+
+"CLASSPATH" EXCEPTION TO THE GPL
+
+Certain source files distributed by Sun Microsystems, Inc.  are subject to
+the following clarification and special exception to the GPL, but only where
+Sun has expressly included in the particular source file's header the words
+"Sun designates this particular file as subject to the "Classpath" exception
+as provided by Sun in the LICENSE file that accompanied this code."
+
+    Linking this library statically or dynamically with other modules is making
+    a combined work based on this library.  Thus, the terms and conditions of
+    the GNU General Public License cover the whole combination.
+
+    As a special exception, the copyright holders of this library give you
+    permission to link this library with independent modules to produce an
+    executable, regardless of the license terms of these independent modules,
+    and to copy and distribute the resulting executable under terms of your
+    choice, provided that you also meet, for each linked independent module,
+    the terms and conditions of the license of that module.  An independent
+    module is a module which is not derived from or based on this library.  If
+    you modify this library, you may extend this exception to your version of
+    the library, but you are not obligated to do so.  If you do not wish to do
+    so, delete this exception statement from your version.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelAbstractChannelMixer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,130 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * ModelAbstractChannelMixer is ready for use class for implement ModelChannelMixer interface.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+
+public abstract class ModelAbstractChannelMixer implements ModelChannelMixer {
+
+	public abstract boolean process(float[][] buffer, int offset, int len);
+
+	public abstract void stop();
+
+	public void allNotesOff() {
+	}
+
+	public void allSoundOff() {
+	}
+
+	public void controlChange(int controller, int value) {
+	}
+
+	public int getChannelPressure() {
+		return 0;
+	}
+
+	public int getController(int controller) {
+		return 0;
+	}
+
+	public boolean getMono() {
+		return false;
+	}
+
+	public boolean getMute() {
+		return false;
+	}
+
+	public boolean getOmni() {
+		return false;
+	}
+
+	public int getPitchBend() {
+		return 0;
+	}
+
+	public int getPolyPressure(int noteNumber) {
+		return 0;
+	}
+
+	public int getProgram() {
+		return 0;
+	}
+
+	public boolean getSolo() {
+		return false;
+	}
+
+	public boolean localControl(boolean on) {
+		return false;
+	}
+
+	public void noteOff(int noteNumber) {
+	}
+
+	public void noteOff(int noteNumber, int velocity) {
+	}
+
+	public void noteOn(int noteNumber, int velocity) {
+	}
+
+	public void programChange(int program) {
+	}
+
+	public void programChange(int bank, int program) {
+	}
+
+	public void resetAllControllers() {
+	}
+
+	public void setChannelPressure(int pressure) {
+	}
+
+	public void setMono(boolean on) {
+	}
+
+	public void setMute(boolean mute) {
+	}
+
+	public void setOmni(boolean on) {
+	}
+
+	public void setPitchBend(int bend) {
+	}
+
+	public void setPolyPressure(int noteNumber, int pressure) {
+	}
+
+	public void setSolo(boolean soloState) {
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelAbstractOscillator.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,205 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.SoundbankResource;
+import javax.sound.midi.VoiceStatus;
+
+/**
+ * 
+ * A abstract class used to simplify creating custom ModelOscillator.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+
+public abstract class ModelAbstractOscillator implements ModelOscillator, ModelOscillatorStream, Soundbank {
+	
+	protected float pitch = 6000;
+	protected float samplerate;
+	protected MidiChannel channel;
+	protected VoiceStatus voice;
+	protected int noteNumber;
+	protected int velocity;
+	protected boolean on = false;
+	
+	public void init() {		
+	}
+
+	public void close() throws IOException {
+	}
+
+	public void noteOff(int velocity) {
+		on = false;
+	}
+
+	public void noteOn(MidiChannel channel, VoiceStatus voice, int noteNumber, int velocity) {
+		this.channel = channel;
+		this.voice = voice;
+		this.noteNumber = noteNumber;
+		this.velocity = velocity;
+		on = true;
+	}
+
+	public int read(float[][] buffer, int offset, int len) throws IOException
+	{
+		return -1;
+	}	
+	
+	public MidiChannel getChannel() {
+		return channel;
+	}
+
+	public VoiceStatus getVoice() {
+		return voice;
+	}
+
+	public int getNoteNumber() {
+		return noteNumber;
+	}
+
+	public int getVelocity() {
+		return velocity;
+	}
+
+	public boolean isOn() {
+		return on;
+	}
+
+	public void setPitch(float pitch) {
+		this.pitch = pitch;
+	}
+	
+	public float getPitch()
+	{
+		return pitch;
+	}
+
+	public void setSampleRate(float samplerate) {
+		this.samplerate = samplerate;
+	}
+	
+	public float getSampleRate()
+	{
+		return samplerate;
+	}	
+	
+	public float getAttenuation() {
+		return 0;
+	}
+	
+	public int getChannels() {
+		return 1;
+	}
+	
+	public String getName() {
+		return getClass().getName();
+	}
+	
+	public Patch getPatch() {
+		return new Patch(0,0);
+	}
+	
+	public ModelOscillatorStream open(float samplerate) {
+		ModelAbstractOscillator oscs;
+		try {
+			oscs = this.getClass().newInstance();
+		} catch (InstantiationException e) {
+			throw new IllegalArgumentException(e.getMessage());
+		} catch (IllegalAccessException e) {
+			throw new IllegalArgumentException(e.getMessage());
+		}
+		oscs.setSampleRate(samplerate);
+		oscs.init();
+		return oscs;
+	}					
+
+	public ModelPerformer getPerformer()
+	{
+		// Create performer for my custom oscillirator
+		ModelPerformer performer = new ModelPerformer();
+		performer.getOscillators().add(this);		
+		return performer;
+		
+	}	
+
+	public ModelInstrument getInstrument()
+	{		
+		// Create Instrument object around my performer
+		SimpleInstrument ins = new SimpleInstrument();
+		ins.setName(getName());
+		ins.add(getPerformer());
+		ins.setPatch(getPatch());		
+		return ins;
+		
+	}
+	
+	public Soundbank getSoundBank()
+	{
+		// Create Soundbank object around the instrument
+		SimpleSoundbank sbk = new SimpleSoundbank();
+		sbk.addInstrument(getInstrument());
+		return sbk;
+	}
+
+	public String getDescription() {
+		return getName();
+	}
+
+	public Instrument getInstrument(Patch patch) {
+		Instrument ins = getInstrument();
+		Patch p = ins.getPatch();
+		if(p.getBank() != patch.getBank()) return null;
+		if(p.getProgram() != patch.getProgram()) return null;
+		if(p instanceof ModelPatch && patch instanceof ModelPatch)
+			if( ((ModelPatch)p).isPercussion() != ((ModelPatch)patch).isPercussion())
+				return null;		
+		return ins;
+	}
+
+	public Instrument[] getInstruments() {
+		return new Instrument[] { getInstrument() };
+	}
+
+	public SoundbankResource[] getResources() {
+		return new SoundbankResource[0];
+	}
+
+	public String getVendor() {
+		return null;
+	}
+
+	public String getVersion() {
+		return null;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,347 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.util.Collection;
+
+/**
+ * 
+ * This class is a pointer to a binary array either in memory or on disk.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelByteBuffer {
+	
+	private ModelByteBuffer root = this;
+	private File file;
+	private long fileoffset;
+	private byte[] buffer;
+	private long offset;
+	private long len;
+	
+	private class RandomFileInputStream extends InputStream
+	{
+		private RandomAccessFile raf;
+		private long left;
+		private long mark = 0;
+		private long markleft = 0;
+		
+		public RandomFileInputStream() throws IOException		
+		{
+			raf = new RandomAccessFile(root.file, "r");
+			raf.seek(root.fileoffset + arrayOffset());
+			left = capacity();
+		}		
+				
+		public int available() throws IOException {
+			if(left > Integer.MAX_VALUE) return Integer.MAX_VALUE;
+			return (int)left;
+		}
+
+		public synchronized void mark(int readlimit) {
+			try {
+				mark = raf.getFilePointer();
+				markleft = left;
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+		
+		public boolean markSupported() {
+			return true;
+		}
+		
+		public synchronized void reset() throws IOException {
+			raf.seek(mark);
+			left = markleft;
+		}
+
+		public long skip(long n) throws IOException {
+			if(n > left) n = left;
+			n = super.skip(n);
+			if(n == -1) return -1;
+			left -= n;
+			return n;
+		}
+		
+		public int read(byte b[], int off, int len) throws IOException {
+			if(len > left) len = (int)left;
+			if(left == 0) 
+				return -1;
+			len = raf.read(b, off, len);
+			if(len == -1) 
+				return -1;
+			left -= len;
+			return len;
+		}
+			
+		public int read(byte[] b) throws IOException {
+			if(len > left) len = (int)left;
+			if(left == 0) 
+				return -1;
+			int len = raf.read(b);
+			if(len == -1) 
+				return -1;
+			left -= len;
+			return len;		}
+
+		public int read() throws IOException {
+			if(len == 0) 
+				return -1;
+			int b = raf.read();
+			if(b == -1) 
+				return -1;
+			len--;
+			return b;
+		}
+		
+		public void close() throws IOException
+		{
+			raf.close();
+		}
+		
+	}
+	
+	private ModelByteBuffer(ModelByteBuffer parent, long beginIndex, long endIndex, boolean independent)
+	{
+		this.root = parent.root;
+		this.offset = 0;
+		this.len = parent.len;
+		if(beginIndex < 0) beginIndex = 0;
+		if(beginIndex > len) beginIndex = len;
+		if(endIndex < 0) endIndex = 0;
+		if(endIndex > len) endIndex = len;
+		if(beginIndex > endIndex) beginIndex = endIndex;
+		offset = beginIndex;
+		len = endIndex - beginIndex;
+		if(independent)
+		{
+			buffer = root.buffer;
+			if(root.file != null)
+			{
+				file = root.file;
+				fileoffset = root.fileoffset + arrayOffset();
+				offset = 0;
+			}
+			else
+				offset = arrayOffset();
+			root = this;						
+		}
+	}
+	
+	public ModelByteBuffer(byte[] buffer)
+	{
+		this.buffer = buffer;
+		this.offset = 0;
+		this.len = buffer.length;
+	}
+	
+	public ModelByteBuffer(byte[] buffer, int offset, int len)
+	{
+		this.buffer = buffer;
+		this.offset = offset;
+		this.len = len;	
+	}
+
+	public ModelByteBuffer(File file)
+	{
+		this.file = file;
+		this.fileoffset = 0;
+		this.len = file.length();
+	}
+	
+	public ModelByteBuffer(File file, long offset, long len)
+	{
+		this.file = file;
+		this.fileoffset = offset;
+		this.len = len;	
+	}	
+	
+	public void writeTo(OutputStream out) throws IOException
+	{		
+		if(root.file != null && root.buffer == null)
+		{
+			InputStream is = getInputStream();
+			byte[] buff = new byte[1024];
+			int ret;
+			while((ret = is.read(buff)) != -1)
+				out.write(buff, 0, ret);							
+		}
+		else
+			out.write(array(), (int)arrayOffset(), (int)capacity());
+	}
+	
+	public InputStream getInputStream()
+	{
+		if(root.file != null && root.buffer == null)
+			try {
+				return new RandomFileInputStream();
+			} catch (IOException e) {
+				e.printStackTrace();
+				return null;
+			}
+		return new ByteArrayInputStream(array(), (int)arrayOffset(), (int)capacity());
+	}
+	
+	public  ModelByteBuffer subbuffer(long beginIndex)
+	{
+		return subbuffer(beginIndex, capacity());
+	}	
+
+	public  ModelByteBuffer subbuffer(long beginIndex, long endIndex)
+	{
+		return subbuffer(beginIndex, endIndex, false);
+	}
+	
+	public  ModelByteBuffer subbuffer(long beginIndex, long endIndex, boolean independent)
+	{
+		return new ModelByteBuffer(this, beginIndex, endIndex, independent);
+	}
+	
+	public byte[] array()
+	{
+		return root.buffer;
+	}
+	
+	public long arrayOffset()
+	{
+		if(root != this)
+			return root.arrayOffset() + offset;
+		return offset;
+	}
+	
+	public long capacity()
+	{
+		return len;
+	}
+
+	public ModelByteBuffer getRoot()
+	{
+		return root;
+	}
+	
+	public File getFile()
+	{
+		return file;
+	}	
+
+	public long getFilePointer()
+	{
+		return fileoffset;
+	}	
+	
+	public static void loadAll(Collection<ModelByteBuffer> col) throws IOException
+	{
+		File selfile = null;
+		RandomAccessFile raf = null;
+		try
+		{
+			for(ModelByteBuffer mbuff : col)
+			{
+				mbuff = mbuff.root;
+				if(mbuff.file == null) continue;
+				if(mbuff.buffer != null) continue;
+				if(selfile == null || !selfile.equals(mbuff.file))
+				{					
+					if(raf != null)
+					{
+						raf.close();
+						raf = null;
+					}
+					selfile = mbuff.file;
+					raf = new RandomAccessFile(mbuff.file, "r");				
+				}
+				raf.seek(mbuff.fileoffset);
+				byte[] buffer = new byte[(int)mbuff.capacity()];
+				
+				int read = 0;
+				int avail = buffer.length;
+				while(read != avail)
+				{
+					if(avail - read > 65536)
+					{
+						raf.read(buffer, read, 65536);
+						read += 65536;
+					}
+					else
+					{
+						raf.read(buffer, read, avail - read);
+						read = avail;
+					}
+					
+				}
+
+				mbuff.buffer = buffer;
+				mbuff.offset = 0;
+			}
+		}
+		finally
+		{
+			if(raf != null) 
+				raf.close();
+		}
+	}
+	
+	public void load() throws IOException
+	{
+		if(root != this) 
+		{
+			root.load();
+			return;
+		}
+		if(buffer != null)
+			return;		
+		if(file == null)		
+			throw new IllegalStateException("No file associated with this ByteBuffer!");
+		
+		InputStream is = getInputStream();
+		buffer = new byte[(int)capacity()];
+		offset = 0;
+		is.read(buffer);
+		is.close();
+		
+	}
+	
+	public void unload()
+	{
+		if(root != this) 
+		{
+			root.unload();
+			return;
+		}
+		if(file == null)		
+			throw new IllegalStateException("No file associated with this ByteBuffer!");		
+		root.buffer = null;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,296 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.AudioFormat.Encoding;
+
+/**
+ * 
+ * Wavetable oscillator for pre-loaded data.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelByteBufferWavetable implements ModelWavetable
+{
+	private class Buffer8PlusInputStream extends InputStream
+	{
+		
+		private boolean bigendian;
+		private int framesize_pc;
+				
+		
+		int pos = 0;
+		int pos2 = 0;
+		
+		int markpos = 0;
+		int markpos2 = 0;
+		
+		public Buffer8PlusInputStream()
+		{
+			framesize_pc = format.getFrameSize() / format.getChannels();
+			bigendian = format.isBigEndian();
+		}
+		
+		public int read(byte[] b, int off, int len) throws IOException {
+			int avail = available();
+			if(avail <= 0) return -1;
+			if(len > avail) len = avail;
+			byte[] buff1 = buffer.array();
+			byte[] buff2 = buffer8.array();
+			pos += buffer.arrayOffset();
+			pos2 += buffer8.arrayOffset();
+			if(bigendian)			
+				for (int i = 0; i < len; i+=(framesize_pc+1)) {
+					System.arraycopy(buff1, pos, b, i, framesize_pc);
+					System.arraycopy(buff2, pos2, b, i + framesize_pc, 1);
+					pos += framesize_pc;
+					pos2 += 1;
+				}
+			else			
+				for (int i = 0; i < len; i+=(framesize_pc+1)) {
+					System.arraycopy(buff2, pos2, b, i, 1);					
+					System.arraycopy(buff1, pos, b, i+1, framesize_pc);					
+					pos += framesize_pc;
+					pos2 += 1;
+				}
+			pos -= buffer.arrayOffset();		
+			pos2 -= buffer8.arrayOffset();			
+			return len;
+		}
+		public long skip(long n) throws IOException {
+			int avail = available();
+			if(avail <= 0) return -1;
+			if(n > avail) n = avail;
+			pos += (n / (framesize_pc+1)) * (framesize_pc);
+			pos2 += n / (framesize_pc+1);
+			return super.skip(n);
+		}		
+		
+		public int read(byte[] b) throws IOException {
+			return read(b, 0, b.length);
+		}
+		public int read() throws IOException {
+			byte[] b = new byte[1];
+			int ret = read(b, 0, 1);
+			if(ret == -1) return -1;
+			return 0 & 0xFF;
+		}
+		
+	    public boolean markSupported() {
+	    	return true;
+	    }
+
+		public int available() throws IOException {
+			return (int)buffer.capacity() + (int)buffer8.capacity() - pos - pos2;
+		}
+
+		public synchronized void mark(int readlimit) {
+			markpos = pos;
+			markpos2 = pos2;			
+		}
+
+		public synchronized void reset() throws IOException {
+			pos = markpos;
+			pos2 = markpos2;
+			
+		}
+
+	}
+	
+	private float loopStart = -1;
+	private float loopLength = -1;
+	private ModelByteBuffer buffer;
+	private ModelByteBuffer buffer8 = null;
+	private AudioFormat format = null;
+	private float pitchcorrection = 0;
+	private float attenuation = 0;
+	private int loopType = LOOP_TYPE_OFF;
+		
+	public ModelByteBufferWavetable(ModelByteBuffer buffer)
+	{
+		this.buffer = buffer;
+	}
+	
+	public ModelByteBufferWavetable(ModelByteBuffer buffer, float pitchcorrection)
+	{
+		this.buffer = buffer;
+		this.pitchcorrection = pitchcorrection;
+	}
+	
+	public ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format)
+	{
+		this.format = format;
+		this.buffer = buffer;
+	}
+	
+	public ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format, float pitchcorrection)
+	{
+		this.format = format;
+		this.buffer = buffer;
+		this.pitchcorrection = pitchcorrection;
+	}
+	
+	public void set8BitExtensionBuffer(ModelByteBuffer buffer)
+	{
+		buffer8 = buffer;
+	}
+	
+	public ModelByteBuffer get8BitExtensionBuffer()
+	{
+		return buffer8;
+	}	
+	
+	public ModelByteBuffer getBuffer()
+	{
+		return buffer;
+	}
+	
+	public AudioFormat getFormat()
+	{
+		if(format == null)
+		{
+			if(buffer == null) return null;
+			InputStream is = buffer.getInputStream();
+			AudioFormat format = null;
+			try
+			{
+				format = AudioSystem.getAudioFileFormat(is).getFormat();				
+			}
+			catch(Exception e)
+			{			
+				e.printStackTrace();
+			}
+			try {
+				is.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			return format;
+		}
+		return format;
+	}
+	
+	public AudioFloatInputStream openStream() 
+	{
+		if(buffer == null) return null;
+		if(format == null)
+		{
+			InputStream is = buffer.getInputStream();
+			AudioInputStream ais = null;
+			try
+			{
+				ais = AudioSystem.getAudioInputStream(is);				
+			}
+			catch(Exception e)
+			{			
+				e.printStackTrace();
+			}
+			return AudioFloatInputStream.getInputStream(ais);
+		}
+		if(buffer.array() == null)
+			 return AudioFloatInputStream.getInputStream(new AudioInputStream(buffer.getInputStream(),  format, buffer.capacity()));			
+		if(buffer8 != null)
+		{
+			if(format.getEncoding().equals(Encoding.PCM_SIGNED)
+					|| format.getEncoding().equals(Encoding.PCM_UNSIGNED))
+			{
+				InputStream is = new Buffer8PlusInputStream();
+				AudioFormat format2 = new AudioFormat(
+						format.getEncoding(), 
+						format.getSampleRate(), 
+						format.getSampleSizeInBits()+8,
+						format.getChannels(),
+						format.getFrameSize()+(1*format.getChannels()),
+						format.getFrameRate(),
+						format.isBigEndian());
+
+				AudioInputStream ais = new AudioInputStream(is, format2, buffer.capacity() / format.getFrameSize());
+				return AudioFloatInputStream.getInputStream(ais);
+			}
+		}
+		return AudioFloatInputStream.getInputStream(format, buffer.array(), (int)buffer.arrayOffset(), (int)buffer.capacity());
+		
+	}
+	
+	public int getChannels()
+	{
+		return getFormat().getChannels();
+	}
+
+	public ModelOscillatorStream open(float samplerate) {
+		// ModelWavetableOscillator doesn't support ModelOscillatorStream		
+		return null;
+	}	
+	
+	// attenuation is in cB
+	public float getAttenuation() {
+		return attenuation;
+	}
+	// attenuation is in cB
+	public void setAttenuation(float attenuation) {
+		this.attenuation = attenuation;
+	}
+	
+	public float getLoopLength() {
+		return loopLength;
+	}
+
+	public void setLoopLength(float loopLength) {
+		this.loopLength = loopLength;
+	}
+
+	public float getLoopStart() {		
+		return loopStart;
+	}
+
+	public void setLoopStart(float loopStart) {
+		this.loopStart = loopStart;
+	}
+	
+	public void setLoopType(int loopType) {
+		this.loopType = loopType;
+	}
+	
+	public int getLoopType() {
+		return loopType;
+	}	
+
+	public float getPitchcorrection() {
+		return pitchcorrection;
+	}
+
+	public void setPitchcorrection(float pitchcorrection) {
+		this.pitchcorrection = pitchcorrection;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelChannelMixer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,54 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import javax.sound.midi.MidiChannel;
+
+/**
+ * 
+ * ModelChannelMixer is used to process channel voice mix output
+ * before going to master output.<br> 
+ * It can be used to:<br>
+ * <ul>
+ *   <li>Implement non-voice oriented instruments.</li>
+ *   <li>Add insert effect to instruments for example: distortion effect.</li>
+ * </ui>
+ * <p>
+ * <b>Warning! Classes that implements ModelChannelMixer must be thread-safe.</b>
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public interface ModelChannelMixer extends MidiChannel {
+	
+	// Used to process input audio from voices mix.
+	public boolean process(float[][] buffer, int offset, int len);
+	
+	// Is used to trigger that this mixer is not be used
+	// and it should fade out.
+	public void stop();
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelConnectionBlock.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,149 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * Connection blocks are used to connect source variable
+ * to a destination variable. 
+ * For example Note On velocity can be connected to output gain.
+ * In DLS this is called articulator and in SoundFonts (SF2) a modulator.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelConnectionBlock {
+	
+	//
+	//   source1 * source2 * scale -> destination 
+	//
+	
+	private final static ModelSource[] no_sources = new ModelSource[0]; 
+	
+	private ModelSource[] sources = no_sources;
+	private double scale = 1;	
+	private ModelDestination destination;
+	
+	public ModelConnectionBlock()
+	{		
+	}
+	public ModelConnectionBlock(double scale, ModelDestination destination)
+	{		
+		this.scale = scale;
+		this.destination = destination;
+	}	
+	public ModelConnectionBlock(ModelSource source, ModelDestination destination)
+	{	
+		if(source != null)
+		{		
+			this.sources = new ModelSource[1];
+			this.sources[0] = source;
+		}
+		this.destination = destination;
+	}
+	public ModelConnectionBlock(ModelSource source, double scale, ModelDestination destination)
+	{
+		if(source != null)
+		{		
+			this.sources = new ModelSource[1];
+			this.sources[0] = source;
+		}
+		this.scale = scale;		
+		this.destination = destination;
+	}
+	public ModelConnectionBlock(ModelSource source, ModelSource control, ModelDestination destination)
+	{		
+		if(source != null)
+		{
+			if(control == null)
+			{
+				this.sources = new ModelSource[1];
+				this.sources[0] = source;			
+			}
+			else
+			{
+				this.sources = new ModelSource[2];
+				this.sources[0] = source;
+				this.sources[1] = control;
+			}
+		}
+		this.destination = destination;
+	}
+	public ModelConnectionBlock(ModelSource source, ModelSource control, double scale, ModelDestination destination)
+	{		
+		if(source != null)
+		{
+			if(control == null)
+			{
+				this.sources = new ModelSource[1];
+				this.sources[0] = source;			
+			}
+			else
+			{
+				this.sources = new ModelSource[2];
+				this.sources[0] = source;
+				this.sources[1] = control;
+			}
+		}
+		this.scale = scale;
+		this.destination = destination;
+	}
+	
+	public ModelDestination getDestination() {
+		return destination;
+	}
+
+	public void setDestination(ModelDestination destination) {
+		this.destination = destination;
+	}
+
+	public double getScale() {
+		return scale;
+	}
+
+	public void setScale(double scale) {
+		this.scale = scale;
+	}
+
+	public ModelSource[] getSources() {
+		return sources;
+	}
+
+	public void setSources(ModelSource[] source) {
+		this.sources = source;
+	}
+	
+	public void addSource(ModelSource source) {
+		ModelSource[] oldsources = sources;
+		sources = new ModelSource[oldsources.length + 1];
+		for (int i = 0; i < oldsources.length; i++) {
+			sources[i] = oldsources[i];
+		}
+		sources[sources.length - 1] = source;
+		
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDestination.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,99 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * This class is used to identify destinations in connection blocks, see ModelConnectionBlock.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelDestination {
+
+	public static final ModelIdentifier DESTINATION_NONE        = null;
+	
+	public static final ModelIdentifier DESTINATION_KEYNUMBER   = new ModelIdentifier("noteon","keynumber");
+	public static final ModelIdentifier DESTINATION_VELOCITY    = new ModelIdentifier("noteon","velocity");
+
+	public static final ModelIdentifier DESTINATION_PITCH       = new ModelIdentifier("osc","pitch");   // cent
+	
+	public static final ModelIdentifier DESTINATION_GAIN        = new ModelIdentifier("mixer","gain");   // cB
+	public static final ModelIdentifier DESTINATION_PAN         = new ModelIdentifier("mixer","pan");   // 0.1 %
+	public static final ModelIdentifier DESTINATION_REVERB      = new ModelIdentifier("mixer","reverb");   // 0.1 %
+	public static final ModelIdentifier DESTINATION_CHORUS      = new ModelIdentifier("mixer","chorus");   // 0.1 %
+	
+	public static final ModelIdentifier DESTINATION_LFO1_DELAY  = new ModelIdentifier("lfo","delay",0); // timecent
+	public static final ModelIdentifier DESTINATION_LFO1_FREQ   = new ModelIdentifier("lfo","freq",0); // cent
+	
+	public static final ModelIdentifier DESTINATION_LFO2_DELAY  = new ModelIdentifier("lfo","delay",1); // timecent
+	public static final ModelIdentifier DESTINATION_LFO2_FREQ   = new ModelIdentifier("lfo","freq",1); // cent
+	
+	public static final ModelIdentifier DESTINATION_EG1_DELAY   = new ModelIdentifier("eg","delay",0); // timecent
+	public static final ModelIdentifier DESTINATION_EG1_ATTACK  = new ModelIdentifier("eg","attack",0); // timecent
+	public static final ModelIdentifier DESTINATION_EG1_HOLD    = new ModelIdentifier("eg","hold",0); // timecent
+	public static final ModelIdentifier DESTINATION_EG1_DECAY   = new ModelIdentifier("eg","decay",0); // timecent
+	public static final ModelIdentifier DESTINATION_EG1_SUSTAIN = new ModelIdentifier("eg","sustain",0); // 0.1 % ( I want this to be value not %)
+	public static final ModelIdentifier DESTINATION_EG1_RELEASE = new ModelIdentifier("eg","release",0); // timecent
+	public static final ModelIdentifier DESTINATION_EG1_SHUTDOWN = new ModelIdentifier("eg","shutdown",0); // timecent
+	
+	public static final ModelIdentifier DESTINATION_EG2_DELAY   = new ModelIdentifier("eg","delay",1); // timecent
+	public static final ModelIdentifier DESTINATION_EG2_ATTACK  = new ModelIdentifier("eg","attack",1); // timecent
+	public static final ModelIdentifier DESTINATION_EG2_HOLD    = new ModelIdentifier("eg","hold",1); // 0.1 %
+	public static final ModelIdentifier DESTINATION_EG2_DECAY   = new ModelIdentifier("eg","decay",1); // timecent
+	public static final ModelIdentifier DESTINATION_EG2_SUSTAIN = new ModelIdentifier("eg","sustain",1); // 0.1 % ( I want this to be value not %)
+	public static final ModelIdentifier DESTINATION_EG2_RELEASE = new ModelIdentifier("eg","release",1); // timecent
+	public static final ModelIdentifier DESTINATION_EG2_SHUTDOWN = new ModelIdentifier("eg","shutdown",1); // timecent
+	
+	public static final ModelIdentifier DESTINATION_FILTER_FREQ = new ModelIdentifier("filter","freq",0); // cent
+	public static final ModelIdentifier DESTINATION_FILTER_Q    = new ModelIdentifier("filter","q",0); // cB
+	
+	private ModelIdentifier destination = DESTINATION_NONE;
+	private ModelTransform transform = new ModelStandardTransform();
+	
+	public ModelDestination()
+	{		
+	}
+
+	public ModelDestination(ModelIdentifier id)
+	{
+		destination = id;
+	}
+	
+	public ModelIdentifier getIdentifier() {
+		return destination;
+	}
+	public void setIdentifier(ModelIdentifier destination) {
+		this.destination = destination;
+	}
+	public ModelTransform getTransform() {
+		return transform;
+	}
+	public void setTransform(ModelTransform transform) {
+		this.transform = transform;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDirectedPlayer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,41 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ *  ModelDirectedPlayer is the one who is directed by ModelDirector
+ *  to play ModelPerformer objects.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+
+public interface ModelDirectedPlayer {
+
+	public void play(int performerIndex, ModelConnectionBlock[] connectionBlocks);
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelDirector.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,47 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * A director chooses what performers should be 
+ * played for each note on and note off events.
+ * 
+ * ModelInstrument can implement custom performer
+ * who chooses what performers to play for example by sustain pedal is off or on.
+ * 
+ * The default director (ModelStandardDirector) chooses performers
+ * by there keyfrom,keyto,velfrom,velto properties.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+
+public interface ModelDirector {
+	   public void noteOn(int noteNumber, int velocity);
+	   public void noteOff(int noteNumber, int velocity);
+	   public void close();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelIdentifier.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,153 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * This class stores the identity of source and destinations in connection blocks, see ModelConnectionBlock.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelIdentifier {
+	
+/*
+ *  Object    Variable
+ *  ------    --------
+ *  
+ *  // INPUT parameters
+ *  noteon    keynumber                7 bit midi value
+ *            velocity                 7 bit midi vale
+ *            on                       1 or 0
+ *            
+ *  midi      pitch                    14 bit midi value
+ *            channel_pressure         7 bit midi value
+ *            poly_pressure            7 bit midi value
+ *  
+ *  midi_cc   0 (midi control #0       7 bit midi value
+ *            1 (midi control #1       7 bit midi value
+ *            ...
+ *            127 (midi control #127   7 bit midi value
+ *            
+ *  midi_rpn  0 (midi rpn control #0)  14 bit midi value
+ *            1 (midi rpn control #1)  14 bit midi value
+ *            ....
+ *  
+ *  // DAHDSR envelope generator
+ *  eg        (null)
+ *            delay                    timecent
+ *            attack                   timecent
+ *            hold                     timecent
+ *            decay                    timecent
+ *            sustain                  0.1 %
+ *            release                  timecent
+ * 
+ *  // Low frequency oscillirator (sine wave)
+ *  lfo       (null)
+ *            delay                    timcent
+ *            freq                     cent
+ *             
+ *  // Resonance LowPass Filter 6dB slope
+ *  filter    (null) (output/input)
+ *            freq                     cent
+ *            q                        cB
+ *            
+ *  // The oscillator with preloaded wavetable data           
+ *  osc       (null)
+ *            pitch                    cent
+ *            
+ *  // Output mixer pins
+ *  mixer     gain                     cB
+ *            pan                      0.1 %  
+ *            reverb                   0.1 %
+ *            chorus                   0.1 %
+ *            
+ */	
+	
+
+	private String object = null;
+	private String variable = null;
+	private int instance = 0;
+	
+	public ModelIdentifier(String object)
+	{
+		this.object = object;
+	}
+	public ModelIdentifier(String object, int instance)
+	{
+		this.object = object;
+		this.instance = instance;
+	}	
+	public ModelIdentifier(String object, String variable)
+	{
+		this.object = object;
+		this.variable = variable;
+		
+	}
+	public ModelIdentifier(String object, String variable, int instance)
+	{
+		this.object = object;
+		this.variable = variable;
+		this.instance = instance;
+
+	}
+	
+	public int getInstance() {
+		return instance;
+	}
+	public void setInstance(int instance) {
+		this.instance = instance;
+	}
+	public String getObject() {
+		return object;
+	}
+	public void setObject(String object) {
+		this.object = object;
+	}
+	public String getVariable() {
+		return variable;
+	}
+	public void setVariable(String variable) {
+		this.variable = variable;
+	}
+	
+	
+	public boolean equals(Object obj) {
+		if(!(obj instanceof ModelIdentifier)) return false;
+		ModelIdentifier mobj = (ModelIdentifier)obj;
+		if((object == null) != (mobj.object == null)) return false;
+		if((variable == null) != (mobj.variable == null)) return false;
+		if(mobj.getInstance() != getInstance()) return false;
+		if(!(object == null || object.equals(mobj.object))) return false;
+		if(!(variable == null || variable.equals(mobj.variable))) return false;
+		return true;
+		
+	}
+	public String toString()
+	{
+		if(variable == null) return object+"[" + instance + "]"; else return object + "[" + instance + "]" + "." + variable;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,143 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * 
+ * The model instrument class. 
+ * <p>
+ * The main methods to override are:<br>
+ * getPerformer, getDirector, getChannelMixer.
+ * <p>
+ * Performers are used to define what voices which will
+ * playback when using the instrument.
+ * <br>
+ * ChannelMixer is used to add channel-wide processing
+ * on voices output or to define non-voice oriented instruments.
+ * <br>
+ * Director is used to change how the synthesizer
+ * chooses what performers to play on midi events. 
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public abstract class ModelInstrument extends Instrument {
+		
+	protected ModelInstrument(Soundbank soundbank, Patch patch, String name, Class<?> dataClass) {
+		super(soundbank, patch, name, dataClass);
+	}
+	
+	public ModelDirector getDirector(ModelPerformer[] performers, MidiChannel channel, ModelDirectedPlayer player)
+	{
+		return new ModelStandardDirector(performers, player);	
+	}
+
+	public ModelPerformer[] getPerformers()
+	{
+		return new ModelPerformer[0];
+	}
+	
+	public ModelChannelMixer getChannelMixer(MidiChannel channel, AudioFormat format)
+	{
+		return null;
+	}
+	
+	// Get General MIDI 2 Alias patch for this instrument.
+	public Patch getPatchAlias()
+	{		
+		Patch patch = getPatch();
+		int program = patch.getProgram();
+		int bank = patch.getBank();		
+		if(bank != 0) return patch;
+		boolean percussion = false;
+		if(getPatch() instanceof ModelPatch)
+			percussion = ((ModelPatch)getPatch()).isPercussion();
+		if(percussion)
+			return new Patch(0x78 << 7, program);
+		else
+			return new Patch(0x79 << 7, program);		
+	}
+
+	// Return name of all the keys.
+	// This information is generated from ModelPerformer.getName() returned from getPerformers().
+	public String[] getKeys()
+	{
+		String[] keys = new String[127];
+		for(ModelPerformer performer : getPerformers())
+		{
+			for(int k = performer.getKeyFrom(); k <= performer.getKeyTo(); k++)
+			{
+				if(keys[k] == null)
+				{
+					String name = performer.getName();
+					if(name == null) name = "untitled";
+					keys[k] = name;
+				}
+			}			
+		}		
+		return keys;			
+	}	
+
+	// Return what channels this instrument will probably response on General MIDI synthesizer.	
+	public boolean[] getChannels()
+	{
+		boolean percussion = false;
+		if(getPatch() instanceof ModelPatch)
+			percussion = ((ModelPatch)getPatch()).isPercussion();
+		
+		// Check if instrument is percussion.
+		if(percussion)
+		{
+			boolean[] ch = new boolean[16];
+			for (int i = 0; i < ch.length; i++) 
+				ch[i] = false;	
+			ch[9] = true;
+			return ch;
+		}
+		
+		// Check if instrument uses General MIDI 2 default banks. 
+		int bank = getPatch().getBank();		
+		if (bank >> 7 == 0x78 || bank >> 7 == 0x79) {
+			boolean[] ch = new boolean[16];
+			for (int i = 0; i < ch.length; i++) 
+				ch[i] = true;				
+			return ch;					
+		}
+		
+		boolean[] ch = new boolean[16];
+		for (int i = 0; i < ch.length; i++) 
+			ch[i] = true;	
+		ch[9] = false;
+		return ch;		
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrumentComparator.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,55 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.util.Comparator;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.Patch;
+
+/**
+ * 
+ * Instrument comparator class. 
+ * Used to order instrument by program, bank, percussion.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelInstrumentComparator implements Comparator<Instrument>  {
+
+	public int compare(Instrument arg0, Instrument arg1) {
+			Patch p0 = arg0.getPatch();
+			Patch p1 = arg1.getPatch();
+			int a = p0.getBank() * 128 + p0.getProgram();
+			int b = p1.getBank() * 128 + p1.getProgram();
+			if (p0 instanceof ModelPatch)
+				a += ((ModelPatch) p0).isPercussion() ? 2097152 : 0;
+			if (p1 instanceof ModelPatch)
+				b += ((ModelPatch) p1).isPercussion() ? 2097152 : 0;
+			return a - b;
+	}
+		
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelMappedInstrument.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,66 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.Patch;
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * 
+ * This class is used to map instrument to another patch.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelMappedInstrument extends ModelInstrument {
+
+	private ModelInstrument ins;
+	
+	public ModelMappedInstrument(ModelInstrument ins, Patch patch) {
+		super(ins.getSoundbank(), patch, ins.getName(), ins.getDataClass());
+		this.ins = ins;
+	}
+
+	public Object getData() {
+		return ins.getData();
+	}
+
+	public ModelPerformer[] getPerformers() {
+		return ins.getPerformers();
+	}
+
+	public ModelDirector getDirector(ModelPerformer[] performers, MidiChannel channel, ModelDirectedPlayer player)
+	{
+		return ins.getDirector(performers, channel, player);	
+	}	
+
+	public ModelChannelMixer getChannelMixer(MidiChannel channel, AudioFormat format)
+	{
+		return ins.getChannelMixer(channel, format);
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelOscillator.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,44 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * This interface is used for oscillators. 
+ * See example in ModelDefaultOscillator which is a wavetable oscillator. 
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public interface ModelOscillator {
+	public int getChannels();
+	/**
+	 * Attenuation is in cB.
+	 * @return
+	 */
+	public float getAttenuation();
+	public ModelOscillatorStream open(float samplerate);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelOscillatorStream.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,46 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.VoiceStatus;
+
+/**
+ * 
+ * This interface is used for audio streams from ModelOscillator.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public interface ModelOscillatorStream {	
+	public void setPitch(float pitch); // Pitch is in cents!
+	public void noteOn(MidiChannel channel, VoiceStatus voice, int noteNumber, int velocity);
+	public void noteOff(int velocity);
+	public int read(float[][] buffer, int offset, int len) throws IOException ;
+	public void close() throws IOException ;	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelPatch.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,57 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import javax.sound.midi.Patch;
+
+/**
+ * 
+ * A extended patch object that has isPercussion function.
+ * Which is necessary to identify percussion instruments from melodic instruments.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelPatch extends Patch {
+		
+	private boolean percussion = false;
+	
+	public ModelPatch(int bank, int program) {
+		super(bank, program);		
+	}
+
+	public ModelPatch(int bank, int program, boolean percussion) {
+		super(bank, program);
+		this.percussion = percussion;
+	}
+	
+	public boolean isPercussion()
+	{
+		return percussion;
+	}
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelPerformer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,130 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 
+ * This class is used to define how to synthesize audio in universal maner
+ * for both SF2 and DLS instruments.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelPerformer {
+	
+	private List<ModelOscillator> oscillators = new ArrayList<ModelOscillator>();	
+	private List<ModelConnectionBlock> connectionBlocks = new ArrayList<ModelConnectionBlock>();
+	
+	private int keyFrom = 0;
+	private int keyTo = 127;
+	private int velFrom = 0;
+	private int velTo = 127;
+	private int exclusiveClass = 0;
+	private boolean releaseTrigger = false;
+	private boolean selfNonExclusive = false;
+	private Object userObject = null;
+	
+	private boolean addDefaultConnections = true;
+	
+	private String name = null;
+	
+    public String getName() {
+    	return name;
+    }
+
+    public void setName(String name) {
+    	this.name = name;
+    }
+    
+	public List<ModelConnectionBlock> getConnectionBlocks() {
+		return connectionBlocks;
+	}
+	public void setConnectionBlocks(List<ModelConnectionBlock> connectionBlocks) {
+		this.connectionBlocks = connectionBlocks;
+	}
+	public List<ModelOscillator> getOscillators() {
+		return oscillators;		
+	}
+	public int getExclusiveClass() {
+		return exclusiveClass;
+	}
+	public void setExclusiveClass(int exclusiveClass) {
+		this.exclusiveClass = exclusiveClass;
+	}
+	public boolean isSelfNonExclusive() {
+		return selfNonExclusive;
+	}
+	public void setSelfNonExclusive(boolean selfNonExclusive) {
+		this.selfNonExclusive = selfNonExclusive;
+	}
+	public int getKeyFrom() {
+		return keyFrom;
+	}
+	public void setKeyFrom(int keyFrom) {
+		this.keyFrom = keyFrom;
+	}
+	public int getKeyTo() {
+		return keyTo;
+	}
+	public void setKeyTo(int keyTo) {
+		this.keyTo = keyTo;
+	}
+	public int getVelFrom() {
+		return velFrom;
+	}
+	public void setVelFrom(int velFrom) {
+		this.velFrom = velFrom;
+	}
+	public int getVelTo() {
+		return velTo;
+	}
+	public void setVelTo(int velTo) {
+		this.velTo = velTo;
+	}
+	public boolean isReleaseTriggered() {
+		return releaseTrigger;
+	}
+	public void setReleaseTriggered(boolean value) {
+		this.releaseTrigger = value;
+	}
+	public Object getUserObject()
+	{
+		return userObject;
+	}
+	public void setUserObject(Object object) {
+		userObject = object;
+	}
+	public boolean isDefaultConnectionsEnabled() {
+		return addDefaultConnections;
+	}
+	public void setDefaultConnectionsEnabled(boolean addDefaultConnections) {
+		this.addDefaultConnections = addDefaultConnections;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelSource.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,104 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * This class is used to identify sources in connection blocks, see ModelConnectionBlock.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelSource {
+	
+	public static final ModelIdentifier SOURCE_NONE = null;	
+	public static final ModelIdentifier SOURCE_NOTEON_KEYNUMBER = new ModelIdentifier("noteon","keynumber");  // midi keynumber
+	public static final ModelIdentifier SOURCE_NOTEON_VELOCITY = new ModelIdentifier("noteon","velocity");    // midi velocity 
+	public static final ModelIdentifier SOURCE_EG1 = new ModelIdentifier("eg",null,0);
+	public static final ModelIdentifier SOURCE_EG2 = new ModelIdentifier("eg",null,1);
+	public static final ModelIdentifier SOURCE_LFO1 = new ModelIdentifier("lfo",null,0); 
+	public static final ModelIdentifier SOURCE_LFO2 = new ModelIdentifier("lfo",null,1); 
+	public static final ModelIdentifier SOURCE_MIDI_PITCH = new ModelIdentifier("midi","pitch",0);                       // (0..16383)
+	public static final ModelIdentifier SOURCE_MIDI_CHANNEL_PRESSURE = new ModelIdentifier("midi","channel_pressure",0); // (0..127)
+//	public static final ModelIdentifier SOURCE_MIDI_MONO_PRESSURE = new ModelIdentifier("midi","mono_pressure",0);       // (0..127)
+	public static final ModelIdentifier SOURCE_MIDI_POLY_PRESSURE = new ModelIdentifier("midi","poly_pressure",0);       // (0..127)
+	
+	public static final ModelIdentifier SOURCE_MIDI_CC_0  =  new ModelIdentifier("midi_cc","0",0);                       // (0..127)
+	public static final ModelIdentifier SOURCE_MIDI_RPN_0 =  new ModelIdentifier("midi_rpn","0",0);                      // (0..16383)
+	
+	private ModelIdentifier source = SOURCE_NONE;
+	private ModelTransform transform;
+	
+	public ModelSource()
+	{		
+		this.transform = new ModelStandardTransform();
+	}
+	
+	public ModelSource(ModelIdentifier id)
+	{
+		source = id;
+		this.transform = new ModelStandardTransform();
+	}
+	
+	public ModelSource(ModelIdentifier id, boolean direction)
+	{
+		source = id;		
+		this.transform = new ModelStandardTransform(direction);
+	}	
+	
+	public ModelSource(ModelIdentifier id, boolean direction, boolean polarity)
+	{
+		source = id;
+		this.transform = new ModelStandardTransform(direction, polarity);
+	}	
+	
+	public ModelSource(ModelIdentifier id, boolean direction, boolean polarity, int transform)
+	{
+		source = id;
+		this.transform = new ModelStandardTransform(direction, polarity, transform);
+	}
+	
+	public ModelSource(ModelIdentifier id, ModelTransform transform)
+	{
+		source = id;
+		this.transform = transform;		
+	}
+
+	public ModelIdentifier getIdentifier() {
+		return source;
+	}
+	public void setIdentifier(ModelIdentifier source) {
+		this.source = source;
+	}
+
+	public ModelTransform getTransform() {
+		return transform;
+	}
+	public void setTransform(ModelTransform transform) {
+		this.transform = transform;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelStandardDirector.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,88 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * A standard director who chooses performers
+ * by there keyfrom,keyto,velfrom,velto properties.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+
+public class ModelStandardDirector implements ModelDirector {
+
+	ModelPerformer[] performers;
+	ModelDirectedPlayer player;
+	boolean noteOnUsed = false;
+	boolean noteOffUsed = false;
+	
+	public ModelStandardDirector(ModelPerformer[] performers, ModelDirectedPlayer player)
+	{
+		this.performers = performers;
+		this.player = player;
+		for (int i = 0; i < performers.length; i++) {
+			ModelPerformer p = performers[i];
+			if(p.isReleaseTriggered())
+			{
+				noteOffUsed = true;
+			}
+			else
+			{
+				noteOnUsed = true;
+			}
+		}
+	}
+
+	public void close() {
+	}
+
+	public void noteOff(int noteNumber, int velocity) {
+		if(!noteOffUsed) return;
+		for (int i = 0; i < performers.length; i++) {
+			ModelPerformer p = performers[i];
+			if (p.getKeyFrom() <= noteNumber && p.getKeyTo() >= noteNumber)
+				if (p.getVelFrom() <= velocity && p.getVelTo() >= velocity)
+					if(p.isReleaseTriggered()){					
+						player.play(i, null);
+					}
+		}			
+	}
+
+	public void noteOn(int noteNumber, int velocity) {
+		if(!noteOnUsed) return;
+		for (int i = 0; i < performers.length; i++) {
+			ModelPerformer p = performers[i];
+			if (p.getKeyFrom() <= noteNumber && p.getKeyTo() >= noteNumber)
+				if (p.getVelFrom() <= velocity && p.getVelTo() >= velocity) 					
+					if(!p.isReleaseTriggered()){					
+						player.play(i, null);
+					}
+		}		
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelStandardTransform.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,134 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * A standard transformer used in connection blocks.
+ * It expects input values to be between 0 and 1.
+ * 
+ * The result of the transform is 
+ * between 0 and 1 if polarity = unipolar and 
+ * between -1 and 1 if polarity = bipolar.
+ * 
+ * These constraints only applies to Concave, Convex and Switch transforms.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class ModelStandardTransform implements ModelTransform {
+
+	public static final boolean DIRECTION_MIN2MAX = false;
+	public static final boolean DIRECTION_MAX2MIN = true;	
+	public static final boolean POLARITY_UNIPOLAR = false;
+	public static final boolean POLARITY_BIPOLAR  = true;
+	
+	public static final int TRANSFORM_LINEAR    = 0;
+	public static final int TRANSFORM_CONCAVE   = 1;  // output = (20*log10(127^2/value^2)) / 96 
+	public static final int TRANSFORM_CONVEX    = 2;  // same as concave except that start and end point are reversed.
+	public static final int TRANSFORM_SWITCH    = 3;  // if value > avg(max,min) then max else min
+	public static final int TRANSFORM_ABSOLUTE  = 4;
+
+	private boolean direction = DIRECTION_MIN2MAX;
+	private boolean polarity = POLARITY_UNIPOLAR;
+	private int transform = TRANSFORM_LINEAR;
+	
+	public ModelStandardTransform()
+	{
+	}
+	
+	public ModelStandardTransform(boolean direction)
+	{
+		this.direction = direction;
+	}	
+	
+	public ModelStandardTransform(boolean direction, boolean polarity)
+	{
+		this.direction = direction;
+		this.polarity = polarity;
+	}	
+	
+	public ModelStandardTransform(boolean direction, boolean polarity, int transform)
+	{
+		this.direction = direction;
+		this.polarity = polarity;
+		this.transform = transform;		
+	}
+		
+	public double transform(double value) {		
+		double s;
+		double a;
+		if(direction == DIRECTION_MAX2MIN)
+			value = 1.0 - value;
+		if(polarity == POLARITY_BIPOLAR)
+			value = value*2.0 - 1.0;		
+		switch (transform) {
+		case TRANSFORM_CONCAVE:		
+			s = Math.signum(value);
+			a = Math.abs(value);
+			a = -((5.0/12.0)/Math.log(10))*Math.log(1.0 - a);
+			if(a < 0) a = 0; else if(a > 1) a = 1;
+			return s*a; 
+		case TRANSFORM_CONVEX:
+			s = Math.signum(value);
+			a = Math.abs(value);
+			a = 1.0+((5.0/12.0)/Math.log(10))*Math.log(a);					
+			if(a < 0) a = 0; else if(a > 1) a = 1;
+			return s*a; 
+		case TRANSFORM_SWITCH:	
+			if(polarity == POLARITY_BIPOLAR)
+				return (value > 0)?1:-1;
+			else
+				return (value > 0.5)?1:0;
+		case TRANSFORM_ABSOLUTE:
+			return Math.abs(value);	
+		default:
+			break;
+		}		
+		
+		return value;
+	}
+	
+	public boolean getDirection() {
+		return direction;
+	}
+	public void setDirection(boolean direction) {
+		this.direction = direction;
+	}
+	public boolean getPolarity() {
+		return polarity;
+	}
+	public void setPolarity(boolean polarity) {
+		this.polarity = polarity;
+	}
+	public int getTransform() {
+		return transform;
+	}
+	public void setTransform(int transform) {
+		this.transform = transform;
+	}		
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelTransform.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,37 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * Model transform interface.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public interface ModelTransform {
+
+	abstract public double transform(double value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelWavetable.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,50 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * This is a wavetable oscillator interface. 
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+
+public interface ModelWavetable extends ModelOscillator
+{
+	public static final int LOOP_TYPE_OFF = 0;
+	public static final int LOOP_TYPE_FORWARD = 1;
+	public static final int LOOP_TYPE_RELEASE = 2;
+	public static final int LOOP_TYPE_PINGPONG = 4;
+	public static final int LOOP_TYPE_REVERSE = 8;
+	
+	public AudioFloatInputStream openStream(); 
+	public float getLoopLength();
+	public float getLoopStart();
+	public int getLoopType();
+	public float getPitchcorrection();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATInstrument.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,536 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.midi.Patch;
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * GUS Instrument.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class PATInstrument extends ModelInstrument {
+	
+	private class OffsetInputStream extends InputStream
+	{
+		
+		private InputStream is;
+		private int filepointer = 0;
+		
+		public OffsetInputStream(InputStream is)
+		{
+			this.is = is;
+		}
+		
+		public long getFilePointer() throws IOException {
+			return filepointer;
+		}		
+		
+		public void close() throws IOException {
+			is.close();
+		}
+
+		public int read(byte[] b, int off, int len) throws IOException {
+			int ret = is.read(b, off, len);
+			if(ret != -1) filepointer+=ret;
+			return ret;			
+		}
+
+		public long skip(long n) throws IOException {
+			long ret = is.skip(n);
+			if(ret != -1) filepointer+=ret;
+			return ret;
+		}
+
+		public int read() throws IOException {
+			int ret = is.read();
+			if(ret != -1) filepointer++;
+			return ret;
+		}
+		
+	}
+
+	protected int preset = 0;
+
+	protected int bank = 0;
+
+	protected boolean percussion = false;
+
+	protected String name = "";
+
+	protected String description = "";
+
+	protected String format = "GF1PATCH110";
+
+	protected String vendor = "ID#000002";
+
+	protected PATSample[] samples = null;
+
+	protected int volume;
+	
+	private boolean largeFormat = false;
+	private File sampleFile;		
+	private OffsetInputStream ois;
+
+	public PATInstrument() {
+		super(null, null, null, null);
+	}
+
+	public PATInstrument(URL url) throws IOException {
+		super(null, null, null, null);
+
+		InputStream is = url.openStream();
+		try {
+			readPatch(is);
+		} finally {
+			is.close();
+		}
+	}
+
+	public PATInstrument(File file) throws IOException {
+		super(null, null, null, null);
+		largeFormat = true;
+		sampleFile = file;
+		InputStream is = new FileInputStream(file);
+		ois = new OffsetInputStream(is);
+		is = ois;
+		try {
+			readPatch(is);
+		} finally {
+			is.close();
+		}
+	}	
+
+	public PATInstrument(InputStream inputstream) throws IOException {
+		super(null, null, null, null);
+		readPatch(inputstream);
+	}
+
+	private String readString(InputStream is, int len) throws IOException {
+		byte[] buffer = new byte[len];
+		is.read(buffer);
+		for (int i = 0; i < buffer.length; i++) {
+			if (buffer[i] == (byte) 0) {
+				return new String(buffer, 0, i, "ASCII");
+			}
+		}
+		return new String(buffer, "ASCII");
+	}
+
+	private void readPatch(InputStream inputstream) throws IOException {
+		format = readString(inputstream, 12);
+		vendor = readString(inputstream, 10);
+		if (!(format.equals("GF1PATCH110") || format.equals("GF1PATCH100")))
+			throw new InvalidFormatException();
+		if (!(vendor.equals("ID#000002")))
+			throw new InvalidFormatException();
+		description = readString(inputstream, 60);
+
+		int instrument_count = inputstream.read();
+		if (instrument_count > 1)
+			throw new InvalidDataException("Invalid instrument count.");
+		@SuppressWarnings("unused")
+		int voices = inputstream.read();
+		int channels = inputstream.read();
+		if (channels > 1)
+			throw new InvalidDataException("Invalid channels count.");
+		@SuppressWarnings("unused")
+		int waveforms = inputstream.read() + (inputstream.read() << 8);
+		volume = inputstream.read() + (inputstream.read() << 8);
+		@SuppressWarnings("unused")
+		int datasize = inputstream.read() + (inputstream.read() << 8)
+				+ (inputstream.read() << 16) + (inputstream.read() << 24);
+		byte[] reserve1 = new byte[36];
+		inputstream.read(reserve1);
+		@SuppressWarnings("unused")
+		int instrumentid = inputstream.read() + (inputstream.read() << 8);
+		name = readString(inputstream, 16);
+		@SuppressWarnings("unused")
+		int instrumentsize = inputstream.read() + (inputstream.read() << 8)
+				+ (inputstream.read() << 16) + (inputstream.read() << 24);
+		int layers = inputstream.read();
+		if (layers > 1)
+			throw new InvalidDataException("Invalid layers count.");
+		byte[] reserve2 = new byte[40];
+		inputstream.read(reserve2);
+		@SuppressWarnings("unused")
+		int layerdupl = inputstream.read();
+		@SuppressWarnings("unused")
+		int layer = inputstream.read();
+		@SuppressWarnings("unused")
+		int layersize = inputstream.read() + (inputstream.read() << 8)
+				+ (inputstream.read() << 16) + (inputstream.read() << 24);
+		int samples = inputstream.read();
+		byte[] reserve3 = new byte[40];
+		inputstream.read(reserve3);
+
+		this.samples = new PATSample[samples];
+		for (int i = 0; i < samples; i++) {
+			this.samples[i] = readSample(inputstream);
+		}
+	}
+
+	private PATSample readSample(InputStream inputstream) throws IOException {
+		PATSample patsample = new PATSample();
+
+		patsample.wavename = readString(inputstream, 7);
+		patsample.fractions = inputstream.read();
+		int sampledatasize = inputstream.read() + (inputstream.read() << 8)
+				+ (inputstream.read() << 16) + (inputstream.read() << 24);
+		patsample.loopstart = inputstream.read() + (inputstream.read() << 8)
+				+ (inputstream.read() << 16) + (inputstream.read() << 24);
+		patsample.loopend = inputstream.read() + (inputstream.read() << 8)
+				+ (inputstream.read() << 16) + (inputstream.read() << 24);
+		patsample.samplerate = inputstream.read() + (inputstream.read() << 8);
+		patsample.lowfreq = inputstream.read() + (inputstream.read() << 8)
+				+ (inputstream.read() << 16) + (inputstream.read() << 24);
+		patsample.hifreq = inputstream.read() + (inputstream.read() << 8)
+				+ (inputstream.read() << 16) + (inputstream.read() << 24);
+		patsample.rootfreq = inputstream.read() + (inputstream.read() << 8)
+				+ (inputstream.read() << 16) + (inputstream.read() << 24);
+		patsample.tune = inputstream.read() + (inputstream.read() << 8);
+		patsample.pan = inputstream.read();
+
+		patsample.env_attack_rate = inputstream.read();
+		patsample.env_decay_rate = inputstream.read();
+		patsample.env_sustain_rate = inputstream.read();
+		patsample.env_release1_rate = inputstream.read();
+		patsample.env_release2_rate = inputstream.read();
+		patsample.env_release3_rate = inputstream.read();
+
+		patsample.env_attack_offset = inputstream.read();
+		patsample.env_decay_offset = inputstream.read();
+		patsample.env_sustain_offset = inputstream.read();
+		patsample.env_release1_offset = inputstream.read();
+		patsample.env_release2_offset = inputstream.read();
+		patsample.env_release3_offset = inputstream.read();
+
+		patsample.tremolo_sweep = inputstream.read();
+		patsample.tremolo_rate = inputstream.read();
+		patsample.tremolo_depth = inputstream.read();
+		patsample.vibrato_sweep = inputstream.read();
+		patsample.vibrato_rate = inputstream.read();
+		patsample.vibrato_depth = inputstream.read();
+		patsample.sampling_mode = inputstream.read();
+		patsample.scalefreq = inputstream.read() + (inputstream.read() << 8);
+		patsample.scalefactor = inputstream.read() + (inputstream.read() << 8);
+		byte[] reserve1 = new byte[36];
+		inputstream.read(reserve1);
+		
+		if(largeFormat)
+		{
+			long offset = ois.getFilePointer();
+			inputstream.skip(sampledatasize);
+			patsample.sampledata = new ModelByteBuffer(sampleFile, offset, sampledatasize);
+		}
+		else
+		{		
+			byte[] buff = new byte[sampledatasize];
+			inputstream.read(buff);
+			patsample.sampledata = new ModelByteBuffer(buff);
+		}
+		
+		return patsample;
+
+	}
+
+	public Object getData() {
+		return null;
+	}
+
+	public String getName() {
+		return this.name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public ModelPatch getPatch() {
+		return new ModelPatch(bank, preset, percussion);
+	}
+
+	public void setPatch(Patch patch) {
+		if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) {
+			percussion = true;
+			bank = patch.getBank();
+			preset = patch.getProgram();
+		} else {
+			percussion = false;
+			bank = patch.getBank();
+			preset = patch.getProgram();
+		}
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	public String getFormat() {
+		return format;
+	}
+
+	public void setFormat(String format) {
+		this.format = format;
+	}
+
+	public String getVendor() {
+		return vendor;
+	}
+
+	public void setVendor(String vendor) {
+		this.vendor = vendor;
+	}
+
+	private double convertRate(int rate) {
+		return (rate & 63) * Math.pow(1.0 / 2.0, 3 * ((rate >> 6) & 3));
+	}
+
+	public ModelPerformer[] getPerformers() {
+
+		ModelPerformer[] performers = new ModelPerformer[samples.length];
+		for (int i = 0; i < performers.length; i++) {
+			ModelPerformer performer = new ModelPerformer();			
+			PATSample patsample = samples[i];
+			performer.setName(samples[i].wavename);
+			
+			double keyfrom = 69 + 12
+					* Math.log((patsample.lowfreq / 1000.0) / 440.0)
+					/ Math.log(2.0);
+			double keyto = 69 + 12
+				* Math.log((patsample.hifreq / 1000.0) / 440.0)
+				/ Math.log(2.0);
+			
+			performer.setKeyFrom((int)Math.ceil(keyfrom));
+			performer.setKeyTo((int)Math.floor(keyto));
+			
+			ModelByteBuffer buffer = patsample.sampledata;
+
+			boolean is16bit = (patsample.sampling_mode & 1) != 0;
+			boolean isUnsigned = (patsample.sampling_mode & 2) != 0;
+			boolean isLooping = (patsample.sampling_mode & 4) != 0;
+			boolean isPingPongLoop = (patsample.sampling_mode & 8) != 0;
+			boolean isReverseLoop = (patsample.sampling_mode & 16) != 0;
+			//boolean isSustain = (patsample.sampling_mode & 32) != 0;
+			boolean isEnv = (patsample.sampling_mode & 64) != 0;
+			//boolean isClampedRelease = (patsample.sampling_mode & 128) != 0;
+			
+						
+			AudioFormat audioformat = null;
+			if (is16bit)
+				audioformat = new AudioFormat(patsample.samplerate, 16, 1,
+						!isUnsigned, false);
+			else
+				audioformat = new AudioFormat(patsample.samplerate, 8, 1,
+						!isUnsigned, false);
+
+			float pitchcorrection = -(float) (69 + 12
+					* Math.log((patsample.rootfreq / 1000.0) / 440.0)
+					/ Math.log(2.0));
+			pitchcorrection *= 100;			
+
+			ModelByteBufferWavetable osc = new ModelByteBufferWavetable(buffer,
+					audioformat, pitchcorrection);
+			
+			float loopstart = patsample.loopstart + ((patsample.fractions&0xF)/16f);
+			float loopend = patsample.loopend + ((patsample.fractions>>4)/16f);
+			
+			if (isLooping) {
+				if (is16bit) {
+					osc.setLoopStart(loopstart / 2f);
+					osc.setLoopLength(loopend / 2f
+							- loopstart / 2f);
+				} else {
+					osc.setLoopStart(loopstart);
+					osc.setLoopLength(loopend - loopstart);
+				}				
+				osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD);
+				if(isPingPongLoop)
+					osc.setLoopType(ModelWavetable.LOOP_TYPE_PINGPONG);
+				if(isReverseLoop)
+					osc.setLoopType(ModelWavetable.LOOP_TYPE_REVERSE);
+			}
+			performer.getOscillators().add(osc);
+
+			double lfo_vib_rate = patsample.vibrato_rate / 42.0;
+			double lfo_vol_rate = patsample.tremolo_rate / 42.0;
+			double lfo_vib_depth = 400.0 * patsample.vibrato_depth / 256.0;
+			
+			performer.getConnectionBlocks().add(
+					new ModelConnectionBlock(6900 + 1200.0
+							* Math.log(lfo_vol_rate / 440.0) / Math.log(2),
+							new ModelDestination(
+									ModelDestination.DESTINATION_LFO1_FREQ)));
+			if(lfo_vib_depth > 0)
+				performer.getConnectionBlocks().add(
+					new ModelConnectionBlock(6900 + 1200.0
+							* Math.log(lfo_vib_rate / 440.0) / Math.log(2),
+							new ModelDestination(
+									ModelDestination.DESTINATION_LFO2_FREQ)));
+
+			
+			if (lfo_vib_depth > 0) {
+				ModelIdentifier src = ModelSource.SOURCE_LFO2;
+				ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
+				performer.getConnectionBlocks().add(
+						new ModelConnectionBlock(new ModelSource(src,
+								ModelStandardTransform.DIRECTION_MIN2MAX,
+								ModelStandardTransform.POLARITY_BIPOLAR),
+								lfo_vib_depth, new ModelDestination(dest)));
+			}
+
+			double lfo_vol_depth = -200
+					* Math.log(1.0 - patsample.tremolo_depth / 256.0)
+					/ Math.log(10);
+			if (lfo_vol_depth > 960)
+				lfo_vol_depth = 960;
+			if (lfo_vol_depth > 0) {
+				ModelIdentifier src = ModelSource.SOURCE_LFO1;
+				ModelIdentifier dest = ModelDestination.DESTINATION_GAIN;
+				performer.getConnectionBlocks().add(
+						new ModelConnectionBlock(new ModelSource(src,
+								ModelStandardTransform.DIRECTION_MIN2MAX,
+								ModelStandardTransform.POLARITY_BIPOLAR),
+								lfo_vol_depth, new ModelDestination(dest)));
+			}
+
+			double volume = this.volume / 128.0;
+			if (isEnv) {
+				double env_attack_msec = patsample.env_attack_offset
+						/ convertRate(patsample.env_attack_rate);
+				double env_decay_msec = 0.5*(patsample.env_attack_offset - patsample.env_decay_offset)
+						/ convertRate(patsample.env_decay_rate);			
+				env_decay_msec += 0.5*(patsample.env_decay_offset - patsample.env_sustain_offset)
+						/ convertRate(patsample.env_sustain_rate); 				
+				double env_release_msec = 0.5*(patsample.env_attack_offset - 0)
+						/ convertRate(patsample.env_release1_rate);
+				/*  patsample.env_release1_offset
+				env_release_msec += (patsample.env_release1_offset - patsample.env_release2_offset)
+				/ convertRate(patsample.env_release2_rate);
+				env_release_msec += (patsample.env_release2_offset - patsample.env_release3_offset)
+				/ convertRate(patsample.env_release3_rate);
+				 */
+				double env_volume_level = patsample.env_attack_offset / 256.0;
+				double env_sustain_level = patsample.env_sustain_offset / 256.0;
+				if (env_attack_msec < 0)
+					env_attack_msec = 0;
+				if (env_decay_msec < 0)
+					env_decay_msec = 0;
+				if (env_release_msec < 0)
+					env_release_msec = 0;
+				volume *= env_volume_level;
+				performer
+						.getConnectionBlocks()
+						.add(
+								new ModelConnectionBlock(
+										env_sustain_level * 1000.0,
+										new ModelDestination(
+												ModelDestination.DESTINATION_EG1_SUSTAIN)));
+				performer.getConnectionBlocks().add(
+						new ModelConnectionBlock(1200.0
+								* Math.log(env_attack_msec / 1000.0)
+								/ Math.log(2), new ModelDestination(
+								ModelDestination.DESTINATION_EG1_ATTACK)));
+				performer.getConnectionBlocks().add(
+						new ModelConnectionBlock(1200.0
+								* Math.log(env_decay_msec / 1000.0)
+								/ Math.log(2), new ModelDestination(
+								ModelDestination.DESTINATION_EG1_DECAY)));
+				performer.getConnectionBlocks().add(
+						new ModelConnectionBlock(1200.0
+								* Math.log(env_release_msec / 1000.0)
+								/ Math.log(2), new ModelDestination(
+								ModelDestination.DESTINATION_EG1_RELEASE)));
+			} else {
+				if (!isLooping)
+					performer
+							.getConnectionBlocks()
+							.add(
+									new ModelConnectionBlock(
+											12000.0,
+											new ModelDestination(
+													ModelDestination.DESTINATION_EG1_RELEASE)));
+			}
+
+			// Linear gain to dB
+			double gain = ((20.0) / Math.log(10)) * Math.log(volume);
+			performer.getConnectionBlocks().add(
+					new ModelConnectionBlock(gain, new ModelDestination(
+							ModelDestination.DESTINATION_GAIN)));
+
+			double panning = 500;
+			if (patsample.pan < 7)
+				panning = (patsample.pan / 7.0) * 500.0;
+			if (patsample.pan > 8)
+				panning += ((patsample.pan - 8) / 7.0) * 500.0;
+			performer.getConnectionBlocks().add(
+					new ModelConnectionBlock(panning - 500.0,
+							new ModelDestination(
+									ModelDestination.DESTINATION_PAN)));
+
+			// Modulation wheel should use SOURCE_LFO2 (vib)
+			performer.getConnectionBlocks().add(
+					new ModelConnectionBlock(new ModelSource(
+							ModelSource.SOURCE_LFO2,
+							ModelStandardTransform.DIRECTION_MIN2MAX,
+							ModelStandardTransform.POLARITY_BIPOLAR,
+							ModelStandardTransform.TRANSFORM_LINEAR),
+							new ModelSource(new ModelIdentifier("midi_cc", "1",
+									0),
+									ModelStandardTransform.DIRECTION_MIN2MAX,
+									ModelStandardTransform.POLARITY_UNIPOLAR,
+									ModelStandardTransform.TRANSFORM_LINEAR),
+							50, new ModelDestination(
+									ModelDestination.DESTINATION_PITCH)));
+
+			performers[i] = performer;
+		}
+
+		return performers;
+	}
+
+	public PATSample[] getSamples() {
+		return samples;
+	}
+
+	public void setSamples(PATSample[] samples) {
+		this.samples = samples;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSample.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * GUS Sample storage.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class PATSample {
+
+	public String wavename = "";
+
+	public int fractions; 
+
+	// bit 0..3: Loop offset start fractions [0/16 .. 15/16]
+	// bit 4..7: Loop offset end fractions [0/16 .. 15/16]
+
+	public int loopstart;
+
+	public int loopend;
+
+	public int samplerate;
+
+	public int lowfreq;
+
+	public int hifreq;
+
+	public int rootfreq;
+
+	public int tune; // not used
+
+	public int pan; // 0..15, 7 and 8 are center
+
+	public int env_attack_rate;
+
+	public int env_decay_rate;
+
+	public int env_sustain_rate;
+
+	public int env_release1_rate;
+
+	public int env_release2_rate; // ignored
+
+	public int env_release3_rate; // ignored
+
+	public int env_attack_offset;
+
+	public int env_decay_offset;
+
+	public int env_sustain_offset;
+
+	public int env_release1_offset;
+
+	public int env_release2_offset; // ignored
+
+	public int env_release3_offset; // ignored
+
+	public int tremolo_sweep; // ignored
+
+	public int tremolo_rate;
+
+	public int tremolo_depth;
+
+	public int vibrato_sweep; // ignored
+
+	public int vibrato_rate;
+
+	public int vibrato_depth;
+
+	public int sampling_mode;
+
+	// bit 0: 16-bit (versus 8-bit)
+	// bit 1: Unsigned (versus signed)
+	// bit 2: Looped
+	// bit 3: Pingpong Loop
+	// bit 4: Reverse
+	// bit 5: Sustain <- Ignored
+	// bit 6: Envelope
+	// bit 7: Clamped release (6th point of envelope) <- Ignored
+
+	public int scalefreq; // ignored
+
+	public int scalefactor; // ignored
+
+	public ModelByteBuffer sampledata;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSoundbankReader.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.spi.SoundbankReader;
+
+/**
+ * GUS-compatible GF1 Patch reader.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class PATSoundbankReader extends SoundbankReader {
+
+	public Soundbank getSoundbank(URL url) throws InvalidMidiDataException,
+			IOException {
+		try {
+			PATInstrument ins = new PATInstrument(url);
+			SimpleSoundbank snk = new SimpleSoundbank();
+			snk.addInstrument(ins);
+			return snk;
+		} catch (InvalidFormatException e) {
+			return null;
+		}
+	}
+
+	public Soundbank getSoundbank(InputStream stream)
+			throws InvalidMidiDataException, IOException {
+		try {
+			stream.mark(512);
+			PATInstrument ins = new PATInstrument(stream);
+			SimpleSoundbank snk = new SimpleSoundbank();
+			snk.addInstrument(ins);
+			return snk;
+		} catch (InvalidFormatException e) {
+			stream.reset();
+			return null;
+		}
+	}
+
+	
+	public Soundbank getSoundbank(File file) throws InvalidMidiDataException, IOException {
+		if (file.getPath().toLowerCase().endsWith(".cfg"))
+			return readConfigFile(file);
+		if (!file.getPath().toLowerCase().endsWith(".pat"))
+			return null;
+		try {
+			PATInstrument ins = new PATInstrument(file);
+			SimpleSoundbank snk = new SimpleSoundbank();
+			snk.addInstrument(ins);
+			return snk;
+		} catch (InvalidFormatException e) {
+			return null;
+		}
+	}	
+	
+	private ModelPerformer[] processDrumKit(PATInstrument ins)
+	{
+		ModelPerformer[] performers = ins.getPerformers();
+		
+		for (ModelPerformer performer : performers) {
+			double pc = -((ModelWavetable) performer
+					.getOscillators().get(0))
+					.getPitchcorrection() / 100.0;
+			performer
+					.getConnectionBlocks()
+					.add(
+							new ModelConnectionBlock(
+									pc / 128.0,
+									new ModelDestination(
+											ModelDestination.DESTINATION_KEYNUMBER)));
+			
+			if(((ModelWavetable) performer.getOscillators().get(0)).getLoopType() == ModelWavetable.LOOP_TYPE_OFF)
+			{
+				performer
+				.getConnectionBlocks()
+				.add(
+						new ModelConnectionBlock(
+								12000,
+								new ModelDestination(
+										ModelDestination.DESTINATION_EG1_RELEASE)));
+											
+			}
+		}
+		return performers;
+	}
+
+	private Soundbank readConfigFile(File file)
+			throws InvalidMidiDataException, IOException {
+		File root = file.getParentFile();
+		SimpleSoundbank soundbank = new SimpleSoundbank();
+		FileInputStream in = new FileInputStream(file);
+		try {
+			try {
+
+				int bank = -2;
+				int drumset = -1;
+				SimpleInstrument drumsetins = null;
+				
+				HashMap<Integer, HashMap<Integer, ModelPerformer[]>> multipatchmaps
+					= new HashMap<Integer, HashMap<Integer, ModelPerformer[]>>();
+
+				Reader r = new InputStreamReader(in, "ASCII");
+				BufferedReader br = new BufferedReader(r);
+				String line = null;
+				while ((line = br.readLine()) != null) {
+					int li = line.indexOf('#');
+					if (li != -1)
+						line = line.substring(0, li);
+					line = line.trim();
+					if (line.length() == 0)
+						continue;
+					StringTokenizer st = new StringTokenizer(line, " ");
+					if (!st.hasMoreTokens())
+						continue;
+					String token = st.nextToken();
+					if (token.equalsIgnoreCase("drumset")) {
+						if (!st.hasMoreTokens())
+							continue;
+						token = st.nextToken();
+						drumset = Integer.parseInt(token);
+						bank = -1;
+						drumsetins = new SimpleInstrument();
+						drumsetins.setPatch(new ModelPatch(0, drumset, true));
+						soundbank.addInstrument(drumsetins);
+					} else if (token.equalsIgnoreCase("bank")) {
+						if (!st.hasMoreTokens())
+							continue;
+						token = st.nextToken();
+						drumset = -1;
+						bank = Integer.parseInt(token);
+					} else
+					if(bank == -2)
+					{				
+						int prg_from = 0;
+						int prg_to = 0;
+						int li2 = token.indexOf('-');
+						if(li2 == -1)
+						{
+							prg_from = Integer.parseInt(token)-1;
+							prg_to = Integer.parseInt(token)-1;
+						}
+						else
+						{
+							prg_from = Integer.parseInt(token.substring(0, li2))-1;
+							prg_to = Integer.parseInt(token.substring(li2+1))-1;							
+						}
+						if(prg_to < 0) continue;
+						if(prg_to < prg_from) continue;
+						if(prg_from < 0) prg_from = 0; 
+						
+						if(!st.hasMoreTokens()) continue;						
+						token = st.nextToken();
+						if(token.equals("begin_multipatch") || token.equals("override_patch"))
+						{
+
+							HashMap<Integer, ModelPerformer[]> multipatchmap = new HashMap<Integer, ModelPerformer[]>();
+							if(token.equals("override_patch"))
+							{
+								HashMap<Integer, ModelPerformer[]> omap = multipatchmaps.get(prg_from);
+								if(omap != null)
+									multipatchmap.putAll(omap);
+							}
+							for (int prg = prg_from; prg <= prg_to; prg++) 
+								multipatchmaps.put(prg, multipatchmap);
+
+							
+							while ((line = br.readLine()) != null) {
+								if(line.equals("end_multipatch")) break;
+								
+								StringTokenizer st2 = new StringTokenizer(line, " ");
+								if(!st2.hasMoreTokens()) continue;
+								int key = Integer.parseInt(st2.nextToken().trim());
+								if(!st2.hasMoreTokens()) continue;
+								token = st2.nextToken();
+								File patfile = new File(root, token);
+								if (!patfile.exists()) 
+									patfile = new File(root, token + ".pat");
+								
+								multipatchmap.put(key, processDrumKit(new PATInstrument(patfile)));
+							}
+						}
+						else
+						{							
+							File patfile = new File(root, token);
+							if (!patfile.exists()) 
+								patfile = new File(root, token + ".pat");							
+							
+							for (int prg = prg_from; prg <= prg_to; prg++) {
+								PATInstrument ins = new PATInstrument(patfile);
+								if(prg != 0)
+								{
+									if(prg >= 128)
+										ins.setPatch(new ModelPatch(0, prg-128, true));
+									else
+										ins.setPatch(new Patch(0, prg));
+								}
+								soundbank.addInstrument(ins);
+							}
+														
+						}						
+					}
+					else
+					{
+						int id = Integer.parseInt(token);
+						if (!st.hasMoreTokens())
+							continue;
+						token = st.nextToken();
+						File patfile = new File(root, token);
+						if (!patfile.exists()) {
+							patfile = new File(root, token + ".pat");
+						}
+						PATInstrument ins = new PATInstrument(patfile);
+
+						if (bank != -1) {
+							ins.setPatch(new Patch(bank, id));
+							soundbank.addInstrument(ins);
+						} else if (drumset != -1) {							
+							drumsetins.add(processDrumKit(ins), id, id);
+						}
+					}
+
+				}
+				
+				for(Map.Entry<Integer, HashMap<Integer, ModelPerformer[]>> entry :
+					multipatchmaps.entrySet())
+				{
+					
+					int prg = entry.getKey();										
+					drumsetins = new SimpleInstrument();
+					if(prg >= 128)
+						drumsetins.setPatch(new ModelPatch(0, prg-128, true));
+					else
+						drumsetins.setPatch(new Patch(0, prg));
+					
+					drumsetins.add(entry.getValue().get(36));					
+					for(Map.Entry<Integer, ModelPerformer[]> entry2 : entry.getValue().entrySet())
+						drumsetins.add(entry2.getValue(), entry2.getKey(), entry2.getKey());
+					
+					soundbank.addInstrument(drumsetins);
+					
+				}
+				
+			} finally {
+				in.close();
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+		return soundbank;
+	}
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/README.txt	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,403 @@
+Gervill - Software Sound Synthesizer
+====================================
+
+Introduction:
+-------------
+
+   "Gervill" is a software sound synthesizer
+   which was created for the open source JDK 
+   Audio Synthesis Engine Project.
+      
+   
+Hightlight of features:
+-----------------------   
+
+   * Downloadable Sound Level 2.2
+   * SoundFonts 2.04 (24 bit)
+   * Gravis Ultrasound-compatible patches
+   * Use Audio files (AIFF, AU and WAV) as SoundBanks
+   * General Midi Level 2
+   * MIDI Tuning Standard
+   * Drumkits can be used on any channel
+   * Sinc interpolation with anti-aliasing
+
+
+List of Technical Specification used:
+-------------------------------------
+
+   The Complete MIDI 1.0 Detailed Specification 
+     (document  version 96.1 second edition). 
+   General MIDI 2 (Version 1.1, September 10, 2003). 
+   GM2 MIDI Tuning Amendment (RP-037)
+   Downloadable Sounds Level 1 (Version 1.1b, September 2004). 
+   Downloadable Sounds Level 2.2 (Version 1.0, April 2006). 
+   MIDI IMPLEMENTATION CHART V2 INSTRUCTIONS
+   CA-020, MIDI TUNING Extensions 
+   CA# 22, Controller Destination Setting
+   CA# 23, Key-Based Instrument Controllers
+   CA# 24, Global Parameter Control
+   CA# 25, Master Fine/Coarse Tuning
+   CA# 26, Modulation Depth Range RPN
+     The MIDI Manufacturers Association Los Angelese, CA.
+     http://www.midi.org
+     
+   SoundFont 2.1 Application Note
+     (Wednesday, August 12, 1998)
+     Joint E-mu/Creative Technology Center E-mu Systems, Inc
+   SoundFont(R) Technical Specification
+     (Version 2.04, February 3, 2006)     
+     http://www.soundfont.com
+     
+   
+Features:
+---------
+
+Audio/Implementation Features:
+
+* Synhtesizer default parameters.
+    Interpolation: Linear
+    Audioformat:   44100 Hz, stereo, 
+                   16 bit, signed, little-endian
+    Control rate:  147 Hz
+    Max Polyphony: 64
+    Latency:       400 msec 
+                  (can be as low as 70 msec on windows plaform)
+            
+* Audio formats supported:
+    Mono/Stereo.
+    8,16,24,32 bit signed/unsigned pcm stream
+    and 32 bit pcm floating point stream.
+    Big/little endian.
+    Any sample rate including 44100 Hz.
+
+
+* Several interpolation algorithms are included:
+    linear, cubic, lanczos and sinc interpolation.
+    The sinc interpolation also includes a anti-alias filtering.
+
+* The synthesizer looks for default soundbank in these locations:
+    %JAVA_RUNTIME_LOCATION%\lib\audio\*.dls and *.sf2
+    %WINDOWS_LOCATION%\system32\drivers\gm.dls
+
+* Multi-format soundbank support.
+    SoundFont 2.4, DLS 2.2, Gravis Patch soundbanks
+    and Simple audio files are also supported
+    as soundbanks like  WAV/AIFF/AU
+    (and other audio files available thru Java SPI)   
+    
+* SoundFont 2.01 NRPN messages are not supported.
+        
+* Editable soundbanks:
+    SoundFont 2.4 and DLS 2.2 soundbanks
+    can be edited in memory and saved back to disk.
+
+* AudioSynthesizer interface is used to 
+  route audio output from the synthesizer.
+
+* The function getVoiceStatus is fully implemented 
+  and it is the real location where active voice parameters are located.
+
+* Support midi time stamping in the Receiver interface.
+  And it is to be used with conjuction with 
+  getMicrosecondPosition() method in the synthesizer class.
+
+* Two global effect engine are included: Chorus and Reverb
+  and they are fully configurated with
+  standard Global Parameter Control Sysex messages.
+
+* Emergency soundbank is include, 
+  it used when no default soundbank can be found.
+
+
+MIDI Features:
+
+* The synthesizer is fully General Midi Level 2 compatible.
+
+* Full support for MIDI tuning standard.
+  Sysex mesages messages from programs like 
+  Scala (http://www.xs4all.nl/~huygensf/scala/).
+  This enables all kinds of microtuning.
+
+* Drumkit and melodic instruments can be on any channel
+  using the GM2 MSB banks 0x78 (drumkit) and 0x79 (melodic).
+
+* Support for Midi Controller destination, 
+  user can customize how midi controllers or channel/poly aftertouch
+  affect internal synthesizer parameters.
+
+* Other sysex messages support are:
+    Master Volume, Master Balance, Global Parameter Control
+    Key-based instrument ctrl, Master Fine/Coarse tune
+
+* These RPN are supported:
+    RPN 00 (Pitch Bend Sensitivity)
+    RPN 01 (Channel Fine Tune) 
+    RPN 02 (Channel Coarse Tune)
+    RPN 03 (Tuning Program Select) 
+    RPN 04 (Tuning Bank Select)
+    RPN 05 (Modulation Depth Range) 
+
+* Support for GS/XG NRPN voice editing parameters:
+    NRPN 1,08 Vibrato Rate
+    NRPN 1,09 Vibrato Depth
+    NRPN 1,10 Vibrato Delay
+    NRPN 1,32 Filter Cutoff
+    NRPN 1,33 Filter Resonance
+    NRPN 1,99 Attack Time
+    NRPN 1,100 Decay Time
+    NRPN 1,102 Release Time
+    NRPN 24,rr Pitch per drum sound (rr)
+    NRPN 26,rr Volume per drum sound (rr)
+    NRPN 28,rr Pan per drum sound (rr)
+    NRPN 29,rr Reverb per drum sound (rr)
+    NRPN 30,rr Chorus per drum sound (rr)
+
+* Both channel and poly aftertouch are supported.
+
+* Full support for portamento control both in poly and mono mode.
+
+* Midi controls supported:
+    0 Bank Select MSB
+    1 Modulation
+    5 Portamento Time
+    6 Data Entry MSB
+    7 Volume
+    8 Balance
+    10 Pan
+    11 Expression
+    32 Ban Select LSB
+    38 Data Entry LSB
+    64 Sustain
+    65 Portamento On/off
+    66 Sostenuto
+    67 Soft Pedal
+    71 Filter Cutoff
+    72 Release Time
+    73 Attack Time
+    74 Filter Resonance
+    75 Decay Time
+    76 Vibrato Rate
+    77 Vibrato Depth
+    78 Vibrato Delay
+    84 Portamento Control
+    91 Reverb send
+    93 Chorus send
+    96 Data Increment
+    97 Data Decrement
+    98 NRPN LSB
+    99 NRPN MSB
+    100 RPN LSB
+    101 RPN MSB
+    120 All Sound Off
+    121 Reset all controllers
+    123 All notes Off
+    126 Poly Mode Off
+    127 Poly Mode On  
+
+
+MIDI Implementation Chart v. 2.0 (Page 1 of 3)              
+----------------------------------------------
+
+                                Transmit/Export Recognize/Import    Remarks
+1. Basic Information                
+MIDI channels                           No      1 - 16  
+Note numbers                            No      1 - 128 
+Program change                          No      1 - 128 
+Bank Select response? (Yes/No)          No      Yes         Both MSB and LSB messages.
+Modes supported :   
+    Mode 1: Omni-On, Poly (Yes/No)      No      No
+    Mode 2: Omni-On, Mono (Yes/No)      No      No
+    Mode 3: Omni-Off, Poly (Yes/No)     No      Yes 
+    Mode 4: Omni-Off, Mono (Yes/No)     No      Yes 
+Multi Mode (Yes/No)                     No      Yes 
+Note-On Velocity (Yes/No)               No      Yes 
+Note-Off Velocity (Yes/No)              No      No  
+Channel Aftertouch (Yes/No)             No      Yes 
+Poly (Key) Aftertouch (Yes/No)          No      Yes 
+Pitch Bend (Yes/No)                     No      Yes 
+Active Sensing (Yes/No)                 No      Yes 
+System Reset (Yes/No)                   No      Yes 
+Tune Request (Yes/No)                   No      No  
+Universal System Exclusive: 
+    Sample Dump Standard (Yes/No)       No      No  
+    Device Inquiry (Yes/No)             No      No  
+    File Dump (Yes/No)                  No      No  
+    MIDI Tuning (Yes/No)                No      Yes 
+    Master Volume (Yes/No)              No      Yes 
+    Master Balance (Yes/No)             No      Yes 
+    Notation Information (Yes/No)       No      No  
+    Turn GM1 System On (Yes/No)         No      Yes 
+    Turn GM2 System On (Yes/No)         No      Yes 
+    Turn GM System Off (Yes/No)         No      Yes 
+    DLS-1 (Yes/No)                      No      Yes 
+    File Reference (Yes/No)             No      No  
+    Controller Destination (Yes/No)     No      Yes 
+    Key-based Instrument Ctrl (Yes/No)  No      Yes 
+    Master Fine/Coarse Tune (Yes/No)    No      Yes 
+    Other Universal System Exclusive    No      Yes         Global Parameter Control
+Manufacturer or Non-Commercial System Exclusive             
+NRPNs (Yes/No)                          No      Yes         GS/XG NRPN voice editing parameters
+RPN 00 (Pitch Bend Sensitivity) (Yes/No)No      Yes 
+RPN 01 (Channel Fine Tune) (Yes/No)     No      Yes 
+RPN 02 (Channel Coarse Tune) (Yes/No)   No      Yes 
+RPN 03 (Tuning Program Select) (Yes/No) No      Yes 
+RPN 04 (Tuning Bank Select) (Yes/No)    No      Yes 
+RPN 05 (Modulation Depth Range) (Yes/No)No      Yes 
+2. MIDI Timing and Synchronization              
+MIDI Clock (Yes/No)                     No      No  
+Song Position Pointer (Yes/No)          No      No  
+Song Select (Yes/No)                    No      No  
+Start (Yes/No)                          No      No  
+Continue (Yes/No)                       No      No  
+Stop (Yes/No)                           No      No  
+MIDI Time Code (Yes/No)                 No      No  
+MIDI Machine Control (Yes/No)           No      No  
+MIDI Show Control (Yes/No)              No      No  
+If yes, MSC Level supported             
+3. Extensions Compatibility             
+General MIDI compatible? (Level(s)/No)  Level 2 
+Is GM default power-up mode? (Level/No) No*                 * Some non-gm NRPN are enabled.
+DLS compatible? (Levels(s)/No)          Level 2 (DLS 2.2)   Also supports SoundFont 2.4
+(DLS File Type(s)/No)                   .DLS    
+Standard MIDI Files (Type(s)/No)        No  
+XMF Files (Type(s)/No)                  No  
+SP-MIDI compatible? (Yes/No)            No  
+    
+MIDI Implementation Chart v. 2.0 (Page 2 of 3)              
+----------------------------------------------
+
+Control#    Function#       Transmitted (Y/N)   Recognized (Y/N)    Remarks
+0   Bank Select (MSB)                   N       Y   
+1   Modulation Wheel (MSB)              N       Y   
+2   Breath Controller (MSB)             N       N   
+3                                       N       N   
+4   Foot Controller (MSB)               N       N   
+5   Portamento Time (MSB)               N       Y   10^(0.5-5*asin(cc5/64-1)/pi) = cent/msec
+6   Data Entry (MSB)                    N       Y   
+7   Channel Volume (MSB)                N       Y   40*log10(cc7/128) = dB
+8   Balance (MSB)                       N       Y   
+9                                       N       N   
+10  Pan (MSB)                           N       Y   
+11  Expression (MSB)                    N       Y   40*log10(cc11/128) = dB
+12  Effect Control 1 (MSB)              N       N   
+13  Effect Control 2 (MSB)              N       N   
+14                                      N       N   
+15                                      N       N   
+16  General Purpose Controller 1 (MSB)  N       N   
+17  General Purpose Controller 2 (MSB)  N       N   
+18  General Purpose Controller 3 (MSB)  N       N   
+19  General Purpose Controller 4 (MSB)  N       N   
+20                                      N       N   
+21                                      N       N   
+22                                      N       N   
+23                                      N       N   
+24                                      N       N   
+25                                      N       N   
+26                                      N       N   
+27                                      N       N   
+28                                      N       N   
+29                                      N       N   
+30                                      N       N   
+31                                      N       N   
+32  Bank Select (LSB)                   N       Y   
+33  Modulation Wheel (LSB)              N       N   
+34  Breath Controller (LSB)             N       N   
+35                                      N       N   
+36  Foot Controller (LSB)               N       N   
+37  Portamento Time (LSB)               N       N   
+38  Data Entry (LSB)                    N       Y   
+39  Channel Volume (LSB)                N       N   
+40  Balance (LSB)                       N       N   
+41                                      N       N   
+42  Pan (LSB)                           N       N   
+43  Expression (LSB)                    N       N   
+44  Effect Control 1 (LSB)              N       N   
+45  Effect Control 2 (LSB)              N       N   
+46                                      N       N   
+47                                      N       N   
+48  General Purpose Controller 1 (LSB)  N       N   
+49  General Purpose Controller 2 (LSB)  N       N   
+50  General Purpose Controller 3 (LSB)  N       N   
+51  General Purpose Controller 4 (LSB)  N       N   
+52                                      N       N   
+53                                      N       N   
+54                                      N       N   
+55                                      N       N   
+56                                      N       N   
+57                                      N       N   
+58                                      N       N   
+59                                      N       N   
+60                                      N       N   
+61                                      N       N   
+62                                      N       N   
+63                                      N       N   
+
+MIDI Implementation Chart v. 2.0 (Page 3 of 3)              
+----------------------------------------------
+
+Control#    Function#       Transmitted (Y/N)   Recognized (Y/N)    Remarks
+64  Sustain Pedal                       N       Y   
+65  Portamento On/Off                   N       Y   
+66  Sostenuto                           N       Y   
+67  Soft Pedal                          N       Y   
+68  Legato Footswitch                   N       N   
+69  Hold 2                              N       N   
+70  Sound Controller 1                  N       N   
+71  Sound Controller 2 (Filter Cutoff)  N       Y    +/- 6400 cents
+72  Sound Controller 3 (Release Time)   N       Y    +/- 6 sec
+73  Sound Controller 4 (Attack Time)    N       Y    +/- 2 sec
+74  Sound Controller 5 (Brightness)     N       Y    +/- 20 db (Filter Resonance)
+75  Sound Controller 6 (Decay Time)     N       Y    +/- 6 sec
+76  Sound Controller 7 (Vibrato Rate)   N       Y    +/- 2400 cents
+77  Sound Controller 8 (Vibrato Depth)  N       Y    +/- 200 cents
+78  Sound Controller 9 (Vibrato Delay)  N       Y    +/- 2 sec
+79  Sound Controller 10                 N       N   
+80  General Purpose Controller 5        N       N   
+81  General Purpose Controller 6        N       N   
+82  General Purpose Controller 7        N       N   
+83  General Purpose Controller 8        N       N   
+84  Portamento Control                  N       Y   
+85                                      N       N   
+86                                      N       N   
+87                                      N       N   
+88                                      N       N   
+89                                      N       N   
+90                                      N       N   
+91  Effects 1 Depth, Reverb             N       Y   
+92  Effects 2 Depth                     N       N   
+93  Effects 3 Depth, chorus             N       Y   
+94  Effects 4 Depth                     N       N   
+95  Effects 5 Depth                     N       N   
+96  Data Increment                      N       Y   
+97  Data Decrement                      N       Y   
+98  NRPN (LSB)                          N       Y   
+99  NRPN (MSB)                          N       Y   
+100 RPN (LSB)                           N       Y   
+101 RPN (MSB)                           N       Y   
+102                                     N       N   
+103                                     N       N   
+104                                     N       N   
+105                                     N       N   
+106                                     N       N   
+107                                     N       N   
+108                                     N       N   
+109                                     N       N   
+110                                     N       N   
+111                                     N       N   
+112                                     N       N   
+113                                     N       N   
+114                                     N       N   
+115                                     N       N   
+116                                     N       N   
+117                                     N       N   
+118                                     N       N   
+119                                     N       N   
+120 All Sound Off                       N       Y   
+121 Reset All Controllers               N       Y   
+122 Local Control On/Off                N       N   
+123 All Notes Off                       N       Y   
+124 Omni Mode Off                       N       N   
+125 Omni Mode On                        N       N   
+126 Poly Mode Off                       N       Y   
+127 Poly Mode On                        N       Y       
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidDataException.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * This exception is used when a RIFF file contains illegal or unexpected data.
+ *  *
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class RIFFInvalidDataException extends InvalidDataException {
+
+	private static final long serialVersionUID = 1L;
+
+	public RIFFInvalidDataException() {
+		super("Invalid Data!");
+	}
+
+	public RIFFInvalidDataException(String s) {
+		super(s);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidFormatException.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * This exception is used when a reader is used to read RIFF file of a format it
+ * doesn't unterstand or support.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class RIFFInvalidFormatException extends InvalidFormatException {
+
+	private static final long serialVersionUID = 1L;
+
+	public RIFFInvalidFormatException() {
+		super("Invalid format!");
+	}
+
+	public RIFFInvalidFormatException(String s) {
+		super(s);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFReader.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Resource Interchange File Format (RIFF) stream decoder.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class RIFFReader extends InputStream {
+	
+	private RIFFReader root;
+	private long filepointer = 0;
+
+	private String fourcc;
+
+	private String riff_type = null;
+
+	private long ckSize = 0;
+
+	private InputStream stream;
+
+	private long avail;
+
+	private RIFFReader lastiterator = null;
+
+	public RIFFReader(InputStream stream) throws IOException {
+		
+		if(stream instanceof RIFFReader)
+			root = ((RIFFReader)stream).root;
+		else
+			root = this;
+
+		this.stream = stream;
+		avail = stream.available();
+		ckSize = stream.available();
+
+		// Check for RIFF null paddings,
+		int b;
+		while (true) {
+			b = read();
+			if (b == -1) {
+				fourcc = ""; // don't put null value into fourcc,
+				// because it is expected to
+				// always contain a string value
+				riff_type = null;
+				avail = 0;
+				return;
+			}
+			if (b != 0)
+				break;
+		}
+
+		byte[] fourcc = new byte[4];
+		fourcc[0] = (byte) b;
+		read(fourcc, 1, 3);		
+		this.fourcc = new String(fourcc, "ascii");
+		ckSize = readUnsignedInt();
+
+		avail = this.ckSize;
+
+		if (getFormat().equals("RIFF") || getFormat().equals("LIST")) {
+			byte[] format = new byte[4];
+			read(format);
+			this.riff_type = new String(format, "ascii");
+
+		}
+
+	}
+	
+	public long getFilePointer() throws IOException {
+		return root.filepointer;
+	}
+
+	public boolean hasNextChunk() throws IOException {
+		if (lastiterator != null)
+			lastiterator.finish();
+		return avail != 0;
+	}
+
+	public RIFFReader nextChunk() throws IOException {
+		if (lastiterator != null)
+			lastiterator.finish();
+		if (avail == 0)
+			return null;
+		lastiterator = new RIFFReader(this);		
+		return lastiterator;
+	}
+
+	public String getFormat() {
+		return fourcc;
+	}
+
+	public String getType() {
+		return riff_type;
+	}
+
+	public long getSize() {
+		return ckSize;
+	}
+
+	public int read() throws IOException {
+		if (avail == 0)
+			return -1;		
+		int b = stream.read();
+		if(b == -1) return -1;
+		avail--;
+		filepointer++;
+		return b;
+	}
+
+	public int read(byte[] b, int offset, int len) throws IOException {
+		if (avail == 0)
+			return -1;
+		if (len > avail) {
+			int rlen = stream.read(b, offset, (int) avail);
+			if(rlen != -1) filepointer += rlen;
+			avail = 0;
+			return rlen;
+		} else {
+			avail -= len;
+			int ret = stream.read(b, offset, len);
+			if(ret == -1) return -1;
+			filepointer += ret;
+			return ret;
+		}
+	}
+
+	public long skip(long n) throws IOException {
+		if (avail == 0)
+			return -1;
+		if (n > avail) {
+			long len = stream.skip(avail);
+			if(len != -1) filepointer += len;
+			avail = 0;
+			return len;
+		} else {
+			avail -= n;
+			long ret = stream.skip(n);
+			if(ret == -1) return -1;
+			filepointer += ret;
+			return ret;			
+		}
+	}
+
+	public int available() {
+		return (int) avail;
+	}
+
+	public void finish() throws IOException {
+		if (avail != 0) {
+			long ret = stream.skip(avail);
+			if(ret != -1) filepointer += ret;
+			avail = 0;
+		}
+	}
+
+	// Read ASCII chars from stream
+	public String readString(int len) throws IOException {
+		byte[] buff = new byte[len];
+		read(buff);
+		for (int i = 0; i < buff.length; i++) {
+			if (buff[i] == 0) {
+				return new String(buff, 0, i, "ascii");
+			}
+		}
+		return new String(buff, "ascii");
+	}
+
+	// Read 8 bit signed integer from stream
+	public byte readByte() throws IOException {
+		int ch = read();
+		if (ch < 0)
+			throw new EOFException();
+		return (byte) ch;
+	}
+
+	// Read 16 bit signed integer from stream
+	public short readShort() throws IOException {
+		int ch1 = read();
+		int ch2 = read();
+		if (ch1 < 0)
+			throw new EOFException();
+		if (ch2 < 0)
+			throw new EOFException();
+		return (short) (ch1 | (ch2 << 8));
+	}
+
+	// Read 32 bit signed integer from stream
+	public int readInt() throws IOException {
+		int ch1 = read();
+		int ch2 = read();
+		int ch3 = read();
+		int ch4 = read();
+		if (ch1 < 0)
+			throw new EOFException();
+		if (ch2 < 0)
+			throw new EOFException();
+		if (ch3 < 0)
+			throw new EOFException();
+		if (ch4 < 0)
+			throw new EOFException();
+		return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24);
+	}
+
+	// Read 64 bit signed integer from stream
+	public long readLong() throws IOException {
+		long ch1 = read();
+		long ch2 = read();
+		long ch3 = read();
+		long ch4 = read();
+		long ch5 = read();
+		long ch6 = read();
+		long ch7 = read();
+		long ch8 = read();
+		if (ch1 < 0)
+			throw new EOFException();
+		if (ch2 < 0)
+			throw new EOFException();
+		if (ch3 < 0)
+			throw new EOFException();
+		if (ch4 < 0)
+			throw new EOFException();
+		if (ch5 < 0)
+			throw new EOFException();
+		if (ch6 < 0)
+			throw new EOFException();
+		if (ch7 < 0)
+			throw new EOFException();
+		if (ch8 < 0)
+			throw new EOFException();
+		return ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24) | (ch5 << 32)
+				| (ch6 << 40) | (ch7 << 48) | (ch8 << 56);
+	}
+
+	// Read 8 bit unsigned integer from stream
+	public int readUnsignedByte() throws IOException {
+		int ch = read();
+		if (ch < 0)
+			throw new EOFException();
+		return ch;
+	}
+
+	// Read 16 bit unsigned integer from stream
+	public int readUnsignedShort() throws IOException {
+		int ch1 = read();
+		int ch2 = read();
+		if (ch1 < 0)
+			throw new EOFException();
+		if (ch2 < 0)
+			throw new EOFException();
+		return ch1 | (ch2 << 8);
+	}
+
+	// Read 32 bit unsigned integer from stream
+	public long readUnsignedInt() throws IOException {
+		long ch1 = read();
+		long ch2 = read();
+		long ch3 = read();
+		long ch4 = read();
+		if (ch1 < 0)
+			throw new EOFException();
+		if (ch2 < 0)
+			throw new EOFException();
+		if (ch3 < 0)
+			throw new EOFException();
+		if (ch4 < 0)
+			throw new EOFException();
+		return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24);
+	}
+	
+	public void close() throws IOException
+	{
+		finish();
+		if(this == root)
+			stream.close();
+		stream = null;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/RIFFWriter.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+
+/**
+ * Resource Interchange File Format (RIFF) stream encoder.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class RIFFWriter extends OutputStream {
+	
+	private interface RandomAccessWriter
+	{
+		public void seek(long chunksizepointer) throws IOException;
+
+		public long getPointer() throws IOException;
+
+		public void close() throws IOException;
+
+		public void write(int b)throws IOException;
+
+		public void write(byte[] b, int off, int len)throws IOException;
+
+		public void write(byte[] bytes) throws IOException;
+
+		public long length() throws IOException;
+
+		public void setLength(long i) throws IOException;		
+	}
+	
+	private static class RandomAccessFileWriter implements RandomAccessWriter
+	{
+		RandomAccessFile raf;
+		
+		public RandomAccessFileWriter(File file) throws FileNotFoundException
+		{
+			this.raf = new RandomAccessFile(file, "rw");
+		}
+
+		public RandomAccessFileWriter(String name) throws FileNotFoundException
+		{
+			this.raf = new RandomAccessFile(name, "rw");
+		}
+		
+		public void seek(long chunksizepointer) throws IOException {
+			raf.seek(chunksizepointer);
+		}
+
+		public long getPointer() throws IOException {
+			return raf.getFilePointer();
+		}
+
+		public void close() throws IOException {
+			raf.close();
+		}
+
+		public void write(int b) throws IOException {
+			raf.write(b);
+		}
+
+		public void write(byte[] b, int off, int len) throws IOException {
+			raf.write(b,off,len);
+		}
+
+		public void write(byte[] bytes) throws IOException {
+			raf.write(bytes);
+		}
+
+		public long length() throws IOException
+		{
+			return raf.length();
+		}
+
+		public void setLength(long i) throws IOException
+		{
+			raf.setLength(i);
+		}
+		
+	}
+	
+	private static class RandomAccessByteWriter implements RandomAccessWriter
+	{
+		
+		byte[] buff = new byte[32];
+		int length = 0;
+		int pos = 0;
+		byte[] s;
+		OutputStream stream;
+		
+		public RandomAccessByteWriter(OutputStream stream)
+		{
+			this.stream = stream;
+		}
+		
+		public void seek(long chunksizepointer) throws IOException {
+			pos = (int)chunksizepointer;
+		}
+
+		public long getPointer() throws IOException {
+			return pos;
+		}
+
+		public void close() throws IOException {
+			stream.write(buff,0,length);
+			stream.close();
+		}
+
+		public void write(int b) throws IOException {
+			if(s == null) s = new byte[1];;
+			s[0] = (byte)b;			
+			write(s, 0, 1);
+		}
+
+		public void write(byte[] b, int off, int len) throws IOException {
+			int newsize = pos + len;
+			if(newsize > length) setLength(newsize);
+			int end = off + len;
+			for (int i = off; i < end; i++) {
+				buff[pos++] = b[i];
+			}
+		}
+
+		public void write(byte[] bytes) throws IOException {
+			write(bytes,0,bytes.length);
+		}
+
+		public long length() throws IOException {
+			return length;
+		}
+
+		public void setLength(long i) throws IOException {
+			length = (int)i;
+			if(length > buff.length)
+			{
+				int newlen = Math.max(buff.length << 1, length);
+				byte[] newbuff = new byte[newlen]; 				
+				System.arraycopy(buff, 0, newbuff, 0, buff.length);
+				buff = newbuff;
+			}
+		}
+		
+	}
+
+	private int chunktype = 0; // 0=RIFF, 1=LIST; 2=CHUNK
+
+	private RandomAccessWriter raf;
+
+	private long chunksizepointer;
+
+	private long startpointer;
+
+	private RIFFWriter childchunk = null;
+
+	private boolean open = true;
+
+	private boolean writeoverride = false;
+
+	public RIFFWriter(String name, String format) throws IOException {
+		this(new RandomAccessFileWriter(name), format, 0);
+	}
+
+	public RIFFWriter(File file, String format) throws IOException {
+		this(new RandomAccessFileWriter(file), format, 0);
+	}
+	
+	public RIFFWriter(OutputStream stream, String format) throws IOException {
+		this(new RandomAccessByteWriter(stream), format, 0);
+	}
+	
+	private RIFFWriter(RandomAccessWriter raf, String format, int chunktype)
+			throws IOException {
+		if (chunktype == 0)
+			if (raf.length() != 0)
+				raf.setLength(0);
+		this.raf = raf;
+		if (raf.getPointer() % 2 != 0)
+			raf.write(0);
+
+		if (chunktype == 0)
+			raf.write("RIFF".getBytes("ascii"));
+		else if (chunktype == 1)
+			raf.write("LIST".getBytes("ascii"));
+		else
+			raf.write((format + "    ").substring(0, 4).getBytes("ascii"));
+		chunksizepointer = raf.getPointer();
+		this.chunktype = 2;
+		writeUnsignedInt(0);
+		this.chunktype = chunktype;
+		startpointer = raf.getPointer();
+		if (chunktype != 2)
+			raf.write((format + "    ").substring(0, 4).getBytes("ascii"));
+
+	}
+
+	public void seek(long pos) throws IOException {
+		raf.seek(pos);
+	}
+
+	public long getFilePointer() throws IOException {
+		return raf.getPointer();
+	}
+
+	public void setWriteOverride(boolean writeoverride) {
+		this.writeoverride = writeoverride;
+	}
+
+	public boolean getWriteOverride() {
+		return writeoverride;
+	}
+
+	public void close() throws IOException {
+		if (!open)
+			return;
+		if (childchunk != null) {
+			childchunk.close();
+			childchunk = null;
+		}
+
+		int bakchunktype = chunktype;
+		long fpointer = raf.getPointer();
+		raf.seek(chunksizepointer);
+		chunktype = 2;
+		writeUnsignedInt(fpointer - startpointer);
+
+		if (bakchunktype == 0)
+			raf.close();
+		else
+			raf.seek(fpointer);
+		open = false;
+		raf = null;
+	}
+
+	public void write(int b) throws IOException {
+		if (!writeoverride) {
+			if (chunktype != 2)
+				throw new IllegalArgumentException(
+						"Only chunks can write bytes!");
+			if (childchunk != null) {
+				childchunk.close();
+				childchunk = null;
+			}
+		}
+		raf.write(b);
+	}
+
+	public void write(byte b[], int off, int len) throws IOException {
+		if (!writeoverride) {
+			if (chunktype != 2)
+				throw new IllegalArgumentException(
+						"Only chunks can write bytes!");
+			if (childchunk != null) {
+				childchunk.close();
+				childchunk = null;
+			}
+		}
+		raf.write(b, off, len);
+	}
+
+	public RIFFWriter writeList(String format) throws IOException {
+		if (chunktype == 2)
+			throw new IllegalArgumentException(
+					"Only LIST and RIFF can write lists!");
+		if (childchunk != null) {
+			childchunk.close();
+			childchunk = null;
+		}
+		childchunk = new RIFFWriter(this.raf, format, 1);
+		return childchunk;
+	}
+
+	public RIFFWriter writeChunk(String format) throws IOException {
+		if (chunktype == 2)
+			throw new IllegalArgumentException(
+					"Only LIST and RIFF can write chunks!");
+		if (childchunk != null) {
+			childchunk.close();
+			childchunk = null;
+		}
+		childchunk = new RIFFWriter(this.raf, format, 2);
+		return childchunk;
+	}
+
+	// Write ASCII chars to stream
+	public void writeString(String string) throws IOException {
+		byte[] buff = string.getBytes();
+		write(buff);
+	}
+
+	// Write ASCII chars to stream
+	public void writeString(String string, int len) throws IOException {
+		byte[] buff = string.getBytes();
+		if (buff.length > len)
+			write(buff, 0, len);
+		else {
+			write(buff);
+			for (int i = buff.length; i < len; i++)
+				write(0);
+		}
+	}
+
+	// Write 8 bit signed integer to stream
+	public void writeByte(int b) throws IOException {
+		write(b);
+	}
+
+	// Write 16 bit signed integer to stream
+	public void writeShort(short b) throws IOException {
+		write((b >>> 0) & 0xFF);
+		write((b >>> 8) & 0xFF);
+	}
+
+	// Write 32 bit signed integer to stream
+	public void writeInt(int b) throws IOException {
+		write((b >>> 0) & 0xFF);
+		write((b >>> 8) & 0xFF);
+		write((b >>> 16) & 0xFF);
+		write((b >>> 24) & 0xFF);
+	}
+
+	// Write 64 bit signed integer to stream
+	public void writeLong(long b) throws IOException {
+		write((int) (b >>> 0) & 0xFF);
+		write((int) (b >>> 8) & 0xFF);
+		write((int) (b >>> 16) & 0xFF);
+		write((int) (b >>> 24) & 0xFF);
+		write((int) (b >>> 32) & 0xFF);
+		write((int) (b >>> 40) & 0xFF);
+		write((int) (b >>> 48) & 0xFF);
+		write((int) (b >>> 56) & 0xFF);
+	}
+
+	// Write 8 bit unsigned integer to stream
+	public void writeUnsignedByte(int b) throws IOException {
+		writeByte((byte) b);
+	}
+
+	// Write 16 bit unsigned integer to stream
+	public void writeUnsignedShort(int b) throws IOException {
+		writeShort((short) b);
+	}
+
+	// Write 32 bit unsigned integer to stream
+	public void writeUnsignedInt(long b) throws IOException {
+		writeInt((int) b);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2GlobalRegion.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,36 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * Soundfont global region.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2GlobalRegion extends SF2Region {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Instrument.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,808 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.sound.midi.Patch;
+
+/**
+ * Soundfont instrument.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2Instrument extends ModelInstrument {
+
+	protected String name = "";
+	protected int preset = 0;
+	protected int bank = 0;
+	protected long library = 0;
+	protected long genre = 0;
+	protected long morphology = 0;
+	
+	protected SF2GlobalRegion globalregion = null;
+	
+	protected List<SF2InstrumentRegion> regions = new ArrayList<SF2InstrumentRegion>();
+
+	public SF2Instrument() {
+		super(null, null, null, null);
+	}
+	
+	public SF2Instrument(SF2Soundbank soundbank) {
+		super(soundbank, null, null, null);
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public void setName(String name)
+	{
+		this.name = name;
+	}
+		
+	public Patch getPatch() {
+		if(bank == 128)
+			return new ModelPatch(0, preset, true);
+		else
+			return new ModelPatch(bank << 7, preset, false);
+	}
+	
+	public void setPatch(Patch patch)
+	{
+		if(patch instanceof ModelPatch && ((ModelPatch)patch).isPercussion())
+		{
+			bank = 128;
+			preset = patch.getProgram();			
+		}
+		else
+		{
+			bank = patch.getBank() >> 7;
+			preset = patch.getProgram();
+		}
+	}
+
+	public Object getData() {
+		return null;
+	}
+
+	public long getGenre() {
+		return genre;
+	}
+
+	public void setGenre(long genre) {
+		this.genre = genre;
+	}
+
+	public long getLibrary() {
+		return library;
+	}
+
+	public void setLibrary(long library) {
+		this.library = library;
+	}
+
+	public long getMorphology() {
+		return morphology;
+	}
+
+	public void setMorphology(long morphology) {
+		this.morphology = morphology;
+	}
+
+	public List<SF2InstrumentRegion> getRegions() {
+		return regions;
+	}
+	
+	public SF2GlobalRegion getGlobalRegion()
+	{
+		return globalregion;
+	}
+	
+	public void setGlobalZone(SF2GlobalRegion zone)
+	{
+		globalregion = zone;
+	}	
+	
+	public String toString()
+	{
+		if(bank == 128)
+			return "Drumkit: " + name + " preset #" + preset;
+		else
+			return "Instrument: " + name + " bank #" + bank + " preset #" + preset; 
+	}
+
+	public ModelPerformer[] getPerformers() {
+		int performercount = 0;
+		for(SF2InstrumentRegion presetzone : regions)
+			performercount += presetzone.getLayer().getRegions().size();		
+		ModelPerformer[] performers = new ModelPerformer[performercount];
+		int pi = 0;
+		
+		SF2GlobalRegion presetglobal = globalregion;		
+		for(SF2InstrumentRegion presetzone : regions)
+		{			
+			Map<Integer, Short> pgenerators = new HashMap<Integer, Short>();
+			pgenerators.putAll(presetzone.getGenerators());
+			if(presetglobal != null)
+			pgenerators.putAll(presetglobal.getGenerators());
+			
+			SF2Layer layer = presetzone.getLayer();
+			SF2GlobalRegion layerglobal = layer.getGlobalRegion();
+			for(SF2LayerRegion layerzone : layer.getRegions())
+			{
+				ModelPerformer performer = new ModelPerformer();
+				if(layerzone.getSample() != null)
+				{
+					performer.setName(layerzone.getSample().getName());
+				}
+				else
+					performer.setName(layer.getName());
+				
+				performers[pi++] = performer;				
+								
+				int keyfrom = 0;
+				int keyto = 127;
+				int velfrom = 0;
+				int velto = 127;
+				
+				if(layerzone.contains(SF2Region.GENERATOR_EXCLUSIVECLASS))
+				{
+					performer.setExclusiveClass(layerzone.getInteger(SF2Region.GENERATOR_EXCLUSIVECLASS));					
+				}				
+				if(layerzone.contains(SF2Region.GENERATOR_KEYRANGE))
+				{
+					byte[] bytes = layerzone.getBytes(SF2Region.GENERATOR_KEYRANGE);
+					if(bytes[0] >= 0)
+						if(bytes[0] > keyfrom) keyfrom = bytes[0];
+					if(bytes[1] >= 0)
+						if(bytes[1] < keyto) keyto = bytes[1];
+				}
+				if(layerzone.contains(SF2Region.GENERATOR_VELRANGE))
+				{
+					byte[] bytes = layerzone.getBytes(SF2Region.GENERATOR_VELRANGE);
+					if(bytes[0] >= 0)
+						if(bytes[0] > velfrom) velfrom = bytes[0];
+					if(bytes[1] >= 0)
+						if(bytes[1] < velto) velto = bytes[1];
+				}
+				if(presetzone.contains(SF2Region.GENERATOR_KEYRANGE))
+				{
+					byte[] bytes = presetzone.getBytes(SF2Region.GENERATOR_KEYRANGE);
+					if(bytes[0] > keyfrom) keyfrom = bytes[0];
+					if(bytes[1] < keyto) keyto = bytes[1];
+				}
+				if(presetzone.contains(SF2Region.GENERATOR_VELRANGE))
+				{
+					byte[] bytes = presetzone.getBytes(SF2Region.GENERATOR_VELRANGE);
+					if(bytes[0] > velfrom) velfrom = bytes[0];
+					if(bytes[1] < velto) velto = bytes[1];
+				}				
+				performer.setKeyFrom(keyfrom);
+				performer.setKeyTo(keyto);
+				performer.setVelFrom(velfrom);				
+				performer.setVelTo(velto);
+															
+				int startAddrsOffset = layerzone.getShort(SF2Region.GENERATOR_STARTADDRSOFFSET);
+				int endAddrsOffset = layerzone.getShort(SF2Region.GENERATOR_ENDADDRSOFFSET);					
+				int startloopAddrsOffset = layerzone.getShort(SF2Region.GENERATOR_STARTLOOPADDRSOFFSET);
+				int endloopAddrsOffset = layerzone.getShort(SF2Region.GENERATOR_ENDLOOPADDRSOFFSET);
+				
+				startAddrsOffset +=  layerzone.getShort(SF2Region.GENERATOR_STARTADDRSCOARSEOFFSET) *32768;
+				endAddrsOffset +=  layerzone.getShort(SF2Region.GENERATOR_ENDADDRSCOARSEOFFSET) *32768;					
+				startloopAddrsOffset +=  layerzone.getShort(SF2Region.GENERATOR_STARTLOOPADDRSCOARSEOFFSET) *32768;
+				endloopAddrsOffset +=  layerzone.getShort(SF2Region.GENERATOR_ENDLOOPADDRSCOARSEOFFSET) *32768;
+				startloopAddrsOffset -= startAddrsOffset;
+				endloopAddrsOffset -= startAddrsOffset;
+								
+				SF2Sample sample = layerzone.getSample();
+				int rootkey = sample.originalPitch;
+				if(layerzone.getShort(SF2Region.GENERATOR_OVERRIDINGROOTKEY) != -1)
+					rootkey = layerzone.getShort(SF2Region.GENERATOR_OVERRIDINGROOTKEY);
+				float pitchcorrection = (-rootkey*100) + sample.pitchCorrection;
+				ModelByteBuffer buff = sample.getDataBuffer();
+				ModelByteBuffer buff24 = sample.getData24Buffer();
+				
+				if(startAddrsOffset != 0 || endAddrsOffset != 0)
+				{
+					buff = buff.subbuffer(startAddrsOffset*2, buff.capacity() + endAddrsOffset*2);
+					if(buff24 != null)
+						buff24 = buff24.subbuffer(startAddrsOffset, buff24.capacity() + endAddrsOffset);
+						
+					/*
+					if(startAddrsOffset < 0) startAddrsOffset = 0;
+					if(endAddrsOffset > (buff.capacity()/2-startAddrsOffset)) startAddrsOffset = (int)buff.capacity()/2-startAddrsOffset;
+					byte[] data = buff.array();
+					int off = (int)buff.arrayOffset() + startAddrsOffset*2;
+					int len = (int)buff.capacity() + endAddrsOffset*2;
+					if(off+len > data.length) len = data.length - off;
+					buff = new ModelByteBuffer(data, off, len);
+					if(buff24 != null)
+					{
+						data = buff.array();
+						off = (int)buff.arrayOffset() + startAddrsOffset;
+						len = (int)buff.capacity() + endAddrsOffset;
+						buff24 = new ModelByteBuffer(data, off, len);
+					} */
+				}
+
+				ModelByteBufferWavetable osc = new ModelByteBufferWavetable(buff, sample.getFormat(),pitchcorrection);
+				if(buff24 != null) osc.set8BitExtensionBuffer(buff24);
+												
+				Map<Integer, Short> generators = new HashMap<Integer, Short>();
+				if(layerglobal != null)
+				generators.putAll(layerglobal.getGenerators());
+				generators.putAll(layerzone.getGenerators());				
+				for(Map.Entry<Integer,Short> gen : pgenerators.entrySet())
+				{
+					short val;
+					if(!generators.containsKey(gen.getKey()))						
+						val = layerzone.getShort(gen.getKey());
+					else
+						val = generators.get(gen.getKey());
+					val += gen.getValue();
+					generators.put(gen.getKey(), val);
+				}
+				
+				// SampleMode:
+				// 0 indicates a sound reproduced with no loop
+				// 1 indicates a sound which loops continuously
+				// 2 is unused but should be interpreted as indicating no loop
+				// 3 indicates a sound which loops for the duration of key depression then proceeds to play the remainder of the sample.
+				int sampleMode = getGeneratorValue(generators, SF2Region.GENERATOR_SAMPLEMODES);				
+				if((sampleMode == 1) || (sampleMode == 3))
+				if(sample.startLoop >= 0 && sample.endLoop > 0)
+				{
+					osc.setLoopStart((int)(sample.startLoop+startloopAddrsOffset));
+					osc.setLoopLength((int)(sample.endLoop - sample.startLoop+endloopAddrsOffset - startloopAddrsOffset));
+					if(sampleMode == 1) osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD);
+					if(sampleMode == 3) osc.setLoopType(ModelWavetable.LOOP_TYPE_RELEASE);
+				}
+				performer.getOscillators().add(osc);
+				
+				
+				short volDelay = getGeneratorValue(generators, SF2Region.GENERATOR_DELAYVOLENV);
+				short volAttack = getGeneratorValue(generators, SF2Region.GENERATOR_ATTACKVOLENV);
+				short volHold = getGeneratorValue(generators, SF2Region.GENERATOR_HOLDVOLENV);
+				short volDecay = getGeneratorValue(generators, SF2Region.GENERATOR_DECAYVOLENV);
+				short volSustain = getGeneratorValue(generators, SF2Region.GENERATOR_SUSTAINVOLENV);
+				short volRelease = getGeneratorValue(generators, SF2Region.GENERATOR_RELEASEVOLENV);
+				
+				if(volHold != -12000)
+				{								
+					short volKeyNumToHold = getGeneratorValue(generators, SF2Region.GENERATOR_KEYNUMTOVOLENVHOLD);					
+					volHold += 60*volKeyNumToHold;
+					float fvalue = -volKeyNumToHold*128; 
+					ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
+					ModelIdentifier dest = ModelDestination.DESTINATION_EG1_HOLD;
+					performer.getConnectionBlocks().add(
+							new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest)));					
+				}
+				if(volDecay != -12000)
+				{
+					short volKeyNumToDecay = getGeneratorValue(generators, SF2Region.GENERATOR_KEYNUMTOVOLENVDECAY);					
+					volDecay += 60*volKeyNumToDecay;
+					float fvalue = -volKeyNumToDecay*128; 
+					ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
+					ModelIdentifier dest = ModelDestination.DESTINATION_EG1_DECAY;
+					performer.getConnectionBlocks().add(
+							new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest)));					
+				}
+				
+				addTimecentValue(performer, ModelDestination.DESTINATION_EG1_DELAY, volDelay);
+				addTimecentValue(performer, ModelDestination.DESTINATION_EG1_ATTACK, volAttack);
+				addTimecentValue(performer, ModelDestination.DESTINATION_EG1_HOLD, volHold);
+				addTimecentValue(performer, ModelDestination.DESTINATION_EG1_DECAY, volDecay);
+				//float fvolsustain = (960-volSustain)*(1000.0f/960.0f);
+				
+				volSustain = (short)(1000 - volSustain);
+				if(volSustain < 0) volSustain = 0;
+				if(volSustain > 1000) volSustain = 1000;
+				
+				addValue(performer, ModelDestination.DESTINATION_EG1_SUSTAIN, volSustain);
+				addTimecentValue(performer, ModelDestination.DESTINATION_EG1_RELEASE, volRelease);
+				
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOFILTERFC) != 0
+				|| getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOPITCH) != 0)
+				{
+					short modDelay = getGeneratorValue(generators, SF2Region.GENERATOR_DELAYMODENV);
+					short modAttack = getGeneratorValue(generators, SF2Region.GENERATOR_ATTACKMODENV);
+					short modHold = getGeneratorValue(generators, SF2Region.GENERATOR_HOLDMODENV);
+					short modDecay = getGeneratorValue(generators, SF2Region.GENERATOR_DECAYMODENV);
+					short modSustain = getGeneratorValue(generators, SF2Region.GENERATOR_SUSTAINMODENV);
+					short modRelease = getGeneratorValue(generators, SF2Region.GENERATOR_RELEASEMODENV);
+	
+					
+					if(modHold != -12000)
+					{								
+						short modKeyNumToHold = getGeneratorValue(generators, SF2Region.GENERATOR_KEYNUMTOMODENVHOLD);					
+						modHold += 60*modKeyNumToHold;
+						float fvalue = -modKeyNumToHold*128; 
+						ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
+						ModelIdentifier dest = ModelDestination.DESTINATION_EG2_HOLD;
+						performer.getConnectionBlocks().add(
+								new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest)));					
+					}
+					if(modDecay != -12000)
+					{
+						short modKeyNumToDecay = getGeneratorValue(generators, SF2Region.GENERATOR_KEYNUMTOMODENVDECAY);					
+						modDecay += 60*modKeyNumToDecay;
+						float fvalue = -modKeyNumToDecay*128; 
+						ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
+						ModelIdentifier dest = ModelDestination.DESTINATION_EG2_DECAY;
+						performer.getConnectionBlocks().add(
+								new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest)));					
+					}
+					
+					addTimecentValue(performer, ModelDestination.DESTINATION_EG2_DELAY, modDelay);
+					addTimecentValue(performer, ModelDestination.DESTINATION_EG2_ATTACK, modAttack);
+					addTimecentValue(performer, ModelDestination.DESTINATION_EG2_HOLD, modHold);
+					addTimecentValue(performer, ModelDestination.DESTINATION_EG2_DECAY, modDecay);
+					if(modSustain < 0) modSustain = 0;
+					if(modSustain > 1000) modSustain = 1000;
+					addValue(performer, ModelDestination.DESTINATION_EG2_SUSTAIN, 1000 - modSustain);
+					addTimecentValue(performer, ModelDestination.DESTINATION_EG2_RELEASE, modRelease);
+					
+					if(getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOFILTERFC) != 0)
+					{
+						double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOFILTERFC);
+						ModelIdentifier src = ModelSource.SOURCE_EG2;
+						ModelIdentifier dest = ModelDestination.DESTINATION_FILTER_FREQ;
+						performer.getConnectionBlocks().add(
+								new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest)));
+					}
+					
+					if(getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOPITCH) != 0)
+					{
+						double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODENVTOPITCH);
+						ModelIdentifier src = ModelSource.SOURCE_EG2;
+						ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
+						performer.getConnectionBlocks().add(
+								new ModelConnectionBlock(new ModelSource(src), fvalue, new ModelDestination(dest)));
+					}
+					
+				}
+				
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOFILTERFC) != 0
+				  || getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOPITCH) != 0
+			      || getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOVOLUME) != 0)
+				{
+					short lfo_freq = getGeneratorValue(generators, SF2Region.GENERATOR_FREQMODLFO);
+					short lfo_delay = getGeneratorValue(generators, SF2Region.GENERATOR_DELAYMODLFO);
+					addTimecentValue(performer, ModelDestination.DESTINATION_LFO1_DELAY, lfo_delay);
+					addValue(performer, ModelDestination.DESTINATION_LFO1_FREQ, lfo_freq);
+				}
+				
+				short vib_freq = getGeneratorValue(generators, SF2Region.GENERATOR_FREQVIBLFO);
+				short vib_delay = getGeneratorValue(generators, SF2Region.GENERATOR_DELAYVIBLFO);
+				addTimecentValue(performer, ModelDestination.DESTINATION_LFO2_DELAY, vib_delay);
+				addValue(performer, ModelDestination.DESTINATION_LFO2_FREQ, vib_freq);
+				
+				
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_VIBLFOTOPITCH) != 0)
+				{
+					double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_VIBLFOTOPITCH);
+					ModelIdentifier src = ModelSource.SOURCE_LFO2;
+					ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
+					performer.getConnectionBlocks().add(
+							new ModelConnectionBlock(new ModelSource(src,ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR), fvalue, new ModelDestination(dest)));
+				}				
+				
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOFILTERFC) != 0)
+				{
+					double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOFILTERFC);
+					ModelIdentifier src = ModelSource.SOURCE_LFO1;
+					ModelIdentifier dest = ModelDestination.DESTINATION_FILTER_FREQ;
+					performer.getConnectionBlocks().add(
+							new ModelConnectionBlock(new ModelSource(src,ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR), fvalue, new ModelDestination(dest)));
+				}				
+
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOPITCH) != 0)
+				{
+					double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOPITCH);
+					ModelIdentifier src = ModelSource.SOURCE_LFO1;
+					ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
+					performer.getConnectionBlocks().add(
+							new ModelConnectionBlock(new ModelSource(src,ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR), fvalue, new ModelDestination(dest)));
+				}
+				
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOVOLUME) != 0)
+				{
+					double fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_MODLFOTOVOLUME);
+					ModelIdentifier src = ModelSource.SOURCE_LFO1;
+					ModelIdentifier dest = ModelDestination.DESTINATION_GAIN;
+					performer.getConnectionBlocks().add(
+							new ModelConnectionBlock(new ModelSource(src,ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR), fvalue, new ModelDestination(dest)));
+				}
+				
+				if(layerzone.getShort(SF2Region.GENERATOR_KEYNUM) != -1)
+				{
+					double val = layerzone.getShort(SF2Region.GENERATOR_KEYNUM)/128.0;
+					addValue(performer, ModelDestination.DESTINATION_KEYNUMBER, val);
+				}
+				
+				if(layerzone.getShort(SF2Region.GENERATOR_VELOCITY) != -1)
+				{
+					double val = layerzone.getShort(SF2Region.GENERATOR_VELOCITY)/128.0;
+					addValue(performer, ModelDestination.DESTINATION_VELOCITY, val);
+				}
+				
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_INITIALFILTERFC) < 13500)
+				{
+					short filter_freq = getGeneratorValue(generators, SF2Region.GENERATOR_INITIALFILTERFC);
+					short filter_q = getGeneratorValue(generators, SF2Region.GENERATOR_INITIALFILTERQ);
+					addValue(performer, ModelDestination.DESTINATION_FILTER_FREQ, filter_freq);
+					addValue(performer, ModelDestination.DESTINATION_FILTER_Q, filter_q);
+				}
+				
+				int tune = 100 * getGeneratorValue(generators, SF2Region.GENERATOR_COARSETUNE);
+				tune += getGeneratorValue(generators, SF2Region.GENERATOR_FINETUNE);
+				if(tune != 0)
+				{
+					addValue(performer, ModelDestination.DESTINATION_PITCH, (short)tune);
+				}
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_PAN) != 0)
+				{
+					short val = getGeneratorValue(generators, SF2Region.GENERATOR_PAN);
+					addValue(performer, ModelDestination.DESTINATION_PAN, val);
+				}
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_INITIALATTENUATION) != 0)
+				{
+					short val = getGeneratorValue(generators, SF2Region.GENERATOR_INITIALATTENUATION);
+					addValue(performer, ModelDestination.DESTINATION_GAIN, -0.376287f*val);
+				}
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_CHORUSEFFECTSSEND) != 0)
+				{
+					short val = getGeneratorValue(generators, SF2Region.GENERATOR_CHORUSEFFECTSSEND);
+					addValue(performer, ModelDestination.DESTINATION_CHORUS, val);
+				}
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_REVERBEFFECTSSEND) != 0)
+				{
+					short val = getGeneratorValue(generators, SF2Region.GENERATOR_REVERBEFFECTSSEND);
+					addValue(performer, ModelDestination.DESTINATION_REVERB, val);
+				}
+				if(getGeneratorValue(generators, SF2Region.GENERATOR_SCALETUNING) != 100)
+				{
+					short fvalue = getGeneratorValue(generators, SF2Region.GENERATOR_SCALETUNING);
+					if(fvalue == 0)
+					{						
+						ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
+						performer.getConnectionBlocks().add(
+							new ModelConnectionBlock(null, rootkey * 100, new ModelDestination(dest)));
+					}
+					else
+					{						
+						ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
+						performer.getConnectionBlocks().add(
+							new ModelConnectionBlock(null, rootkey * (100 - fvalue), new ModelDestination(dest)));
+					}		
+					
+					ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
+					ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
+					performer.getConnectionBlocks().add(
+						new ModelConnectionBlock(new ModelSource(src), 128*fvalue, new ModelDestination(dest)));
+					
+				}
+			
+				performer.getConnectionBlocks().add(new ModelConnectionBlock(
+						new ModelSource(ModelSource.SOURCE_NOTEON_VELOCITY,
+								new ModelTransform()
+								{
+									public double transform(double value) {
+										if(value < 0.5)
+										{
+											return 1 - value*2;
+										}
+										else
+											return 0;
+									}
+								}
+						)
+						,-2400,new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ)));					
+
+				
+				performer.getConnectionBlocks().add(new ModelConnectionBlock(
+						new ModelSource(ModelSource.SOURCE_LFO2,
+						ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR),
+						new ModelSource(new ModelIdentifier("midi_cc","1",0),
+						ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR),
+						50,new ModelDestination(ModelDestination.DESTINATION_PITCH)));					
+				
+				if(layer.getGlobalRegion() != null)
+					for(SF2Modulator modulator : layer.getGlobalRegion().getModulators())
+						convertModulator(performer, modulator);
+				for(SF2Modulator modulator : layerzone.getModulators())
+					convertModulator(performer, modulator);
+
+				if(presetglobal != null)
+					for(SF2Modulator modulator : presetglobal.getModulators())
+						convertModulator(performer, modulator);
+				for(SF2Modulator modulator : presetzone.getModulators())
+					convertModulator(performer, modulator);
+
+				
+				
+				
+			}
+		}
+		return performers;
+	}
+	
+	private void convertModulator(ModelPerformer performer, SF2Modulator modulator)
+	{
+		ModelSource src1 = convertSource(modulator.getSourceOperator());
+		ModelSource src2 = convertSource(modulator.getAmountSourceOperator());
+		if(src1 == null && modulator.getSourceOperator() != 0) return;
+		if(src2 == null && modulator.getAmountSourceOperator() != 0) return;
+		double amount = modulator.getAmount();
+		double[] amountcorrection = new double[1];
+		ModelSource[] extrasrc = new ModelSource[1]; 
+		amountcorrection[0] = 1;
+		ModelDestination dst = convertDestination(modulator.getDestinationOperator(), amountcorrection, extrasrc);			
+		amount *= amountcorrection[0];
+		if(dst == null) return;
+		if(modulator.getTransportOperator() == SF2Modulator.TRANSFORM_ABSOLUTE) 
+			((ModelStandardTransform)dst.getTransform()).setTransform(ModelStandardTransform.TRANSFORM_ABSOLUTE);				
+		ModelConnectionBlock conn = new ModelConnectionBlock(src1,src2,amount,dst);
+		if(extrasrc[0] != null) conn.addSource(extrasrc[0]);
+		performer.getConnectionBlocks().add(conn);
+		
+		
+	}
+	
+	private static ModelSource convertSource(int src)
+	{
+		if(src == 0) return null;
+		ModelIdentifier id = null;
+		int idsrc = src & 0x7F;
+		if((src & SF2Modulator.SOURCE_MIDI_CONTROL) != 0)
+		{
+			id = new ModelIdentifier("midi_cc", Integer.toString(idsrc));
+		}
+		else
+		{
+			if(idsrc == SF2Modulator.SOURCE_NOTE_ON_VELOCITY)
+				id = ModelSource.SOURCE_NOTEON_VELOCITY;
+			if(idsrc == SF2Modulator.SOURCE_NOTE_ON_KEYNUMBER)
+				id = ModelSource.SOURCE_NOTEON_KEYNUMBER;			
+			if(idsrc == SF2Modulator.SOURCE_POLY_PRESSURE)
+				id = ModelSource.SOURCE_MIDI_POLY_PRESSURE;
+			if(idsrc == SF2Modulator.SOURCE_CHANNEL_PRESSURE)
+				id = ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE;			
+			if(idsrc == SF2Modulator.SOURCE_PITCH_WHEEL)
+				id = ModelSource.SOURCE_MIDI_PITCH;
+			if(idsrc == SF2Modulator.SOURCE_PITCH_SENSITIVITY)
+				id = new ModelIdentifier("midi_rpn", "0");
+
+		}
+		if(id == null) return null;
+		
+		ModelSource msrc = new ModelSource(id);		
+		ModelStandardTransform transform = (ModelStandardTransform)msrc.getTransform();
+				
+		if((SF2Modulator.SOURCE_DIRECTION_MAX_MIN & src) != 0)
+			transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN);
+		else
+			transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX);
+
+		if((SF2Modulator.SOURCE_POLARITY_BIPOLAR & src) != 0)
+			transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR);
+		else
+			transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR);
+		
+		if((SF2Modulator.SOURCE_TYPE_CONCAVE & src) != 0)
+			transform.setTransform(ModelStandardTransform.TRANSFORM_CONCAVE);
+		if((SF2Modulator.SOURCE_TYPE_CONVEX & src) != 0)
+			transform.setTransform(ModelStandardTransform.TRANSFORM_CONVEX);
+		if((SF2Modulator.SOURCE_TYPE_SWITCH & src) != 0)
+			transform.setTransform(ModelStandardTransform.TRANSFORM_SWITCH);
+		
+		return msrc;
+	}
+	
+	protected static ModelDestination convertDestination(int dst, double[] amountcorrection, ModelSource[] extrasrc)
+	{
+		ModelIdentifier id = null; 
+		switch (dst) {
+		case SF2Region.GENERATOR_INITIALFILTERFC :
+			id = ModelDestination.DESTINATION_FILTER_FREQ;
+			break;
+		case SF2Region.GENERATOR_INITIALFILTERQ  :
+			id = ModelDestination.DESTINATION_FILTER_Q;
+			break;			
+		case SF2Region.GENERATOR_CHORUSEFFECTSSEND   :
+			id = ModelDestination.DESTINATION_CHORUS;
+			break;
+		case SF2Region.GENERATOR_REVERBEFFECTSSEND   :
+			id = ModelDestination.DESTINATION_REVERB;
+			break;			
+		case SF2Region.GENERATOR_PAN  :
+			id = ModelDestination.DESTINATION_PAN;
+			break;		
+		case SF2Region.GENERATOR_DELAYMODLFO  :
+			id = ModelDestination.DESTINATION_LFO1_DELAY;
+			break;			
+		case SF2Region.GENERATOR_FREQMODLFO   :
+			id = ModelDestination.DESTINATION_LFO1_FREQ;
+			break;			
+		case SF2Region.GENERATOR_DELAYVIBLFO   :
+			id = ModelDestination.DESTINATION_LFO2_DELAY;
+			break;			
+		case SF2Region.GENERATOR_FREQVIBLFO    :
+			id = ModelDestination.DESTINATION_LFO2_FREQ;
+			break;
+			
+			
+			
+		case SF2Region.GENERATOR_DELAYMODENV    :
+			id = ModelDestination.DESTINATION_EG2_DELAY;
+			break;						
+		case SF2Region.GENERATOR_ATTACKMODENV    :
+			id = ModelDestination.DESTINATION_EG2_ATTACK;
+			break;						
+		case SF2Region.GENERATOR_HOLDMODENV    :
+			id = ModelDestination.DESTINATION_EG2_HOLD;
+			break;						
+		case SF2Region.GENERATOR_DECAYMODENV    :
+			id = ModelDestination.DESTINATION_EG2_DECAY;
+			break;						
+		case SF2Region.GENERATOR_SUSTAINMODENV    :
+			id = ModelDestination.DESTINATION_EG2_SUSTAIN;
+			amountcorrection[0] = -1;
+			break;						
+		case SF2Region.GENERATOR_RELEASEMODENV    :
+			id = ModelDestination.DESTINATION_EG2_RELEASE;
+			break;									
+		case SF2Region.GENERATOR_DELAYVOLENV    :
+			id = ModelDestination.DESTINATION_EG1_DELAY;
+			break;						
+		case SF2Region.GENERATOR_ATTACKVOLENV    :
+			id = ModelDestination.DESTINATION_EG1_ATTACK;
+			break;						
+		case SF2Region.GENERATOR_HOLDVOLENV    :
+			id = ModelDestination.DESTINATION_EG1_HOLD;
+			break;						
+		case SF2Region.GENERATOR_DECAYVOLENV    :
+			id = ModelDestination.DESTINATION_EG1_DECAY;
+			break;						
+		case SF2Region.GENERATOR_SUSTAINVOLENV    :
+			id = ModelDestination.DESTINATION_EG1_SUSTAIN;
+			amountcorrection[0] = -1;
+			break;						
+		case SF2Region.GENERATOR_RELEASEVOLENV    :
+			id = ModelDestination.DESTINATION_EG1_RELEASE;
+			break;														
+		case SF2Region.GENERATOR_KEYNUM     :
+			id = ModelDestination.DESTINATION_KEYNUMBER;
+			break;									
+		case SF2Region.GENERATOR_VELOCITY     :
+			id = ModelDestination.DESTINATION_VELOCITY;
+			break;									
+
+		case SF2Region.GENERATOR_COARSETUNE       :
+			amountcorrection[0] = 100;
+			id = ModelDestination.DESTINATION_PITCH;
+			break;									
+
+		case SF2Region.GENERATOR_FINETUNE        :
+			id = ModelDestination.DESTINATION_PITCH;
+			break;									
+
+		case SF2Region.GENERATOR_INITIALATTENUATION      :
+			id = ModelDestination.DESTINATION_GAIN;
+			amountcorrection[0] = -0.376287f;
+			break;									
+
+		case SF2Region.GENERATOR_VIBLFOTOPITCH         :
+			id = ModelDestination.DESTINATION_PITCH;
+			extrasrc[0] = new ModelSource(
+					ModelSource.SOURCE_LFO2, 
+					ModelStandardTransform.DIRECTION_MIN2MAX, 
+					ModelStandardTransform.POLARITY_BIPOLAR);	
+			break;	
+			
+		case SF2Region.GENERATOR_MODLFOTOPITCH          :
+			id = ModelDestination.DESTINATION_PITCH;
+			extrasrc[0] = new ModelSource(
+					ModelSource.SOURCE_LFO1, 
+					ModelStandardTransform.DIRECTION_MIN2MAX, 
+					ModelStandardTransform.POLARITY_BIPOLAR);		
+			break;			
+			
+		case SF2Region.GENERATOR_MODLFOTOFILTERFC          :
+			id = ModelDestination.DESTINATION_FILTER_FREQ;
+			extrasrc[0] = new ModelSource(
+					ModelSource.SOURCE_LFO1, 
+					ModelStandardTransform.DIRECTION_MIN2MAX, 
+					ModelStandardTransform.POLARITY_BIPOLAR);		
+			break;		
+			
+		case SF2Region.GENERATOR_MODLFOTOVOLUME           :
+			id = ModelDestination.DESTINATION_GAIN;
+			amountcorrection[0] = -0.376287f;
+			extrasrc[0] = new ModelSource(
+					ModelSource.SOURCE_LFO1, 
+					ModelStandardTransform.DIRECTION_MIN2MAX, 
+					ModelStandardTransform.POLARITY_BIPOLAR);		
+			break;			
+			
+		case SF2Region.GENERATOR_MODENVTOPITCH           :
+			id = ModelDestination.DESTINATION_PITCH;
+			extrasrc[0] = new ModelSource(
+					ModelSource.SOURCE_EG2, 
+					ModelStandardTransform.DIRECTION_MIN2MAX, 
+					ModelStandardTransform.POLARITY_BIPOLAR);					
+			break;			
+			
+		case SF2Region.GENERATOR_MODENVTOFILTERFC           :
+			id = ModelDestination.DESTINATION_FILTER_FREQ;
+			extrasrc[0] = new ModelSource(
+					ModelSource.SOURCE_EG2, 
+					ModelStandardTransform.DIRECTION_MIN2MAX, 
+					ModelStandardTransform.POLARITY_BIPOLAR);		
+			break;		
+						
+			
+		default:		
+			break;
+		}
+		if(id != null) return new ModelDestination(id);
+		return null;
+	}	
+	
+	private void addTimecentValue(ModelPerformer performer, ModelIdentifier dest, short value)
+	{
+		double fvalue;
+		if(value == -12000) 
+			fvalue = Double.NEGATIVE_INFINITY;
+		else
+			fvalue = value;
+		performer.getConnectionBlocks().add(new ModelConnectionBlock(fvalue, new ModelDestination(dest)));
+	}
+	
+	private void addValue(ModelPerformer performer, ModelIdentifier dest, short value)
+	{
+		double fvalue = value;
+		performer.getConnectionBlocks().add(new ModelConnectionBlock(fvalue, new ModelDestination(dest)));
+	}
+	
+	private void addValue(ModelPerformer performer, ModelIdentifier dest, double value)
+	{
+		double fvalue = value;
+		performer.getConnectionBlocks().add(new ModelConnectionBlock(fvalue, new ModelDestination(dest)));
+	}
+	
+	private short getGeneratorValue(Map<Integer, Short> generators, int gen)
+	{
+		if(generators.containsKey(gen)) return generators.get(gen);
+		return SF2Region.getDefaultValue(gen);
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2InstrumentRegion.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,46 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * Soundfont instrument region. 
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2InstrumentRegion extends SF2Region {
+	
+	protected SF2Layer layer;
+
+	public SF2Layer getLayer() {
+		return layer;
+	}
+
+	public void setLayer(SF2Layer layer) {
+		this.layer = layer;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Layer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,85 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sound.midi.SoundbankResource;
+
+/**
+ * Soundfont layer.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2Layer extends SoundbankResource {
+	
+	protected String name = "";
+	protected SF2GlobalRegion globalregion = null;
+	protected List<SF2LayerRegion> regions = new ArrayList<SF2LayerRegion>();
+	
+	public SF2Layer(SF2Soundbank soundBank) {
+		super(soundBank, null, null);
+	}
+	
+	public SF2Layer() {
+		super(null, null, null);
+	}	
+	
+	public Object getData() {
+		return null;
+	}
+
+	public String getName() {
+		return name;
+	}
+	
+	public void setName(String name)
+	{
+		this.name = name;
+	}
+	
+	public List<SF2LayerRegion> getRegions() {
+		return regions;
+	}	
+	
+	public SF2GlobalRegion getGlobalRegion()
+	{
+		return globalregion;
+	}
+	
+	public void setGlobalZone(SF2GlobalRegion zone)
+	{
+		globalregion = zone;
+	}	
+	
+	public String toString()
+	{
+		return "Layer: " + name;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2LayerRegion.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,46 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * Soundfont layer region.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2LayerRegion extends SF2Region {
+	
+	protected SF2Sample sample;
+
+	public SF2Sample getSample() {
+		return sample;
+	}
+
+	public void setSample(SF2Sample sample) {
+		this.sample = sample;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Modulator.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,96 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+/**
+ * Soundfont modulator container.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2Modulator {
+	
+	public final static int SOURCE_NONE = 0;
+	public final static int SOURCE_NOTE_ON_VELOCITY = 2;
+	public final static int SOURCE_NOTE_ON_KEYNUMBER = 3;
+	public final static int SOURCE_POLY_PRESSURE = 10;
+	public final static int SOURCE_CHANNEL_PRESSURE = 13;
+	public final static int SOURCE_PITCH_WHEEL = 14;
+	public final static int SOURCE_PITCH_SENSITIVITY = 16;		
+	public final static int SOURCE_MIDI_CONTROL = 128*1;
+	
+	public final static int SOURCE_DIRECTION_MIN_MAX = 256*0;
+	public final static int SOURCE_DIRECTION_MAX_MIN = 256*1;
+
+	public final static int SOURCE_POLARITY_UNIPOLAR = 512*0;
+	public final static int SOURCE_POLARITY_BIPOLAR  = 512*1;
+	
+	public final static int SOURCE_TYPE_LINEAR   = 1024*0;
+	public final static int SOURCE_TYPE_CONCAVE  = 1024*1;
+	public final static int SOURCE_TYPE_CONVEX   = 1024*2;
+	public final static int SOURCE_TYPE_SWITCH   = 1024*3;
+	
+	public final static int TRANSFORM_LINEAR = 0;
+	public final static int TRANSFORM_ABSOLUTE = 2;	
+	
+	protected int sourceOperator;
+	protected int destinationOperator;
+	protected short amount;
+	protected int amountSourceOperator;
+	protected int transportOperator;
+	
+	public short getAmount() {
+		return amount;
+	}
+	public void setAmount(short amount) {
+		this.amount = amount;
+	}
+	public int getAmountSourceOperator() {
+		return amountSourceOperator;
+	}
+	public void setAmountSourceOperator(int amountSourceOperator) {
+		this.amountSourceOperator = amountSourceOperator;
+	}
+	public int getTransportOperator() {
+		return transportOperator;
+	}
+	public void setTransportOperator(int transportOperator) {
+		this.transportOperator = transportOperator;
+	}
+	public int getDestinationOperator() {
+		return destinationOperator;
+	}
+	public void setDestinationOperator(int destinationOperator) {
+		this.destinationOperator = destinationOperator;
+	}
+	public int getSourceOperator() {
+		return sourceOperator;
+	}
+	public void setSourceOperator(int sourceOperator) {
+		this.sourceOperator = sourceOperator;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Region.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,179 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Soundfont general region.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2Region {
+	
+	public final static int GENERATOR_STARTADDRSOFFSET = 0;
+	public final static int GENERATOR_ENDADDRSOFFSET = 1;
+	public final static int GENERATOR_STARTLOOPADDRSOFFSET = 2;
+	public final static int GENERATOR_ENDLOOPADDRSOFFSET = 3;
+	public final static int GENERATOR_STARTADDRSCOARSEOFFSET = 4;
+	public final static int GENERATOR_MODLFOTOPITCH = 5;
+	public final static int GENERATOR_VIBLFOTOPITCH = 6;
+	public final static int GENERATOR_MODENVTOPITCH = 7;
+	public final static int GENERATOR_INITIALFILTERFC = 8;
+	public final static int GENERATOR_INITIALFILTERQ = 9;
+	public final static int GENERATOR_MODLFOTOFILTERFC = 10;
+	public final static int GENERATOR_MODENVTOFILTERFC = 11;
+	public final static int GENERATOR_ENDADDRSCOARSEOFFSET = 12;
+	public final static int GENERATOR_MODLFOTOVOLUME = 13;
+	public final static int GENERATOR_UNUSED1 = 14;
+	public final static int GENERATOR_CHORUSEFFECTSSEND = 15;
+	public final static int GENERATOR_REVERBEFFECTSSEND = 16;
+	public final static int GENERATOR_PAN = 17;
+	public final static int GENERATOR_UNUSED2 = 18;
+	public final static int GENERATOR_UNUSED3 = 19;
+	public final static int GENERATOR_UNUSED4 = 20;
+	public final static int GENERATOR_DELAYMODLFO = 21;
+	public final static int GENERATOR_FREQMODLFO = 22;
+	public final static int GENERATOR_DELAYVIBLFO = 23;
+	public final static int GENERATOR_FREQVIBLFO = 24;
+	public final static int GENERATOR_DELAYMODENV = 25;
+	public final static int GENERATOR_ATTACKMODENV = 26;
+	public final static int GENERATOR_HOLDMODENV = 27;
+	public final static int GENERATOR_DECAYMODENV = 28;
+	public final static int GENERATOR_SUSTAINMODENV = 29;
+	public final static int GENERATOR_RELEASEMODENV = 30;
+	public final static int GENERATOR_KEYNUMTOMODENVHOLD = 31;
+	public final static int GENERATOR_KEYNUMTOMODENVDECAY = 32;
+	public final static int GENERATOR_DELAYVOLENV = 33;
+	public final static int GENERATOR_ATTACKVOLENV = 34;
+	public final static int GENERATOR_HOLDVOLENV = 35;
+	public final static int GENERATOR_DECAYVOLENV = 36;
+	public final static int GENERATOR_SUSTAINVOLENV = 37;
+	public final static int GENERATOR_RELEASEVOLENV = 38;
+	public final static int GENERATOR_KEYNUMTOVOLENVHOLD = 39;
+	public final static int GENERATOR_KEYNUMTOVOLENVDECAY = 40;
+	public final static int GENERATOR_INSTRUMENT = 41;
+	public final static int GENERATOR_RESERVED1 = 42;
+	public final static int GENERATOR_KEYRANGE = 43;
+	public final static int GENERATOR_VELRANGE = 44;
+	public final static int GENERATOR_STARTLOOPADDRSCOARSEOFFSET = 45;
+	public final static int GENERATOR_KEYNUM = 46;
+	public final static int GENERATOR_VELOCITY = 47;
+	public final static int GENERATOR_INITIALATTENUATION = 48;
+	public final static int GENERATOR_RESERVED2 = 49;
+	public final static int GENERATOR_ENDLOOPADDRSCOARSEOFFSET = 50;
+	public final static int GENERATOR_COARSETUNE = 51;
+	public final static int GENERATOR_FINETUNE = 52;
+	public final static int GENERATOR_SAMPLEID = 53;
+	public final static int GENERATOR_SAMPLEMODES = 54;
+	public final static int GENERATOR_RESERVED3 = 55;
+	public final static int GENERATOR_SCALETUNING = 56;
+	public final static int GENERATOR_EXCLUSIVECLASS = 57;
+	public final static int GENERATOR_OVERRIDINGROOTKEY = 58;
+	public final static int GENERATOR_UNUSED5 = 59;
+	public final static int GENERATOR_ENDOPR = 60;
+	
+	protected Map<Integer, Short> generators = new HashMap<Integer, Short>();
+	protected List<SF2Modulator> modulators = new ArrayList<SF2Modulator>();
+	
+	public Map<Integer, Short>  getGenerators()
+	{
+		return generators;
+	}
+	
+	public boolean contains(int generator)
+	{
+		return generators.containsKey(generator);
+	}
+	
+	static public short getDefaultValue(int generator)
+	{		
+		if(generator == 8) return (short)13500;
+		if(generator == 21) return (short)-12000;
+		if(generator == 23) return (short)-12000;
+		if(generator == 25) return (short)-12000;
+		if(generator == 26) return (short)-12000;
+		if(generator == 27) return (short)-12000;
+		if(generator == 28) return (short)-12000;
+		if(generator == 30) return (short)-12000;
+		if(generator == 33) return (short)-12000;
+		if(generator == 34) return (short)-12000;
+		if(generator == 35) return (short)-12000;
+		if(generator == 36) return (short)-12000;
+		if(generator == 38) return (short)-12000;
+		if(generator == 43) return (short)0x7F00;
+		if(generator == 44) return (short)0x7F00;
+		if(generator == 46) return (short)-1;
+		if(generator == 47) return (short)-1;
+		if(generator == 56) return (short)100;
+		if(generator == 58) return (short)-1;
+		return 0;
+	}
+	public short getShort(int generator)
+	{
+		if(!contains(generator)) return getDefaultValue(generator);
+		return generators.get(generator);
+	}	
+	
+	public void putShort(int generator, short value)
+	{
+		generators.put(generator, value);
+	}	
+	
+	public byte[] getBytes(int generator)
+	{
+		int val = getInteger(generator);
+		byte[] bytes = new byte[2];
+		bytes[0] = (byte)(0xFF & val);
+		bytes[1] = (byte)((0xFF00 & val) >> 8);
+		return bytes;
+	}
+
+	public void putBytes(int generator, byte[] bytes)
+	{
+		generators.put(generator, (short)(bytes[0] + (bytes[1] << 8)));
+	}
+
+	public int getInteger(int generator)
+	{
+		return 0xFFFF & getShort(generator);
+	}
+	
+	public void putInteger(int generator, int value)
+	{
+		generators.put(generator, (short)value);
+	}		
+	
+	public List<SF2Modulator> getModulators()
+	{
+		return modulators;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Sample.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,219 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.InputStream;
+
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.SoundbankResource;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+
+/**
+ * Soundfont sample storage.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2Sample extends SoundbankResource {
+
+	protected String name = "";
+	protected long startLoop = 0;
+	protected long endLoop = 0;
+	protected long sampleRate = 44100;
+	protected int originalPitch = 60;
+	protected byte pitchCorrection = 0;
+	protected int sampleLink = 0;
+	protected int sampleType = 0;	
+	protected ModelByteBuffer data;
+	protected ModelByteBuffer data24;
+	
+	public SF2Sample(Soundbank soundBank) {
+		super(soundBank, null, AudioInputStream.class);
+	}
+	
+	public SF2Sample() {
+		super(null, null, AudioInputStream.class);
+	}
+
+	public Object getData() {		
+		
+		AudioFormat format = getFormat();
+		/*
+		if(sampleFile != null)
+		{
+			FileInputStream fis;
+			try {
+				fis = new FileInputStream(sampleFile);
+				RIFFReader riff = new RIFFReader(fis);
+				if (!riff.getFormat().equals("RIFF"))
+					throw new RIFFInvalidDataException("Input stream is not a valid RIFF stream!");
+				if (!riff.getType().equals("sfbk"))
+					throw new RIFFInvalidDataException("Input stream is not a valid SoundFont!");
+				while (riff.hasNextChunk()) {
+					RIFFReader chunk = riff.nextChunk();
+					if (chunk.getFormat().equals("LIST")) {
+						if (chunk.getType().equals("sdta"))
+						{
+							while(chunk.hasNextChunk())
+							{
+								RIFFReader chunkchunk = chunk.nextChunk();
+								if(chunkchunk.getFormat().equals("smpl"))
+								{
+									chunkchunk.skip(sampleOffset);
+									return new AudioInputStream(chunkchunk, format, sampleLen);
+								}
+							}																					
+						}
+					}
+				}								
+				return null;								
+			} catch (Exception e) {
+				return new Throwable(e.toString());			
+			}			
+		}		
+		 */
+		InputStream is = data.getInputStream();
+		if(is == null) return null;
+		return new AudioInputStream(is, format, data.capacity());
+	}
+	
+	public ModelByteBuffer getDataBuffer()
+	{
+		return data;
+	}
+	
+	public ModelByteBuffer getData24Buffer()
+	{
+		return data24;
+	}	
+	
+	public AudioFormat getFormat()
+	{
+		return new AudioFormat(sampleRate, 16, 1, true, false);
+	}
+	
+	public void setData(ModelByteBuffer data) {
+		this.data = data;
+	}	
+	
+	public void setData(byte[] data) {
+		this.data = new ModelByteBuffer(data);
+	}
+	
+	public void setData(byte[] data, int offset, int length) {
+		this.data = new ModelByteBuffer(data, offset, length);
+	}		
+	
+	public void setData24(ModelByteBuffer data24) {
+		this.data24 = data24;
+	}	
+	
+	public void setData24(byte[] data24) {
+		this.data24 = new ModelByteBuffer(data24);
+	}
+	
+	public void setData24(byte[] data24, int offset, int length) {
+		this.data24 = new ModelByteBuffer(data24, offset, length);
+	}			
+	/*
+	public void setData(File file, int offset, int length) {
+		this.data = null;
+		this.sampleFile = file;
+		this.sampleOffset = offset;
+		this.sampleLen = length;
+	}		
+	*/
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}	
+		
+	public long getEndLoop() {
+		return endLoop;
+	}
+
+	public void setEndLoop(long endLoop) {
+		this.endLoop = endLoop;
+	}
+
+	public int getOriginalPitch() {
+		return originalPitch;
+	}
+
+	public void setOriginalPitch(int originalPitch) {
+		this.originalPitch = originalPitch;
+	}
+
+	public byte getPitchCorrection() {
+		return pitchCorrection;
+	}
+
+	public void setPitchCorrection(byte pitchCorrection) {
+		this.pitchCorrection = pitchCorrection;
+	}
+
+	public int getSampleLink() {
+		return sampleLink;
+	}
+
+	public void setSampleLink(int sampleLink) {
+		this.sampleLink = sampleLink;
+	}
+
+	public long getSampleRate() {
+		return sampleRate;
+	}
+
+	public void setSampleRate(long sampleRate) {
+		this.sampleRate = sampleRate;
+	}
+
+	public int getSampleType() {
+		return sampleType;
+	}
+
+	public void setSampleType(int sampleType) {
+		this.sampleType = sampleType;
+	}
+
+	public long getStartLoop() {
+		return startLoop;
+	}
+
+	public void setStartLoop(long startLoop) {
+		this.startLoop = startLoop;
+	}
+
+	public String toString()
+	{
+		return "Sample: " + name;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,1000 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.SoundbankResource;
+
+
+/**
+ * 
+ * A SoundFont 2.04 soundbank reader. 
+ * 
+ * Based on SoundFont 2.04 specification from:
+ * <p>
+ *    http://developer.creative.com
+ * <br>
+ *    http://www.soundfont.com/ ; 
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2Soundbank implements Soundbank {
+	
+	// version of the Sound Font RIFF file
+	protected int major = 2;
+	protected int minor = 1;
+	
+	// target Sound Engine
+	protected String targetEngine = "EMU8000";
+	
+	// Sound Font Bank Name	
+	protected String name = "untitled";
+	
+	// Sound ROM Name
+	protected String romName = null;
+	
+	// Sound ROM Version
+	protected int romVersionMajor = -1;
+	protected int romVersionMinor = -1;
+	
+	// Date of Creation of the Bank
+	protected String creationDate = null;
+	
+	// Sound Designers and Engineers for the Bank
+	protected String engineers = null;
+	
+	// Product for which the Bank was intended
+	protected String product = null;
+	
+	// Copyright message
+	protected String copyright = null;
+	
+	// Comments
+	protected String comments = null;
+	
+	// The SoundFont tools used to create and alter the bank
+	protected String tools = null;		
+	
+	// The Sample Data loaded from the SoundFont
+	private ModelByteBuffer sampleData = null;
+	private ModelByteBuffer sampleData24 = null;
+	private File sampleFile = null;
+	private boolean largeFormat = false;
+	
+	private List<SF2Instrument> instruments = new ArrayList<SF2Instrument>();
+	private List<SF2Layer> layers = new ArrayList<SF2Layer>();
+	private List<SF2Sample> samples = new ArrayList<SF2Sample>();
+	
+	public SF2Soundbank()
+	{
+	}
+	
+	public SF2Soundbank(URL url) throws IOException {
+		
+		InputStream is = url.openStream();
+		try
+		{
+			readSoundbank(is);
+		}
+		finally
+		{
+			is.close();
+		}
+	}	
+	
+	public SF2Soundbank(File file) throws IOException {
+		largeFormat = true;
+		sampleFile = file;
+		InputStream is = new FileInputStream(file);
+		try
+		{
+			readSoundbank(is);
+		}
+		finally
+		{
+			is.close();
+		}
+	}	
+
+	public SF2Soundbank(InputStream inputstream) throws IOException {
+		readSoundbank(inputstream);
+	}
+	
+	private void readSoundbank(InputStream inputstream) throws IOException {	
+		RIFFReader riff = new RIFFReader(inputstream);
+		if (!riff.getFormat().equals("RIFF"))
+			throw new RIFFInvalidFormatException("Input stream is not a valid RIFF stream!");
+		if (!riff.getType().equals("sfbk"))
+			throw new RIFFInvalidFormatException("Input stream is not a valid SoundFont!");
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			if (chunk.getFormat().equals("LIST")) {
+				if (chunk.getType().equals("INFO"))
+					readInfoChunk(chunk);
+				if (chunk.getType().equals("sdta"))
+					readSdtaChunk(chunk);
+				if (chunk.getType().equals("pdta"))
+					readPdtaChunk(chunk);
+			}
+		}
+	}
+
+	private void readInfoChunk(RIFFReader riff) throws IOException {
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			String format = chunk.getFormat();			
+			if(format.equals("ifil"))
+			{
+				major = chunk.readUnsignedShort();
+				minor = chunk.readUnsignedShort();
+			}
+			else if(format.equals("isng"))
+				this.targetEngine = chunk.readString(chunk.available());
+			else if(format.equals("INAM"))
+				this.name = chunk.readString(chunk.available());
+			else if(format.equals("irom"))
+				this.romName = chunk.readString(chunk.available());
+			else if(format.equals("iver"))
+			{
+				romVersionMajor = chunk.readUnsignedShort();
+				romVersionMinor = chunk.readUnsignedShort();
+			}									
+			else if(format.equals("ICRD"))
+				this.creationDate = chunk.readString(chunk.available());
+			else if(format.equals("IENG"))
+				this.engineers = chunk.readString(chunk.available());
+			else if(format.equals("IPRD"))
+				this.product = chunk.readString(chunk.available());
+			else if(format.equals("ICOP"))
+				this.copyright = chunk.readString(chunk.available());
+			else if(format.equals("ICMT"))
+				this.comments = chunk.readString(chunk.available());
+			else if(format.equals("ISFT"))
+				this.tools = chunk.readString(chunk.available());
+			
+		}
+	}
+
+	private void readSdtaChunk(RIFFReader riff) throws IOException {
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			if (chunk.getFormat().equals("smpl")) {			
+				if(!largeFormat)
+				{					
+					byte[] sampleData = new byte[chunk.available()];
+					
+					int read = 0;
+					int avail = chunk.available();
+					while(read != avail)
+					{
+						if(avail - read > 65536)
+						{
+							chunk.read(sampleData, read, 65536);
+							read += 65536;
+						}
+						else
+						{
+							chunk.read(sampleData, read, avail - read);
+							read = avail;
+						}
+						
+					}
+					this.sampleData = new ModelByteBuffer(sampleData);
+					//chunk.read(sampleData);
+				}
+				else
+				{
+					this.sampleData = new ModelByteBuffer(sampleFile, chunk.getFilePointer(), chunk.available());
+				}
+					
+			} 
+			if (chunk.getFormat().equals("sm24")) {			
+				if(!largeFormat)
+				{
+					byte[] sampleData24 = new byte[chunk.available()];
+					//chunk.read(sampleData24);
+					
+					int read = 0;
+					int avail = chunk.available();
+					while(read != avail)
+					{
+						if(avail - read > 65536)
+						{
+							chunk.read(sampleData24, read, 65536);
+							read += 65536;
+						}
+						else
+						{
+							chunk.read(sampleData24, read, avail - read);
+							read = avail;
+						}
+						
+					}	
+					this.sampleData24 = new ModelByteBuffer(sampleData24);
+				}
+				else
+					this.sampleData24 = new ModelByteBuffer(sampleFile, chunk.getFilePointer(), chunk.available());
+				
+			}			
+		}
+	}
+
+	private void readPdtaChunk(RIFFReader riff) throws IOException {
+		
+		List<SF2Instrument> presets = new ArrayList<SF2Instrument>();
+		List<Integer> presets_bagNdx = new ArrayList<Integer>();
+		List<SF2InstrumentRegion> presets_splits_gen = new ArrayList<SF2InstrumentRegion>();
+		List<SF2InstrumentRegion> presets_splits_mod = new ArrayList<SF2InstrumentRegion>();
+		
+		List<SF2Layer> instruments = new ArrayList<SF2Layer>();
+		List<Integer> instruments_bagNdx = new ArrayList<Integer>();				
+		List<SF2LayerRegion> instruments_splits_gen = new ArrayList<SF2LayerRegion>();
+		List<SF2LayerRegion> instruments_splits_mod = new ArrayList<SF2LayerRegion>();
+		
+		while (riff.hasNextChunk()) {
+			RIFFReader chunk = riff.nextChunk();
+			String format = chunk.getFormat();
+			if(format.equals("phdr")) // Preset Header / Instrument
+			{
+				if(chunk.available() % 38 != 0) throw new RIFFInvalidDataException();
+				int count = chunk.available() / 38;
+				for (int i = 0; i < count; i++) {					
+					SF2Instrument preset = new SF2Instrument(this);
+					preset.name = chunk.readString(20);
+					preset.preset = chunk.readUnsignedShort();
+					preset.bank = chunk.readUnsignedShort();
+					presets_bagNdx.add(chunk.readUnsignedShort());
+					preset.library = chunk.readUnsignedInt();
+					preset.genre = chunk.readUnsignedInt();
+					preset.morphology = chunk.readUnsignedInt();
+					presets.add(preset);					
+					if(i != count - 1) this.instruments.add(preset);					
+				}
+			}
+			else if(format.equals("pbag")) // Preset Zones / Instruments splits
+			{							
+				if(chunk.available() % 4 != 0) throw new RIFFInvalidDataException();
+				int count = chunk.available() / 4;
+				
+				// Skip first record
+				{
+					int gencount = chunk.readUnsignedShort();
+					int modcount = chunk.readUnsignedShort();
+					while( presets_splits_gen.size() < gencount) 
+						presets_splits_gen.add(null);
+					while( presets_splits_mod.size() < modcount) 
+						presets_splits_mod.add(null);
+					count--;
+				}
+				
+				int offset = presets_bagNdx.get(0);
+				// Offset should be 0 (but just case)
+				for (int i = 0; i < offset; i++) {
+					if(count == 0) throw new RIFFInvalidDataException();
+					int gencount = chunk.readUnsignedShort();
+					int modcount = chunk.readUnsignedShort();
+					while( presets_splits_gen.size() < gencount) 
+						presets_splits_gen.add(null);
+					while( presets_splits_mod.size() < modcount) 
+						presets_splits_mod.add(null);
+					count--;					
+				}
+				
+				for (int i = 0; i < presets_bagNdx.size()-1; i++) {
+					int zone_count = presets_bagNdx.get(i+1) - presets_bagNdx.get(i);
+					SF2Instrument preset = presets.get(i);
+					for (int ii = 0; ii < zone_count; ii++) {
+						if(count == 0) throw new RIFFInvalidDataException();
+						int gencount = chunk.readUnsignedShort();
+						int modcount = chunk.readUnsignedShort();
+						SF2InstrumentRegion split = new SF2InstrumentRegion();
+						preset.regions.add(split);
+						while( presets_splits_gen.size() < gencount) 
+							presets_splits_gen.add(split);
+						while( presets_splits_mod.size() < modcount) 
+							presets_splits_mod.add(split);
+						count--;											
+					}
+				}				
+			}		
+			else if(format.equals("pmod")) // Preset Modulators / Split Modulators
+			{				
+				for (int i = 0; i < presets_splits_mod.size(); i++) {
+					SF2Modulator modulator = new SF2Modulator();
+					modulator.sourceOperator = chunk.readUnsignedShort();
+					modulator.destinationOperator = chunk.readUnsignedShort();
+					modulator.amount = chunk.readShort();
+					modulator.amountSourceOperator = chunk.readUnsignedShort();
+					modulator.transportOperator= chunk.readUnsignedShort();
+					SF2InstrumentRegion split = presets_splits_mod.get(i);
+					if(split != null)  split.modulators.add(modulator);
+				}				
+			}		
+			else if(format.equals("pgen")) // Preset Generators / Split Generators
+			{				
+				for (int i = 0; i < presets_splits_gen.size(); i++) {
+					int operator = chunk.readUnsignedShort();
+					short amount = chunk.readShort();
+					SF2InstrumentRegion split = presets_splits_gen.get(i);
+					if(split != null) split.generators.put(operator, amount);
+				}
+			}					
+			else if(format.equals("inst")) // Instrument Header / Layers
+			{
+				if(chunk.available() % 22 != 0) throw new RIFFInvalidDataException();
+				int count = chunk.available() / 22;
+				for (int i = 0; i < count; i++) {					
+					SF2Layer layer = new SF2Layer(this);
+					layer.name = chunk.readString(20);
+					instruments_bagNdx.add(chunk.readUnsignedShort());
+					instruments.add(layer);
+					if(i != count - 1) this.layers.add(layer);
+				}				
+			}
+			else if(format.equals("ibag")) // Instrument Zones / Layer splits
+			{				
+				if(chunk.available() % 4 != 0) throw new RIFFInvalidDataException();
+				int count = chunk.available() / 4;
+				
+				// Skip first record
+				{
+					int gencount = chunk.readUnsignedShort();
+					int modcount = chunk.readUnsignedShort();
+					while( instruments_splits_gen.size() < gencount) 
+						instruments_splits_gen.add(null);
+					while( instruments_splits_mod.size() < modcount) 
+						instruments_splits_mod.add(null);
+					count--;
+				}
+				
+				int offset = instruments_bagNdx.get(0);
+				// Offset should be 0 (but just case)
+				for (int i = 0; i < offset; i++) {
+					if(count == 0) throw new RIFFInvalidDataException();
+					int gencount = chunk.readUnsignedShort();
+					int modcount = chunk.readUnsignedShort();
+					while( instruments_splits_gen.size() < gencount) 
+						instruments_splits_gen.add(null);
+					while( instruments_splits_mod.size() < modcount) 
+						instruments_splits_mod.add(null);
+					count--;					
+				}
+				
+				for (int i = 0; i < instruments_bagNdx.size()-1; i++) {
+					int zone_count = instruments_bagNdx.get(i+1) - instruments_bagNdx.get(i);
+					SF2Layer layer = layers.get(i);
+					for (int ii = 0; ii < zone_count; ii++) {
+						if(count == 0) throw new RIFFInvalidDataException();
+						int gencount = chunk.readUnsignedShort();
+						int modcount = chunk.readUnsignedShort();
+						SF2LayerRegion split = new SF2LayerRegion();
+						layer.regions.add(split);
+						while( instruments_splits_gen.size() < gencount) 
+							instruments_splits_gen.add(split);
+						while( instruments_splits_mod.size() < modcount) 
+							instruments_splits_mod.add(split);
+						count--;											
+					}
+				}
+				
+			}		
+			else if(format.equals("imod")) // Instrument Modulators / Split Modulators
+			{				
+				for (int i = 0; i < instruments_splits_mod.size(); i++) {
+					SF2Modulator modulator = new SF2Modulator();
+					modulator.sourceOperator = chunk.readUnsignedShort();
+					modulator.destinationOperator = chunk.readUnsignedShort();
+					modulator.amount = chunk.readShort();
+					modulator.amountSourceOperator = chunk.readUnsignedShort();
+					modulator.transportOperator= chunk.readUnsignedShort();
+					SF2LayerRegion split = instruments_splits_gen.get(i);
+					if(split != null)  split.modulators.add(modulator);
+				}				
+			}		
+			else if(format.equals("igen")) // Instrument Generators / Split Generators
+			{				
+				for (int i = 0; i < instruments_splits_gen.size(); i++) {
+					int operator = chunk.readUnsignedShort();
+					short amount = chunk.readShort();
+					SF2LayerRegion split = instruments_splits_gen.get(i);
+					if(split != null) split.generators.put(operator, amount);
+				}				
+			}
+			else if(format.equals("shdr")) // Sample Headers
+			{				
+				if(chunk.available() % 46 != 0) throw new RIFFInvalidDataException();
+				int count = chunk.available() / 46;
+				for (int i = 0; i < count; i++) {					
+					SF2Sample sample = new SF2Sample(this);				
+					sample.name = chunk.readString(20);
+					long start = chunk.readUnsignedInt();
+					long end = chunk.readUnsignedInt();					
+					sample.data = sampleData.subbuffer(start*2, end*2, true);
+					if(sampleData24 != null)
+						sample.data24 = sampleData24.subbuffer(start, end, true); 
+						/*
+						sample.data = new ModelByteBuffer(sampleData, (int)(start*2), (int)((end - start)*2));
+						if(sampleData24 != null)
+							sample.data24 = new ModelByteBuffer(sampleData24, (int)start, (int)(end - start)); */
+					sample.startLoop = chunk.readUnsignedInt() - start;
+					sample.endLoop = chunk.readUnsignedInt() - start;					
+					if(sample.startLoop < 0) sample.startLoop = -1;
+					if(sample.endLoop < 0) sample.endLoop = -1;
+					sample.sampleRate = chunk.readUnsignedInt();
+					sample.originalPitch = chunk.readUnsignedByte();
+					sample.pitchCorrection = chunk.readByte();
+					sample.sampleLink = chunk.readUnsignedShort();
+					sample.sampleType = chunk.readUnsignedShort();					
+					if(i != count - 1) this.samples.add(sample);
+				}
+			}					
+		}
+		
+		Iterator<SF2Layer> liter = this.layers.iterator();
+		while (liter.hasNext()) {			
+			SF2Layer layer = liter.next();
+			Iterator<SF2LayerRegion> siter = layer.regions.iterator();
+			SF2Region globalsplit = null;
+			while (siter.hasNext()) {
+				SF2LayerRegion split = siter.next();
+				if(split.generators.get(SF2LayerRegion.GENERATOR_SAMPLEID) != null)
+				{
+					int sampleid = split.generators.get(SF2LayerRegion.GENERATOR_SAMPLEID);
+					split.generators.remove(SF2LayerRegion.GENERATOR_SAMPLEID);
+					split.sample = samples.get(sampleid);
+				}
+				else
+				{
+					globalsplit = split;
+				}
+			}
+			if(globalsplit != null)
+			{
+				layer.getRegions().remove(globalsplit);
+				SF2GlobalRegion gsplit = new SF2GlobalRegion();
+				gsplit.generators = globalsplit.generators;
+				gsplit.modulators = globalsplit.modulators;
+				layer.setGlobalZone(gsplit);
+			}
+		}
+		
+		
+		Iterator<SF2Instrument> iiter = this.instruments.iterator();
+		while (iiter.hasNext()) {
+			SF2Instrument instrument = iiter.next();
+			Iterator<SF2InstrumentRegion> siter = instrument.regions.iterator();
+			SF2Region globalsplit = null;
+			while (siter.hasNext()) {
+				SF2InstrumentRegion split = siter.next();
+				if(split.generators.get(SF2LayerRegion.GENERATOR_INSTRUMENT) != null)
+				{				
+					int instrumentid = split.generators.get(SF2InstrumentRegion.GENERATOR_INSTRUMENT);
+					split.generators.remove(SF2LayerRegion.GENERATOR_INSTRUMENT);
+					split.layer = layers.get(instrumentid);
+				}
+				else
+				{
+					globalsplit = split;
+				}
+			}
+			
+			if(globalsplit != null)
+			{
+				instrument.getRegions().remove(globalsplit);
+				SF2GlobalRegion gsplit = new SF2GlobalRegion();
+				gsplit.generators = globalsplit.generators;
+				gsplit.modulators = globalsplit.modulators;
+				instrument.setGlobalZone(gsplit);
+			}			
+		}
+		
+	}
+
+	public void save(String name) throws IOException
+	{
+		writeSoundbank(new RIFFWriter(name, "sfbk"));
+	}
+	
+	public void save(File file) throws IOException
+	{
+		writeSoundbank(new RIFFWriter(file, "sfbk"));
+	}
+	
+	public void save(OutputStream out) throws IOException
+	{
+		writeSoundbank(new RIFFWriter(out, "sfbk"));
+	}		
+	
+	private void writeSoundbank(RIFFWriter writer) throws IOException
+	{
+		writeInfo(writer.writeList("INFO"));
+		writeSdtaChunk(writer.writeList("sdta"));
+		writePdtaChunk(writer.writeList("pdta"));
+		writer.close();
+	}
+	
+	private void writeInfoStringChunk(RIFFWriter writer, String name, String value) throws IOException
+	{
+		if(value == null) return;
+		RIFFWriter chunk = writer.writeChunk(name);
+		chunk.writeString(value);
+		int len = value.getBytes("ascii").length;
+		chunk.write(0);
+		len++;
+		if(len % 2 != 0) chunk.write(0);
+	}
+	
+	private void writeInfo(RIFFWriter writer) throws IOException
+	{
+		if(this.targetEngine == null) this.targetEngine = "EMU8000";
+		if(this.name == null) this.name = "";
+
+		RIFFWriter ifil_chunk = writer.writeChunk("ifil");
+		ifil_chunk.writeUnsignedShort(this.major);
+		ifil_chunk.writeUnsignedShort(this.minor);
+		writeInfoStringChunk(writer, "isng", this.targetEngine);
+		writeInfoStringChunk(writer, "INAM", this.name);
+		writeInfoStringChunk(writer, "irom", this.romName);		
+		if(romVersionMajor != -1)
+		{
+			RIFFWriter iver_chunk = writer.writeChunk("iver");
+			iver_chunk.writeUnsignedShort(this.romVersionMajor);
+			iver_chunk.writeUnsignedShort(this.romVersionMinor);
+		}
+		writeInfoStringChunk(writer, "ICRD", this.creationDate);
+		writeInfoStringChunk(writer, "IENG", this.engineers);
+		writeInfoStringChunk(writer, "IPRD", this.product);
+		writeInfoStringChunk(writer, "ICOP", this.copyright);
+		writeInfoStringChunk(writer, "ICMT", this.comments);
+		writeInfoStringChunk(writer, "ISFT", this.tools);
+		
+		writer.close();
+	}
+	
+	private void writeSdtaChunk(RIFFWriter writer) throws IOException
+	{
+		
+		byte[] pad = new byte[32];
+		
+		RIFFWriter smpl_chunk = writer.writeChunk("smpl");
+		for(SF2Sample sample : samples)
+		{
+			ModelByteBuffer data = sample.getDataBuffer();
+			data.writeTo(smpl_chunk);
+			/*
+			smpl_chunk.write(data.array(),
+					data.arrayOffset(),
+					data.capacity());
+			*/
+			smpl_chunk.write(pad);
+			smpl_chunk.write(pad);
+		}
+		if(major < 2) return;
+		if(major == 2 && minor < 4) return;
+				
+		
+		for(SF2Sample sample : samples)
+		{
+			ModelByteBuffer data24 = sample.getData24Buffer();
+			if(data24 == null) return;
+		}		
+
+		RIFFWriter sm24_chunk = writer.writeChunk("sm24");
+		for(SF2Sample sample : samples)
+		{
+			ModelByteBuffer data = sample.getData24Buffer();
+			data.writeTo(sm24_chunk);
+			/*
+			sm24_chunk.write(data.array(),
+					data.arrayOffset(),
+					data.capacity());*/
+			smpl_chunk.write(pad);
+		}		
+	}
+	
+	private void writeModulators(RIFFWriter writer, List<SF2Modulator> modulators) throws IOException
+	{
+		for(SF2Modulator modulator : modulators)
+		{
+			writer.writeUnsignedShort(modulator.sourceOperator);
+			writer.writeUnsignedShort(modulator.destinationOperator);
+			writer.writeShort(modulator.amount);
+			writer.writeUnsignedShort(modulator.amountSourceOperator);
+			writer.writeUnsignedShort(modulator.transportOperator);		
+		}		
+	}
+	
+	private void writeGenerators(RIFFWriter writer, Map<Integer, Short> generators) throws IOException
+	{
+		Short keyrange = (Short)generators.get(SF2Region.GENERATOR_KEYRANGE);
+		Short velrange = (Short)generators.get(SF2Region.GENERATOR_VELRANGE);
+		if(keyrange != null)
+		{
+			writer.writeUnsignedShort(SF2Region.GENERATOR_KEYRANGE);
+			writer.writeShort(keyrange);			
+		}
+		if(velrange != null)
+		{
+			writer.writeUnsignedShort(SF2Region.GENERATOR_VELRANGE);
+			writer.writeShort(velrange);			
+		}		
+		for(Map.Entry<Integer, Short> generator : generators.entrySet())
+		{
+			if(generator.getKey() == SF2Region.GENERATOR_KEYRANGE) continue;
+			if(generator.getKey() == SF2Region.GENERATOR_VELRANGE) continue;
+			writer.writeUnsignedShort(generator.getKey());
+			writer.writeShort(generator.getValue());
+		}		
+	}		
+	
+	private void writePdtaChunk(RIFFWriter writer) throws IOException
+	{
+
+		RIFFWriter phdr_chunk = writer.writeChunk("phdr");
+		int phdr_zone_count = 0;
+		for(SF2Instrument preset : this.instruments)
+		{		
+			phdr_chunk.writeString(preset.name, 20);
+			phdr_chunk.writeUnsignedShort(preset.preset);
+			phdr_chunk.writeUnsignedShort(preset.bank);
+			phdr_chunk.writeUnsignedShort(phdr_zone_count);
+			if(preset.getGlobalRegion() != null)
+				phdr_zone_count += 1;
+			phdr_zone_count += preset.getRegions().size();		
+			phdr_chunk.writeUnsignedInt(preset.library);
+			phdr_chunk.writeUnsignedInt(preset.genre);
+			phdr_chunk.writeUnsignedInt(preset.morphology);	
+		}
+		phdr_chunk.writeString("EOP", 20);
+		phdr_chunk.writeUnsignedShort(0);
+		phdr_chunk.writeUnsignedShort(0);
+		phdr_chunk.writeUnsignedShort(phdr_zone_count);
+		phdr_chunk.writeUnsignedInt(0);
+		phdr_chunk.writeUnsignedInt(0);
+		phdr_chunk.writeUnsignedInt(0);	
+		
+		
+		RIFFWriter pbag_chunk = writer.writeChunk("pbag");
+		int pbag_gencount = 0;
+		int pbag_modcount = 0;
+		for(SF2Instrument preset : this.instruments)
+		{		
+			if(preset.getGlobalRegion() != null)
+			{
+				pbag_chunk.writeUnsignedShort(pbag_gencount);
+				pbag_chunk.writeUnsignedShort(pbag_modcount);
+				pbag_gencount += preset.getGlobalRegion().getGenerators().size();
+				pbag_modcount += preset.getGlobalRegion().getModulators().size();
+			}
+			for(SF2InstrumentRegion region : preset.getRegions())
+			{
+				pbag_chunk.writeUnsignedShort(pbag_gencount);
+				pbag_chunk.writeUnsignedShort(pbag_modcount);
+				if(layers.indexOf(region.layer) != -1)
+					pbag_gencount += 1; // One generator is used to reference to instrument record
+				pbag_gencount += region.getGenerators().size();
+				pbag_modcount += region.getModulators().size();				
+				
+			}
+		}
+		pbag_chunk.writeUnsignedShort(pbag_gencount);
+		pbag_chunk.writeUnsignedShort(pbag_modcount);
+				
+		RIFFWriter pmod_chunk = writer.writeChunk("pmod");		
+		for(SF2Instrument preset : this.instruments)
+		{		
+			if(preset.getGlobalRegion() != null)
+				writeModulators(pmod_chunk, preset.getGlobalRegion().getModulators());
+			for(SF2InstrumentRegion region : preset.getRegions())
+				writeModulators(pmod_chunk, region.getModulators());
+		}			
+		pmod_chunk.write(new byte[10]);
+		
+		RIFFWriter pgen_chunk = writer.writeChunk("pgen");		
+		for(SF2Instrument preset : this.instruments)
+		{		
+			if(preset.getGlobalRegion() != null)
+				writeGenerators(pgen_chunk, preset.getGlobalRegion().getGenerators());
+			for(SF2InstrumentRegion region : preset.getRegions())
+			{
+				writeGenerators(pgen_chunk, region.getGenerators());
+				int ix = (int)layers.indexOf(region.layer);
+				if(ix != -1)
+				{
+					pgen_chunk.writeUnsignedShort(SF2Region.GENERATOR_INSTRUMENT);
+					pgen_chunk.writeShort((short)ix);
+				}
+			}
+		}		
+		pgen_chunk.write(new byte[4]);
+				
+		RIFFWriter inst_chunk = writer.writeChunk("inst");
+		int inst_zone_count = 0;
+		for(SF2Layer instrument : this.layers)
+		{		
+			inst_chunk.writeString(instrument.name, 20);
+			inst_chunk.writeUnsignedShort(inst_zone_count);
+			if(instrument.getGlobalRegion() != null)
+				inst_zone_count += 1;
+			inst_zone_count += instrument.getRegions().size();		
+		}
+		inst_chunk.writeString("EOI", 20);
+		inst_chunk.writeUnsignedShort(inst_zone_count);
+		
+		
+		RIFFWriter ibag_chunk = writer.writeChunk("ibag");
+		int ibag_gencount = 0;
+		int ibag_modcount = 0;
+		for(SF2Layer instrument : this.layers)
+		{		
+			if(instrument.getGlobalRegion() != null)
+			{
+				ibag_chunk.writeUnsignedShort(ibag_gencount);
+				ibag_chunk.writeUnsignedShort(ibag_modcount);
+				ibag_gencount += instrument.getGlobalRegion().getGenerators().size();
+				ibag_modcount += instrument.getGlobalRegion().getModulators().size();
+			}
+			for(SF2LayerRegion region : instrument.getRegions())
+			{
+				ibag_chunk.writeUnsignedShort(ibag_gencount);
+				ibag_chunk.writeUnsignedShort(ibag_modcount);
+				if(samples.indexOf(region.sample) != -1)
+					ibag_gencount += 1; // One generator is used to reference to instrument record
+				ibag_gencount += region.getGenerators().size();
+				ibag_modcount += region.getModulators().size();
+				
+			}
+		}
+		ibag_chunk.writeUnsignedShort(ibag_gencount);
+		ibag_chunk.writeUnsignedShort(ibag_modcount);
+		
+		
+		RIFFWriter imod_chunk = writer.writeChunk("imod");		
+		for(SF2Layer instrument : this.layers)
+		{		
+			if(instrument.getGlobalRegion() != null)
+				writeModulators(imod_chunk, instrument.getGlobalRegion().getModulators());
+			for(SF2LayerRegion region : instrument.getRegions())
+				writeModulators(imod_chunk, region.getModulators());
+		}			
+		imod_chunk.write(new byte[10]);
+		
+		RIFFWriter igen_chunk = writer.writeChunk("igen");		
+		for(SF2Layer instrument : this.layers)
+		{		
+			if(instrument.getGlobalRegion() != null)
+				writeGenerators(igen_chunk, instrument.getGlobalRegion().getGenerators());
+			for(SF2LayerRegion region : instrument.getRegions())
+			{
+				writeGenerators(igen_chunk, region.getGenerators());
+				int ix = samples.indexOf(region.sample);
+				if(ix != -1)
+				{
+					igen_chunk.writeUnsignedShort(SF2Region.GENERATOR_SAMPLEID);
+					igen_chunk.writeShort((short)ix);
+				}
+			}
+		}		
+		igen_chunk.write(new byte[4]);		
+		
+
+		RIFFWriter shdr_chunk = writer.writeChunk("shdr");
+		long sample_pos = 0;
+		for(SF2Sample sample : samples)
+		{
+			shdr_chunk.writeString(sample.name, 20);			
+			long start = sample_pos;
+			sample_pos += sample.data.capacity()/2;
+			long end = sample_pos;
+			long startLoop = sample.startLoop + start;
+			long endLoop = sample.endLoop + start;
+			if(startLoop < start) startLoop = start;
+			if(endLoop > end) endLoop = end;			
+			shdr_chunk.writeUnsignedInt(start);
+			shdr_chunk.writeUnsignedInt(end);			
+			shdr_chunk.writeUnsignedInt(startLoop);
+			shdr_chunk.writeUnsignedInt(endLoop);
+			shdr_chunk.writeUnsignedInt(sample.sampleRate);
+			shdr_chunk.writeUnsignedByte(sample.originalPitch);
+			shdr_chunk.writeByte(sample.pitchCorrection);
+			shdr_chunk.writeUnsignedShort(sample.sampleLink);
+			shdr_chunk.writeUnsignedShort(sample.sampleType);			
+			sample_pos += 32;
+		}
+		shdr_chunk.writeString("EOS", 20);
+		shdr_chunk.write(new byte[26]);
+			
+	}
+	
+	public String getName() {
+		return name;
+	}
+
+	public String getVersion() {
+		return major + "." + minor;
+	}
+
+	public String getVendor() {
+		return engineers;
+	}
+
+	public String getDescription() {
+		return comments;
+	}
+	
+	public void setName(String s) {
+		name = s;
+	}
+
+	public void setVendor(String s) {
+		engineers = s;
+	}
+
+	public void setDescription(String s) {
+		comments = s;
+	}	
+
+	public SoundbankResource[] getResources() {
+		SoundbankResource[] resources = new SoundbankResource[layers.size() + samples.size()];
+		int j = 0;
+		for (int i = 0; i < layers.size(); i++) 
+			resources[j++] = layers.get(i);
+		for (int i = 0; i < samples.size(); i++) 
+			resources[j++] = samples.get(i);		
+		return resources;
+	}
+
+	public SF2Instrument[] getInstruments() {
+		SF2Instrument[] inslist_array = instruments.toArray(new SF2Instrument[instruments.size()]);
+		Arrays.sort(inslist_array, new ModelInstrumentComparator());
+		return inslist_array;		
+	}
+	
+	public SF2Layer[] getLayers() {
+		return layers.toArray(new SF2Layer[layers.size()]);
+	}
+	
+	public SF2Sample[] getSamples() {
+		return samples.toArray(new SF2Sample[samples.size()]);
+	}
+
+	public Instrument getInstrument(Patch patch) {
+		int program = patch.getProgram();
+		int bank = patch.getBank();
+		boolean percussion = false;
+		if (patch instanceof ModelPatch)
+			percussion = ((ModelPatch) patch).isPercussion();
+		for (Instrument instrument : instruments) {
+			Patch patch2 = instrument.getPatch();
+			int program2 = patch2.getProgram();
+			int bank2 = patch2.getBank();
+			if (program == program2 && bank == bank2) {
+				boolean percussion2 = false;
+				if (patch2 instanceof ModelPatch)
+					percussion2 = ((ModelPatch) patch2).isPercussion();
+				if (percussion == percussion2)
+					return instrument;
+			}
+		}
+		return null;
+	}
+
+	public String getCreationDate() {
+		return creationDate;
+	}
+
+	public void setCreationDate(String creationDate) {
+		this.creationDate = creationDate;
+	}
+
+	public String getProduct() {
+		return product;
+	}
+
+	public void setProduct(String product) {
+		this.product = product;
+	}
+
+	public String getRomName() {
+		return romName;
+	}
+
+	public void setRomName(String romName) {
+		this.romName = romName;
+	}
+
+	public int getRomVersionMajor() {
+		return romVersionMajor;
+	}
+
+	public void setRomVersionMajor(int romVersionMajor) {
+		this.romVersionMajor = romVersionMajor;
+	}
+
+	public int getRomVersionMinor() {
+		return romVersionMinor;
+	}
+
+	public void setRomVersionMinor(int romVersionMinor) {
+		this.romVersionMinor = romVersionMinor;
+	}
+
+	public String getTargetEngine() {
+		return targetEngine;
+	}
+
+	public void setTargetEngine(String targetEngine) {
+		this.targetEngine = targetEngine;
+	}
+
+	public String getTools() {
+		return tools;
+	}
+
+	public void setTools(String tools) {
+		this.tools = tools;
+	}		
+
+	public void addResource(SoundbankResource resource)
+	{
+		if(resource instanceof SF2Instrument) instruments.add((SF2Instrument)resource);
+		if(resource instanceof SF2Layer) layers.add((SF2Layer)resource);
+		if(resource instanceof SF2Sample) samples.add((SF2Sample)resource);
+	}
+	
+	public void removeResource(SoundbankResource resource)
+	{
+		if(resource instanceof SF2Instrument) instruments.remove((SF2Instrument)resource);
+		if(resource instanceof SF2Layer) layers.remove((SF2Layer)resource);
+		if(resource instanceof SF2Sample) samples.remove((SF2Sample)resource);
+	}		
+	
+	public void addInstrument(SF2Instrument resource)
+	{
+		instruments.add(resource);
+	}
+	
+	public void removeInstrument(SF2Instrument resource)
+	{
+		instruments.remove(resource);
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SF2SoundbankReader.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,86 @@
+/*
+  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License version 2 only, as
+  * published by the Free Software Foundation.  Sun designates this
+  * particular file as subject to the "Classpath" exception as provided
+  * by Sun in the LICENSE file that accompanied this code.
+  *
+  * This code is distributed in the hope that it will be useful, but WITHOUT
+  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  * version 2 for more details (a copy is included in the LICENSE file that
+  * accompanied this code).
+  *
+  * You should have received a copy of the GNU General Public License version
+  * 2 along with this work; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+  *
+  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  * CA 95054 USA or visit www.sun.com if you need additional information or
+  * have any questions.
+  */ 
+
+package com.sun.media.sound;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.spi.SoundbankReader;
+
+/**
+ * 
+ * This class is used to connect the SF2SoundBank class
+ * to the SoundbankReader SPI interface.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */ 
+public class SF2SoundbankReader extends SoundbankReader {
+
+
+	public Soundbank getSoundbank(URL url) throws InvalidMidiDataException, IOException {
+		try
+		{
+			return new SF2Soundbank(url);
+		}
+		catch(RIFFInvalidFormatException e)
+		{
+			return null;
+		}		
+	}
+
+	public Soundbank getSoundbank(InputStream stream) throws InvalidMidiDataException, IOException {
+		try
+		{
+			stream.mark(512);
+			return new SF2Soundbank(stream);
+		}
+		catch(RIFFInvalidFormatException e)
+		{
+			stream.reset();
+			return null;
+		}
+	}
+
+	public Soundbank getSoundbank(File file) throws InvalidMidiDataException, IOException {
+		if(!file.getPath().toLowerCase().endsWith(".sf2")) return null;		
+		try
+		{
+			return new SF2Soundbank(file);
+		}
+		catch(RIFFInvalidFormatException e)
+		{
+			return null;
+		}			
+	}
+	
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SimpleInstrument.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sound.midi.Patch;
+
+/**
+ * A simple instrument that is made of other ModelInstrument, ModelPerformer
+ * objects.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class SimpleInstrument extends ModelInstrument {
+
+	private class SimpleInstrumentPart {
+		ModelPerformer[] performers;
+
+		int keyFrom;
+
+		int keyTo;
+
+		int velFrom;
+
+		int velTo;
+
+		int exclusiveClass;
+	}
+
+	protected int preset = 0;
+
+	protected int bank = 0;
+
+	protected boolean percussion = false;
+
+	protected String name = "";
+
+	protected List<SimpleInstrumentPart> parts = new ArrayList<SimpleInstrumentPart>();
+
+	public SimpleInstrument() {
+		super(null, null, null, null);
+	}
+
+	public void clear() {
+		parts.clear();
+	}
+
+	public void add(ModelPerformer[] performers, int keyFrom, int keyTo,
+			int velFrom, int velTo, int exclusiveClass) {
+		SimpleInstrumentPart part = new SimpleInstrumentPart();
+		part.performers = performers;
+		part.keyFrom = keyFrom;
+		part.keyTo = keyTo;
+		part.velFrom = velFrom;
+		part.velTo = velTo;
+		part.exclusiveClass = exclusiveClass;
+		parts.add(part);
+	}
+
+	public void add(ModelPerformer[] performers, int keyFrom, int keyTo,
+			int velFrom, int velTo) {
+		add(performers, keyFrom, keyTo, velFrom, velTo, -1);
+	}
+
+	public void add(ModelPerformer[] performers, int keyFrom, int keyTo) {
+		add(performers, keyFrom, keyTo, 0, 127, -1);
+	}
+
+	public void add(ModelPerformer[] performers) {
+		add(performers, 0, 127, 0, 127, -1);
+	}
+
+	public void add(ModelPerformer performer, int keyFrom, int keyTo,
+			int velFrom, int velTo, int exclusiveClass) {
+		add(new ModelPerformer[] { performer }, keyFrom, keyTo, velFrom, velTo,
+				exclusiveClass);
+	}
+
+	public void add(ModelPerformer performer, int keyFrom, int keyTo,
+			int velFrom, int velTo) {
+		add(new ModelPerformer[] { performer }, keyFrom, keyTo, velFrom, velTo);
+	}
+
+	public void add(ModelPerformer performer, int keyFrom, int keyTo) {
+		add(new ModelPerformer[] { performer }, keyFrom, keyTo);
+	}
+
+	public void add(ModelPerformer performer) {
+		add(new ModelPerformer[] { performer });
+	}
+
+	public void add(ModelInstrument ins, int keyFrom, int keyTo, int velFrom,
+			int velTo, int exclusiveClass) {
+		add(ins.getPerformers(), keyFrom, keyTo, velFrom, velTo, exclusiveClass);
+	}
+
+	public void add(ModelInstrument ins, int keyFrom, int keyTo, int velFrom,
+			int velTo) {
+		add(ins.getPerformers(), keyFrom, keyTo, velFrom, velTo);
+	}
+
+	public void add(ModelInstrument ins, int keyFrom, int keyTo) {
+		add(ins.getPerformers(), keyFrom, keyTo);
+	}
+
+	public void add(ModelInstrument ins) {
+		add(ins.getPerformers());
+	}
+
+	public ModelPerformer[] getPerformers() {
+
+		int percount = 0;
+		for (SimpleInstrumentPart part : parts)
+			if (part.performers != null)
+				percount += part.performers.length;
+
+		ModelPerformer[] performers = new ModelPerformer[percount];
+		int px = 0;
+		for (SimpleInstrumentPart part : parts) {
+			if (part.performers != null) {
+				for (ModelPerformer mperfm : part.performers) {
+					ModelPerformer performer = new ModelPerformer();
+					performer.setName(getName());
+					performers[px++] = performer;
+
+					performer.setDefaultConnectionsEnabled(mperfm
+							.isDefaultConnectionsEnabled());
+					performer.setKeyFrom(mperfm.getKeyFrom());
+					performer.setKeyTo(mperfm.getKeyTo());
+					performer.setVelFrom(mperfm.getVelFrom());
+					performer.setVelTo(mperfm.getVelTo());
+					performer.setExclusiveClass(mperfm.getExclusiveClass());
+					performer.setSelfNonExclusive(mperfm.isSelfNonExclusive());
+					performer.setReleaseTriggered(mperfm.isReleaseTriggered());
+					if (part.exclusiveClass != -1)
+						performer.setExclusiveClass(part.exclusiveClass);
+					if (part.keyFrom > performer.getKeyFrom())
+						performer.setKeyFrom(part.keyFrom);
+					if (part.keyTo < performer.getKeyTo())
+						performer.setKeyTo(part.keyTo);
+					if (part.velFrom > performer.getVelFrom())
+						performer.setVelFrom(part.velFrom);
+					if (part.velTo < performer.getVelTo())
+						performer.setVelTo(part.velTo);
+					performer.getOscillators().addAll(mperfm.getOscillators());
+					performer.getConnectionBlocks().addAll(
+							mperfm.getConnectionBlocks());
+				}
+			}
+		}
+
+		return performers;
+	}
+
+	public Object getData() {
+		return null;
+	}
+
+	public String getName() {
+		return this.name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public ModelPatch getPatch() {
+		return new ModelPatch(bank, preset, percussion);
+	}
+
+	public void setPatch(Patch patch) {
+		if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) {
+			percussion = true;
+			bank = patch.getBank();
+			preset = patch.getProgram();
+		} else {
+			percussion = false;
+			bank = patch.getBank();
+			preset = patch.getProgram();
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SimpleSoundbank.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.SoundbankResource;
+
+/**
+ * A simple soundbank that contains instruments and soundbankresources.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class SimpleSoundbank implements Soundbank {
+
+	String name = "";
+
+	String version = "";
+
+	String vendor = "";
+
+	String description = "";
+
+	List<SoundbankResource> resources = new ArrayList<SoundbankResource>();
+
+	List<Instrument> instruments = new ArrayList<Instrument>();
+
+	public String getName() {
+		return name;
+	}
+
+	public String getVersion() {
+		return version;
+	}
+
+	public String getVendor() {
+		return vendor;
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public void setVendor(String vendor) {
+		this.vendor = vendor;
+	}
+
+	public void setVersion(String version) {
+		this.version = version;
+	}
+
+	public SoundbankResource[] getResources() {
+		return (SoundbankResource[]) resources
+				.toArray(new SoundbankResource[resources.size()]);
+	}
+
+	public Instrument[] getInstruments() {
+		Instrument[] inslist_array = (Instrument[]) instruments.toArray(new Instrument[resources
+				.size()]);
+		Arrays.sort(inslist_array, new ModelInstrumentComparator());
+		return inslist_array;		
+	}
+
+	public Instrument getInstrument(Patch patch) {
+		int program = patch.getProgram();
+		int bank = patch.getBank();
+		boolean percussion = false;
+		if (patch instanceof ModelPatch)
+			percussion = ((ModelPatch) patch).isPercussion();
+		for (Instrument instrument : instruments) {
+			Patch patch2 = instrument.getPatch();
+			int program2 = patch2.getProgram();
+			int bank2 = patch2.getBank();
+			if (program == program2 && bank == bank2) {
+				boolean percussion2 = false;
+				if (patch2 instanceof ModelPatch)
+					percussion2 = ((ModelPatch) patch2).isPercussion();
+				if (percussion == percussion2)
+					return instrument;
+			}
+		}
+		return null;
+	}
+
+	public void addResource(SoundbankResource resource) {
+		if (resource instanceof Instrument)
+			instruments.add((Instrument) resource);
+		else
+			resources.add(resource);
+	}
+
+	public void removeResource(SoundbankResource resource) {
+		if (resource instanceof Instrument)
+			instruments.remove((Instrument) resource);
+		else
+			resources.remove(resource);
+	}
+
+	public void addInstrument(Instrument resource) {
+		instruments.add(resource);
+	}
+
+	public void removeInstrument(Instrument resource) {
+		instruments.remove(resource);
+	}
+
+	public void addAllInstruments(Soundbank soundbank) {
+		for(Instrument ins : soundbank.getInstruments())
+			addInstrument(ins);		
+	}
+
+	public void removeAllInstruments(Soundbank soundbank) {
+		for(Instrument ins : soundbank.getInstruments())
+			removeInstrument(ins);		
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAbstractResampler.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,422 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.VoiceStatus;
+
+/**
+ * 
+ * Abstract resampler class. 
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public abstract class SoftAbstractResampler implements SoftResampler {
+
+	private class ModelAbstractResamplerStream implements SoftResamplerStreamer {
+		AudioFloatInputStream stream;
+
+		boolean stream_eof = false;
+
+		int loopmode;
+		boolean loopdirection = true; // true = forward
+
+		float loopstart;
+
+		float looplen;
+
+		float target_pitch;
+
+		float[] current_pitch = new float[1];
+
+		boolean started;
+
+		boolean eof;
+
+		boolean loopreadevent = false;
+
+		int sector_pos = 0;
+
+		int sector_size = 400;
+
+		int sector_loopstart = -1;
+
+		boolean markset = false;
+
+		int marklimit = 0;
+
+		int streampos = 0;
+
+		int nrofchannels = 2;
+		
+		boolean noteOff_flag = false;
+
+		float[][] ibuffer;
+		boolean ibuffer_order = true;
+
+		float[] sbuffer;
+
+		int pad;
+
+		int pad2;
+
+		float[] ix = new float[1];
+		
+		int[] ox = new int[1];
+
+		float samplerateconv = 1;
+
+		float pitchcorrection = 0;
+
+		boolean streammarked = true;
+
+		public ModelAbstractResamplerStream() {
+			pad = getPadding();
+			pad2 = getPadding() * 2;
+			ibuffer = new float[2][sector_size + pad2];
+			ibuffer_order = true;		
+		}
+
+		public void noteOn(MidiChannel channel, VoiceStatus voice,
+				int noteNumber, int velocity) {
+		}
+
+		public void noteOff(int velocity) {
+			noteOff_flag = true;
+		}
+
+		public void open(ModelWavetable osc, float outputsamplerate)
+				throws IOException {
+
+			eof = false;
+			nrofchannels = osc.getChannels();
+			if (ibuffer.length < nrofchannels)
+			{
+				ibuffer = new float[nrofchannels][sector_size + pad2];
+			}
+
+			stream = osc.openStream();
+			streampos = 0;
+			stream_eof = false;
+			pitchcorrection = osc.getPitchcorrection();
+			samplerateconv = stream.getFormat().getSampleRate()
+					/ outputsamplerate;
+			looplen = osc.getLoopLength();
+			loopstart = osc.getLoopStart();
+			sector_loopstart = (int) (loopstart / sector_size);
+			sector_loopstart = sector_loopstart - 1;
+
+			sector_pos = 0;
+
+			if (sector_loopstart < 0)
+				sector_loopstart = 0;
+			started = false;
+			loopmode = osc.getLoopType();
+
+			if (loopmode != 0) {
+				markset = false;
+				marklimit = nrofchannels * (int) (looplen + pad2 + 1);
+			} else
+				markset = true;
+			// loopmode = 0;
+
+			target_pitch = samplerateconv;
+			current_pitch[0] = samplerateconv;
+			
+			ibuffer_order = true;				
+			loopdirection = true;
+			noteOff_flag = false;
+
+			for (int i = 0; i < nrofchannels; i++)
+				Arrays.fill(ibuffer[i], sector_size, sector_size + pad2, 0);
+			ix[0] = pad;
+			eof = false;
+			loopreadevent = false;
+
+			ix[0] = sector_size + pad;
+			sector_pos = -1;
+			streampos = -sector_size;
+
+			nextBuffer();
+		}
+
+		public void setPitch(float pitch) {
+			/*
+			this.pitch = (float) Math.pow(2f,
+					(pitchcorrection + pitch) / 1200.0f)
+					* samplerateconv;
+			*/
+			this.target_pitch = (float) Math.exp(
+					(pitchcorrection + pitch) * (Math.log(2.0) / 1200.0))
+					* samplerateconv;
+			
+			if (!started)
+				current_pitch[0] = this.target_pitch;
+		}
+
+		public void nextBuffer() throws IOException {
+			if (ix[0] < pad) {
+				if (markset) {
+					// reset to target sector
+					stream.reset();
+					ix[0] += streampos - (sector_loopstart * sector_size);
+					sector_pos = sector_loopstart;
+					streampos = sector_pos * sector_size;
+					;
+
+					// and go one sector backward
+					ix[0] += sector_size;
+					sector_pos -= 1;
+					streampos -= sector_size;
+					stream_eof = false;
+				}
+			}
+
+			if (ix[0] >= sector_size + pad)
+				if (stream_eof) {
+					eof = true;
+					return;
+				}
+			
+			if(ix[0] >= sector_size*4 + pad)
+			{
+				int skips = (int)( (ix[0] - sector_size*4 + pad)/sector_size );
+				ix[0] -= sector_size*skips;
+				sector_pos += skips;
+				streampos += sector_size*skips;
+				stream.skip(sector_size*skips);
+			} 
+
+			while (ix[0] >= sector_size + pad) {
+				if (!markset)
+					if (sector_pos + 1 == sector_loopstart) {
+						stream.mark(marklimit);
+						markset = true;
+					}
+				ix[0] -= sector_size;
+				sector_pos++;
+				streampos += sector_size;
+
+				for (int c = 0; c < nrofchannels; c++) {
+					float[] cbuffer = ibuffer[c];
+					for (int i = 0; i < pad2; i++)
+						cbuffer[i] = cbuffer[i + sector_size];
+				}
+
+				int ret;
+				if (nrofchannels == 1)
+					ret = stream.read(ibuffer[0], pad2, sector_size);
+				else {
+					int slen = sector_size * nrofchannels;
+					if (sbuffer == null || sbuffer.length < slen)
+						sbuffer = new float[slen];
+					int sret = stream.read(sbuffer, 0, slen);
+					if (sret == -1)
+						ret = -1;
+					else {
+						ret = sret / nrofchannels;
+						for (int i = 0; i < nrofchannels; i++) {
+							float[] buff = ibuffer[i];
+							int ix = i;
+							int ix_step = nrofchannels;
+							int ox = pad2;
+							for (int j = 0; j < ret; j++, ix += ix_step, ox++)
+								buff[ox] = sbuffer[ix];
+						}
+					}
+
+				}
+
+				if (ret == -1) {
+					ret = 0;
+					stream_eof = true;
+					for (int i = 0; i < nrofchannels; i++)
+						Arrays.fill(ibuffer[i], pad2, pad2 + sector_size, 0f);
+					return;
+				}
+				if (ret != sector_size)
+					for (int i = 0; i < nrofchannels; i++)
+						Arrays.fill(ibuffer[i], pad2 + ret, pad2 + sector_size,
+								0f);
+								
+				ibuffer_order = true;				
+
+			}
+
+		}
+		
+		public void reverseBuffers()
+		{
+			ibuffer_order = !ibuffer_order;
+			for (int c = 0; c < nrofchannels; c++)
+			{
+				float[] cbuff = ibuffer[c];
+				int len = cbuff.length-1;
+				int len2 = cbuff.length/2; 
+				for (int i = 0; i < len2; i++) {
+					float x = cbuff[i];
+					cbuff[i] = cbuff[len - i];
+					cbuff[len - i] = x;
+				}
+			}
+		}
+
+		public int read(float[][] buffer, int offset, int len)
+				throws IOException {
+
+			if (eof)
+				return -1;
+			
+			if(noteOff_flag)
+				if((loopmode & 2) != 0)
+					if(loopdirection)
+						loopmode = 0;
+			
+			
+			float pitchstep = (target_pitch - current_pitch[0]) / len;
+			float[] current_pitch = this.current_pitch;
+			started = true;
+
+			int[] ox = this.ox;
+			ox[0] = offset;
+			int ox_end = len + offset;			
+				
+			float ixend = sector_size + pad;
+			if(!loopdirection) ixend = pad;
+			while (ox[0] != ox_end) {
+				nextBuffer();
+				if(!loopdirection)
+				{
+					// If we are in backward playing part of pingpong or reverse loop
+					
+					if (streampos < (loopstart + pad)) {
+						ixend = loopstart - streampos + pad2;
+						if(ix[0] <= ixend)
+						{							
+							if((loopmode & 4) != 0)
+							{
+								// Ping pong loop, change loopdirection
+								loopdirection = true;
+								ixend = sector_size + pad;
+								continue;
+							}
+		
+							ix[0] += looplen;			
+							ixend = pad;
+							continue;							
+						}
+					}
+					
+					if(ibuffer_order != loopdirection) reverseBuffers();
+					
+					ix[0] = (sector_size + pad2) - ix[0];
+					ixend = (sector_size + pad2) - ixend;
+					ixend++;
+													
+					float bak_ix = ix[0];
+					int bak_ox = ox[0];
+					float bak_pitch = current_pitch[0];
+					for (int i = 0; i < nrofchannels; i++)
+						if (buffer[i] != null) {
+							ix[0] = bak_ix;
+							ox[0] = bak_ox;
+							current_pitch[0] = bak_pitch;
+							interpolate(ibuffer[i], ix, ixend, current_pitch, pitchstep,
+									buffer[i], ox, ox_end);
+						}
+					
+					ix[0] = (sector_size + pad2) - ix[0];
+					ixend--;
+					ixend = (sector_size + pad2) - ixend;
+
+					if (eof) {
+						current_pitch[0] = this.target_pitch;
+						return ox[0] - offset;
+					}					
+					
+					continue;
+				}
+				if (loopmode != 0)					
+					if (streampos + sector_size > (looplen + loopstart + pad)) {
+						ixend = loopstart + looplen - streampos + pad2;
+						if (ix[0] >= ixend) {							
+							if((loopmode & 4) != 0 || (loopmode & 8) != 0 )
+							{
+								// Ping pong or revese loop, change loopdirection
+								loopdirection = false;
+								ixend = pad;
+								continue;
+							}
+							ixend = sector_size + pad;
+							ix[0] -= looplen;							
+							continue;
+						}
+					}
+				
+				if(ibuffer_order != loopdirection) reverseBuffers();
+
+				float bak_ix = ix[0];
+				int bak_ox = ox[0];
+				float bak_pitch = current_pitch[0];
+				for (int i = 0; i < nrofchannels; i++)
+					if (buffer[i] != null) {
+						ix[0] = bak_ix;
+						ox[0] = bak_ox;
+						current_pitch[0] = bak_pitch;
+						interpolate(ibuffer[i], ix, ixend, current_pitch, pitchstep,
+								buffer[i], ox, ox_end);
+					}
+
+				if (eof) {
+					current_pitch[0] = this.target_pitch;
+					return ox[0] - offset;
+				}
+			}
+
+			current_pitch[0] = this.target_pitch;
+			return len;
+		}
+
+		public void close() throws IOException {
+			stream.close();
+		}
+	}
+
+	public abstract int getPadding();
+
+	public abstract void interpolate(float[] in, float[] in_offset,
+			float in_end, float[] pitch, float pitchstep, float[] out,
+			int[] out_offset, int out_end);
+
+	public SoftResamplerStreamer openStreamer() {
+		return new ModelAbstractResamplerStream();
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioBuffer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.util.Arrays;
+
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * This class is used to store audio buffer.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftAudioBuffer {
+
+	private int size;
+
+	private float[] buffer;
+
+	private boolean empty = true;
+
+	private AudioFormat format;
+
+	private AudioFloatConverter converter;
+
+	private byte[] converter_buffer;
+
+	public SoftAudioBuffer(int size, AudioFormat format) {
+		this.size = size;
+		this.format = format;
+		converter = AudioFloatConverter.getConverter(format);
+	}
+
+	public AudioFormat getFormat() {
+		return format;
+	}
+
+	public int getSize() {
+		return size;
+	}
+
+	public void clear() {
+		if (!empty) {
+			Arrays.fill(buffer, 0);
+			empty = true;
+		}
+	}
+
+	public boolean isSilent() {
+		return empty;
+	}
+
+	public float[] array() {
+		empty = false;
+		if (buffer == null)
+			buffer = new float[size];
+		return buffer;
+	}
+
+	public void get(byte[] buffer, int channel) {
+
+		int framesize_pc = (format.getFrameSize() / format.getChannels());
+		int c_len = size * framesize_pc;
+		if (converter_buffer == null || converter_buffer.length < c_len)
+			converter_buffer = new byte[c_len];
+
+		if (format.getChannels() == 1) {
+			converter.toByteArray(array(), size, buffer);
+		} else {
+			converter.toByteArray(array(), size, converter_buffer);
+			if (channel >= format.getChannels())
+				return;
+			int z_stepover = format.getChannels() * framesize_pc;
+			int k_stepover = framesize_pc;
+			for (int j = 0; j < framesize_pc; j++) {
+				int k = j;
+				int z = channel * framesize_pc + j;
+				for (int i = 0; i < size; i++) {
+					buffer[z] = converter_buffer[k];
+					z += z_stepover;
+					k += k_stepover;
+				}
+			}
+		}
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioProcessor.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * Audio processor interface.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public interface SoftAudioProcessor {
+
+	public void globalParameterControlChange(int[] slothpath, long param,
+			long value);
+
+	public void init(SoftSynthesizer synthesizer);
+
+	public void setInput(int pin, SoftAudioBuffer input);
+
+	public void setOutput(int pin, SoftAudioBuffer output);
+
+	public void setMixMode(boolean mix);
+
+	public void processAudio();
+
+	public void processControlLogic();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * This is a processor object that writes into SourceDataLine
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftAudioPusher implements Runnable {
+
+	private volatile boolean active = false;
+
+	private SourceDataLine sourceDataLine = null;
+
+	private Thread audiothread;
+
+	private AudioInputStream ais;
+
+	private byte[] buffer;
+
+	public SoftAudioPusher(SourceDataLine sourceDataLine, AudioInputStream ais,
+			int workbuffersizer) {
+		this.ais = ais;
+		this.buffer = new byte[workbuffersizer];
+		this.sourceDataLine = sourceDataLine;
+	}
+
+	public synchronized void start() {
+		if (active)
+			return;
+		active = true;
+		audiothread = new Thread(this);
+		audiothread.setPriority(Thread.MAX_PRIORITY);
+		try {
+			Thread.sleep(100);
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+		audiothread.start();
+	}
+
+	public synchronized void stop() {
+		if (!active)
+			return;
+		active = false;
+		try {
+			audiothread.join();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+	}
+
+	public void run() {
+		byte[] buffer = SoftAudioPusher.this.buffer;
+		AudioInputStream ais = SoftAudioPusher.this.ais;
+		SourceDataLine sourceDataLine = SoftAudioPusher.this.sourceDataLine;
+
+		try {
+			while (active) {
+				// Read from audio source
+				ais.read(buffer);
+				// Write byte buffer to source output
+				sourceDataLine.write(buffer, 0, buffer.length);
+			}
+		} catch (IOException e) {
+			active = false;
+			e.printStackTrace();
+		}
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,1502 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.Patch;
+
+/**
+ * 
+ * Software Synthesizer MIDI channel class.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
+	private static boolean[] dontResetControls = new boolean[128];
+	static {
+		for (int i = 0; i < dontResetControls.length; i++) 
+			dontResetControls[i] = false;
+
+		dontResetControls[0] = true;   // Bank Select (MSB)
+		dontResetControls[32] = true;  // Bank Select (LSB)
+		dontResetControls[7] = true;   // Channel Volume (MSB)
+		dontResetControls[8] = true;   // Balance (MSB)
+		dontResetControls[10] = true;  // Pan (MSB)
+		dontResetControls[11] = true;  // Expression (MSB)
+		dontResetControls[91] = true;  // Effects 1 Depth (default: Reverb Send)
+		dontResetControls[92] = true;  // Effects 2 Depth (default: Tremolo Depth)
+		dontResetControls[93] = true;  // Effects 3 Depth (default: Chorus Send)
+		dontResetControls[94] = true;  // Effects 4 Depth (default: Celeste [Detune] Depth)
+		dontResetControls[95] = true;  // Effects 5 Depth (default: Phaser Depth)
+		dontResetControls[70] = true;  // Sound Controller 1 (default: Sound Variation)
+		dontResetControls[71] = true;  // Sound Controller 2 (default: Timbre / Harmonic Quality)
+		dontResetControls[72] = true;  // Sound Controller 3 (default: Release Time)
+		dontResetControls[73] = true;  // Sound Controller 4 (default: Attack Time)
+		dontResetControls[74] = true;  // Sound Controller 5 (default: Brightness)
+		dontResetControls[75] = true;  // Sound Controller 6 (GM2 default: Decay Time)		
+		dontResetControls[76] = true;  // Sound Controller 7 (GM2 default: Vibrato Rate)
+		dontResetControls[77] = true;  // Sound Controller 8 (GM2 default: Vibrato Depth)
+		dontResetControls[78] = true;  // Sound Controller 9 (GM2 default: Vibrato Delay)
+		dontResetControls[79] = true;  // Sound Controller 10 (GM2 default: Undefined)
+		dontResetControls[120] = true; // All Sound Off
+		dontResetControls[121] = true; // Reset All Controllers
+		dontResetControls[122] = true; // Local Control On/Off
+		dontResetControls[123] = true; // All Notes Off
+		dontResetControls[124] = true; // Omni Mode Off
+		dontResetControls[125] = true; // Omni Mode On
+		dontResetControls[126] = true; // Poly Mode Off
+		dontResetControls[127] = true; // Poly Mode On
+		
+		dontResetControls[6] = true;   // Data Entry (MSB)					
+		dontResetControls[38] = true;  // Data Entry (LSB)
+		dontResetControls[96] = true;  // Data Increment					
+		dontResetControls[97] = true;  // Data Decrement							
+		dontResetControls[98] = true;  // Non-Registered Parameter Number (LSB)					
+		dontResetControls[99] = true;  // Non-Registered Parameter Number(MSB)					
+		dontResetControls[100] = true; // RPN = Null					
+		dontResetControls[101] = true; // RPN = Null		
+		
+		
+	}
+	
+	private static final int RPN_NULL_VALUE = (127 << 7) + 127;
+	private int rpn_control = RPN_NULL_VALUE;
+	private int nrpn_control = RPN_NULL_VALUE;
+
+	protected double portamento_time = 1; // keyschanges per control buffer time
+	protected int[] portamento_lastnote = new int[128];
+	protected int portamento_lastnote_ix = 0;
+	private int portamento_control_note = -1;
+	private boolean portamento = false;
+	private boolean mono = false;
+	private boolean mute = false;
+	private boolean solo = false;
+	private boolean solomute = false;
+
+	private Object control_mutex;
+
+	private int channel;
+
+	private SoftVoice[] voices;
+
+	private int bank;
+
+	private int program;
+
+	private SoftSynthesizer synthesizer;
+	private SoftMainMixer mainmixer;			
+
+	private int[] polypressure = new int[128];
+
+	private int channelpressure = 0;
+
+	private int[] controller = new int[128];	
+
+	private int pitchbend;
+	
+	private double[] co_midi_pitch = new double[1];
+	private double[] co_midi_channel_pressure = new double[1];
+	
+	protected SoftTuning tuning = new SoftTuning();
+	protected int tuning_bank = 0;
+	protected int tuning_program = 0;
+	
+	protected SoftInstrument current_instrument = null;
+	protected ModelChannelMixer current_mixer = null;
+	private ModelDirector current_director = null;; 
+	
+	// Controller Destination Settings
+	protected int cds_control_number = -1;
+	protected ModelConnectionBlock[] cds_control_connections = null;
+	protected ModelConnectionBlock[] cds_channelpressure_connections = null;
+	protected ModelConnectionBlock[] cds_polypressure_connections = null;
+	
+	protected boolean sustain = false;
+	protected boolean[][] keybasedcontroller_active = null;
+	protected double[][] keybasedcontroller_value = null;
+	
+	private class MidiControlObject implements SoftControl
+	{
+		double[] pitch = co_midi_pitch;
+		double[] channel_pressure = co_midi_channel_pressure;
+		double[] poly_pressure = new double[1];		
+		public double[] get(int instance, String name) {
+			if(name == null) return null;
+			if(name.equals("pitch")) return pitch;
+			if(name.equals("channel_pressure")) return channel_pressure;
+			if(name.equals("poly_pressure")) return poly_pressure;
+			return null;
+		}
+	};	
+	private SoftControl[] co_midi = new SoftControl[128];
+	{
+		for (int i = 0; i < co_midi.length; i++) {
+			co_midi[i] = new MidiControlObject();
+		}
+	}
+	private double[][] co_midi_cc_cc = new double[128][1];
+	private SoftControl co_midi_cc = new SoftControl()
+	{
+		double[][] cc = co_midi_cc_cc;
+		public double[] get(int instance, String name) {
+			if(name == null) return null;
+			return cc[Integer.parseInt(name)];
+		}
+	};	
+	
+	Map<Integer, int[]>co_midi_rpn_rpn_i = new HashMap<Integer, int[]>();
+	Map<Integer, double[]>co_midi_rpn_rpn = new HashMap<Integer, double[]>();	
+	private SoftControl co_midi_rpn = new SoftControl()
+	{
+		Map<Integer, double[]> rpn = co_midi_rpn_rpn;
+		public double[] get(int instance, String name) {
+			if(name == null) return null;
+			int iname = Integer.parseInt(name);
+			double[] v = rpn.get(iname);
+			if(v == null)
+			{
+				v = new double[1];
+				rpn.put(iname, v);
+			}
+			return v;
+		}
+	};		
+	
+	
+	Map<Integer, int[]>co_midi_nrpn_nrpn_i = new HashMap<Integer, int[]>();
+	Map<Integer, double[]>co_midi_nrpn_nrpn = new HashMap<Integer, double[]>();
+	private SoftControl co_midi_nrpn = new SoftControl()
+	{
+		Map<Integer, double[]> nrpn = co_midi_nrpn_nrpn;
+		public double[] get(int instance, String name) {
+			if(name == null) return null;
+			int iname = Integer.parseInt(name);
+			double[] v = nrpn.get(iname);
+			if(v == null)
+			{
+				v = new double[1];
+				nrpn.put(iname, v);
+			}
+			return v;
+		}
+	};
+
+	public SoftChannel(SoftSynthesizer synth, int channel) {
+		this.channel = channel;
+		this.voices = synth.getVoices();
+		this.synthesizer = synth;
+		this.mainmixer = synth.getMainMixer();
+		control_mutex = synth.control_mutex;		
+		resetAllControllers(true);
+	}
+
+	private int findFreeVoice(int x) {
+		for (int i = x; i < voices.length; i++)
+			if (!voices[i].active)
+				return i;
+		
+		// No free voice was found, we must steal one 
+		
+		int vmode = synthesizer.getVoiceAllocationMode();
+		if(vmode == 1)
+		{
+			// DLS Static Voice Allocation
+			
+			//  * priority ( 10, 1-9, 11-16)
+			// Search for channel to steal from
+			int steal_channel = channel;			
+			for (int j = 0; j < voices.length; j++) {
+				if(voices[j].stealer_channel == null)
+				{								
+					if(steal_channel == 9)
+					{
+						steal_channel = voices[j].channel;
+					}
+					else
+					{
+						if(voices[j].channel != 9)
+						{
+							if(voices[j].channel > steal_channel) steal_channel = voices[j].channel; 
+						}
+					}
+				}
+			}
+				
+			int voiceNo = -1;
+			
+			SoftVoice v = null; 
+			// Search for oldest voice in off state on steal_channel
+			for (int j = 0; j < voices.length; j++) {
+				if(voices[j].channel == steal_channel)
+				if(voices[j].stealer_channel == null && !voices[j].on)				
+				{
+					if(v == null)
+					{
+						v = voices[j];
+						voiceNo = j;
+					}
+					if(voices[j].voiceID < v.voiceID)
+					{
+						v = voices[j];
+						voiceNo = j;
+					}
+				}
+			}
+			// Search for oldest voice in on state on steal_channel
+			if(voiceNo == -1)
+			{							
+				for (int j = 0; j < voices.length; j++) {
+					if(voices[j].channel == steal_channel)
+					if(voices[j].stealer_channel == null)
+					{
+					if(v == null)
+					{
+						v = voices[j];
+						voiceNo = j;
+						}
+						if(voices[j].voiceID < v.voiceID)
+						{
+							v = voices[j];
+							voiceNo = j;
+						}
+					}
+				}								
+			}
+			
+			return voiceNo;			
+			
+		}
+		else
+		{
+			// Default Voice Allocation
+			//  * Find voice that is on
+			//  	and Find voice which has lowest voiceID ( oldest voice)
+			//  * Or find voice that is off
+			//  	and Find voice which has lowest voiceID ( oldest voice)
+			
+			int voiceNo = -1;
+									
+			SoftVoice v = null; 
+			// Search for oldest voice in off state
+			for (int j = 0; j < voices.length; j++) {
+				if(voices[j].stealer_channel == null && !voices[j].on)
+				{
+					if(v == null)
+					{
+						v = voices[j];
+						voiceNo = j;
+					}
+					if(voices[j].voiceID < v.voiceID)
+					{
+						v = voices[j];
+						voiceNo = j;
+					}
+				}
+			}
+			// Search for oldest voice in on state
+			if(voiceNo == -1)
+			{
+			
+				for (int j = 0; j < voices.length; j++) {
+					if(voices[j].stealer_channel == null)
+					{
+					if(v == null)
+					{
+						v = voices[j];
+						voiceNo = j;
+						}
+						if(voices[j].voiceID < v.voiceID)
+						{
+							v = voices[j];
+							voiceNo = j;
+						}
+					}
+				}								
+			}
+			
+			return voiceNo;
+		}					
+				
+	}
+	
+	protected void initVoice(SoftVoice voice, SoftPerformer p, int voiceID, int noteNumber, int velocity, ModelConnectionBlock[] connectionBlocks, ModelChannelMixer channelmixer, boolean releaseTriggered)
+	{
+		if(voice.active)
+		{
+			// Voice is active , we must steal the voice
+			voice.stealer_channel = this;
+			voice.stealer_performer = p;
+			voice.stealer_voiceID = voiceID;
+			voice.stealer_noteNumber = noteNumber;
+			voice.stealer_velocity = velocity;
+			voice.stealer_extendedConnectionBlocks = connectionBlocks;
+			voice.stealer_channelmixer = channelmixer;
+			voice.stealer_releaseTriggered = releaseTriggered;
+			for (int i = 0; i < voices.length; i++)
+				if(voices[i].active && voices[i].voiceID == voice.voiceID)			
+					voices[i].soundOff();
+			return;
+		}
+		
+		voice.extendedConnectionBlocks = connectionBlocks;
+		voice.channelmixer = channelmixer;
+		voice.releaseTriggered = releaseTriggered;
+		voice.voiceID = voiceID;
+		voice.tuning = tuning;
+		voice.exclusiveClass = p.exclusiveClass;
+		voice.softchannel = this;
+		voice.channel = channel;
+		voice.bank = bank;
+		voice.program = program;
+		voice.instrument = current_instrument;
+		voice.performer = p;
+		voice.objects.clear();
+		voice.objects.put("midi", co_midi[noteNumber]);
+		voice.objects.put("midi_cc", co_midi_cc);
+		voice.objects.put("midi_rpn", co_midi_rpn);
+		voice.objects.put("midi_nrpn", co_midi_nrpn);
+		voice.noteOn(noteNumber, velocity);
+		voice.setMute(mute);
+		voice.setSoloMute(solomute);
+		if(releaseTriggered) return;
+		if(portamento_control_note != -1)
+		{
+			voice.co_noteon_keynumber[0] = (tuning.getTuning(portamento_control_note) / 100.0) * (1f/128f);
+			voice.portamento = true;
+			portamento_control_note = -1;
+		}
+		else
+		if(portamento)
+		{
+			if(mono)
+			{
+				if(portamento_lastnote[0] != -1)
+				{
+					voice.co_noteon_keynumber[0] = (tuning.getTuning(portamento_lastnote[0]) / 100.0)*(1f/128f);
+					voice.portamento = true;
+					portamento_control_note = -1;									
+				}
+				portamento_lastnote[0] = noteNumber;
+			}
+			else
+			{
+				if(portamento_lastnote_ix != 0)
+				{
+					portamento_lastnote_ix--;
+					voice.co_noteon_keynumber[0] = (tuning.getTuning(portamento_lastnote[portamento_lastnote_ix]) / 100.0)*(1f/128f);
+					voice.portamento = true;
+				}
+			}
+		}		
+	}
+	
+	public void noteOn(int noteNumber, int velocity) {
+
+		noteOn_internal(noteNumber, velocity);
+		if(current_mixer != null) current_mixer.noteOn(noteNumber, velocity);
+	}
+
+	private void noteOn_internal(int noteNumber, int velocity) {
+
+		if (velocity == 0) {
+			noteOff_internal(noteNumber, 64);
+			return;
+		}
+
+		synchronized (control_mutex) {
+						
+			if(sustain)
+			{				
+				sustain = false;
+				for (int i = 0; i < voices.length; i++)
+					if ((voices[i].sustain || voices[i].on)
+							&& voices[i].channel == channel
+							&& voices[i].active && voices[i].note == noteNumber ) {
+						
+						voices[i].sustain = false;
+						voices[i].on = true;
+						voices[i].noteOff(0);
+					}			
+				sustain = true;
+			}
+			
+			mainmixer.msec_last_activity = mainmixer.msec_pos;
+			
+			if(mono)
+			{
+			if(portamento)
+			{
+				
+				boolean n_found = false;
+				for (int i = 0; i < voices.length; i++)
+					if (voices[i].on && voices[i].channel == channel
+							&& voices[i].active  
+							&& voices[i].releaseTriggered == false ) {
+						voices[i].portamento = true;
+						voices[i].setNote(noteNumber);
+						n_found = true;
+					}
+				if(n_found)
+				{
+					portamento_lastnote[0] = noteNumber;
+					return;
+				}
+			}
+						
+			if(portamento_control_note != -1)
+			{
+				boolean n_found = false;
+				for (int i = 0; i < voices.length; i++)
+					if (voices[i].on && voices[i].channel == channel
+							&& voices[i].active && voices[i].note == portamento_control_note
+							&& voices[i].releaseTriggered == false ) {
+						voices[i].portamento = true;
+						voices[i].setNote(noteNumber);
+						n_found = true;
+					}
+				portamento_control_note = -1;
+				if(n_found) return;				
+			}
+			}
+			
+			if(mono) allNotesOff();
+									
+			if(current_instrument == null)
+			{
+				current_instrument = synthesizer.findInstrument(program, bank, channel);
+				if(current_instrument == null) return;
+				if(current_mixer != null) mainmixer.stopMixer(current_mixer);
+				current_mixer = current_instrument.getSourceInstrument().getChannelMixer(this, synthesizer.getFormat());
+				if(current_mixer != null) mainmixer.registerMixer(current_mixer);
+				current_director = current_instrument.getDirector(this, this);
+				applyInstrumentCustomization();
+
+			}
+			prevVoiceID = synthesizer.voiceIDCounter++;
+			firstVoice = true;
+			voiceNo = 0;
+			
+			int tunedKey = (int)( Math.round(tuning.getTuning()[noteNumber] / 100.0));
+			play_noteNumber = noteNumber;
+			play_velocity = velocity;
+			play_releasetriggered = false;
+			lastVelocity[noteNumber] = velocity;
+			current_director.noteOn(tunedKey, velocity);
+			
+			/*
+			SoftPerformer[] performers = current_instrument.getPerformers();
+			for (int i = 0; i < performers.length; i++) {
+				SoftPerformer p = performers[i];
+				if (p.keyFrom <= tunedKey && p.keyTo >= tunedKey)
+					if (p.velFrom <= velocity && p.velTo >= velocity) {
+						
+						if(firstVoice)
+						{
+							firstVoice = false;
+							if(p.exclusiveClass != 0)
+							{
+								int x = p.exclusiveClass;								
+								for (int j = 0; j < voices.length; j++)
+									if (voices[j].active && voices[j].channel == channel
+											&& voices[j].exclusiveClass == x) {
+										if(!(p.selfNonExclusive && voices[j].note == noteNumber))
+											voices[j].shutdown();
+									}
+							}
+						}
+						
+						voiceNo = findFreeVoice(voiceNo);
+			
+						if(voiceNo == -1)
+							return;
+						
+						initVoice(voices[voiceNo], p, prevVoiceID, noteNumber, velocity);
+
+
+					}
+			}*/
+		}
+	}
+	
+	public void noteOff(int noteNumber, int velocity) {
+		
+		noteOff_internal(noteNumber, velocity);
+
+		if(current_mixer != null) current_mixer.noteOff(noteNumber, velocity);
+		
+	}
+
+	private void noteOff_internal(int noteNumber, int velocity) {
+		synchronized (control_mutex) {
+			
+			if(!mono)
+				if(portamento)
+				{
+					if(portamento_lastnote_ix != 127)
+					{
+						portamento_lastnote[portamento_lastnote_ix] = noteNumber;
+						portamento_lastnote_ix++;
+					}
+				}
+			
+			mainmixer.msec_last_activity = mainmixer.msec_pos;
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].on && voices[i].channel == channel
+						&& voices[i].note == noteNumber && voices[i].releaseTriggered == false) {
+					voices[i].noteOff(velocity);
+				}
+						
+			// Try play back note-off triggered voices,
+			
+			if(current_instrument == null)
+			{
+				current_instrument = synthesizer.findInstrument(program, bank, channel);
+				if(current_instrument == null) return;
+				if(current_mixer != null) mainmixer.stopMixer(current_mixer);
+				current_mixer = current_instrument.getSourceInstrument().getChannelMixer(this, synthesizer.getFormat());
+				if(current_mixer != null) mainmixer.registerMixer(current_mixer);
+				current_director = current_instrument.getDirector(this, this);
+				applyInstrumentCustomization();
+
+			}
+			prevVoiceID = synthesizer.voiceIDCounter++;
+			firstVoice = true;
+			voiceNo = 0;
+			
+			int tunedKey = (int)( Math.round(tuning.getTuning()[noteNumber] / 100.0));
+			play_noteNumber = noteNumber;
+			play_velocity = lastVelocity[noteNumber];
+			play_releasetriggered = true;
+			current_director.noteOff(tunedKey, velocity);			
+
+		}
+	}
+	
+	private int[] lastVelocity = new int[128];
+	private int prevVoiceID;
+	private boolean firstVoice = true;
+	private int voiceNo = 0;
+	private int play_noteNumber = 0;
+	private int play_velocity = 0;
+	private boolean play_releasetriggered = false;
+	
+	public void play(int performerIndex, ModelConnectionBlock[] connectionBlocks)
+	{
+		
+		int noteNumber = play_noteNumber;
+		int velocity = play_velocity;
+		boolean releasetriggered = play_releasetriggered;
+		
+		SoftPerformer p = current_instrument.getPerformers()[performerIndex];
+		
+		if(firstVoice)
+		{
+			firstVoice = false;
+			if(p.exclusiveClass != 0)
+			{
+				int x = p.exclusiveClass;								
+				for (int j = 0; j < voices.length; j++)
+					if (voices[j].active && voices[j].channel == channel
+							&& voices[j].exclusiveClass == x) {
+						if(!(p.selfNonExclusive && voices[j].note == noteNumber))
+							voices[j].shutdown();
+					}
+			}
+		}
+		
+		voiceNo = findFreeVoice(voiceNo);
+
+		if(voiceNo == -1)
+			return;
+		
+		initVoice(voices[voiceNo], p, prevVoiceID, noteNumber, velocity, connectionBlocks, current_mixer, releasetriggered);
+	}
+
+	public void noteOff(int noteNumber) {
+		noteOff_internal(noteNumber, 64);
+	}
+
+	public void setPolyPressure(int noteNumber, int pressure) {
+		if(current_mixer != null) current_mixer.setPolyPressure(noteNumber, pressure);
+
+		synchronized (control_mutex) {
+			mainmixer.msec_last_activity = mainmixer.msec_pos;
+			co_midi[noteNumber].get(0,"poly_pressure")[0] = pressure * (1.0/128.0);
+			polypressure[noteNumber] = pressure;
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].active && voices[i].note == noteNumber)
+					voices[i].setPolyPressure(pressure);
+		}
+	}
+
+	public int getPolyPressure(int noteNumber) {
+		synchronized (control_mutex) {
+			return polypressure[noteNumber];
+		}
+	}
+
+	public void setChannelPressure(int pressure) {
+		if(current_mixer != null) current_mixer.setChannelPressure(pressure);
+		synchronized (control_mutex) {
+			mainmixer.msec_last_activity = mainmixer.msec_pos;
+			co_midi_channel_pressure[0] = pressure * (1.0/128.0);
+			channelpressure = pressure;
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].active)
+					voices[i].setChannelPressure(pressure);
+		}
+	}
+
+	public int getChannelPressure() {
+		synchronized (control_mutex) {
+			return channelpressure;
+		}
+	}
+	
+	protected void applyInstrumentCustomization()
+	{
+		if(cds_control_connections == null 
+				&& cds_channelpressure_connections == null 
+				&& cds_polypressure_connections == null) return;				
+		
+		ModelInstrument src_instrument = current_instrument.getSourceInstrument();
+		ModelPerformer[] performers = src_instrument.getPerformers();
+		ModelPerformer[] new_performers = new ModelPerformer[performers.length];
+		for (int i = 0; i < new_performers.length; i++) {
+			ModelPerformer performer = performers[i];
+			ModelPerformer new_performer = new ModelPerformer();
+			new_performer.setName(performer.getName());
+			new_performer.setExclusiveClass(performer.getExclusiveClass());
+			new_performer.setKeyFrom(performer.getKeyFrom());
+			new_performer.setKeyTo(performer.getKeyTo());
+			new_performer.setVelFrom(performer.getVelFrom());
+			new_performer.setVelTo(performer.getVelTo());
+			new_performer.getOscillators().addAll(performer.getOscillators());
+			new_performer.getConnectionBlocks().addAll(performer.getConnectionBlocks());
+			new_performers[i] = new_performer;
+
+			List<ModelConnectionBlock> connblocks = new_performer.getConnectionBlocks();
+			
+			if(cds_control_connections != null)
+			{
+				String cc = Integer.toString(cds_control_number);
+				Iterator<ModelConnectionBlock> iter = connblocks.iterator();
+				while (iter.hasNext()) {
+					ModelConnectionBlock conn = iter.next();
+					ModelSource[] sources = conn.getSources();
+					boolean removeok = false;
+					if(sources != null)
+					for (int j = 0; j < sources.length; j++) {
+						ModelSource src = sources[j];
+						if("midi_cc".equals(src.getIdentifier().getObject())
+						&& cc.equals(src.getIdentifier().getVariable()))
+							removeok = true;
+					}
+					if(removeok) iter.remove();
+				}
+				for (int j = 0; j < cds_control_connections.length; j++) 
+					connblocks.add(cds_control_connections[j]);				
+			}
+			
+			if(cds_polypressure_connections != null)
+			{
+				Iterator<ModelConnectionBlock> iter = connblocks.iterator();
+				while (iter.hasNext()) {
+					ModelConnectionBlock conn = iter.next();
+					ModelSource[] sources = conn.getSources();
+					boolean removeok = false;
+					if(sources != null)
+					for (int j = 0; j < sources.length; j++) {
+						ModelSource src = sources[j];
+						if("midi".equals(src.getIdentifier().getObject())
+						&& "poly_pressure".equals(src.getIdentifier().getVariable()))
+							removeok = true;
+					}
+					if(removeok) iter.remove();
+				}
+				for (int j = 0; j < cds_polypressure_connections.length; j++) 
+					connblocks.add(cds_polypressure_connections[j]);								
+			}
+			
+			
+			if(cds_channelpressure_connections != null)
+			{
+				Iterator<ModelConnectionBlock> iter = connblocks.iterator();
+				while (iter.hasNext()) {
+					ModelConnectionBlock conn = iter.next();
+					ModelSource[] sources = conn.getSources();
+					boolean removeok = false;
+					if(sources != null)
+					for (int j = 0; j < sources.length; j++) {
+						ModelIdentifier srcid = sources[j].getIdentifier();
+						if("midi".equals(srcid.getObject())
+						&& "channel_pressure".equals(srcid.getVariable()))
+							removeok = true;
+					}
+					if(removeok) iter.remove();
+				}
+				for (int j = 0; j < cds_channelpressure_connections.length; j++) 
+					connblocks.add(cds_channelpressure_connections[j]);								
+			}
+			
+		}
+		
+		current_instrument = new SoftInstrument(src_instrument, new_performers);
+		
+	}
+	
+	private ModelConnectionBlock[] createModelConnections(ModelIdentifier sid, int[] destination, int[] range) {
+
+		// controlled parameter (pp) 	range (rr) Description                  Default
+		// ------------------------------------------------------------------------------
+		// 00 Pitch Control 			28H - 58H	-24 - +24 semitones			40H
+		// 01 Filter Cutoff Control 	00H - 7FH	-9600 - +9450 cents			40H
+		// 02 Amplitude Control 		00H - 7FH	0 - (127/64) * 100 percent	40H 
+		// 03 LFO Pitch Depth 			00H - 7FH	0 - 600 cents				0
+		// 04 LFO Filter Depth 			00H - 7FH	0 - 2400 cents				0
+		// 05 LFO Amplitude Depth 		00H - 7FH	0 - 100 percent				0  
+				
+		List<ModelConnectionBlock> conns = new ArrayList<ModelConnectionBlock>();
+
+		for (int i = 0; i < destination.length; i++) {
+			int d = destination[i];
+			int r = range[i];
+			if(d == 0) 
+			{
+				double scale = (r - 64)*100;
+				ModelConnectionBlock conn = new ModelConnectionBlock(
+						new ModelSource(sid,
+								ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR)
+								,scale,new ModelDestination(new ModelIdentifier("osc", "pitch")));				
+				conns.add(conn);
+				
+			}
+			if(d == 1)
+			{
+				double scale = (r / 64.0 - 1.0) * 9600.0;
+				ModelConnectionBlock conn;
+				if(scale > 0)
+					conn = new ModelConnectionBlock(
+						new ModelSource(sid,
+								ModelStandardTransform.DIRECTION_MAX2MIN,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR)
+								,-scale,new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ));
+				else
+					conn = new ModelConnectionBlock(
+							new ModelSource(sid,
+									ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR)
+									,scale,new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ));
+				conns.add(conn);
+			}
+			if(d == 2)
+			{	
+				final double scale = (r / 64.0); 
+				
+				ModelTransform mt = new ModelTransform()
+				{
+					double s = scale;
+					public double transform(double value) {
+						if(s < 1) value = s + (value*(1.0-s));
+						else
+						if(s > 1) value = 1 + (value*(s - 1.0));
+						else
+							return 0;
+						return -((5.0/12.0)/Math.log(10))*Math.log(value);
+					}
+				};
+				
+				ModelConnectionBlock conn = new ModelConnectionBlock(
+						new ModelSource(sid,mt),-960,new ModelDestination(ModelDestination.DESTINATION_GAIN));				
+				conns.add(conn);
+				
+			}
+			if(d == 3)
+			{			
+				double scale = (r / 64.0 - 1.0) * 9600.0;
+				ModelConnectionBlock conn = new ModelConnectionBlock(
+						new ModelSource(ModelSource.SOURCE_LFO1,
+						ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR),
+						new ModelSource(sid,
+						ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR),
+						scale,new ModelDestination(ModelDestination.DESTINATION_PITCH));
+				conns.add(conn);
+			}
+			if(d == 4) 
+			{	
+				double scale = (r / 128.0) * 2400.0;
+				ModelConnectionBlock conn = new ModelConnectionBlock(
+						new ModelSource(ModelSource.SOURCE_LFO1,
+						ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_BIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR),
+						new ModelSource(sid,
+						ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR),
+						scale,new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ));
+				conns.add(conn);
+			}
+			if(d == 5)
+			{			
+				final double scale = (r / 127.0);
+				
+				ModelTransform mt = new ModelTransform()
+				{
+					double s = scale;
+					public double transform(double value) {
+						return -((5.0/12.0)/Math.log(10))*Math.log(1 - value*s);
+					}
+				};				
+				
+				ModelConnectionBlock conn = new ModelConnectionBlock(
+						new ModelSource(ModelSource.SOURCE_LFO1,
+						ModelStandardTransform.DIRECTION_MIN2MAX,ModelStandardTransform.POLARITY_UNIPOLAR,ModelStandardTransform.TRANSFORM_LINEAR),
+						new ModelSource(sid,
+						mt),
+						-960,new ModelDestination(ModelDestination.DESTINATION_GAIN));
+				conns.add(conn);				
+			}
+		}
+
+		return (ModelConnectionBlock[])conns.toArray(new ModelConnectionBlock[conns.size()]);
+	}
+	
+	public void mapPolyPressureToDestination(int[] destination, int[] range) {
+		current_instrument = null;
+		if(destination.length == 0)
+		{
+			cds_polypressure_connections = null;
+			return;
+		}
+		cds_polypressure_connections = createModelConnections(new ModelIdentifier("midi","poly_pressure"), destination, range);
+	}	
+	
+	public void mapChannelPressureToDestination(int[] destination, int[] range) {
+		current_instrument = null;
+		if(destination.length == 0)
+		{
+			cds_channelpressure_connections = null;
+			return;
+		}
+		cds_channelpressure_connections = createModelConnections(new ModelIdentifier("midi","channel_pressure"), destination, range);
+	}
+	
+	public void mapControlToDestination(int control, int[] destination, int[] range) {
+		
+		if(!( (control >= 0x01 && control <= 0x1F) || (control >= 0x40 && control <= 0x5F) ) )
+		{
+			cds_control_connections = null;
+			return;			
+		}
+		
+		current_instrument = null;
+		cds_control_number = control;
+		if(destination.length == 0)
+		{
+			cds_control_connections = null;
+			return;
+		}
+		cds_control_connections = createModelConnections(new ModelIdentifier("midi_cc",Integer.toString(control)), destination, range);
+	}
+	
+	
+	public void controlChangePerNote(int noteNumber, int controller, int value) {
+
+		/*
+		
+		CC# 	nn 		Name 						vv					default				description
+		--------------------------------------------------------------------------------------------------------------------
+		7 		07H		Note Volume 				00H-40H-7FH			40H					0-100-(127/64)*100 (%) (Relative)
+		10 		0AH 	*Pan 						00H-7FH absolute	(Preset Value)		Left-Center-Right (absolute)
+		33-63 	21-3FH 	LSB for 					01H-1FH
+		71 		47H 	Timbre/Harmonic Intensity 	00H-40H-7FH			40H (???)
+		72 		48H 	Release Time 				00H-40H-7FH			40H (???)
+		73 		49H 	Attack Time 				00H-40H-7FH			40H (???)
+		74 		4AH 	Brightness 					00H-40H-7FH			40H (???)
+		75 		4BH 	Decay Time 					00H-40H-7FH			40H (???)
+		76 		4CH 	Vibrato Rate 				00H-40H-7FH			40H (???)
+		77 		4DH 	Vibrato Depth 				00H-40H-7FH			40H (???)
+		78 		4EH 	Vibrato Delay 				00H-40H-7FH			40H (???)
+		91 		5BH 	*Reverb Send 				00H-7FH absolute	(Preset Value)		Left-Center-RIght (absolute)
+		93 		5DH 	*Chorus Send 				00H-7FH absolute	(Preset Value)		Left-Center-RIght (absolute)
+		120 	78H 	**Fine Tuning 				00H-40H-7FH			40H (???)
+		121 	79H 	**Coarse Tuning 			00H-40H-7FH			40H (???)
+		
+		*/		
+		
+		if(keybasedcontroller_active == null)
+		{
+			keybasedcontroller_active = new boolean[128][];
+		    keybasedcontroller_value = new double[128][];
+		}		
+		if(keybasedcontroller_active[noteNumber] == null)
+		{
+			keybasedcontroller_active[noteNumber] = new boolean[128];
+			Arrays.fill(keybasedcontroller_active[noteNumber], false);
+			keybasedcontroller_value[noteNumber] = new double[128];
+			Arrays.fill(keybasedcontroller_value[noteNumber], 0);
+		}
+		
+		if(value == -1)
+		{
+			keybasedcontroller_active[noteNumber][controller] = false;
+		}
+		else
+		{		
+			keybasedcontroller_active[noteNumber][controller] = true;
+			keybasedcontroller_value[noteNumber][controller] = value/128.0;
+		}
+
+		if(controller < 120)
+		{			
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].active)
+				voices[i].controlChange(controller,-1);										
+		}
+		else if(controller == 120)
+		{
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].active)
+				voices[i].rpnChange(1,-1);										
+		}				
+		else if(controller == 121)
+		{
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].active)
+				voices[i].rpnChange(2,-1);										
+		}				
+
+		
+	}
+	public int getControlPerNote(int noteNumber, int controller) {
+		if(keybasedcontroller_active == null) return -1;
+		if(keybasedcontroller_active[noteNumber] == null) return -1;
+		if(!keybasedcontroller_active[noteNumber][controller]) return -1;
+		return (int)(keybasedcontroller_value[noteNumber][controller]*128);	
+	}
+
+	public void controlChange(int controller, int value) {
+		{
+			if(current_mixer != null) current_mixer.controlChange(controller, value);
+
+			synchronized (control_mutex) {
+				
+			switch (controller) {
+			
+			/*
+			Map<String, int[]>co_midi_rpn_rpn_i = new HashMap<String, int[]>();
+			Map<String, double[]>co_midi_rpn_rpn = new HashMap<String, double[]>();	
+			Map<String, int[]>co_midi_nrpn_nrpn_i = new HashMap<String, int[]>();
+			Map<String, double[]>co_midi_nrpn_nrpn = new HashMap<String, double[]>();
+			*/
+			
+			case 5:
+				// This produce asin-like curve 
+				// as described in General Midi Level 2 Specification, page 6
+			    double x = -Math.asin((value / 128.0)*2-1)/Math.PI + 0.5; 
+			    x = Math.pow(100000.0, x)/100.0;       // x is now cent/msec			    
+			    // Convert x from cent/msec to key/controlbuffertime
+			    x = x / 100.0;                         // x is now keys/msec
+			    x = x * 1000.0;                        // x is now keys/sec
+			    x = x / synthesizer.getControlRate() ; // x is now keys/controlbuffertime
+			    portamento_time = x;
+			    break;			 
+			case 6:
+			case 38:
+			case 96:
+			case 97:
+				int val = 0;
+				if(nrpn_control != RPN_NULL_VALUE)
+				{
+					int[] val_i = co_midi_nrpn_nrpn_i.get(nrpn_control);
+					if(val_i != null) val = val_i[0];
+				}
+				if(rpn_control != RPN_NULL_VALUE)
+				{
+					int[] val_i = co_midi_rpn_rpn_i.get(rpn_control);
+					if(val_i != null) val = val_i[0];
+				}
+				
+				if(controller == 6)
+					val = (val & 127) + (value << 7);
+				else if(controller == 38)
+					val = (val & (127 << 7)) + value;
+				else if(controller == 96 || controller == 97)
+				{
+					int step = 1;
+					if(rpn_control == 2 || rpn_control == 3 || rpn_control == 4)
+						step = 128;
+					if(controller == 96)
+						val += step;
+					if(controller == 97)
+						val -= step;
+				}
+				
+				if(nrpn_control != RPN_NULL_VALUE)
+					nrpnChange(nrpn_control, val);
+				if(rpn_control != RPN_NULL_VALUE)
+					rpnChange(rpn_control, val);
+
+				break;
+			case 64: // Hold1 (Damper) (cc#64)
+				boolean on = value >= 64;
+				if(sustain != on)
+				{
+				sustain = on;
+				if(!on)
+				{
+					for (int i = 0; i < voices.length; i++)
+					if (voices[i].active && voices[i].sustain && voices[i].channel == channel)						
+					{
+						voices[i].sustain = false;
+						if(!voices[i].on)
+						{
+							voices[i].on = true;
+							voices[i].noteOff(0);
+						}
+					}
+				}			
+				else
+				{
+					for (int i = 0; i < voices.length; i++)
+					if (voices[i].active && voices[i].channel == channel)						
+					{
+						voices[i].redamp();						
+					}
+				}
+				}
+				break;			
+			case 65:			
+				//allNotesOff();				
+				portamento = value >= 64;
+				portamento_lastnote[0] = -1;
+				/*
+				for (int i = 0; i < portamento_lastnote.length; i++) {
+					portamento_lastnote[i] = -1;
+				}*/
+				portamento_lastnote_ix = 0;
+				break;			
+			case 66: // Sostenuto (cc#66)					
+				on = value >= 64;				
+				if(on)
+				{
+					for (int i = 0; i < voices.length; i++)
+					if (voices[i].active && voices[i].on && voices[i].channel == channel)
+						voices[i].sostenuto = true;						
+				}
+				if(!on)
+				{
+					for (int i = 0; i < voices.length; i++)
+					if (voices[i].active && voices[i].sostenuto && voices[i].channel == channel)						
+					{
+						voices[i].sostenuto = false;
+						if(!voices[i].on)
+						{
+							voices[i].on = true;
+							voices[i].noteOff(0);
+						}
+					}
+				}	
+				break;
+			case 84: 
+				portamento_control_note = value;
+				break;
+			case 98:
+				nrpn_control = (nrpn_control & (127 << 7)) + value;
+				rpn_control = RPN_NULL_VALUE;
+				break;
+			case 99:
+				nrpn_control = (nrpn_control & 127) + (value << 7);
+				rpn_control = RPN_NULL_VALUE;
+				break;
+			case 100:
+				rpn_control = (rpn_control & (127 << 7)) + value;
+				nrpn_control = RPN_NULL_VALUE;
+				break;
+			case 101:
+				rpn_control = (rpn_control & 127) + (value << 7);
+				nrpn_control = RPN_NULL_VALUE;
+				break;
+			case 120: allSoundOff(); break;
+			case 121: resetAllControllers(value == 127); break;
+			case 122: localControl(value >= 64); break;
+			case 123: allNotesOff(); break;
+			case 124: setOmni(false); break;
+			case 125: setOmni(true); break;
+			case 126: if(value == 1) setMono(true); break;
+			case 127: setMono(false); break;
+			
+			default:
+				break;
+			}
+			
+			
+			co_midi_cc_cc[controller][0] = value * (1.0/128.0);			
+			
+			
+			if (controller == 0x00) {
+				bank = (bank & 127) + (value << 7);
+				return;
+			}
+
+			if (controller == 0x20) {
+				bank = (bank & (127 << 7)) + value;
+				return;
+			}			
+
+			this.controller[controller] = value;
+
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].active)
+					voices[i].controlChange(controller, value);
+			
+			}
+		}
+	}
+
+	public int getController(int controller) {
+		synchronized (control_mutex) {
+			return this.controller[controller];
+		}
+	}
+
+	public void tuningChange(int program)
+	{
+		tuningChange(0, program);
+	}
+	
+	public void tuningChange(int bank, int program)
+	{
+		synchronized (control_mutex) {
+			tuning = synthesizer.getTuning(new Patch(bank , program));
+		}
+	}
+	
+	public void programChange(int program) {
+		programChange(bank, program);
+	}
+
+	public void programChange(int bank, int program) {
+		synchronized (control_mutex) {
+			mainmixer.msec_last_activity = mainmixer.msec_pos;
+			this.bank = bank;
+			this.program = program;
+			current_instrument = null;
+		}
+	}
+
+	public int getProgram() {
+		synchronized (control_mutex) {
+			return program;
+		}
+	}
+
+	public void setPitchBend(int bend) {
+		if(current_mixer != null) current_mixer.setPitchBend(bend);
+		synchronized (control_mutex) {
+			mainmixer.msec_last_activity = mainmixer.msec_pos;
+			co_midi_pitch[0] = bend * (1.0/16384.0);
+			pitchbend = bend;
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].active)
+					voices[i].setPitchBend(bend);
+		}
+	}
+
+	public int getPitchBend() {
+		synchronized (control_mutex) {
+			return pitchbend;
+		}
+	}
+
+	public void nrpnChange(int controller, int value) {
+		
+		/*
+		System.out.println("(" + channel + ").nrpnChange(" + 
+				Integer.toHexString(controller >> 7) + " " + Integer.toHexString(controller & 127) + 
+				", " + Integer.toHexString(value >> 7) + " " + Integer.toHexString(value & 127) + ")"); 				
+		 */
+		
+		if(synthesizer.getGeneralMidiMode() == 0)
+		{			
+			if(controller == (0x01<<7) + (0x08) ) controlChange(76, value >> 7); // Vibrato Rate
+			if(controller == (0x01<<7) + (0x09) ) controlChange(77, value >> 7); // Vibrato Depth
+			if(controller == (0x01<<7) + (0x0A) ) controlChange(78, value >> 7); // Vibrato Delay
+			if(controller == (0x01<<7) + (0x20) ) controlChange(74, value >> 7); // Brightness
+			if(controller == (0x01<<7) + (0x21) ) controlChange(71, value >> 7); // Filter Resonance
+			if(controller == (0x01<<7) + (0x63) ) controlChange(73, value >> 7); // Attack Time
+			if(controller == (0x01<<7) + (0x64) ) controlChange(75, value >> 7); // Decay Time
+			if(controller == (0x01<<7) + (0x66) ) controlChange(72, value >> 7); // Release Time
+						
+			
+			if(controller>>7 == 0x18) controlChangePerNote(controller % 128, 120, value >> 7); // Pitch coarse
+			if(controller>>7 == 0x1A) controlChangePerNote(controller % 128, 7, value >> 7); // Volume
+			if(controller>>7 == 0x1C) controlChangePerNote(controller % 128, 10, value >> 7); // Panpot
+			if(controller>>7 == 0x1D) controlChangePerNote(controller % 128, 91, value >> 7); // Reverb
+			if(controller>>7 == 0x1E) controlChangePerNote(controller % 128, 93, value >> 7); // Chorus
+		}
+		
+		int[] val_i = co_midi_nrpn_nrpn_i.get(controller);
+		double[] val_d = co_midi_nrpn_nrpn.get(controller);
+		if(val_i == null)
+		{
+			val_i = new int[1];
+			co_midi_nrpn_nrpn_i.put(controller, val_i);
+		}
+		if(val_d == null)
+		{
+			val_d = new double[1];
+			co_midi_nrpn_nrpn.put(controller, val_d);
+		}
+		val_i[0] = value;
+		val_d[0] = val_i[0] * (1.0/16384.0);
+
+		for (int i = 0; i < voices.length; i++)
+			if (voices[i].active)
+				voices[i].nrpnChange(controller, val_i[0]);		
+		
+	}
+	
+	public void rpnChange(int controller, int value) {
+		
+		/*
+		System.out.println("(" + channel + ").rpnChange(" + 
+				Integer.toHexString(controller >> 7) + " " + Integer.toHexString(controller & 127) + 
+				", " + Integer.toHexString(value >> 7) + " " + Integer.toHexString(value & 127) + ")"); 
+		 */
+		
+		if(controller == 3)
+		{
+			tuning_program = (value >> 7) & 127;
+			tuningChange(tuning_bank, tuning_program);
+		}
+		if(controller == 4)
+		{
+			tuning_bank = (value >> 7) & 127;
+		}		
+		
+		int[] val_i = co_midi_rpn_rpn_i.get(controller);
+		double[] val_d = co_midi_rpn_rpn.get(controller);
+		if(val_i == null)
+		{
+			val_i = new int[1];
+			co_midi_rpn_rpn_i.put(controller, val_i);
+		}
+		if(val_d == null)
+		{
+			val_d = new double[1];
+			co_midi_rpn_rpn.put(controller, val_d);
+		}
+		val_i[0] = value;
+		val_d[0] = val_i[0] * (1.0/16384.0);
+
+		for (int i = 0; i < voices.length; i++)
+			if (voices[i].active)
+				voices[i].rpnChange(controller, val_i[0]);		
+	}	
+	
+	public void resetAllControllers() {
+		resetAllControllers(false);
+	}
+
+	public void resetAllControllers(boolean allControls) {
+		synchronized (control_mutex) {
+			mainmixer.msec_last_activity = mainmixer.msec_pos;
+
+
+			for (int i = 0; i < 128; i++) {
+				setPolyPressure(i, 0);
+			}
+			setChannelPressure(0);
+			setPitchBend(8192);
+			for (int i = 0; i < 128; i++) {
+				if(!dontResetControls[i])
+				controlChange(i, 0);
+			}
+		
+			controlChange(71, 64); // Filter Resonance
+			controlChange(72, 64); // Release Time
+			controlChange(73, 64); // Attack Time
+			controlChange(74, 64); // Brightness
+			controlChange(75, 64); // Decay Time
+			controlChange(76, 64); // Vibrato Rate
+			controlChange(77, 64); // Vibrato Depth
+			controlChange(78, 64); // Vibrato Delay
+			
+			controlChange(8, 64); // Balance
+			controlChange(11, 127); // Expression
+			controlChange(98, 127); // NRPN Null					
+			controlChange(99, 127); // NRPN Null					
+			controlChange(100, 127); // RPN = Null					
+			controlChange(101, 127); // RPN = Null		
+			
+			// see DLS 2.1 (Power-on Default Values) 
+			if(allControls)
+			{
+				
+				keybasedcontroller_active = null;
+				keybasedcontroller_value = null;
+				
+				controlChange(7, 100); // Volume
+				controlChange(10, 64); // Pan
+				controlChange(91, 40); // Reverb
+				
+				for(int controller : co_midi_rpn_rpn.keySet())
+				{
+					// don't reset tuning settings
+					if(controller != 3 && controller != 4)
+						rpnChange(controller, 0);
+				}
+				for(int controller : co_midi_nrpn_nrpn.keySet())
+					nrpnChange(controller, 0);				
+				rpnChange(0, 2 << 7);   // Bitch Bend sensitivity
+				rpnChange(1, 64 << 7);  // Channel fine tunning
+				rpnChange(2, 64 << 7);  // Channel Coarse Tuning
+				rpnChange(5, 64);       // Modulation Depth, +/- 50 cent
+				
+				tuning_bank = 0;
+				tuning_program = 0;
+				tuning = new SoftTuning();
+				
+			}
+			
+		}
+	}
+
+	public void allNotesOff() {
+		if(current_mixer != null) current_mixer.allNotesOff();
+		synchronized (control_mutex) {
+		for (int i = 0; i < voices.length; i++)
+			if (voices[i].on && voices[i].channel == channel && voices[i].releaseTriggered == false)
+				voices[i].noteOff(0);		
+		}
+	}
+
+	public void allSoundOff() {
+		if(current_mixer != null) current_mixer.allSoundOff();		
+		synchronized (control_mutex) {		
+		for (int i = 0; i < voices.length; i++)
+			if (voices[i].on && voices[i].channel == channel)
+				voices[i].soundOff();
+		}
+	}
+
+	public boolean localControl(boolean on) {
+		return false;
+	}
+
+	public void setMono(boolean on) {
+		if(current_mixer != null) current_mixer.setMono(on);				
+		synchronized (control_mutex) {
+			allNotesOff();
+			mono = on;
+		}
+	}
+
+	public boolean getMono() {
+		synchronized (control_mutex) {
+			return mono;
+		}
+	}
+
+	public void setOmni(boolean on) {
+		if(current_mixer != null) current_mixer.setOmni(on);				
+		allNotesOff();
+		// Omni is not supported by GM2
+	}
+
+	public boolean getOmni() {
+		return false;
+	}
+
+	public void setMute(boolean mute) {
+		if(current_mixer != null) current_mixer.setMute(mute);				
+		synchronized (control_mutex) {
+			this.mute = mute;
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].active && voices[i].channel == channel)
+					voices[i].setMute(mute);
+			
+		}
+	}
+
+	public boolean getMute() {
+		synchronized (control_mutex) {
+			return mute;
+		}
+	}
+
+	
+	public void setSolo(boolean soloState) {
+		if(current_mixer != null) current_mixer.setSolo(soloState);				
+
+		synchronized (control_mutex) {
+					
+		this.solo = soloState;
+		
+		boolean soloinuse = false;
+		for(SoftChannel c : synthesizer.channels)
+			if(c.solo)
+			{
+				soloinuse = true;
+				break;
+			}
+		
+		if(!soloinuse)
+		{
+			for(SoftChannel c : synthesizer.channels)
+				c.setSoloMute(false);
+			return;
+		}
+			
+		for(SoftChannel c : synthesizer.channels)
+			c.setSoloMute(!c.solo);
+		
+		}
+		
+	}
+	
+	private void setSoloMute(boolean mute) {	
+		synchronized (control_mutex) {			
+			if(solomute == mute) return;
+			this.solomute = mute;
+			for (int i = 0; i < voices.length; i++)
+				if (voices[i].active && voices[i].channel == channel)
+					voices[i].setSoloMute(solomute);
+			
+		}
+	}	
+
+	public boolean getSolo() {
+		synchronized (control_mutex) {		
+			return solo;
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannelProxy.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import javax.sound.midi.MidiChannel;
+
+/**
+ * 
+ * A MidiChannel proxy object used for external access to synthesizer internal
+ * channel objects.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftChannelProxy implements MidiChannel {
+
+	private MidiChannel channel = null;
+
+	public MidiChannel getChannel() {
+		return channel;
+	}
+
+	public void setChannel(MidiChannel channel) {
+		this.channel = channel;
+	}
+
+	public void allNotesOff() {
+		if (channel == null)
+			return;
+		channel.allNotesOff();
+	}
+
+	public void allSoundOff() {
+		if (channel == null)
+			return;
+		channel.allSoundOff();
+	}
+
+	public void controlChange(int controller, int value) {
+		if (channel == null)
+			return;
+		channel.controlChange(controller, value);
+	}
+
+	public int getChannelPressure() {
+		if (channel == null)
+			return 0;
+		return channel.getChannelPressure();
+	}
+
+	public int getController(int controller) {
+		if (channel == null)
+			return 0;
+		return channel.getController(controller);
+	}
+
+	public boolean getMono() {
+		if (channel == null)
+			return false;
+		return channel.getMono();
+	}
+
+	public boolean getMute() {
+		if (channel == null)
+			return false;
+		return channel.getMute();
+	}
+
+	public boolean getOmni() {
+		if (channel == null)
+			return false;
+		return channel.getOmni();
+	}
+
+	public int getPitchBend() {
+		if (channel == null)
+			return 8192;
+		return channel.getPitchBend();
+	}
+
+	public int getPolyPressure(int noteNumber) {
+		if (channel == null)
+			return 0;
+		return channel.getPolyPressure(noteNumber);
+	}
+
+	public int getProgram() {
+		if (channel == null)
+			return 0;
+		return channel.getProgram();
+	}
+
+	public boolean getSolo() {
+		if (channel == null)
+			return false;
+		return channel.getSolo();
+	}
+
+	public boolean localControl(boolean on) {
+		if (channel == null)
+			return false;
+		return channel.localControl(on);
+	}
+
+	public void noteOff(int noteNumber) {
+		if (channel == null)
+			return;
+		channel.noteOff(noteNumber);
+	}
+
+	public void noteOff(int noteNumber, int velocity) {
+		if (channel == null)
+			return;
+		channel.noteOff(noteNumber, velocity);
+	}
+
+	public void noteOn(int noteNumber, int velocity) {
+		if (channel == null)
+			return;
+		channel.noteOn(noteNumber, velocity);
+	}
+
+	public void programChange(int program) {
+		if (channel == null)
+			return;
+		channel.programChange(program);
+	}
+
+	public void programChange(int bank, int program) {
+		if (channel == null)
+			return;
+		channel.programChange(bank, program);
+	}
+
+	public void resetAllControllers() {
+		if (channel == null)
+			return;
+		channel.resetAllControllers();
+	}
+
+	public void setChannelPressure(int pressure) {
+		if (channel == null)
+			return;
+		channel.setChannelPressure(pressure);
+	}
+
+	public void setMono(boolean on) {
+		if (channel == null)
+			return;
+		channel.setMono(on);
+	}
+
+	public void setMute(boolean mute) {
+		if (channel == null)
+			return;
+		channel.setMute(mute);
+	}
+
+	public void setOmni(boolean on) {
+		if (channel == null)
+			return;
+		channel.setOmni(on);
+	}
+
+	public void setPitchBend(int bend) {
+		if (channel == null)
+			return;
+		channel.setPitchBend(bend);
+	}
+
+	public void setPolyPressure(int noteNumber, int pressure) {
+		if (channel == null)
+			return;
+		channel.setPolyPressure(noteNumber, pressure);
+	}
+
+	public void setSolo(boolean soloState) {
+		if (channel == null)
+			return;
+		channel.setSolo(soloState);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChorus.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.util.Arrays;
+
+/**
+ * A chorus effect made using LFO and variable delay. One for each channel
+ * (left,right), with different starting phase for stereo effect.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftChorus implements SoftAudioProcessor {
+
+	private class VariableDelay {
+		private float[] delaybuffer;
+
+		private int rovepos = 0;
+
+		private volatile float gain = 1;
+
+		private volatile float rgain = 0;
+
+		private volatile float delay = 0;
+
+		private float lastdelay = 0;
+
+		private volatile float feedback = 0;
+
+		public VariableDelay(int maxbuffersize) {
+			delaybuffer = new float[maxbuffersize];
+		}
+
+		public void setDelay(float delay) {
+			this.delay = delay;
+		}
+
+		public void setFeedBack(float feedback) {
+			this.feedback = feedback;
+		}
+
+		public void setGain(float gain) {
+			this.gain = gain;
+		}
+
+		public void setReverbSendGain(float rgain) {
+			this.rgain = rgain;
+		}
+
+		public void processMix(float[] in, float[] out, float[] rout) {
+			float gain = this.gain;
+			float delay = this.delay;
+			float feedback = this.feedback;
+
+			float[] delaybuffer = this.delaybuffer;
+			int len = in.length;
+			float delaydelta = (delay - lastdelay) / len;
+			int rnlen = delaybuffer.length;
+			int rovepos = this.rovepos;
+
+			if (rout == null)
+				for (int i = 0; i < len; i++) {
+					float r = rovepos - (lastdelay + 2) + rnlen;
+					int ri = (int) r;
+					float s = r - ri;
+					float a = delaybuffer[ri % rnlen];
+					float b = delaybuffer[(ri + 1) % rnlen];
+					float o = a * (1 - s) + b * (s);
+					out[i] += o * gain;
+					delaybuffer[rovepos] = in[i] + o * feedback;
+					rovepos = (rovepos + 1) % rnlen;
+					lastdelay += delaydelta;
+				}
+			else
+				for (int i = 0; i < len; i++) {
+					float r = rovepos - (lastdelay + 2) + rnlen;
+					int ri = (int) r;
+					float s = r - ri;
+					float a = delaybuffer[ri % rnlen];
+					float b = delaybuffer[(ri + 1) % rnlen];
+					float o = a * (1 - s) + b * (s);
+					out[i] += o * gain;
+					rout[i] += o * rgain;
+					delaybuffer[rovepos] = in[i] + o * feedback;
+					rovepos = (rovepos + 1) % rnlen;
+					lastdelay += delaydelta;
+				}
+			this.rovepos = rovepos;
+			lastdelay = delay;
+		}
+
+		public void processReplace(float[] in, float[] out, float[] rout) {
+			Arrays.fill(out, 0);
+			Arrays.fill(rout, 0);
+			processMix(in, out, rout);
+		}
+
+	}
+
+	private class LFODelay {
+
+		private volatile double c_cos_delta;
+
+		private volatile double c_sin_delta;
+
+		private double c_cos = 1;
+
+		private double c_sin = 0;
+
+		private double depth = 0;
+
+		private VariableDelay vdelay;
+
+		private double samplerate;
+
+		private double controlrate;
+
+		public LFODelay(double samplerate, double controlrate) {
+			this.samplerate = samplerate;
+			this.controlrate = controlrate;
+			// vdelay = new VariableDelay((int)(samplerate*4));
+			vdelay = new VariableDelay((int) ((this.depth + 10) * 2));
+
+		}
+
+		public void setDepth(double depth) {
+			this.depth = depth * samplerate;
+			vdelay = new VariableDelay((int) ((this.depth + 10) * 2));
+		}
+
+		public void setRate(double rate) {
+			double g = (Math.PI * 2) * (rate / controlrate);
+			c_cos_delta = Math.cos(g);
+			c_sin_delta = Math.sin(g);
+		}
+
+		public void setPhase(double phase) {
+			c_cos = Math.cos(phase);
+			c_sin = Math.sin(phase);
+		}
+
+		public void setFeedBack(float feedback) {
+			vdelay.setFeedBack(feedback);
+		}
+
+		public void setGain(float gain) {
+			vdelay.setGain(gain);
+		}
+
+		public void setReverbSendGain(float rgain) {
+			vdelay.setReverbSendGain(rgain);
+		}
+
+		public void processMix(float[] in, float[] out, float[] rout) {
+			c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta;
+			c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta;
+			vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2)));
+			vdelay.processMix(in, out, rout);
+		}
+
+		public void processReplace(float[] in, float[] out, float[] rout) {
+			c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta;
+			c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta;
+			vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2)));
+			vdelay.processReplace(in, out, rout);
+
+		}
+	}
+
+	private boolean mix = true;
+
+	private SoftAudioBuffer inputA;
+
+	private SoftAudioBuffer left;
+
+	private SoftAudioBuffer right;
+
+	private SoftAudioBuffer reverb;
+
+	private LFODelay vdelay1L;
+
+	private LFODelay vdelay1R;
+
+	private float rgain = 0;
+
+	private SoftSynthesizer synth;
+
+	private boolean dirty = true;
+
+	private double dirty_vdelay1L_rate;
+
+	private double dirty_vdelay1R_rate;
+
+	private double dirty_vdelay1L_depth;
+
+	private double dirty_vdelay1R_depth;
+
+	private float dirty_vdelay1L_feedback;
+
+	private float dirty_vdelay1R_feedback;
+
+	private float dirty_vdelay1L_reverbsendgain;
+
+	private float dirty_vdelay1R_reverbsendgain;
+
+	public void init(SoftSynthesizer synth) {
+		this.synth = synth;
+		double samplerate = synth.getFormat().getSampleRate();
+		double controlrate = synth.getControlRate();
+		vdelay1L = new LFODelay(samplerate, controlrate);
+		vdelay1R = new LFODelay(samplerate, controlrate);
+		vdelay1L.setGain(1.0f); // %
+		vdelay1R.setGain(1.0f); // %
+		vdelay1L.setPhase(0.5 * Math.PI);
+		vdelay1R.setPhase(0);
+
+		globalParameterControlChange(new int[] { 0x01 * 128 + 0x02 }, 0, 2);
+	}
+
+	public void globalParameterControlChange(int[] slothpath, long param,
+			long value) {
+		if (slothpath.length == 1)
+			if (slothpath[0] == 0x01 * 128 + 0x02) {
+
+				if (param == 0) // Chorus Type
+				{
+					switch ((int) value) {
+					case 0: // Chorus 1 0 (0%) 3 (0.4Hz) 5 (1.9ms) 0 (0%)
+						globalParameterControlChange(slothpath, 3, 0);
+						globalParameterControlChange(slothpath, 1, 3);
+						globalParameterControlChange(slothpath, 2, 5);
+						globalParameterControlChange(slothpath, 4, 0);
+						break;
+					case 1: // Chorus 2 5 (4%) 9 (1.1Hz) 19 (6.3ms) 0 (0%)
+						globalParameterControlChange(slothpath, 3, 5);
+						globalParameterControlChange(slothpath, 1, 9);
+						globalParameterControlChange(slothpath, 2, 19);
+						globalParameterControlChange(slothpath, 4, 0);
+						break;
+					case 2: // Chorus 3 8 (6%) 3 (0.4Hz) 19 (6.3ms) 0 (0%)
+						globalParameterControlChange(slothpath, 3, 8);
+						globalParameterControlChange(slothpath, 1, 3);
+						globalParameterControlChange(slothpath, 2, 19);
+						globalParameterControlChange(slothpath, 4, 0);
+						break;
+					case 3: // Chorus 4 16 (12%) 9 (1.1Hz) 16 (5.3ms) 0 (0%)
+						globalParameterControlChange(slothpath, 3, 16);
+						globalParameterControlChange(slothpath, 1, 9);
+						globalParameterControlChange(slothpath, 2, 16);
+						globalParameterControlChange(slothpath, 4, 0);
+						break;
+					case 4: // FB Chorus 64 (49%) 2 (0.2Hz) 24 (7.8ms) 0 (0%)
+						globalParameterControlChange(slothpath, 3, 64);
+						globalParameterControlChange(slothpath, 1, 2);
+						globalParameterControlChange(slothpath, 2, 24);
+						globalParameterControlChange(slothpath, 4, 0);
+						break;
+					case 5: // Flanger 112 (86%) 1 (0.1Hz) 5 (1.9ms) 0 (0%)
+						globalParameterControlChange(slothpath, 3, 112);
+						globalParameterControlChange(slothpath, 1, 1);
+						globalParameterControlChange(slothpath, 2, 5);
+						globalParameterControlChange(slothpath, 4, 0);
+						break;
+					default:
+						break;
+					}
+				} else if (param == 1) // Mod Rate
+				{
+					dirty_vdelay1L_rate = (value * 0.122);
+					dirty_vdelay1R_rate = (value * 0.122);
+					dirty = true;
+				} else if (param == 2) // Mod Depth
+				{
+					dirty_vdelay1L_depth = ((value + 1) / 3200.0);
+					dirty_vdelay1R_depth = ((value + 1) / 3200.0);
+					dirty = true;
+				} else if (param == 3) // Feedback
+				{
+					dirty_vdelay1L_feedback = (value * 0.00763f);
+					dirty_vdelay1R_feedback = (value * 0.00763f);
+					dirty = true;
+				}
+				if (param == 4) // Send to Reverb
+				{
+					rgain = value * 0.00787f;
+					dirty_vdelay1L_reverbsendgain = (value * 0.00787f);
+					dirty_vdelay1R_reverbsendgain = (value * 0.00787f);
+					dirty = true;
+				}
+
+			}
+	}
+
+	public void processControlLogic() {
+		if (dirty) {
+			dirty = false;
+			vdelay1L.setRate(dirty_vdelay1L_rate);
+			vdelay1R.setRate(dirty_vdelay1R_rate);
+			vdelay1L.setDepth(dirty_vdelay1L_depth);
+			vdelay1R.setDepth(dirty_vdelay1R_depth);
+			vdelay1L.setFeedBack(dirty_vdelay1L_feedback);
+			vdelay1R.setFeedBack(dirty_vdelay1R_feedback);
+			vdelay1L.setReverbSendGain(dirty_vdelay1L_reverbsendgain);
+			vdelay1R.setReverbSendGain(dirty_vdelay1R_reverbsendgain);
+		}
+	}
+
+	double silentcounter = 1000;
+
+	public void processAudio() {
+
+		if (inputA.isSilent()) {
+			silentcounter += 1 / synth.getControlRate();
+
+			if (silentcounter > 1) {
+				if (!mix) {
+					left.clear();
+					right.clear();
+				}
+				return;
+			}
+		} else
+			silentcounter = 0;
+
+		float[] inputA = this.inputA.array();
+		float[] left = this.left.array();
+		float[] right = this.right == null ? null : this.right.array();
+		float[] reverb = rgain != 0 ? this.reverb.array() : null;
+
+		if (mix) {
+			vdelay1L.processMix(inputA, left, reverb);
+			if (right != null)
+				vdelay1R.processMix(inputA, right, reverb);
+		} else {
+			vdelay1L.processReplace(inputA, left, reverb);
+			if (right != null)
+				vdelay1R.processReplace(inputA, right, reverb);
+		}
+	}
+
+	public void setInput(int pin, SoftAudioBuffer input) {
+		if (pin == 0)
+			inputA = input;
+	}
+
+	public void setMixMode(boolean mix) {
+		this.mix = mix;
+	}
+
+	public void setOutput(int pin, SoftAudioBuffer output) {
+		if (pin == 0)
+			left = output;
+		if (pin == 1)
+			right = output;
+		if (pin == 2)
+			reverb = output;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftControl.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * <code>SoftControl</code> are the basic controls
+ * used for control-rate processing.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public interface SoftControl {
+
+	public double[] get(int instance, String name);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * A resampler that uses third-order (cubic) interpolation.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftCubicResampler extends SoftAbstractResampler {
+
+	public int getPadding() {
+		return 3;
+	}
+
+	public void interpolate(float[] in, float[] in_offset, float in_end,
+			float[] startpitch, float pitchstep, float[] out, int[] out_offset,
+			int out_end) {
+		float pitch = startpitch[0];
+		float ix = in_offset[0];
+		int ox = out_offset[0];
+		float ix_end = in_end;
+		int ox_end = out_end;
+		if (pitchstep == 0) {
+			while (ix < ix_end && ox < ox_end) {
+				int iix = (int) ix;
+				float fix = ix - iix;
+				float y0 = in[iix - 1];
+				float y1 = in[iix];
+				float y2 = in[iix + 1];
+				float y3 = in[iix + 2];
+				float a0 = y3 - y2 + y1 - y0;
+				float a1 = y0 - y1 - a0;
+				float a2 = y2 - y0;
+				float a3 = y1;				
+				//float fix2 = fix * fix;
+				//out[ox++] = (a0 * fix + a1) * fix2 + (a2 * fix + a3);
+				out[ox++] = ((a0 * fix + a1) * fix + a2) * fix + a3;
+				ix += pitch;
+			}
+		} else {
+			while (ix < ix_end && ox < ox_end) {
+				int iix = (int) ix;
+				float fix = ix - iix;
+				float y0 = in[iix - 1];
+				float y1 = in[iix];
+				float y2 = in[iix + 1];
+				float y3 = in[iix + 2];
+				float a0 = y3 - y2 + y1 - y0;
+				float a1 = y0 - y1 - a0;
+				float a2 = y2 - y0;
+				float a3 = y1;
+				//float fix2 = fix * fix;
+				//out[ox++] = (a0 * fix + a1) * fix2 + (a2 * fix + a3);
+				out[ox++] = ((a0 * fix + a1) * fix + a2) * fix + a3;
+				ix += pitch;
+				pitch += pitchstep;
+			}
+		}
+		in_offset[0] = ix;
+		out_offset[0] = ox;
+		startpitch[0] = pitch;
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * AHDSR control signal envelope generator.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftEnvelopeGenerator implements SoftProcess {
+
+	public final static int EG_OFF = 0;
+	
+	public final static int EG_DELAY = 1;
+
+	public final static int EG_ATTACK = 2;
+
+	public final static int EG_HOLD = 3;
+
+	public final static int EG_DECAY = 4;
+
+	public final static int EG_SUSTAIN = 5;
+
+	public final static int EG_RELEASE = 6;
+
+	public final static int EG_SHUTDOWN = 7;
+
+	public final static int EG_END = 8;
+
+	int max_count = 10;
+
+	int used_count = 0;
+
+	private int[] stage = new int[max_count];
+
+	private int[] stage_ix = new int[max_count];
+
+	private double[] stage_v = new double[max_count];
+
+	private int[] stage_count = new int[max_count];
+
+	private double[][] on = new double[max_count][1];
+
+	private double[][] active = new double[max_count][1];
+
+	private double[][] out = new double[max_count][1];
+
+	private double[][] delay = new double[max_count][1];
+
+	private double[][] attack = new double[max_count][1];
+
+	private double[][] hold = new double[max_count][1];
+
+	private double[][] decay = new double[max_count][1];
+
+	private double[][] sustain = new double[max_count][1];
+
+	private double[][] release = new double[max_count][1];
+
+	private double[][] shutdown = new double[max_count][1];
+
+	private double[][] release2 = new double[max_count][1];
+
+	private double[][] attack2 = new double[max_count][1];
+
+	private double[][] decay2 = new double[max_count][1];
+
+	private double control_time = 0;
+
+	public void reset() {
+		for (int i = 0; i < used_count; i++) {
+			stage[i] = 0;
+			on[i][0] = 0;
+			out[i][0] = 0;
+			delay[i][0] = 0;
+			attack[i][0] = 0;
+			hold[i][0] = 0;
+			decay[i][0] = 0;
+			sustain[i][0] = 0;
+			release[i][0] = 0;
+			shutdown[i][0] = 0;
+			attack2[i][0] = 0;
+			decay2[i][0] = 0;
+			release2[i][0] = 0;
+
+		}
+		used_count = 0;
+	}
+
+	public void init(SoftSynthesizer synth) {
+		control_time = 1.0 / synth.getControlRate();
+		processControlLogic();
+	}
+
+	public double[] get(int instance, String name) {
+		if (instance >= used_count)
+			used_count = instance + 1;
+		if (name == null)
+			return out[instance];
+		if (name.equals("on"))
+			return on[instance];
+		if (name.equals("active"))
+			return active[instance];
+		if (name.equals("delay"))
+			return delay[instance];
+		if (name.equals("attack"))
+			return attack[instance];
+		if (name.equals("hold"))
+			return hold[instance];
+		if (name.equals("decay"))
+			return decay[instance];
+		if (name.equals("sustain"))
+			return sustain[instance];
+		if (name.equals("release"))
+			return release[instance];
+		if (name.equals("shutdown"))
+			return shutdown[instance];
+		if (name.equals("attack2"))
+			return attack2[instance];
+		if (name.equals("decay2"))
+			return decay2[instance];
+		if (name.equals("release2"))
+			return release2[instance];
+
+		return null;
+	}
+
+	public void processControlLogic() {
+		for (int i = 0; i < used_count; i++) {
+
+			if (stage[i] == EG_END) {
+				continue;
+			}
+
+			if ((stage[i] > EG_OFF) && (stage[i] < EG_RELEASE))
+				if (on[i][0] < 0.5) {
+
+					if (on[i][0] < -0.5) {
+						stage_count[i] = (int) (Math.pow(2,
+								this.shutdown[i][0] / 1200.0) / control_time);
+						if (stage_count[i] < 0)
+							stage_count[i] = 0;
+						stage_v[i] = out[i][0];
+						stage_ix[i] = 0;
+						stage[i] = EG_SHUTDOWN;
+					} else {
+
+						if ((release2[i][0] < 0.000001) && release[i][0] < 0
+								&& Double.isInfinite(release[i][0])) {
+							out[i][0] = 0;
+							active[i][0] = 0;
+							stage[i] = EG_END;
+							continue;
+						}
+
+						stage_count[i] = (int) (Math.pow(2,
+								this.release[i][0] / 1200.0) / control_time);
+						stage_count[i] += (int) (this.release2[i][0] / (control_time * 1000));
+						if (stage_count[i] < 0)
+							stage_count[i] = 0;
+						// stage_v[i] = out[i][0];
+						stage_ix[i] = 0; // þetta á ekki að vera svona !!!!
+
+						double m = 1 - out[i][0];
+						stage_ix[i] = (int) (stage_count[i] * m);
+
+						stage[i] = EG_RELEASE;
+
+					}
+				}
+
+			switch (stage[i]) {
+			case EG_OFF:
+				active[i][0] = 1;
+				if (on[i][0] < 0.5) break;
+				stage[i] = EG_DELAY;
+				stage_ix[i] = (int) (Math.pow(2, this.delay[i][0] / 1200.0) / control_time);
+				if(stage_ix[i] < 0) stage_ix[i] = 0;
+			case EG_DELAY:
+				if (stage_ix[i] == 0) {
+					double attack = this.attack[i][0];
+					double attack2 = this.attack2[i][0];
+
+					if (attack2 < 0.000001
+							&& (attack < 0 && Double.isInfinite(attack))) {
+						out[i][0] = 1;
+						stage[i] = EG_HOLD;
+						stage_count[i] = (int) (Math.pow(2,
+								this.hold[i][0] / 1200.0) / control_time);
+						stage_ix[i] = 0;
+					} else {
+						stage[i] = EG_ATTACK;
+						stage_count[i] = (int) (Math.pow(2, attack / 1200.0) / control_time);
+						stage_count[i] += (int) (attack2 / (control_time * 1000));
+						if (stage_count[i] < 0)
+							stage_count[i] = 0;
+						stage_ix[i] = 0;
+					}
+				}
+				else
+					stage_ix[i]--;
+				break;
+			case EG_ATTACK:
+				stage_ix[i]++;
+				if (stage_ix[i] >= stage_count[i]) {
+					out[i][0] = 1;
+					stage[i] = EG_HOLD;
+				} else {
+					// CONVEX attack
+					double a = ((double) stage_ix[i])
+							/ ((double) stage_count[i]);
+					a = 1 + ((40.0 / 96.0) / Math.log(10)) * Math.log(a);					
+					if (a < 0)
+						a = 0;
+					else if (a > 1)
+						a = 1;
+					out[i][0] = a;
+
+				}
+				break;
+			case EG_HOLD:
+				stage_ix[i]++;
+				if (stage_ix[i] >= stage_count[i]) {
+					stage[i] = EG_DECAY;
+					stage_count[i] = (int) (Math.pow(2,
+							this.decay[i][0] / 1200.0) / control_time);
+					stage_count[i] += (int) (this.decay2[i][0] / (control_time * 1000));
+					if (stage_count[i] < 0)
+						stage_count[i] = 0;
+					stage_ix[i] = 0;
+
+				}
+				break;
+			case EG_DECAY:
+
+				stage_ix[i]++;
+				double sustain = this.sustain[i][0] * (1.0 / 1000.0);
+				if (stage_ix[i] >= stage_count[i]) {
+					out[i][0] = sustain;
+					stage[i] = EG_SUSTAIN;
+					if (sustain < 0.001) {
+						out[i][0] = 0;
+						active[i][0] = 0;
+						stage[i] = EG_END;
+					}
+				} else {
+					double m = ((double) stage_ix[i])
+							/ ((double) stage_count[i]);
+					out[i][0] = (1 - m) + sustain * m;
+				}
+
+				break;
+			case EG_SUSTAIN:
+				break;
+			case EG_RELEASE:
+				stage_ix[i]++;
+				if (stage_ix[i] >= stage_count[i]) {
+					out[i][0] = 0;
+					active[i][0] = 0;
+					stage[i] = EG_END;
+				} else {
+					double m = ((double) stage_ix[i])
+							/ ((double) stage_count[i]);
+					out[i][0] = (1 - m); // *stage_v[i];
+
+					if (on[i][0] < -0.5) {
+						stage_count[i] = (int) (Math.pow(2,
+								this.shutdown[i][0] / 1200.0) / control_time);
+						if (stage_count[i] < 0)
+							stage_count[i] = 0;
+						stage_v[i] = out[i][0];
+						stage_ix[i] = 0;
+						stage[i] = EG_SHUTDOWN;
+					}
+
+					// re-damping
+					if (on[i][0] > 0.5) {
+						sustain = this.sustain[i][0] * (1.0 / 1000.0);
+						if (out[i][0] > sustain) {
+
+							stage[i] = EG_DECAY;
+							stage_count[i] = (int) (Math.pow(2,
+									this.decay[i][0] / 1200.0) / control_time);
+							stage_count[i] += (int) (this.decay2[i][0] / (control_time * 1000));
+							if (stage_count[i] < 0)
+								stage_count[i] = 0;
+							m = (out[i][0] - 1) / (sustain - 1);
+							stage_ix[i] = (int) (stage_count[i] * m);
+						}
+					}
+
+				}
+				break;
+			case EG_SHUTDOWN:
+				stage_ix[i]++;
+				if (stage_ix[i] >= stage_count[i]) {
+					out[i][0] = 0;
+					active[i][0] = 0;
+					stage[i] = EG_END;
+				} else {
+					double m = ((double) stage_ix[i])
+							/ ((double) stage_count[i]);
+					out[i][0] = (1 - m) * stage_v[i];
+				}
+				break;
+			default:
+				break;
+			}
+		}
+
+	}
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * Infinite impulse response (IIR) filter class.
+ * 
+ * The filters where implemented and adapted using algorithms from musicdsp.org
+ * archive: 1-RC and C filter, Simple 2-pole LP LP and HP filter, biquad,
+ * tweaked butterworth RBJ Audio-EQ-Cookbook, EQ filter kookbook
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftFilter {
+
+	public static int FILTERTYPE_LP6 = 0x00;
+
+	public static int FILTERTYPE_LP12 = 0x01;
+
+	public static int FILTERTYPE_HP12 = 0x11;
+
+	public static int FILTERTYPE_BP12 = 0x21;
+
+	public static int FILTERTYPE_NP12 = 0x31;
+
+	public static int FILTERTYPE_LP24 = 0x03;
+
+	public static int FILTERTYPE_HP24 = 0x13;
+
+	//
+	// 0x0 = 1st-order, 6 dB/oct
+	// 0x1 = 2nd-order, 12 dB/oct
+	// 0x2 = 3rd-order, 18 dB/oct
+	// 0x3 = 4th-order, 24 db/oct
+	//
+	// 0x00 = LP, Low Pass Filter
+	// 0x10 = HP, High Pass Filter
+	// 0x20 = BP, Band Pass Filter
+	// 0x30 = NP, Notch or Band Elimination Filter
+	//
+
+	private int filtertype = FILTERTYPE_LP6;
+
+	private float samplerate;
+
+	private float x1;
+
+	private float x2;
+
+	private float y1;
+
+	private float y2;
+
+	private float xx1;
+
+	private float xx2;
+
+	private float yy1;
+
+	private float yy2;
+
+	private float a0;
+
+	private float a1;
+
+	private float a2;
+
+	private float b1;
+
+	private float b2;
+
+	private float q;
+
+	private float gain = 1;
+
+	private float wet = 0;
+
+	private float last_wet = 0;
+
+	private float last_a0;
+
+	private float last_a1;
+
+	private float last_a2;
+
+	private float last_b1;
+
+	private float last_b2;
+
+	private float last_q;
+
+	private float last_gain;
+
+	private boolean last_set = false;
+
+	private double cutoff = 44100;
+
+	private double resonancedB = 0;
+
+	private boolean dirty = true;
+
+	public SoftFilter(float samplerate) {
+		this.samplerate = samplerate;
+		dirty = true;
+	}
+
+	public void setFrequency(double cent) {
+		if (cutoff == cent)
+			return;
+		cutoff = cent;
+		dirty = true;
+	}
+
+	public void setResonance(double db) {
+		if (resonancedB == db)
+			return;
+		resonancedB = db;
+		dirty = true;
+	}
+
+	public void reset() {
+		dirty = true;
+		last_set = false;
+		x1 = 0;
+		x2 = 0;
+		y1 = 0;
+		y2 = 0;
+		xx1 = 0;
+		xx2 = 0;
+		yy1 = 0;
+		yy2 = 0;
+		wet = 0.0f;
+		gain = 1.0f;
+		a0 = 0;
+		a1 = 0;
+		a2 = 0;
+		b1 = 0;
+		b2 = 0;		
+	}
+
+	public void setFilterType(int filtertype) {
+		this.filtertype = filtertype;
+	}
+
+	public void processAudio(SoftAudioBuffer sbuffer) {
+		if (filtertype == FILTERTYPE_LP6)
+			filter1(sbuffer);
+		if (filtertype == FILTERTYPE_LP12)
+			filter2(sbuffer);
+		if (filtertype == FILTERTYPE_HP12)
+			filter2(sbuffer);
+		if (filtertype == FILTERTYPE_BP12)
+			filter2(sbuffer);
+		if (filtertype == FILTERTYPE_NP12)
+			filter2(sbuffer);
+		if (filtertype == FILTERTYPE_LP24)
+			filter4(sbuffer);
+		if (filtertype == FILTERTYPE_HP24)
+			filter4(sbuffer);
+	}
+
+	public void filter4(SoftAudioBuffer sbuffer) {
+
+		float[] buffer = sbuffer.array();
+
+		if (dirty) {
+			filter2calc();
+			dirty = false;
+		}
+		if (!last_set) {
+			last_a0 = a0;
+			last_a1 = a1;
+			last_a2 = a2;
+			last_b1 = b1;
+			last_b2 = b2;
+			last_gain = gain;
+			last_wet = wet;
+			last_set = true;
+		}
+
+		if (wet > 0 || last_wet > 0) {
+
+			int len = buffer.length;
+			float a0 = this.last_a0;
+			float a1 = this.last_a1;
+			float a2 = this.last_a2;
+			float b1 = this.last_b1;
+			float b2 = this.last_b2;
+			float gain = this.last_gain;
+			float wet = this.last_wet;
+			float a0_delta = (this.a0 - this.last_a0) / len;
+			float a1_delta = (this.a1 - this.last_a1) / len;
+			float a2_delta = (this.a2 - this.last_a2) / len;
+			float b1_delta = (this.b1 - this.last_b1) / len;
+			float b2_delta = (this.b2 - this.last_b2) / len;
+			float gain_delta = (this.gain - this.last_gain) / len;
+			float wet_delta = (this.wet - this.last_wet) / len;
+			float x1 = this.x1;
+			float x2 = this.x2;
+			float y1 = this.y1;
+			float y2 = this.y2;
+			float xx1 = this.xx1;
+			float xx2 = this.xx2;
+			float yy1 = this.yy1;
+			float yy2 = this.yy2;
+
+			if (wet_delta != 0) {
+				for (int i = 0; i < len; i++) {
+					a0 += a0_delta;
+					a1 += a1_delta;
+					a2 += a2_delta;
+					b1 += b1_delta;
+					b2 += b2_delta;
+					gain += gain_delta;
+					wet += wet_delta;
+					float x = buffer[i];
+					float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2);
+					float xx = (y * gain) * wet + (x) * (1 - wet);
+					x2 = x1;
+					x1 = x;
+					y2 = y1;
+					y1 = y;
+					float yy = (a0 * xx + a1 * xx1 + a2 * xx2 - b1 * yy1 - b2
+							* yy2);
+					buffer[i] = (yy * gain) * wet + (xx) * (1 - wet);
+					xx2 = xx1;
+					xx1 = xx;
+					yy2 = yy1;
+					yy1 = yy;
+				}
+			} else if (a0_delta == 0 && a1_delta == 0 && a2_delta == 0
+					&& b1_delta == 0 && b2_delta == 0) {
+				for (int i = 0; i < len; i++) {
+					float x = buffer[i];
+					float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2);
+					float xx = (y * gain) * wet + (x) * (1 - wet);
+					x2 = x1;
+					x1 = x;
+					y2 = y1;
+					y1 = y;
+					float yy = (a0 * xx + a1 * xx1 + a2 * xx2 - b1 * yy1 - b2
+							* yy2);
+					buffer[i] = (yy * gain) * wet + (xx) * (1 - wet);
+					xx2 = xx1;
+					xx1 = xx;
+					yy2 = yy1;
+					yy1 = yy;
+				}
+			} else {
+				for (int i = 0; i < len; i++) {
+					a0 += a0_delta;
+					a1 += a1_delta;
+					a2 += a2_delta;
+					b1 += b1_delta;
+					b2 += b2_delta;
+					gain += gain_delta;
+					float x = buffer[i];
+					float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2);
+					float xx = (y * gain) * wet + (x) * (1 - wet);
+					x2 = x1;
+					x1 = x;
+					y2 = y1;
+					y1 = y;
+					float yy = (a0 * xx + a1 * xx1 + a2 * xx2 - b1 * yy1 - b2
+							* yy2);
+					buffer[i] = (yy * gain) * wet + (xx) * (1 - wet);
+					xx2 = xx1;
+					xx1 = xx;
+					yy2 = yy1;
+					yy1 = yy;
+				}
+			}
+
+			if (Math.abs(x1) < 1.0E-8)
+				x1 = 0;
+			if (Math.abs(x2) < 1.0E-8)
+				x2 = 0;
+			if (Math.abs(y1) < 1.0E-8)
+				y1 = 0;
+			if (Math.abs(y2) < 1.0E-8)
+				y2 = 0;
+			this.x1 = x1;
+			this.x2 = x2;
+			this.y1 = y1;
+			this.y2 = y2;
+			this.xx1 = xx1;
+			this.xx2 = xx2;
+			this.yy1 = yy1;
+			this.yy2 = yy2;
+		}
+
+		this.last_a0 = this.a0;
+		this.last_a1 = this.a1;
+		this.last_a2 = this.a2;
+		this.last_b1 = this.b1;
+		this.last_b2 = this.b2;
+		this.last_gain = this.gain;
+		this.last_wet = this.wet;
+
+	}
+
+	private double sinh(double x) {
+		return (Math.exp(x) - Math.exp(-x)) * 0.5;
+	}
+
+	public void filter2calc() {
+
+		double resonancedB = this.resonancedB;
+		if (resonancedB < 0)
+			resonancedB = 0; // Negative dB are illegal.
+		if (resonancedB > 30)
+			resonancedB = 30; // At least 22.5 dB is needed.
+		if (filtertype == FILTERTYPE_LP24 || filtertype == FILTERTYPE_HP24)
+			resonancedB *= 0.6;
+
+		if (filtertype == FILTERTYPE_BP12) {
+			wet = 1;
+			double r = (cutoff / samplerate);
+			if (r > 0.45)
+				r = 0.45;
+
+			double bandwidth = Math.PI * Math.pow(10.0, -(resonancedB / 20));
+
+			double omega = 2 * Math.PI * r;
+			double cs = Math.cos(omega);
+			double sn = Math.sin(omega);
+			double alpha = sn
+					* sinh((Math.log(2) * bandwidth * omega) / (sn * 2));
+
+			double b0 = alpha;
+			double b1 = 0;
+			double b2 = -alpha;
+			double a0 = 1 + alpha;
+			double a1 = -2 * cs;
+			double a2 = 1 - alpha;
+
+			double cf = 1.0 / a0;
+			this.b1 = (float) (a1 * cf);
+			this.b2 = (float) (a2 * cf);
+			this.a0 = (float) (b0 * cf);
+			this.a1 = (float) (b1 * cf);
+			this.a2 = (float) (b2 * cf);
+		}
+
+		if (filtertype == FILTERTYPE_NP12) {
+			wet = 1;
+			double r = (cutoff / samplerate);
+			if (r > 0.45)
+				r = 0.45;
+
+			double bandwidth = Math.PI * Math.pow(10.0, -(resonancedB / 20));
+
+			double omega = 2 * Math.PI * r;
+			double cs = Math.cos(omega);
+			double sn = Math.sin(omega);
+			double alpha = sn
+					* sinh((Math.log(2) * bandwidth * omega) / (sn * 2));
+
+			double b0 = 1;
+			double b1 = -2 * cs;
+			double b2 = 1;
+			double a0 = 1 + alpha;
+			double a1 = -2 * cs;
+			double a2 = 1 - alpha;
+
+			double cf = 1.0 / a0;
+			this.b1 = (float) (a1 * cf);
+			this.b2 = (float) (a2 * cf);
+			this.a0 = (float) (b0 * cf);
+			this.a1 = (float) (b1 * cf);
+			this.a2 = (float) (b2 * cf);
+		}
+
+		if (filtertype == FILTERTYPE_LP12 || filtertype == FILTERTYPE_LP24) {
+			double r = (cutoff / samplerate);
+			if (r > 0.45) {
+				if (wet == 0)
+					if (resonancedB < 0.00001)
+						wet = 0.0f;
+					else
+						wet = 1.0f;
+				r = 0.45;
+			} else
+				wet = 1.0f;
+
+			double c = 1.0 / (Math.tan(Math.PI * r));
+			double csq = c * c;
+			double resonance = Math.pow(10.0, -(resonancedB / 20));
+			double q = Math.sqrt(2.0f) * resonance;
+			double a0 = 1.0 / (1.0 + (q * c) + (csq));
+			double a1 = 2.0 * a0;
+			double a2 = a0;
+			double b1 = (2.0 * a0) * (1.0 - csq);
+			double b2 = a0 * (1.0 - (q * c) + csq);
+
+			this.a0 = (float) a0;
+			this.a1 = (float) a1;
+			this.a2 = (float) a2;
+			this.b1 = (float) b1;
+			this.b2 = (float) b2;
+
+		}
+
+		if (filtertype == FILTERTYPE_HP12 || filtertype == FILTERTYPE_HP24) {
+			double r = (cutoff / samplerate);
+			if (r > 0.45)
+				r = 0.45;
+			if (r < 0.0001)
+				r = 0.0001;
+			wet = 1.0f;
+			double c = (Math.tan(Math.PI * (r)));
+			double csq = c * c;
+			double resonance = Math.pow(10.0, -(resonancedB / 20));
+			double q = Math.sqrt(2.0f) * resonance;
+			double a0 = 1.0 / (1.0 + (q * c) + (csq));
+			double a1 = -2.0 * a0;
+			double a2 = a0;
+			double b1 = (2.0 * a0) * (csq - 1.0);
+			double b2 = a0 * (1.0 - (q * c) + csq);
+
+			this.a0 = (float) a0;
+			this.a1 = (float) a1;
+			this.a2 = (float) a2;
+			this.b1 = (float) b1;
+			this.b2 = (float) b2;
+
+		}
+
+	}
+
+	public void filter2(SoftAudioBuffer sbuffer) {
+
+		float[] buffer = sbuffer.array();
+
+		if (dirty) {
+			filter2calc();
+			dirty = false;
+		}
+		if (!last_set) {
+			last_a0 = a0;
+			last_a1 = a1;
+			last_a2 = a2;
+			last_b1 = b1;
+			last_b2 = b2;
+			last_q = q;
+			last_gain = gain;
+			last_wet = wet;
+			last_set = true;
+		}
+
+		if (wet > 0 || last_wet > 0) {
+
+			int len = buffer.length;
+			float a0 = this.last_a0;
+			float a1 = this.last_a1;
+			float a2 = this.last_a2;
+			float b1 = this.last_b1;
+			float b2 = this.last_b2;
+			float gain = this.last_gain;
+			float wet = this.last_wet;
+			float a0_delta = (this.a0 - this.last_a0) / len;
+			float a1_delta = (this.a1 - this.last_a1) / len;
+			float a2_delta = (this.a2 - this.last_a2) / len;
+			float b1_delta = (this.b1 - this.last_b1) / len;
+			float b2_delta = (this.b2 - this.last_b2) / len;
+			float gain_delta = (this.gain - this.last_gain) / len;
+			float wet_delta = (this.wet - this.last_wet) / len;
+			float x1 = this.x1;
+			float x2 = this.x2;
+			float y1 = this.y1;
+			float y2 = this.y2;
+
+			if (wet_delta != 0) {
+				for (int i = 0; i < len; i++) {
+					a0 += a0_delta;
+					a1 += a1_delta;
+					a2 += a2_delta;
+					b1 += b1_delta;
+					b2 += b2_delta;
+					gain += gain_delta;
+					wet += wet_delta;
+					float x = buffer[i];
+					float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2);
+					buffer[i] = (y * gain) * wet + (x) * (1 - wet);
+					x2 = x1;
+					x1 = x;
+					y2 = y1;
+					y1 = y;
+				}
+			} else if (a0_delta == 0 && a1_delta == 0 && a2_delta == 0
+					&& b1_delta == 0 && b2_delta == 0) {
+				for (int i = 0; i < len; i++) {
+					float x = buffer[i];
+					float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2);
+					buffer[i] = y * gain;
+					x2 = x1;
+					x1 = x;
+					y2 = y1;
+					y1 = y;
+				}
+			} else {
+				for (int i = 0; i < len; i++) {
+					a0 += a0_delta;
+					a1 += a1_delta;
+					a2 += a2_delta;
+					b1 += b1_delta;
+					b2 += b2_delta;
+					gain += gain_delta;
+					float x = buffer[i];
+					float y = (a0 * x + a1 * x1 + a2 * x2 - b1 * y1 - b2 * y2);
+					buffer[i] = y * gain;
+					x2 = x1;
+					x1 = x;
+					y2 = y1;
+					y1 = y;
+				}
+			}
+
+			if (Math.abs(x1) < 1.0E-8)
+				x1 = 0;
+			if (Math.abs(x2) < 1.0E-8)
+				x2 = 0;
+			if (Math.abs(y1) < 1.0E-8)
+				y1 = 0;
+			if (Math.abs(y2) < 1.0E-8)
+				y2 = 0;
+			this.x1 = x1;
+			this.x2 = x2;
+			this.y1 = y1;
+			this.y2 = y2;
+		}
+
+		this.last_a0 = this.a0;
+		this.last_a1 = this.a1;
+		this.last_a2 = this.a2;
+		this.last_b1 = this.b1;
+		this.last_b2 = this.b2;
+		this.last_q = this.q;
+		this.last_gain = this.gain;
+		this.last_wet = this.wet;
+
+	}
+
+	public void filter1calc() {
+		if (cutoff < 120)
+			cutoff = 120;
+		double c = (7.0 / 6.0) * Math.PI * 2 * cutoff / samplerate;
+		if (c > 1)
+			c = 1;
+		a0 = (float) (Math.sqrt(1 - Math.cos(c)) * Math.sqrt(0.5 * Math.PI));
+		if (resonancedB < 0)
+			resonancedB = 0;
+		if (resonancedB > 20)
+			resonancedB = 20;
+		q = (float) (Math.sqrt(0.5) * Math.pow(10.0, -(resonancedB / 20)));
+		gain = (float) Math.pow(10, -((resonancedB)) / 40.0);
+		if (wet == 0.0f)
+			if (resonancedB > 0.00001 || c < 0.9999999)
+				wet = 1.0f;
+	}
+
+	public void filter1(SoftAudioBuffer sbuffer) {
+
+		float[] buffer = sbuffer.array();
+
+		if (dirty) {
+			filter1calc();
+			dirty = false;
+		}
+		if (!last_set) {
+			last_a0 = a0;
+			last_q = q;
+			last_gain = gain;
+			last_wet = wet;
+			last_set = true;
+		}
+
+		if (wet > 0 || last_wet > 0) {
+
+			int len = buffer.length;
+			float a0 = this.last_a0;
+			float q = this.last_q;
+			float gain = this.last_gain;
+			float wet = this.last_wet;
+			float a0_delta = (this.a0 - this.last_a0) / len;
+			float q_delta = (this.q - this.last_q) / len;
+			float gain_delta = (this.gain - this.last_gain) / len;
+			float wet_delta = (this.wet - this.last_wet) / len;
+			float y2 = this.y2;
+			float y1 = this.y1;
+
+			if (wet_delta != 0) {
+				for (int i = 0; i < len; i++) {
+					a0 += a0_delta;
+					q += q_delta;
+					gain += gain_delta;
+					wet += wet_delta;
+					y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
+					y2 = (1 - q * a0) * y2 + (a0) * y1;
+					buffer[i] = y2 * gain * wet + buffer[i] * (1 - wet);
+				}
+			} else if (a0_delta == 0 && q_delta == 0) {
+				for (int i = 0; i < len; i++) {
+					y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
+					y2 = (1 - q * a0) * y2 + (a0) * y1;
+					buffer[i] = y2 * gain;
+				}
+			} else {
+				for (int i = 0; i < len; i++) {
+					a0 += a0_delta;
+					q += q_delta;
+					gain += gain_delta;
+					y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
+					y2 = (1 - q * a0) * y2 + (a0) * y1;
+					buffer[i] = y2 * gain;
+				}
+			}
+
+			if (Math.abs(y2) < 1.0E-8)
+				y2 = 0;
+			if (Math.abs(y1) < 1.0E-8)
+				y1 = 0;
+			this.y2 = y2;
+			this.y1 = y1;
+		}
+
+		this.last_a0 = this.a0;
+		this.last_q = this.q;
+		this.last_gain = this.gain;
+		this.last_wet = this.wet;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftInstrument.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.MidiChannel;
+
+/**
+ * 
+ * Software synthesizer internal instrument.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftInstrument extends Instrument {
+
+	private SoftPerformer[] performers;
+	
+	private ModelPerformer[] modelperformers;
+
+	private Object data;
+
+	private ModelInstrument ins;
+
+	public SoftInstrument(ModelInstrument ins) {
+		super(ins.getSoundbank(), ins.getPatch(), ins.getName(), ins
+				.getDataClass());
+		if (!(ins instanceof ModelInstrument))
+			throw new IllegalArgumentException(
+					"Instrument doesn't implement ModelInstrument interface!");
+		data = ins.getData();
+		this.ins = ins;
+		initPerformers(((ModelInstrument) ins).getPerformers());
+	}
+
+	public SoftInstrument(ModelInstrument ins,
+			ModelPerformer[] overrideperformers) {
+		super(ins.getSoundbank(), ins.getPatch(), ins.getName(), ins
+				.getDataClass());
+		if (!(ins instanceof ModelInstrument))
+			throw new IllegalArgumentException(
+					"Instrument doesn't implement ModelInstrument interface!");
+		data = ins.getData();
+		this.ins = ins;
+		initPerformers(overrideperformers);
+	}
+
+	private void initPerformers(ModelPerformer[] modelperformers) {
+		this.modelperformers = modelperformers;
+		performers = new SoftPerformer[modelperformers.length];
+		for (int i = 0; i < modelperformers.length; i++)
+			performers[i] = new SoftPerformer(modelperformers[i]);
+	}
+	
+	public ModelDirector getDirector(MidiChannel channel, ModelDirectedPlayer player)
+	{
+		return ins.getDirector(modelperformers, channel, player);
+	}
+
+	public ModelInstrument getSourceInstrument() {
+		return ins;
+	}
+
+	public Object getData() {
+		return data;
+	}
+
+	public SoftPerformer[] getPerformers() {
+		return performers;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+
+/**
+ * A jitter corrector to be used with SoftAudioPusher.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftJitterCorrector extends AudioInputStream {
+	private static class JitterStream extends InputStream {
+		
+		static int MAX_BUFFER_SIZE = 1048576;
+		
+		boolean active = true;
+		Thread thread;
+		AudioInputStream stream;	
+		
+		// Cyclic buffer
+		int writepos = 0;
+		int readpos = 0;
+		byte[][] buffers;		
+		byte[] nullbuff;
+
+		// Adapative Drift Statistics
+		int w_count = 1000;
+		int w_min_tol = 2;
+		int w_max_tol = 10;		
+		int w = 0;
+		int w_min = -1;
+				
+		// Current read buffer
+		int bbuffer_pos = 0;
+		int bbuffer_max = 0;
+		byte[] bbuffer = null; 
+		
+		public byte[] nextReadBuffer()
+		{
+			synchronized(buffers)
+			{
+				if(writepos > readpos)
+				{
+					int w_m = writepos - readpos;
+					if(w_m < w_min) w_min = w_m;
+					
+					int buffpos = readpos;				
+					readpos++;
+					return buffers[buffpos % buffers.length];
+				}
+				w_min = -1;
+				w = w_count-1;
+			}
+			while(true)
+			{
+				try {
+					Thread.sleep(1);
+				} catch (InterruptedException e) {
+					e.printStackTrace();
+					return null;
+				}
+				synchronized(buffers)
+				{
+					if(writepos > readpos)
+					{
+						w = 0;
+						w_min = -1;
+						w = w_count-1;
+						int buffpos = readpos;				
+						readpos++;
+						return buffers[buffpos % buffers.length];
+					}						
+				}
+			}
+		}
+		
+		public byte[] nextWriteBuffer()
+		{
+			synchronized(buffers)
+			{			
+				return buffers[writepos % buffers.length];			
+			}
+		}
+		
+		public void commit()
+		{
+			synchronized(buffers)
+			{			
+				writepos++;
+				if((writepos - readpos) > buffers.length)
+				{
+					int newsize = (writepos - readpos) + 10;
+					newsize = Math.max(buffers.length*2, newsize);
+					buffers = new byte[newsize][buffers[0].length];
+				}
+			}		
+		}
+		
+		public JitterStream(AudioInputStream s, int buffersize, int smallbuffersize)
+		{
+			this.w_count = 10 * (buffersize/smallbuffersize);
+			if(w_count < 100) w_count = 100;
+			this.buffers = new byte[(buffersize/smallbuffersize)+10][smallbuffersize];
+			this.bbuffer_max = MAX_BUFFER_SIZE / smallbuffersize;
+			this.nullbuff = new byte[smallbuffersize];
+			this.stream = s;
+			
+
+			Runnable runnable = new Runnable()
+			{
+				public void run()
+				{				
+					AudioFormat format = stream.getFormat();
+					int bufflen = buffers[0].length;
+					int frames = bufflen / format.getFrameSize();
+					long nanos = (long) ( frames * 1000000000.0 / format.getSampleRate() );					
+					long now = System.nanoTime();
+					long next = now + nanos;
+					int correction = 0;
+					while(true)
+					{
+						synchronized (JitterStream.this) {
+							if(!active) break;
+						}				
+						int curbuffsize;
+						synchronized (buffers) {
+							curbuffsize = writepos - readpos;
+							if(correction == 0)
+							{
+								w++;
+								if(w_min != Integer.MAX_VALUE)
+								if(w == w_count)
+								{					
+									correction = 0;														
+									if(w_min < w_min_tol) correction = (w_min_tol+ w_max_tol)/2 - w_min;
+									if(w_min > w_max_tol) correction = (w_min_tol+ w_max_tol)/2 - w_min;
+									w = 0;
+									w_min = Integer.MAX_VALUE;
+								}				
+							}
+						}
+						while(curbuffsize > bbuffer_max)
+						{
+							synchronized (buffers) {
+								curbuffsize = writepos - readpos;
+							}
+							synchronized (JitterStream.this) {
+								if(!active) break;
+							}				
+							try {
+								Thread.sleep(1);
+							} catch (InterruptedException e) {
+								e.printStackTrace();
+							}
+						}
+						
+						if(correction < 0)
+						{
+							correction++;
+						}
+						else
+						{
+							byte[] buff = nextWriteBuffer();
+							try {
+								stream.read(buff, 0, buff.length);
+							} catch (IOException e1) {
+								e1.printStackTrace();
+							}
+							commit();
+						}
+						
+						if(correction > 0)
+						{
+							correction--;
+							next = System.nanoTime() + nanos;
+							continue;
+						}
+						long wait = next - System.nanoTime(); 
+						if(wait > 0)
+						{
+							try {
+								Thread.sleep(wait / 1000000L);
+							} catch (InterruptedException e) {
+								e.printStackTrace();
+							}
+						}
+						next += nanos;
+					}
+				}
+			};
+			
+			thread = new Thread(runnable);
+			thread.setPriority(Thread.MAX_PRIORITY);
+			thread.start();
+		}
+
+		public void close() throws IOException {
+			synchronized (this) {
+				active = false;
+			}			
+			try {
+				thread.join();
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+			stream.close();
+		}		
+		
+		public int read() throws IOException {
+			byte[] b = new byte[1];
+			if (read(b) == -1)
+				return -1;
+			return b[0] & 0xFF;
+		}
+		
+		public void fillBuffer() {
+			bbuffer = nextReadBuffer();
+			bbuffer_pos = 0;
+		}
+
+		public int read(byte[] b, int off, int len) {
+			if(bbuffer == null) fillBuffer();
+			int bbuffer_len = bbuffer.length;
+			int offlen = off + len;
+			while (off < offlen)
+				if (available() == 0)
+					fillBuffer();
+				else {
+					byte[] bbuffer = this.bbuffer;
+					int bbuffer_pos = this.bbuffer_pos;
+					while (off < offlen && bbuffer_pos < bbuffer_len)
+						b[off++] = bbuffer[bbuffer_pos++];
+					this.bbuffer_pos = bbuffer_pos;
+				}
+			return len;
+		}
+		
+		public int available() {
+			return bbuffer.length - bbuffer_pos;
+		}	
+
+	};
+
+	public SoftJitterCorrector(AudioInputStream stream, int buffersize, int smallbuffersize) {		
+		super(new JitterStream(stream, buffersize, smallbuffersize), stream.getFormat(), stream
+				.getFrameLength());
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLanczosResampler.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * Lanczos interpolation resampler.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftLanczosResampler extends SoftAbstractResampler {
+
+	double[] din;
+
+	float[][] sinc_table;
+
+	int sinc_table_fsize = 2000;
+
+	int sinc_table_size = 5;
+
+	int sinc_table_center = sinc_table_size / 2;
+
+	public SoftLanczosResampler() {
+		super();
+		sinc_table = new float[sinc_table_fsize][];
+		for (int i = 0; i < sinc_table_fsize; i++)
+			sinc_table[i] = sincTable(sinc_table_size, -i
+					/ ((float) sinc_table_fsize));
+	}
+
+	// Normalized sinc function
+	public static double sinc(double x) {
+		return (x == 0.0) ? 1.0 : Math.sin(Math.PI * x) / (Math.PI * x);
+	}
+
+	// Generate sinc table
+	public static float[] sincTable(int size, float offset) {
+		int center = size / 2;
+		float[] w = new float[size];
+		for (int k = 0; k < size; k++) {
+			float x = (-center + k + offset);
+			if (x < -2 || x > 2)
+				w[k] = 0;
+			else if (x == 0)
+				w[k] = 1;
+			else
+				w[k] = (float) (2.0 * Math.sin(Math.PI * x)
+						* Math.sin(Math.PI * x / 2.0) / ((Math.PI * x) * (Math.PI * x)));
+		}
+		return w;
+	}
+
+	public int getPadding() // must be at least half of sinc_table_size
+	{
+		return sinc_table_size / 2 + 2;
+	}
+
+	public void interpolate(float[] in, float[] in_offset, float in_end,
+			float[] startpitch, float pitchstep, float[] out, int[] out_offset,
+			int out_end) {
+		float pitch = startpitch[0];
+		float ix = in_offset[0];
+		int ox = out_offset[0];
+		float ix_end = in_end;
+		int ox_end = out_end;
+
+		if (pitchstep == 0) {
+			while (ix < ix_end && ox < ox_end) {
+				int iix = (int) ix;
+				float[] sinc_table = this.sinc_table[(int) ((ix - iix) * sinc_table_fsize)];
+				int xx = iix - sinc_table_center;
+				float y = 0;
+				for (int i = 0; i < sinc_table_size; i++, xx++)
+					y += in[xx] * sinc_table[i];
+				out[ox++] = y;
+				ix += pitch;
+			}
+		} else {
+			while (ix < ix_end && ox < ox_end) {
+				int iix = (int) ix;
+				float[] sinc_table = this.sinc_table[(int) ((ix - iix) * sinc_table_fsize)];
+				int xx = iix - sinc_table_center;
+				float y = 0;
+				for (int i = 0; i < sinc_table_size; i++, xx++)
+					y += in[xx] * sinc_table[i];
+				out[ox++] = y;
+
+				ix += pitch;
+				pitch += pitchstep;
+			}
+		}
+		in_offset[0] = ix;
+		out_offset[0] = ox;
+		startpitch[0] = pitch;
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLimiter.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * A simple look-ahead volume limiter with very fast attack and fast release.
+ * This filter is used for preventing clipping.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftLimiter implements SoftAudioProcessor {
+
+	float lastmax = 0;
+
+	float gain = 1;
+
+	float[] temp_bufferL;
+
+	float[] temp_bufferR;
+
+	boolean mix = false;
+
+	SoftAudioBuffer bufferL;
+
+	SoftAudioBuffer bufferR;
+
+	SoftAudioBuffer bufferLout;
+
+	SoftAudioBuffer bufferRout;
+
+	SoftSynthesizer synth;
+
+	public void init(SoftSynthesizer synth) {
+		this.synth = synth;
+	}
+
+	public void setInput(int pin, SoftAudioBuffer input) {
+		if (pin == 0)
+			bufferL = input;
+		if (pin == 1)
+			bufferR = input;
+	}
+
+	public void setOutput(int pin, SoftAudioBuffer output) {
+		if (pin == 0)
+			bufferLout = output;
+		if (pin == 1)
+			bufferRout = output;
+	}
+
+	public void setMixMode(boolean mix) {
+		this.mix = mix;
+	}
+
+	public void globalParameterControlChange(int[] slothpath, long param,
+			long value) {
+
+	}
+
+	double silentcounter = 0;
+
+	public void processAudio() {
+		if (this.bufferL.isSilent()
+				&& (this.bufferR == null || this.bufferR.isSilent())) {
+			silentcounter += 1 / synth.getControlRate();
+
+			if (silentcounter > 60) {
+				if (!mix) {
+					bufferLout.clear();
+					bufferRout.clear();
+				}
+				return;
+			}
+		} else
+			silentcounter = 0;
+
+		float[] bufferL = this.bufferL.array();
+		float[] bufferR = this.bufferR == null ? null : this.bufferR.array();
+		float[] bufferLout = this.bufferLout.array();
+		float[] bufferRout = this.bufferRout == null ? null : this.bufferRout
+				.array();
+
+		if (temp_bufferL == null || temp_bufferL.length < bufferL.length)
+			temp_bufferL = new float[bufferL.length];
+		if (bufferR != null)
+			if (temp_bufferR == null || temp_bufferR.length < bufferR.length)
+				temp_bufferR = new float[bufferR.length];
+
+		float max = 0;
+		int len = bufferL.length;
+
+		if (bufferR == null)
+			for (int i = 0; i < len; i++) {
+				if (bufferL[i] > max)
+					max = bufferL[i];
+				if (-bufferL[i] > max)
+					max = -bufferL[i];
+			}
+		else
+			for (int i = 0; i < len; i++) {
+				if (bufferL[i] > max)
+					max = bufferL[i];
+				if (bufferR[i] > max)
+					max = bufferR[i];
+				if (-bufferL[i] > max)
+					max = -bufferL[i];
+				if (-bufferR[i] > max)
+					max = -bufferR[i];
+			}
+
+		float lmax = lastmax;
+		lastmax = max;
+		if (lmax > max)
+			max = lmax;
+
+		float newgain = 1;
+		if (max > 0.99f)
+			newgain = 0.99f / max;
+		else
+			newgain = 1;
+
+		if (newgain > gain)
+			newgain = (newgain + gain * 9) / 10f;
+
+		float gaindelta = (newgain - gain) / len;
+		if (mix) {
+			if (bufferR == null)
+				for (int i = 0; i < len; i++) {
+					gain += gaindelta;
+					float bL = bufferL[i];
+					float tL = temp_bufferL[i];
+					temp_bufferL[i] = bL;
+					bufferLout[i] += tL * gain;
+				}
+			else
+				for (int i = 0; i < len; i++) {
+					gain += gaindelta;
+					float bL = bufferL[i];
+					float bR = bufferR[i];
+					float tL = temp_bufferL[i];
+					float tR = temp_bufferR[i];
+					temp_bufferL[i] = bL;
+					temp_bufferR[i] = bR;
+					bufferLout[i] += tL * gain;
+					bufferRout[i] += tR * gain;
+				}
+
+		} else {
+			if (bufferR == null)
+				for (int i = 0; i < len; i++) {
+					gain += gaindelta;
+					float bL = bufferL[i];
+					float tL = temp_bufferL[i];
+					temp_bufferL[i] = bL;
+					bufferLout[i] = tL * gain;
+				}
+			else
+				for (int i = 0; i < len; i++) {
+					gain += gaindelta;
+					float bL = bufferL[i];
+					float bR = bufferR[i];
+					float tL = temp_bufferL[i];
+					float tR = temp_bufferR[i];
+					temp_bufferL[i] = bL;
+					temp_bufferR[i] = bR;
+					bufferLout[i] = tL * gain;
+					bufferRout[i] = tR * gain;
+				}
+
+		}
+		gain = newgain;
+	}
+
+	public void processControlLogic() {
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * A resampler that uses first-order (linear) interpolation.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftLinearResampler extends SoftAbstractResampler {
+
+	public int getPadding() {
+		return 2;
+	}
+	
+	public void interpolate(float[] in, float[] in_offset, float in_end,
+			float[] startpitch, float pitchstep, float[] out, int[] out_offset,
+			int out_end) {
+		
+ 		float pitch = startpitch[0];
+		float ix = in_offset[0];
+		int ox = out_offset[0];
+		float ix_end = in_end;
+		int ox_end = out_end;
+		if (pitchstep == 0f) {			
+			while (ix < ix_end && ox < ox_end) {
+				int iix = (int) ix;
+				float fix = ix - iix;
+				float i = in[iix];
+				out[ox++] = i + (in[iix + 1] - i) * fix;				
+				ix += pitch;
+			}			
+		} else {
+			while (ix < ix_end && ox < ox_end) {
+				int iix = (int) ix;
+				float fix = ix - iix;
+				float i = in[iix];
+				out[ox++] = i + (in[iix + 1] - i) * fix;				
+				ix += pitch;
+				pitch += pitchstep;
+			}
+		}
+		in_offset[0] = ix;
+		out_offset[0] = ox;
+		startpitch[0] = pitch;
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler2.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * A resampler that uses first-order (linear) interpolation.
+ * 
+ * This one doesn't perform float to int casting
+ * inside the processing loop.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftLinearResampler2 extends SoftAbstractResampler {
+
+	public int getPadding() {
+		return 2;
+	}
+	
+	public void interpolate(float[] in, float[] in_offset, float in_end,
+			float[] startpitch, float pitchstep, float[] out, int[] out_offset,
+			int out_end) {
+		
+ 		float pitch = startpitch[0];
+		float ix = in_offset[0];
+		int ox = out_offset[0];
+		float ix_end = in_end;
+		int ox_end = out_end;
+		
+		// Check if we have do anything		
+		if(!(ix < ix_end && ox < ox_end)) return;
+
+		// 15 bit shift was choosed because
+		// it resulted in no drift between p_ix and ix.
+		int p_ix = (int)(ix * (1 << 15));
+		int p_ix_end = (int)(ix_end * (1 << 15));
+		int p_pitch = (int)(pitch * (1 << 15));
+		// Pitch needs to recalculated
+		// to ensure no drift between p_ix and ix.
+		pitch = p_pitch * (1f/(1 << 15)); 
+		
+		if (pitchstep == 0f) {			
+						
+			// To reduce
+			//    while (p_ix < p_ix_end && ox < ox_end)
+			// into
+			//    while  (ox < ox_end)
+			// We need to calculate new ox_end value.
+			int p_ix_len = p_ix_end - p_ix;
+			int p_mod = p_ix_len % p_pitch;
+			if(p_mod != 0) p_ix_len += p_pitch - p_mod;
+			int ox_end2 = ox + p_ix_len/p_pitch;
+			if(ox_end2 < ox_end) ox_end = ox_end2;
+			
+			while (ox < ox_end) {			
+				int iix = p_ix >> 15;
+				float fix = ix - iix;
+				float i = in[iix];
+				out[ox++] = i + (in[iix + 1] - i) * fix;								
+				p_ix += p_pitch;
+				ix += pitch;
+			}	
+			  
+		} else {
+			
+			int p_pitchstep = (int)(pitchstep * (1 << 15)); 
+			pitchstep = p_pitchstep * (1f/(1 << 15));
+			
+			while (p_ix < p_ix_end && ox < ox_end) {
+				int iix = p_ix >> 15;
+				float fix = ix - iix;
+				float i = in[iix];
+				out[ox++] = i + (in[iix + 1] - i) * fix;				
+				ix += pitch;
+				p_ix += p_pitch;
+				pitch += pitchstep;
+				p_pitch += p_pitchstep;
+			}
+		}
+		in_offset[0] = ix;
+		out_offset[0] = ox;
+		startpitch[0] = pitch;
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * LFO control signal generator.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftLowFrequencyOscillator implements SoftProcess {
+
+	private int max_count = 10;
+
+	private int used_count = 0;
+
+	private double[][] out = new double[max_count][1];
+
+	private double[][] delay = new double[max_count][1];
+
+	private double[][] delay2 = new double[max_count][1];
+
+	private double[][] freq = new double[max_count][1];
+
+	private int[] delay_counter = new int[max_count];
+
+	private double[] sin_phase = new double[max_count];
+	
+	private double[] sin_stepfreq = new double[max_count];
+	private double[] sin_step = new double[max_count];
+
+	private double control_time = 0;
+
+	private double sin_factor = 0;
+	
+	private static double PI2 = 2.0 * Math.PI;
+
+	public void reset() {
+		for (int i = 0; i < used_count; i++) {
+			out[i][0] = 0;
+			delay[i][0] = 0;
+			delay2[i][0] = 0;
+			freq[i][0] = 0;
+			delay_counter[i] = 0;
+			sin_phase[i] = 0;
+			sin_stepfreq[i] = 0;
+			sin_step[i] = 0;
+		}
+		used_count = 0;
+	}
+
+	public void init(SoftSynthesizer synth) {
+		control_time = 1.0 / synth.getControlRate();
+		sin_factor = control_time * 2 * Math.PI;
+		for (int i = 0; i < used_count; i++) {
+			delay_counter[i] = (int) (Math.pow(2, this.delay[i][0] / 1200.0) / control_time);
+			delay_counter[i] += (int) (delay2[i][0] / (control_time * 1000));
+		}
+		processControlLogic();
+	}
+
+	public void processControlLogic() {
+		for (int i = 0; i < used_count; i++) {
+			if (delay_counter[i] > 0) {
+				delay_counter[i]--;
+				out[i][0] = 0.5;
+			} else {				
+				double f = freq[i][0];
+				
+				if(sin_stepfreq[i] != f)
+				{			
+					sin_stepfreq[i] = f;
+					double fr = 440.0 * Math.exp(
+							(f - 6900.0) * (Math.log(2)/ 1200.0));
+					sin_step[i] = fr * sin_factor;
+				}					
+				/*
+				double fr = 440.0 * Math.pow(2.0,
+						(freq[i][0] - 6900.0) / 1200.0);
+				sin_phase[i] += fr * sin_factor;
+				*/		
+				/*
+				sin_phase[i] += sin_step[i];				
+				while (sin_phase[i] > PI2)
+					sin_phase[i] -= PI2;
+				out[i][0] = 0.5 + Math.sin(sin_phase[i]) * 0.5;
+				*/
+				double p = sin_phase[i];
+				p += sin_step[i];				
+				while (p > PI2)
+					p -= PI2;
+				out[i][0] = 0.5 + Math.sin(p) * 0.5;
+				sin_phase[i] = p;
+				
+				
+			}
+		}
+	}
+
+	public double[] get(int instance, String name) {
+		if (instance >= used_count)
+			used_count = instance + 1;
+		if (name == null)
+			return out[instance];
+		if (name.equals("delay"))
+			return delay[instance];
+		if (name.equals("delay2"))
+			return delay2[instance];
+		if (name.equals("freq"))
+			return freq[instance];
+		return null;
+	}
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,1003 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.Patch;
+import javax.sound.midi.ShortMessage;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * Software synthesizer main audio mixer.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftMainMixer {
+
+	public final static int CHANNEL_LEFT = 0;
+
+	public final static int CHANNEL_RIGHT = 1;
+
+	public final static int CHANNEL_EFFECT1 = 2;
+
+	public final static int CHANNEL_EFFECT2 = 3;
+
+	public final static int CHANNEL_EFFECT3 = 4;
+
+	public final static int CHANNEL_EFFECT4 = 5;
+
+	public final static int CHANNEL_LEFT_DRY = 10;
+
+	public final static int CHANNEL_RIGHT_DRY = 11;
+
+	public final static int CHANNEL_SCRATCH1 = 12;
+
+	public final static int CHANNEL_SCRATCH2 = 13;
+
+	public final static int CHANNEL_CHANNELMIXER_LEFT = 14;
+
+	public final static int CHANNEL_CHANNELMIXER_RIGHT = 15;
+	
+	protected boolean active_sensing_on = false;
+
+	protected long msec_last_activity = -1;
+
+	protected long msec_pos = 0;
+	
+	protected boolean readfully = true;	
+
+	private Object control_mutex;
+
+	private SoftSynthesizer synth;
+
+	private int nrofchannels = 2;
+
+	private SoftVoice[] voicestatus = null;
+
+	private SoftAudioBuffer[] buffers;
+
+	private SoftAudioProcessor reverb;
+
+	private SoftAudioProcessor chorus;
+
+	private SoftAudioProcessor agc;
+
+	private long msec_buffer_len = 0;
+	
+	protected TreeMap<Long, Object> midimessages = new TreeMap<Long, Object>();	
+
+	double finetuning = 0;
+
+	double coarsetuning = 0;
+
+	double last_volume_left = 1.0;
+
+	double last_volume_right = 1.0;
+
+	private double[] co_master_balance = new double[1];
+
+	private double[] co_master_volume = new double[1];
+
+	private double[] co_master_coarse_tuning = new double[1];
+
+	private double[] co_master_fine_tuning = new double[1];
+	
+	private AudioInputStream ais;
+	
+	private Set<ModelChannelMixer> registeredMixers = null;
+	
+	private Set<ModelChannelMixer> stoppedMixers = null;
+	
+	private ModelChannelMixer[] cur_registeredMixers = null;
+
+	protected SoftControl co_master = new SoftControl() {
+		double[] balance = co_master_balance;
+
+		double[] volume = co_master_volume;
+
+		double[] coarse_tuning = co_master_coarse_tuning;
+
+		double[] fine_tuning = co_master_fine_tuning;
+
+		public double[] get(int instance, String name) {
+			if (name == null)
+				return null;
+			if (name.equals("balance"))
+				return balance;
+			if (name.equals("volume"))
+				return volume;
+			if (name.equals("coarse_tuning"))
+				return coarse_tuning;
+			if (name.equals("fine_tuning"))
+				return fine_tuning;
+			return null;
+		}
+	};
+	
+	private void processSystemExclusiveMessage(byte[] data) {
+		synchronized (synth.control_mutex) {
+			msec_last_activity = msec_pos;
+
+			// Universal Non-Real-Time SysEx
+			if ((data[1] & 0xFF) == 0x7E) {
+				int deviceID = data[2] & 0xFF;
+				if (deviceID == 0x7F || deviceID == synth.getDeviceID()) {
+					int subid1 = data[3] & 0xFF;
+					int subid2;
+					switch (subid1) {
+					case 0x08: // MIDI Tuning Standard
+						subid2 = data[4] & 0xFF;
+						switch (subid2) {
+						case 0x01: // BULK TUNING DUMP
+						{
+							// http://www.midi.org/about-midi/tuning.shtml
+							SoftTuning tuning = synth.getTuning(new Patch(0,
+									data[5] & 0xFF));
+							tuning.load(data);
+							break;
+						}
+						case 0x04: // KEY-BASED TUNING DUMP
+						case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format
+						case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format
+						case 0x07: // SINGLE NOTE TUNING CHANGE (NON REAL-TIME)
+									// (BANK)
+						{
+							// http://www.midi.org/about-midi/tuning_extens.shtml
+							SoftTuning tuning = synth.getTuning(new Patch(
+									data[5] & 0xFF, data[6] & 0xFF));
+							tuning.load(data);
+							break;
+						}
+						case 0x08: // scale/octave tuning 1-byte form (Non
+									// Real-Time)
+						case 0x09: // scale/octave tuning 2-byte form (Non
+									// Real-Time)
+						{
+							// http://www.midi.org/about-midi/tuning-scale.shtml
+							SoftTuning tuning = new SoftTuning(data);
+							int channelmask = (data[5] & 0xFF) * 16384
+									+ (data[6] & 0xFF) * 128 + (data[7] & 0xFF);
+							SoftChannel[] channels = synth.channels;
+							for (int i = 0; i < channels.length; i++)
+								if ((channelmask & (1 << i)) != 0)
+									channels[i].tuning = tuning;
+							break;
+						}
+						default:
+							break;
+						}
+						break;
+					case 0x09: // General Midi Message
+						subid2 = data[4] & 0xFF;
+						switch (subid2) {
+						case 0x01: // General Midi 1 On
+							synth.setGeneralMidiMode(1);
+							reset();
+							break;
+						case 0x02: // General Midi Off
+							synth.setGeneralMidiMode(0);
+							reset();
+							break;
+						case 0x03: // General MidI Level 2 On
+							synth.setGeneralMidiMode(2);
+							reset();
+							break;
+						default:
+							break;
+						}
+						break;
+					case 0x0A: // DLS Message
+						subid2 = data[4] & 0xFF;
+						switch (subid2) {
+						case 0x01: // DLS On
+							if (synth.getGeneralMidiMode() == 0)
+								synth.setGeneralMidiMode(1);
+							synth.voice_allocation_mode = 1;
+							reset();
+							break;
+						case 0x02: // DLS Off
+							synth.setGeneralMidiMode(0);
+							synth.voice_allocation_mode = 0;
+							reset();
+							break;
+						case 0x03: // DLS Static Voice Allocation Off
+							synth.voice_allocation_mode = 0;
+							break;
+						case 0x04: // DLS Static Voice Allocation On
+							synth.voice_allocation_mode = 1;
+							break;
+						default:
+							break;
+						}
+						break;
+
+					default:
+						break;
+					}
+				}
+			}
+
+			// Universal Real-Time SysEx
+			if ((data[1] & 0xFF) == 0x7F) {
+				int deviceID = data[2] & 0xFF;
+				if (deviceID == 0x7F || deviceID == synth.getDeviceID()) {
+					int subid1 = data[3] & 0xFF;
+					int subid2;
+					switch (subid1) {
+					case 0x04: // Device Control
+
+						subid2 = data[4] & 0xFF;
+						switch (subid2) {
+						case 0x01: // Master Volume
+						case 0x02: // Master Balane
+						case 0x03: // Master fine tuning
+						case 0x04: // Master coarse tuning
+							int val = (data[5] & 0x7F)
+									+ ((data[6] & 0x7F) * 128);
+							if (subid2 == 0x01)
+								setVolume(val);
+							else if (subid2 == 0x02)
+								setBalance(val);
+							else if (subid2 == 0x03)
+								setFineTuning(val);
+							else if (subid2 == 0x04)
+								setCoarseTuning(val);
+							break;
+						case 0x05: // Global Parameter Control
+							int ix = 5;
+							int slotPathLen = (data[ix++] & 0xFF);
+							int paramWidth = (data[ix++] & 0xFF);
+							int valueWidth = (data[ix++] & 0xFF);
+							int[] slotPath = new int[slotPathLen];
+							for (int i = 0; i < slotPathLen; i++) {
+								int msb = (data[ix++] & 0xFF);
+								int lsb = (data[ix++] & 0xFF);
+								slotPath[i] = msb * 128 + lsb;
+							}
+							int paramCount = (data.length - 1 - ix)
+									/ (paramWidth + valueWidth);
+							long[] params = new long[paramCount];
+							long[] values = new long[paramCount];
+							for (int i = 0; i < paramCount; i++) {
+								values[i] = 0;
+								for (int j = 0; j < paramWidth; j++)
+									params[i] = params[i] * 128
+											+ (data[ix++] & 0xFF);
+								for (int j = 0; j < valueWidth; j++)
+									values[i] = values[i] * 128
+											+ (data[ix++] & 0xFF);
+
+							}
+							globalParameterControlChange(slotPath, params, values);
+							break;
+						default:
+							break;
+						}
+						break;
+
+					case 0x08: // MIDI Tuning Standard
+						subid2 = data[4] & 0xFF;
+						switch (subid2) {
+						case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME)
+						{
+							// http://www.midi.org/about-midi/tuning.shtml
+							SoftTuning tuning = synth.getTuning(new Patch(0,
+									data[5] & 0xFF));
+							tuning.load(data);
+							SoftVoice[] voices = synth.getVoices();
+							for (int i = 0; i < voices.length; i++)
+								if (voices[i].active)
+									if (voices[i].tuning == tuning)
+										voices[i].updateTuning(tuning);
+							break;
+						}
+						case 0x07: // SINGLE NOTE TUNING CHANGE (REAL-TIME)
+									// (BANK)
+						{
+							// http://www.midi.org/about-midi/tuning_extens.shtml
+							SoftTuning tuning = synth.getTuning(new Patch(
+									data[5] & 0xFF, data[6] & 0xFF));
+							tuning.load(data);
+							SoftVoice[] voices = synth.getVoices();
+							for (int i = 0; i < voices.length; i++)
+								if (voices[i].active)
+									if (voices[i].tuning == tuning)
+										voices[i].updateTuning(tuning);
+
+							break;
+						}
+						case 0x08: // scale/octave tuning 1-byte form
+									// (Real-Time)
+						case 0x09: // scale/octave tuning 2-byte form
+									// (Real-Time)
+						{
+							// http://www.midi.org/about-midi/tuning-scale.shtml
+							SoftTuning tuning = new SoftTuning(data);
+							int channelmask = (data[5] & 0xFF) * 16384
+									+ (data[6] & 0xFF) * 128 + (data[7] & 0xFF);
+							SoftChannel[] channels = synth.channels;
+							for (int i = 0; i < channels.length; i++)
+								if ((channelmask & (1 << i)) != 0)
+									channels[i].tuning = tuning;
+							SoftVoice[] voices = synth.getVoices();
+							for (int i = 0; i < voices.length; i++)
+								if (voices[i].active)
+									if ((channelmask & (1 << (voices[i].channel))) != 0)
+										voices[i].updateTuning(tuning);
+							break;
+						}
+						default:
+							break;
+						}
+						break;
+					case 0x09: // Control Destination Settings
+
+						subid2 = data[4] & 0xFF;
+						switch (subid2) {
+						case 0x01: // Channel Pressure
+						{
+							int[] destinations = new int[(data.length - 7) / 2];
+							int[] ranges = new int[(data.length - 7) / 2];
+							int ix = 0;
+							for (int j = 6; j < data.length - 1; j += 2) {
+								destinations[ix] = data[j] & 0xFF;
+								ranges[ix] = data[j + 1] & 0xFF;
+								ix++;
+							}
+							int channel = data[5] & 0xFF;
+							SoftChannel softchannel = synth.channels[channel];
+							softchannel.mapChannelPressureToDestination(
+									destinations, ranges);
+							break;
+						}
+						case 0x02: // Poly Pressure
+						{
+							int[] destinations = new int[(data.length - 7) / 2];
+							int[] ranges = new int[(data.length - 7) / 2];
+							int ix = 0;
+							for (int j = 6; j < data.length - 1; j += 2) {
+								destinations[ix] = data[j] & 0xFF;
+								ranges[ix] = data[j + 1] & 0xFF;
+								ix++;
+							}
+							int channel = data[5] & 0xFF;
+							SoftChannel softchannel = synth.channels[channel];
+							softchannel.mapPolyPressureToDestination(
+									destinations, ranges);
+							break;
+						}
+						case 0x03: // Control Change
+						{
+
+							int[] destinations = new int[(data.length - 7) / 2];
+							int[] ranges = new int[(data.length - 7) / 2];
+							int ix = 0;
+							for (int j = 7; j < data.length - 1; j += 2) {
+								destinations[ix] = data[j] & 0xFF;
+								ranges[ix] = data[j + 1] & 0xFF;
+								ix++;
+							}
+							int channel = data[5] & 0xFF;
+							SoftChannel softchannel = synth.channels[channel];
+							int control = data[6] & 0xFF;
+							softchannel.mapControlToDestination(control,
+									destinations, ranges);
+							break;
+						}
+						default:
+							break;
+						}
+						break;
+
+					case 0x0A: // Key Based Instrument Control
+					{
+						subid2 = data[4] & 0xFF;
+						switch (subid2) {
+						case 0x01: // Basic Message
+							int channel = data[5] & 0xFF;
+							int keynumber = data[6] & 0xFF;
+							SoftChannel softchannel = synth.channels[channel];
+							for (int j = 7; j < data.length - 1; j += 2) {
+								int controlnumber = data[j] & 0xFF;
+								int controlvalue = data[j + 1] & 0xFF;
+								softchannel.controlChangePerNote(keynumber,
+										controlnumber, controlvalue);
+							}
+							break;
+						default:
+							break;
+						}
+						break;
+					}
+					default:
+						break;
+					}
+				}
+			}
+
+		}
+	}
+	
+	private void processMessages(long timeStamp) {
+		
+		Iterator<Entry<Long, Object>> iter = midimessages.entrySet().iterator();
+		while (iter.hasNext()) {
+			Entry<Long, Object> entry = iter.next();
+			if (entry.getKey() > (timeStamp + 100))
+				return;
+			processMessage(entry.getValue());
+			iter.remove();
+		}
+	}
+	
+	protected void processAudioBuffers() {
+		for (int i = 0; i < buffers.length; i++) {
+			buffers[i].clear();
+		}
+
+		double volume_left;
+		double volume_right;
+		
+		ModelChannelMixer[] act_registeredMixers;
+		
+		// perform control logic
+		synchronized (control_mutex) {
+			
+			processMessages(msec_pos);
+
+			if (active_sensing_on) {
+				// Active Sensing
+				// if no message occurs for max 1000 ms
+				// then do AllSoundOff on all channels
+				if ((msec_pos - msec_last_activity) > 1000000) {
+					active_sensing_on = false;
+					for (SoftChannel c : synth.channels)
+						c.allSoundOff();
+				}
+
+			}
+
+			for (int i = 0; i < voicestatus.length; i++)
+				if (voicestatus[i].active)
+					voicestatus[i].processControlLogic();
+			msec_pos += msec_buffer_len;
+
+			double volume = co_master_volume[0];
+			volume_left = volume;
+			volume_right = volume;
+
+			double balance = co_master_balance[0];
+			if (balance > 0.5)
+				volume_left *= (1 - balance) * 2;
+			else
+				volume_right *= balance * 2;
+
+			chorus.processControlLogic();
+			reverb.processControlLogic();
+			agc.processControlLogic();
+			
+			if(cur_registeredMixers == null)
+				if(registeredMixers != null)
+				{
+					cur_registeredMixers = new ModelChannelMixer[registeredMixers.size()];
+					registeredMixers.toArray(cur_registeredMixers);
+				}
+
+			act_registeredMixers = cur_registeredMixers;
+			if(act_registeredMixers != null)
+				if(act_registeredMixers.length == 0)
+					act_registeredMixers = null;
+
+		}
+		
+		if(act_registeredMixers != null)
+		{
+		
+			// Reroute default left,right output
+			// to channelmixer left,right input/output
+			SoftAudioBuffer leftbak = buffers[CHANNEL_LEFT];
+			SoftAudioBuffer rightbak = buffers[CHANNEL_RIGHT];
+			buffers[CHANNEL_LEFT] = buffers[CHANNEL_CHANNELMIXER_LEFT];
+			buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_LEFT];
+			
+			int bufferlen = buffers[CHANNEL_LEFT].getSize();
+			
+			float[][] cbuffer = new float[nrofchannels][];
+			cbuffer[0] = buffers[CHANNEL_LEFT].array();
+			if (nrofchannels != 1) 
+				cbuffer[1] = buffers[CHANNEL_RIGHT].array();
+			
+			float[][] obuffer = new float[nrofchannels][];
+			obuffer[0] = leftbak.array();
+			if (nrofchannels != 1) 
+				obuffer[1] = rightbak.array();
+			
+			for (ModelChannelMixer cmixer : act_registeredMixers) {
+				for (int i = 0; i < cbuffer.length; i++) 
+					Arrays.fill(cbuffer[i], 0);	
+				boolean hasactivevoices = false;
+				for (int i = 0; i < voicestatus.length; i++)
+					if (voicestatus[i].active)
+						if(voicestatus[i].channelmixer == cmixer)
+						{
+							voicestatus[i].processAudioLogic(buffers);
+							hasactivevoices = true;
+						}
+				if(!cmixer.process(cbuffer, 0, bufferlen))
+				{
+					synchronized (control_mutex) {
+						registeredMixers.remove(cmixer);
+						cur_registeredMixers = null;
+					}					
+				}
+				
+				for (int i = 0; i < cbuffer.length; i++)
+				{
+					float[] cbuff = cbuffer[i];
+					float[] obuff = obuffer[i];
+					for (int j = 0; j < bufferlen; j++) 
+						obuff[j] += cbuff[j];					
+				}
+				
+				if(!hasactivevoices)
+				{
+					synchronized (control_mutex) {
+						if(stoppedMixers != null)
+						if(stoppedMixers.contains(cmixer))
+						{
+							stoppedMixers.remove(cmixer);
+							cmixer.stop();
+						}
+					}
+				}
+				
+			}
+		
+			buffers[CHANNEL_LEFT] = leftbak;
+			buffers[CHANNEL_RIGHT] = rightbak;
+			
+		}
+		
+		for (int i = 0; i < voicestatus.length; i++)
+			if (voicestatus[i].active)
+				if(voicestatus[i].channelmixer == null)
+					voicestatus[i].processAudioLogic(buffers); 
+				
+		// Run effects		
+		if(synth.chorus_on)		
+			chorus.processAudio();
+		
+		if(synth.reverb_on)
+			reverb.processAudio();
+
+		if (nrofchannels == 1)
+			volume_left = (volume_left + volume_right) / 2;
+
+		// Set Volume / Balance
+		if (last_volume_left != volume_left
+				|| last_volume_right != volume_right) {
+			float[] left = buffers[CHANNEL_LEFT].array();
+			float[] right = buffers[CHANNEL_RIGHT].array();
+			int bufferlen = buffers[CHANNEL_LEFT].getSize();
+
+			float amp;
+			float amp_delta;
+			amp = (float) (last_volume_left * last_volume_left);
+			amp_delta = (float) ((volume_left * volume_left - amp) / bufferlen);
+			for (int i = 0; i < bufferlen; i++) {
+				amp += amp_delta;
+				left[i] *= amp;
+			}
+			if (nrofchannels != 1) {
+				amp = (float) (last_volume_right * last_volume_right);
+				amp_delta = (float) ((volume_right * volume_right - amp) / bufferlen);
+				for (int i = 0; i < bufferlen; i++) {
+					amp += amp_delta;
+					right[i] *= volume_right;
+				}
+			}
+			last_volume_left = volume_left;
+			last_volume_right = volume_right;
+
+		} else {
+			if (volume_left != 1.0 || volume_right != 1.0) {
+				float[] left = buffers[CHANNEL_LEFT].array();
+				float[] right = buffers[CHANNEL_RIGHT].array();
+				int bufferlen = buffers[CHANNEL_LEFT].getSize();
+				float amp;
+				amp = (float) (volume_left * volume_left);
+				for (int i = 0; i < bufferlen; i++)
+					left[i] *= amp;
+				if (nrofchannels != 1) {
+					amp = (float) (volume_right * volume_right);
+					for (int i = 0; i < bufferlen; i++)
+						right[i] *= amp;
+				}
+
+			}
+		}
+
+		if(synth.agc_on)
+			agc.processAudio();
+
+	}
+	
+	public void stopMixer(ModelChannelMixer mixer)
+	{
+		if(stoppedMixers == null)
+			stoppedMixers = new HashSet<ModelChannelMixer>();
+		stoppedMixers.add(mixer);
+	}
+	
+	public void registerMixer(ModelChannelMixer mixer)
+	{
+		if(registeredMixers == null)
+			registeredMixers = new HashSet<ModelChannelMixer>();
+		registeredMixers.add(mixer);
+		cur_registeredMixers = null;
+	}
+	
+	
+	public SoftMainMixer(SoftSynthesizer synth) {
+		this.synth = synth;
+		
+		msec_pos = 0;
+
+		co_master_balance[0] = 0.5;
+		co_master_volume[0] = 1;
+		co_master_coarse_tuning[0] = 0.5;
+		co_master_fine_tuning[0] = 0.5;
+
+		msec_buffer_len = (long) (1000000.0 / synth.getControlRate());
+
+		nrofchannels = synth.getFormat().getChannels();
+
+		int buffersize = (int) (synth.getFormat().getSampleRate() / synth
+				.getControlRate());
+		;
+
+		control_mutex = synth.control_mutex;
+		buffers = new SoftAudioBuffer[16];
+		for (int i = 0; i < buffers.length; i++) {
+			buffers[i] = new SoftAudioBuffer(buffersize, synth.getFormat());
+
+		}
+		voicestatus = synth.getVoices();
+
+		reverb = new SoftReverb();
+		chorus = new SoftChorus();
+		agc = new SoftLimiter();
+
+		reverb.init(synth);
+		chorus.init(synth);
+		agc.init(synth);
+
+		reverb.setMixMode(true);
+		chorus.setMixMode(true);
+		agc.setMixMode(false);
+
+		chorus.setInput(0, buffers[CHANNEL_EFFECT2]);
+		chorus.setOutput(0, buffers[CHANNEL_LEFT]);
+		if (nrofchannels != 1)
+			chorus.setOutput(1, buffers[CHANNEL_RIGHT]);
+		chorus.setOutput(2, buffers[CHANNEL_EFFECT1]);
+
+		reverb.setInput(0, buffers[CHANNEL_EFFECT1]);
+		reverb.setOutput(0, buffers[CHANNEL_LEFT]);
+		if (nrofchannels != 1)
+			reverb.setOutput(1, buffers[CHANNEL_RIGHT]);
+
+		agc.setInput(0, buffers[CHANNEL_LEFT]);
+		if (nrofchannels != 1)
+			agc.setInput(1, buffers[CHANNEL_RIGHT]);
+		agc.setOutput(0, buffers[CHANNEL_LEFT]);
+		if (nrofchannels != 1)
+			agc.setOutput(1, buffers[CHANNEL_RIGHT]);
+
+		InputStream in = new InputStream() {
+
+			private SoftAudioBuffer[] buffers = SoftMainMixer.this.buffers;
+			private int nrofchannels = SoftMainMixer.this.synth.getFormat().getChannels();
+			private int buffersize = buffers[0].getSize();
+			private byte[] bbuffer = new byte[buffersize
+			  	* (SoftMainMixer.this.synth.getFormat().getSampleSizeInBits() / 8) * nrofchannels];
+			private int bbuffer_pos = 0;			
+			private byte[] single = new byte[1];
+
+			public void fillBuffer() {
+				processAudioBuffers();
+				for (int i = 0; i < nrofchannels; i++)
+					buffers[i].get(bbuffer, i);
+				bbuffer_pos = 0;
+			}
+
+			public int read(byte[] b, int off, int len) {
+				int bbuffer_len = bbuffer.length;
+				int offlen = off + len;
+				int orgoff = off;
+				byte[] bbuffer = this.bbuffer;
+				while (off < offlen)
+					if (available() == 0)
+						fillBuffer();
+					else {
+						int bbuffer_pos = this.bbuffer_pos;
+						while (off < offlen && bbuffer_pos < bbuffer_len)
+							b[off++] = bbuffer[bbuffer_pos++];
+						this.bbuffer_pos = bbuffer_pos;
+						if(!readfully) 
+							return off - orgoff;
+					}
+				return len;
+			}
+
+			public int read() throws IOException {
+				int ret = read(single);
+				if(ret == -1) return -1;
+				return single[0] & 0xFF;
+			}
+
+			public int available() {
+				return bbuffer.length - bbuffer_pos;
+			}
+
+			public void close() {
+				SoftMainMixer.this.synth.close();
+			}
+
+		};
+		
+		ais = new AudioInputStream(in, synth.getFormat(), AudioSystem.NOT_SPECIFIED);
+
+	}
+	
+	public AudioInputStream getInputStream() {
+		return ais;
+	}
+	
+	public void reset() {
+		
+		SoftChannel[] channels = synth.channels;
+		for (int i = 0; i < channels.length; i++) {
+			channels[i].allSoundOff();
+			channels[i].resetAllControllers(true);
+
+			if (synth.getGeneralMidiMode() == 2) {
+				if (i == 9)
+					channels[i].programChange(0, 0x78 * 128);
+				else
+					channels[i].programChange(0, 0x79 * 128);
+			} else
+				channels[i].programChange(0, 0);
+		}
+		setVolume(0x7F * 128 + 0x7F);
+		setBalance(0x40 * 128 + 0x00);
+		setCoarseTuning(0x40 * 128 + 0x00);
+		setFineTuning(0x40 * 128 + 0x00);
+		// Reset Reverb
+		globalParameterControlChange(
+				new int[] { 0x01 * 128 + 0x01 }, new long[] { 0 },
+				new long[] { 4 });
+		// Reset Chorus
+		globalParameterControlChange(
+				new int[] { 0x01 * 128 + 0x02 }, new long[] { 0 },
+				new long[] { 2 });
+	}	
+	
+
+	public void setVolume(int value) {
+		synchronized (control_mutex) {
+			co_master_volume[0] = value / 16384.0;
+		}
+	}
+
+	public void setBalance(int value) {
+		synchronized (control_mutex) {
+			co_master_balance[0] = value / 16384.0;
+		}
+	}
+
+	public void setFineTuning(int value) {
+		synchronized (control_mutex) {
+			co_master_fine_tuning[0] = value / 16384.0;
+		}
+	}
+
+	public void setCoarseTuning(int value) {
+		synchronized (control_mutex) {
+			co_master_coarse_tuning[0] = value / 16384.0;
+		}
+	}
+	
+	public int getVolume() {
+		synchronized (control_mutex) {
+			return (int)(co_master_volume[0] * 16384.0);
+		}
+	}
+
+	public int getBalance() {
+		synchronized (control_mutex) {
+			return (int)(co_master_balance[0] * 16384.0);
+		}
+	}
+
+	public int getFineTuning() {
+		synchronized (control_mutex) {
+			return (int)(co_master_fine_tuning[0] * 16384.0);
+		}
+	}
+
+	public int getCoarseTuning() {
+		synchronized (control_mutex) {
+			return (int)(co_master_coarse_tuning[0] * 16384.0);
+		}
+	}
+	
+	public void globalParameterControlChange(int[] slothpath, long[] params,
+			long[] paramsvalue) {
+		if (slothpath.length == 0)
+			return;
+
+		synchronized (control_mutex) {
+
+			// slothpath: 01xx are reserved only for GM2
+
+			if (slothpath[0] == 0x01 * 128 + 0x01) {
+				for (int i = 0; i < paramsvalue.length; i++) {
+					reverb.globalParameterControlChange(slothpath, params[i],
+							paramsvalue[i]);
+				}
+			}
+			if (slothpath[0] == 0x01 * 128 + 0x02) {
+				for (int i = 0; i < paramsvalue.length; i++) {
+					chorus.globalParameterControlChange(slothpath, params[i],
+							paramsvalue[i]);
+				}
+
+			}
+
+		}
+	}
+	
+	public void processMessage(Object object) {
+		if(object instanceof byte[])
+			processMessage((byte[])object);
+		if(object instanceof MidiMessage)
+			processMessage((MidiMessage)object);
+	}
+	
+	public void processMessage(MidiMessage message) {		
+		if(message instanceof ShortMessage)
+		{
+			ShortMessage sms = (ShortMessage)message;
+			processMessage(
+					sms.getChannel(), sms.getCommand(), 
+					sms.getData1(), sms.getData2());
+			return;
+		}
+		processMessage(message.getMessage());
+	}	
+	
+	public void processMessage(byte[] data) {
+		int status = 0;
+		if (data.length > 0)
+			status = data[0] & 0xFF;
+
+		if (status == 0xF0) {
+			processSystemExclusiveMessage(data);
+			return;
+		}		
+
+		int cmd = (status & 0xF0);
+		int ch = (status & 0x0F);
+	
+		int data1;
+		int data2;
+		if (data.length > 1)
+			data1 = data[1] & 0xFF;
+		else
+			data1 = 0;
+		if (data.length > 2)
+			data2 = data[2] & 0xFF;
+		else
+			data2 = 0;
+		
+		processMessage(ch, cmd, data1, data2);
+		
+	}
+	
+	public void processMessage(int ch, int cmd, int data1, int data2) {	
+		synchronized (synth.control_mutex) {
+			msec_last_activity = msec_pos;
+		}
+		
+		if(cmd == 0xF0)
+		{
+			int status = cmd | ch;
+			switch (status) {
+			case ShortMessage.ACTIVE_SENSING:
+				synchronized (synth.control_mutex) {
+					active_sensing_on = true;
+				}			
+				break;
+			default:
+				break;
+			}
+			return;
+		}
+		
+		SoftChannel[] channels = synth.channels;
+		if(ch >= channels.length) return;
+		SoftChannel softchannel = channels[ch];
+		
+		switch (cmd) {
+		case ShortMessage.NOTE_ON:
+			softchannel.noteOn(data1, data2);
+			break;
+		case ShortMessage.NOTE_OFF:
+			softchannel.noteOff(data1, data2);
+			break;
+		case ShortMessage.POLY_PRESSURE:
+			softchannel.setPolyPressure(data1, data2);
+			break;
+		case ShortMessage.CONTROL_CHANGE:
+			softchannel.controlChange(data1, data2);
+			break;
+		case ShortMessage.PROGRAM_CHANGE:
+			softchannel.programChange(data1);
+			break;
+		case ShortMessage.CHANNEL_PRESSURE:
+			softchannel.setChannelPressure(data1);
+			break;
+		case ShortMessage.PITCH_BEND:
+			softchannel.setPitchBend(data1 + data2 * 128);
+			break;
+		default:
+			break;
+		}
+
+	}
+
+	public long getMicrosecondPosition() {
+		return msec_pos;
+	}
+	
+	public void close()
+	{
+	}
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaMessage;
+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.Track;
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.UnsupportedAudioFileException;
+import javax.sound.sampled.AudioFileFormat.Type;
+import javax.sound.sampled.spi.AudioFileReader;
+
+/**
+ * MIDI File Audio Renderer/Reader
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class SoftMidiAudioFileReader extends AudioFileReader {
+
+	public static final Type MIDI = new Type("MIDI", "mid");
+	private static AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
+	
+	public AudioFileFormat getAudioFileFormat(Sequence seq)
+	throws UnsupportedAudioFileException, IOException {
+
+		long totallen = seq.getMicrosecondLength() / 1000000;
+		long len = (long) (format.getFrameRate() * (totallen + 4));		
+		return new AudioFileFormat(MIDI, format, (int)len);
+	}	
+	
+	public AudioInputStream getAudioInputStream(Sequence seq)
+	throws UnsupportedAudioFileException, IOException {
+			AudioSynthesizer synth = (AudioSynthesizer) new SoftSynthesizer();
+			AudioInputStream stream;
+			Receiver recv;
+			try {
+				stream = synth.openStream(format, null);
+				recv = synth.getReceiver();
+			} catch (MidiUnavailableException e) {
+				throw new IOException(e.toString());
+			}
+			float divtype = seq.getDivisionType();			
+			Track[] tracks = seq.getTracks();
+			int[] trackspos = new int[tracks.length];
+			int mpq = 500000;
+			int seqres = seq.getResolution();
+			long lasttick = 0;
+			long curtime = 0;
+			while (true) {
+				MidiEvent selevent = null;
+				int seltrack = -1;
+				for (int i = 0; i < tracks.length; i++) {
+					int trackpos = trackspos[i];
+					Track track = tracks[i];
+					if (trackpos < track.size()) {
+						MidiEvent event = track.get(trackpos);
+						if (selevent == null
+								|| event.getTick() < selevent.getTick()) {
+							selevent = event;
+							seltrack = i;
+						}
+					}
+				}
+				if (seltrack == -1)
+					break;
+				trackspos[seltrack]++;
+				long tick = selevent.getTick();
+				if(divtype == Sequence.PPQ)
+					curtime += ((tick - lasttick) * mpq) / seqres;
+				else
+					curtime = (long)((tick * 1000000.0 * divtype) / seqres);
+				lasttick = tick;
+				MidiMessage msg = selevent.getMessage();
+				if (msg instanceof MetaMessage) {
+					if(divtype == Sequence.PPQ)
+					if (((MetaMessage) msg).getType() == 0x51) {
+						byte[] data = ((MetaMessage) msg).getData();
+						mpq = ((data[0] & 0xff) << 16)
+								| ((data[1] & 0xff) << 8) | (data[2] & 0xff);
+					}
+				} else {
+					recv.send(msg, curtime);
+				}
+			}
+
+			long totallen = curtime / 1000000;
+			long len = (long) (stream.getFormat().getFrameRate() * (totallen + 4));
+			stream = new AudioInputStream(stream, stream.getFormat(), len);
+			return stream;
+	}
+	
+
+	public AudioInputStream getAudioInputStream(InputStream inputstream)
+			throws UnsupportedAudioFileException, IOException {
+
+		inputstream.mark(200);
+		Sequence seq;
+		try {
+			seq = MidiSystem.getSequence(inputstream);
+		} catch (InvalidMidiDataException e) {
+			inputstream.reset();
+			throw new UnsupportedAudioFileException();
+		} catch (IOException e) {
+			inputstream.reset();
+			throw new UnsupportedAudioFileException();
+		}
+		return getAudioInputStream(seq);
+	}
+
+	public AudioFileFormat getAudioFileFormat(URL url)
+			throws UnsupportedAudioFileException, IOException {		
+		Sequence seq;
+		try {
+			seq = MidiSystem.getSequence(url);
+		} catch (InvalidMidiDataException e) {
+			throw new UnsupportedAudioFileException();
+		} catch (IOException e) {
+			throw new UnsupportedAudioFileException();
+		}		
+		return getAudioFileFormat(seq);		
+	}
+
+	public AudioFileFormat getAudioFileFormat(File file)
+			throws UnsupportedAudioFileException, IOException {
+		Sequence seq;
+		try {
+			seq = MidiSystem.getSequence(file);
+		} catch (InvalidMidiDataException e) {
+			throw new UnsupportedAudioFileException();
+		} catch (IOException e) {
+			throw new UnsupportedAudioFileException();
+		}		
+		return getAudioFileFormat(seq);		
+	}
+
+	public AudioInputStream getAudioInputStream(URL url)
+			throws UnsupportedAudioFileException, IOException {
+		Sequence seq;
+		try {
+			seq = MidiSystem.getSequence(url);
+		} catch (InvalidMidiDataException e) {
+			throw new UnsupportedAudioFileException();
+		} catch (IOException e) {
+			throw new UnsupportedAudioFileException();
+		}
+		return getAudioInputStream(seq);
+	}
+
+	public AudioInputStream getAudioInputStream(File file)
+			throws UnsupportedAudioFileException, IOException {
+		if (!file.getName().toLowerCase().endsWith(".mid"))
+			throw new UnsupportedAudioFileException();
+		Sequence seq;
+		try {
+			seq = MidiSystem.getSequence(file);
+		} catch (InvalidMidiDataException e) {
+			throw new UnsupportedAudioFileException();
+		} catch (IOException e) {
+			throw new UnsupportedAudioFileException();
+		}
+		return getAudioInputStream(seq);	}
+
+	public AudioFileFormat getAudioFileFormat(InputStream inputstream)
+			throws UnsupportedAudioFileException, IOException {
+		
+		inputstream.mark(200);
+		Sequence seq;
+		try {
+			seq = MidiSystem.getSequence(inputstream);
+		} catch (InvalidMidiDataException e) {
+			inputstream.reset();
+			throw new UnsupportedAudioFileException();
+		} catch (IOException e) {
+			inputstream.reset();
+			throw new UnsupportedAudioFileException();
+		}		
+		return getAudioFileFormat(seq);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftPerformer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,763 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class decodes information from ModelPeformer for use in SoftVoice. It
+ * also adds default connections if they where missing in ModelPerformer.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftPerformer {
+
+	static ModelConnectionBlock[] defaultconnections = new ModelConnectionBlock[42];
+	static {
+
+		int o = 0;
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("noteon", "on", 0),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 1,
+				new ModelDestination(new ModelIdentifier("eg", "on", 0)));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("noteon", "on", 0),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 1,
+				new ModelDestination(new ModelIdentifier("eg", "on", 1)));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("eg", "active", 0),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 1,
+				new ModelDestination(new ModelIdentifier("mixer", "active", 0)));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("eg", 0),
+				ModelStandardTransform.DIRECTION_MAX2MIN,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), -960,
+				new ModelDestination(new ModelIdentifier("mixer", "gain")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("noteon", "velocity"),
+				ModelStandardTransform.DIRECTION_MAX2MIN,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_CONCAVE), -960,
+				new ModelDestination(new ModelIdentifier("mixer", "gain")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi", "pitch"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), new ModelSource(
+				new ModelIdentifier("midi_rpn", "0"), new ModelTransform() {
+					public double transform(double value) {
+						int v = (int) (value * 16384.0);
+						int msb = v >> 7;
+						int lsb = v & 127;
+						return msb * 100 + lsb;
+					}
+				}), new ModelDestination(new ModelIdentifier("osc", "pitch")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("noteon", "keynumber"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 12800,
+				new ModelDestination(new ModelIdentifier("osc", "pitch")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "7"),
+				ModelStandardTransform.DIRECTION_MAX2MIN,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_CONCAVE), -960,
+				new ModelDestination(new ModelIdentifier("mixer", "gain")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "8"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 1000,
+				new ModelDestination(new ModelIdentifier("mixer", "balance")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "10"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 1000,
+				new ModelDestination(new ModelIdentifier("mixer", "pan")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "11"),
+				ModelStandardTransform.DIRECTION_MAX2MIN,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_CONCAVE), -960,
+				new ModelDestination(new ModelIdentifier("mixer", "gain")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "91"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 1000,
+				new ModelDestination(new ModelIdentifier("mixer", "reverb")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "93"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 1000,
+				new ModelDestination(new ModelIdentifier("mixer", "chorus")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "71"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 200,
+				new ModelDestination(new ModelIdentifier("filter", "q")));
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "74"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 9600,
+				new ModelDestination(new ModelIdentifier("filter", "freq")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "72"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 6000,
+				new ModelDestination(new ModelIdentifier("eg", "release2")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "73"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 2000,
+				new ModelDestination(new ModelIdentifier("eg", "attack2")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "75"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 6000,
+				new ModelDestination(new ModelIdentifier("eg", "decay2")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "67"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_SWITCH), -50,
+				new ModelDestination(ModelDestination.DESTINATION_GAIN));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_cc", "67"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_UNIPOLAR,
+				ModelStandardTransform.TRANSFORM_SWITCH), -2400,
+				new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_rpn", "1"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 100,
+				new ModelDestination(new ModelIdentifier("osc", "pitch")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("midi_rpn", "2"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 12800,
+				new ModelDestination(new ModelIdentifier("osc", "pitch")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("master", "fine_tuning"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 100,
+				new ModelDestination(new ModelIdentifier("osc", "pitch")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
+				new ModelIdentifier("master", "coarse_tuning"),
+				ModelStandardTransform.DIRECTION_MIN2MAX,
+				ModelStandardTransform.POLARITY_BIPOLAR,
+				ModelStandardTransform.TRANSFORM_LINEAR), 12800,
+				new ModelDestination(new ModelIdentifier("osc", "pitch")));
+
+		defaultconnections[o++] = new ModelConnectionBlock(13500,
+				new ModelDestination(new ModelIdentifier("filter", "freq", 0)));
+
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "delay", 0)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "attack", 0)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "hold", 0)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "decay", 0)));
+		defaultconnections[o++] = new ModelConnectionBlock(1000,
+				new ModelDestination(new ModelIdentifier("eg", "sustain", 0)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "release", 0)));
+		defaultconnections[o++] = new ModelConnectionBlock(1200.0
+				* Math.log(0.015) / Math.log(2), new ModelDestination(
+				new ModelIdentifier("eg", "shutdown", 0))); // 15 msec default
+
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "delay", 1)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "attack", 1)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "hold", 1)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "decay", 1)));
+		defaultconnections[o++] = new ModelConnectionBlock(1000,
+				new ModelDestination(new ModelIdentifier("eg", "sustain", 1)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("eg", "release", 1)));
+
+		defaultconnections[o++] = new ModelConnectionBlock(-8.51318,
+				new ModelDestination(new ModelIdentifier("lfo", "freq", 0)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("lfo", "delay", 0)));
+		defaultconnections[o++] = new ModelConnectionBlock(-8.51318,
+				new ModelDestination(new ModelIdentifier("lfo", "freq", 1)));
+		defaultconnections[o++] = new ModelConnectionBlock(
+				Float.NEGATIVE_INFINITY, new ModelDestination(
+						new ModelIdentifier("lfo", "delay", 1)));
+
+	}
+
+	public int keyFrom = 0;
+
+	public int keyTo = 127;
+
+	public int velFrom = 0;
+
+	public int velTo = 127;
+
+	public int exclusiveClass = 0;
+
+	public boolean selfNonExclusive = false;
+
+	public boolean forcedVelocity = false;
+
+	public boolean forcedKeynumber = false;
+
+	public ModelPerformer performer;
+
+	public ModelConnectionBlock[] connections;
+
+	public ModelOscillator[] oscillators;
+
+	public Map<Integer, int[]> midi_rpn_connections = new HashMap<Integer, int[]>();
+
+	public Map<Integer, int[]> midi_nrpn_connections = new HashMap<Integer, int[]>();
+
+	public int[][] midi_ctrl_connections;
+
+	public int[][] midi_connections;
+
+	public int[] ctrl_connections;
+
+	private List<Integer> ctrl_connections_list = new ArrayList<Integer>();
+
+	private static class KeySortComparator implements Comparator<ModelSource> {
+		public int compare(ModelSource o1, ModelSource o2) {
+			return o1.getIdentifier().toString().compareTo(
+					o2.getIdentifier().toString());
+		}
+	}
+
+	private static KeySortComparator keySortComparator = new KeySortComparator();
+
+	private String extractKeys(ModelConnectionBlock conn) {
+		StringBuffer sb = new StringBuffer();
+		if (conn.getSources() != null) {
+			sb.append("[");
+			ModelSource[] srcs = conn.getSources();
+			ModelSource[] srcs2 = new ModelSource[srcs.length];
+			for (int i = 0; i < srcs.length; i++)
+				srcs2[i] = srcs[i];
+			Arrays.sort(srcs2, keySortComparator);
+			for (int i = 0; i < srcs.length; i++) {
+				sb.append(srcs[i].getIdentifier());
+				sb.append(";");
+			}
+			sb.append("]");
+		}
+		sb.append(";");
+		if (conn.getDestination() != null) {
+			sb.append(conn.getDestination().getIdentifier());
+		}
+		sb.append(";");
+		return sb.toString();
+	}
+
+	private void processSource(ModelSource src, int ix) {
+		ModelIdentifier id = src.getIdentifier();
+		String o = id.getObject();
+		if (o.equals("midi_cc"))
+			processMidiControlSource(src, ix);
+		else if (o.equals("midi_rpn"))
+			processMidiRpnSource(src, ix);
+		else if (o.equals("midi_nrpn"))
+			processMidiNrpnSource(src, ix);
+		else if (o.equals("midi"))
+			processMidiSource(src, ix);
+		else if (o.equals("noteon"))
+			processNoteOnSource(src, ix);
+		else if (o.equals("osc"))
+			return;
+		else if (o.equals("mixer"))
+			return;
+		else
+			ctrl_connections_list.add(ix);
+	}
+
+	private void processMidiControlSource(ModelSource src, int ix) {
+		String v = src.getIdentifier().getVariable();
+		if (v == null)
+			return;
+		int c = Integer.parseInt(v);
+		if (midi_ctrl_connections[c] == null)
+			midi_ctrl_connections[c] = new int[] { ix };
+		else {
+			int[] olda = midi_ctrl_connections[c];
+			int[] newa = new int[olda.length + 1];
+			for (int i = 0; i < olda.length; i++)
+				newa[i] = olda[i];
+			newa[newa.length - 1] = ix;
+			midi_ctrl_connections[c] = newa;
+		}
+	}
+
+	private void processNoteOnSource(ModelSource src, int ix) {
+		String v = src.getIdentifier().getVariable();
+		int c = -1;
+		if (v.equals("on"))
+			c = 3;
+		if (v.equals("keynumber"))
+			c = 4;
+		if (c == -1)
+			return;
+		if (midi_connections[c] == null)
+			midi_connections[c] = new int[] { ix };
+		else {
+			int[] olda = midi_connections[c];
+			int[] newa = new int[olda.length + 1];
+			for (int i = 0; i < olda.length; i++)
+				newa[i] = olda[i];
+			newa[newa.length - 1] = ix;
+			midi_connections[c] = newa;
+		}
+	}
+
+	private void processMidiSource(ModelSource src, int ix) {
+		String v = src.getIdentifier().getVariable();
+		int c = -1;
+		if (v.equals("pitch"))
+			c = 0;
+		if (v.equals("channel_pressure"))
+			c = 1;
+		if (v.equals("poly_pressure"))
+			c = 2;
+		if (c == -1)
+			return;
+		if (midi_connections[c] == null)
+			midi_connections[c] = new int[] { ix };
+		else {
+			int[] olda = midi_connections[c];
+			int[] newa = new int[olda.length + 1];
+			for (int i = 0; i < olda.length; i++)
+				newa[i] = olda[i];
+			newa[newa.length - 1] = ix;
+			midi_connections[c] = newa;
+		}
+	}
+
+	private void processMidiRpnSource(ModelSource src, int ix) {
+		String v = src.getIdentifier().getVariable();
+		if (v == null)
+			return;
+		int c = Integer.parseInt(v);
+		if (midi_rpn_connections.get(c) == null)
+			midi_rpn_connections.put(c, new int[] { ix });
+		else {
+			int[] olda = midi_rpn_connections.get(c);
+			int[] newa = new int[olda.length + 1];
+			for (int i = 0; i < olda.length; i++)
+				newa[i] = olda[i];
+			newa[newa.length - 1] = ix;
+			midi_rpn_connections.put(c, newa);
+		}
+	}
+
+	private void processMidiNrpnSource(ModelSource src, int ix) {
+		String v = src.getIdentifier().getVariable();
+		if (v == null)
+			return;
+		int c = Integer.parseInt(v);
+		if (midi_nrpn_connections.get(c) == null)
+			midi_nrpn_connections.put(c, new int[] { ix });
+		else {
+			int[] olda = midi_nrpn_connections.get(c);
+			int[] newa = new int[olda.length + 1];
+			for (int i = 0; i < olda.length; i++)
+				newa[i] = olda[i];
+			newa[newa.length - 1] = ix;
+			midi_nrpn_connections.put(c, newa);
+		}
+	}
+
+	public SoftPerformer(ModelPerformer performer) {
+		this.performer = performer;
+
+		keyFrom = performer.getKeyFrom();
+		keyTo = performer.getKeyTo();
+		velFrom = performer.getVelFrom();
+		velTo = performer.getVelTo();
+		exclusiveClass = performer.getExclusiveClass();
+		selfNonExclusive = performer.isSelfNonExclusive();
+
+		Map<String, ModelConnectionBlock> connmap = new HashMap<String, ModelConnectionBlock>();
+
+		List<ModelConnectionBlock> performer_connections = new ArrayList<ModelConnectionBlock>();
+		performer_connections.addAll(performer.getConnectionBlocks());
+
+		if (performer.isDefaultConnectionsEnabled()) {
+
+			// Add modulation depth range (RPN 5) to the modulation wheel (cc#1)
+
+			boolean isModulationWheelConectionFound = false;
+			for (int j = 0; j < performer_connections.size(); j++) {
+				ModelConnectionBlock connection = performer_connections.get(j);
+				ModelSource[] sources = connection.getSources();
+				ModelDestination dest = connection.getDestination();
+				boolean isModulationWheelConection = false;
+				if (dest != null && sources != null && sources.length > 1)
+					for (int i = 0; i < sources.length; i++) {
+						// check if connection block has the source "modulation
+						// wheel cc#1"
+						if (sources[i].getIdentifier().getObject().equals(
+								"midi_cc"))
+							if (sources[i].getIdentifier().getVariable()
+									.equals("1")) {
+								isModulationWheelConection = true;
+								isModulationWheelConectionFound = true;
+								break;
+							}
+					}
+				if (isModulationWheelConection) {
+
+					ModelConnectionBlock newconnection = new ModelConnectionBlock();
+					newconnection.setSources(connection.getSources());
+					newconnection.setDestination(connection.getDestination());
+					newconnection.addSource(new ModelSource(
+							new ModelIdentifier("midi_rpn", "5")));
+					newconnection.setScale(connection.getScale() * 256.0);
+					performer_connections.set(j, newconnection);
+				}
+			}
+
+			if (!isModulationWheelConectionFound) {
+				ModelConnectionBlock conn = new ModelConnectionBlock(
+						new ModelSource(ModelSource.SOURCE_LFO1,
+								ModelStandardTransform.DIRECTION_MIN2MAX,
+								ModelStandardTransform.POLARITY_BIPOLAR,
+								ModelStandardTransform.TRANSFORM_LINEAR),
+						new ModelSource(new ModelIdentifier("midi_cc", "1", 0),
+								ModelStandardTransform.DIRECTION_MIN2MAX,
+								ModelStandardTransform.POLARITY_UNIPOLAR,
+								ModelStandardTransform.TRANSFORM_LINEAR),
+						50,
+						new ModelDestination(ModelDestination.DESTINATION_PITCH));				
+				conn.addSource(new ModelSource(new ModelIdentifier("midi_rpn",
+						"5")));
+				conn.setScale(conn.getScale() * 256.0); 
+				performer_connections.add(conn);
+
+			}
+
+			// Let Aftertouch to behave just like modulation wheel (cc#1)
+			boolean channel_pressure_set = false;
+			boolean poly_pressure = false;
+			ModelConnectionBlock mod_cc_1_connection = null;
+			int mod_cc_1_connection_src_ix = 0;
+
+			for (ModelConnectionBlock connection : performer_connections) {
+				ModelSource[] sources = connection.getSources();
+				ModelDestination dest = connection.getDestination();
+				// if(dest != null && sources != null)
+				if (dest != null && sources != null)
+					for (int i = 0; i < sources.length; i++) {
+						ModelIdentifier srcid = sources[i].getIdentifier();
+						// check if connection block has the source "modulation
+						// wheel cc#1"
+						if (srcid.getObject().equals("midi_cc"))
+							if (srcid.getVariable().equals("1")) {
+								mod_cc_1_connection = connection;
+								mod_cc_1_connection_src_ix = i;
+							}
+						// check if channel or poly pressure are already
+						// connected
+						if (srcid.getObject().equals("midi")) {
+							if (srcid.getVariable().equals("channel_pressure"))
+								channel_pressure_set = true;
+							if (srcid.getVariable().equals("poly_pressure"))
+								poly_pressure = true;
+						}
+					}
+
+			}
+
+			if (mod_cc_1_connection != null) {
+				if (!channel_pressure_set) {
+					ModelConnectionBlock mc = new ModelConnectionBlock();
+					mc.setDestination(mod_cc_1_connection.getDestination());
+					mc.setScale(mod_cc_1_connection.getScale());
+					ModelSource[] src_list = mod_cc_1_connection.getSources();
+					ModelSource[] src_list_new = new ModelSource[src_list.length];
+					for (int i = 0; i < src_list_new.length; i++)
+						src_list_new[i] = src_list[i];
+					src_list_new[mod_cc_1_connection_src_ix] = new ModelSource(
+							new ModelIdentifier("midi", "channel_pressure"));
+					mc.setSources(src_list_new);
+					connmap.put(extractKeys(mc), mc);
+				}
+				if (!poly_pressure) {
+					ModelConnectionBlock mc = new ModelConnectionBlock();
+					mc.setDestination(mod_cc_1_connection.getDestination());
+					mc.setScale(mod_cc_1_connection.getScale());
+					ModelSource[] src_list = mod_cc_1_connection.getSources();
+					ModelSource[] src_list_new = new ModelSource[src_list.length];
+					for (int i = 0; i < src_list_new.length; i++)
+						src_list_new[i] = src_list[i];
+					src_list_new[mod_cc_1_connection_src_ix] = new ModelSource(
+							new ModelIdentifier("midi", "poly_pressure"));
+					mc.setSources(src_list_new);
+					connmap.put(extractKeys(mc), mc);
+				}
+			}
+
+			// Enable Vibration Sound Controllers : 76, 77, 78
+			ModelConnectionBlock found_vib_connection = null;
+			for (ModelConnectionBlock connection : performer_connections) {
+				ModelSource[] sources = connection.getSources();
+				if (sources.length != 0
+						&& sources[0].getIdentifier().getObject().equals("lfo"))
+					if (connection.getDestination().getIdentifier().equals(
+							ModelDestination.DESTINATION_PITCH)) {
+						if (found_vib_connection == null)
+							found_vib_connection = connection;
+						else {
+							if (found_vib_connection.getSources().length > sources.length)
+								found_vib_connection = connection;
+							else if (found_vib_connection.getSources()[0]
+									.getIdentifier().getInstance() < 1)
+								if (found_vib_connection.getSources()[0]
+										.getIdentifier().getInstance() > sources[0]
+										.getIdentifier().getInstance())
+									found_vib_connection = connection;
+						}
+
+					}
+			}
+
+			int instance = 1;
+
+			if (found_vib_connection != null)
+				instance = found_vib_connection.getSources()[0].getIdentifier()
+						.getInstance();
+			ModelConnectionBlock connection;
+
+			connection = new ModelConnectionBlock(new ModelSource(
+					new ModelIdentifier("midi_cc", "78"),
+					ModelStandardTransform.DIRECTION_MIN2MAX,
+					ModelStandardTransform.POLARITY_BIPOLAR,
+					ModelStandardTransform.TRANSFORM_LINEAR), 2000,
+					new ModelDestination(new ModelIdentifier("lfo", "delay2",
+							instance)));
+			connmap.put(extractKeys(connection), connection);
+
+			final double scale = found_vib_connection == null ? 0
+					: found_vib_connection.getScale();
+			connection = new ModelConnectionBlock(new ModelSource(
+					new ModelIdentifier("lfo", instance)), new ModelSource(
+					new ModelIdentifier("midi_cc", "77"), new ModelTransform() {
+						double s = scale;
+
+						public double transform(double value) {
+							value = value * 2 - 1;
+							value *= 600;
+							if (s == 0) {
+								return value;
+							} else if (s > 0) {
+								if (value < -s)
+									value = -s;
+								return value;
+							} else {
+								if (value < s)
+									value = -s;
+								return -value;
+							}
+						}
+					}),
+					new ModelDestination(ModelDestination.DESTINATION_PITCH));
+			connmap.put(extractKeys(connection), connection);
+
+			connection = new ModelConnectionBlock(new ModelSource(
+					new ModelIdentifier("midi_cc", "76"),
+					ModelStandardTransform.DIRECTION_MIN2MAX,
+					ModelStandardTransform.POLARITY_BIPOLAR,
+					ModelStandardTransform.TRANSFORM_LINEAR), 2400,
+					new ModelDestination(new ModelIdentifier("lfo", "freq",
+							instance)));
+			connmap.put(extractKeys(connection), connection);
+
+		}
+
+		// Add default connection blocks
+		if (performer.isDefaultConnectionsEnabled())
+			for (ModelConnectionBlock connection : defaultconnections)
+				connmap.put(extractKeys(connection), connection);
+		// Add connection blocks from modelperformer
+		for (ModelConnectionBlock connection : performer_connections)
+			connmap.put(extractKeys(connection), connection);
+		// seperate connection blocks : Init time, Midi Time, Midi/Control Time,
+		// Control Time
+		List<ModelConnectionBlock> connections = new ArrayList<ModelConnectionBlock>();
+
+		midi_ctrl_connections = new int[128][];
+		for (int i = 0; i < midi_ctrl_connections.length; i++) {
+			midi_ctrl_connections[i] = null;
+		}
+		midi_connections = new int[5][];
+		for (int i = 0; i < midi_connections.length; i++) {
+			midi_connections[i] = null;
+		}
+
+		int ix = 0;
+		boolean mustBeOnTop = false;
+
+		for (ModelConnectionBlock connection : connmap.values()) {
+			if (connection.getDestination() != null) {
+				ModelDestination dest = connection.getDestination();
+				ModelIdentifier id = dest.getIdentifier();
+				if (id.getObject().equals("noteon")) {
+					mustBeOnTop = true;
+					if (id.getVariable().equals("keynumber"))
+						forcedKeynumber = true;
+					if (id.getVariable().equals("velocity"))
+						forcedVelocity = true;
+				}
+			}
+			if (mustBeOnTop) {
+				connections.add(0, connection);
+				mustBeOnTop = false;
+			} else
+				connections.add(connection);
+		}
+
+		for (ModelConnectionBlock connection : connections) {
+			if (connection.getSources() != null) {
+				ModelSource[] srcs = connection.getSources();
+				for (int i = 0; i < srcs.length; i++) {
+					processSource(srcs[i], ix);
+				}
+			}
+			ix++;
+		}
+
+		this.connections = new ModelConnectionBlock[connections.size()];
+		connections.toArray(this.connections);
+
+		this.ctrl_connections = new int[ctrl_connections_list.size()];
+
+		for (int i = 0; i < this.ctrl_connections.length; i++)
+			this.ctrl_connections[i] = ctrl_connections_list.get(i);
+
+		oscillators = new ModelOscillator[performer.getOscillators().size()];
+		performer.getOscillators().toArray(oscillators);
+		
+		for(ModelConnectionBlock conn : connections)
+		{
+			if(conn.getDestination() != null)
+			{
+				if(isUnnecessaryTransform(conn.getDestination().getTransform()))					
+				{
+					conn.getDestination().setTransform(null);
+				}
+			}	
+			if(conn.getSources() != null)
+			{
+				for(ModelSource src : conn.getSources())
+				{
+					if(isUnnecessaryTransform(src.getTransform()))					
+					{
+						src.setTransform(null);
+					}
+				}
+			}
+		}
+
+	}
+	
+	private static boolean isUnnecessaryTransform(ModelTransform transform)
+	{
+		if(transform == null) return false;
+		if(!(transform instanceof ModelStandardTransform)) return false;
+		ModelStandardTransform stransform = (ModelStandardTransform)transform;
+		if(stransform.getDirection() != ModelStandardTransform.DIRECTION_MIN2MAX) return false; 
+		if(stransform.getPolarity() != ModelStandardTransform.POLARITY_UNIPOLAR) return false;
+		if(stransform.getTransform() != ModelStandardTransform.TRANSFORM_LINEAR) return false;
+		return false;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftPointResampler.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * A resampler that uses 0-order (nearest-neighbor) interpolation.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftPointResampler extends SoftAbstractResampler {
+
+	public int getPadding() {
+		return 100;
+	}
+
+	public void interpolate(float[] in, float[] in_offset, float in_end,
+			float[] startpitch, float pitchstep, float[] out, int[] out_offset,
+			int out_end) {
+		float pitch = startpitch[0];
+		float ix = in_offset[0];
+		int ox = out_offset[0];
+		float ix_end = in_end;
+		float ox_end = out_end;
+		if (pitchstep == 0) {
+			while (ix < ix_end && ox < ox_end) {
+				out[ox++] = in[(int) ix];
+				ix += pitch;
+			}
+		} else {
+			while (ix < ix_end && ox < ox_end) {
+				out[ox++] = in[(int) ix];
+				ix += pitch;
+				pitch += pitchstep;
+			}
+		}
+		in_offset[0] = ix;
+		out_offset[0] = ox;
+		startpitch[0] = pitch;
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftProcess.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * Control signal processor interface
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public interface SoftProcess extends SoftControl {
+	public void init(SoftSynthesizer synth);
+
+	public double[] get(int instance, String name);
+
+	public void processControlLogic();
+
+	public void reset();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftProvider.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiDevice.Info;
+import javax.sound.midi.spi.MidiDeviceProvider;
+
+/**
+ * 
+ * Software synthesizer provider class.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftProvider extends MidiDeviceProvider {
+
+	protected static Info softinfo = SoftSynthesizer.info;
+
+	private static Info[] softinfos = { softinfo };
+
+	public MidiDevice.Info[] getDeviceInfo() {
+		return softinfos;
+	}
+
+	public MidiDevice getDevice(MidiDevice.Info info) {
+		if (info == softinfo) {
+			return new SoftSynthesizer();
+		}
+		return null;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReceiver.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.util.TreeMap;
+
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.ShortMessage;
+
+/**
+ * 
+ * Software synthesizer MIDI receiver class.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftReceiver implements Receiver {
+
+	protected boolean open = true;
+	
+	private Object control_mutex;
+	
+	private SoftSynthesizer synth;
+		
+	protected TreeMap<Long, Object> midimessages ;
+
+	protected SoftMainMixer mainmixer;
+
+	public SoftReceiver(SoftSynthesizer synth) {
+		this.control_mutex = synth.control_mutex;
+		this.synth = synth;		
+		this.mainmixer = synth.getMainMixer();
+		if(mainmixer != null)
+			this.midimessages = mainmixer.midimessages;
+	}
+	
+	public void send(MidiMessage message, long timeStamp) {
+
+		synchronized (control_mutex) {
+			if(!open)
+				throw new IllegalStateException("Receiver is not open");
+		}
+		
+		if (timeStamp != -1) {
+			synchronized (control_mutex) {
+
+				while (midimessages.get(timeStamp) != null)
+					timeStamp++;
+				if(message instanceof ShortMessage
+					&& (((ShortMessage)message).getChannel() > 0xF))
+					midimessages.put(timeStamp, message.clone());
+				else
+					midimessages.put(timeStamp, message.getMessage());
+
+			}
+		} 
+		else
+		{
+				mainmixer.processMessage(message);
+		}
+	}	
+	
+	public void close() {		
+		synchronized (control_mutex) {
+			open = false;		
+		}
+		synth.removeReceiver(this);
+	}	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftResampler.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * 
+ * Basic resampler interface.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public interface SoftResampler {
+
+	public SoftResamplerStreamer openStreamer();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftResamplerStreamer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+
+/**
+ * 
+ * Resampler stream interface.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public interface SoftResamplerStreamer extends ModelOscillatorStream {
+	public void open(ModelWavetable osc, float outputsamplerate)
+			throws IOException;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,500 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.util.Arrays;
+
+/**
+ * 
+ * Reverb effect based on allpass/comb filters. First audio is send to 8
+ * parelled comb filters and then mixed together and then finally send thru 3
+ * different allpass filters.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class SoftReverb implements SoftAudioProcessor {
+
+	private class Delay {
+		private float[] delaybuffer;
+
+		private int rovepos = 0;
+
+		public Delay() {
+			delaybuffer = null;
+		}
+
+		public void setDelay(int delay) {
+			if (delay == 0)
+				delaybuffer = null;
+			else
+				delaybuffer = new float[delay];
+			rovepos = 0;
+		}
+
+		public void processReplace(float[] in, float[] out) {
+			float[] delaybuffer = this.delaybuffer;
+			if (delaybuffer == null)
+				return;
+			int len = in.length;
+			int rnlen = delaybuffer.length;
+			int rovepos = this.rovepos;
+
+			for (int i = 0; i < len; i++) {
+				float x = in[i];
+				out[i] = delaybuffer[rovepos];
+				delaybuffer[rovepos] = x;
+				rovepos = rovepos + 1;
+				if(rovepos == rnlen) rovepos = 0;  
+				//rovepos = (rovepos + 1) % rnlen;
+			}
+			this.rovepos = rovepos;
+		}
+
+	}
+
+	private class AllPass {
+
+		private float[] delaybuffer;
+
+		private int delaybuffersize;
+
+		private int rovepos = 0;
+
+		private float feedback;
+
+		public AllPass(int size) {
+			delaybuffer = new float[size];
+			delaybuffersize = size;
+		}
+
+		public void setFeedBack(float feedback) {
+			this.feedback = feedback;
+		}
+		
+		int ucount = 0;
+
+		public void processReplace(float in[], float out[]) {
+			int len = in.length;
+			for (int i = 0; i < len; i++) {
+
+				float delayout = delaybuffer[rovepos];
+
+				// undenormalise(delayout)
+				/*
+				if (((delayout > 0.0) && (delayout < 1.0E-10))
+						|| ((delayout < 0.0) && (delayout > -1.0E-10)))
+					delayout = 0;*/
+
+				float input = in[i];
+				out[i] = -input + delayout;
+				delaybuffer[rovepos] = input + delayout * feedback;
+				if (++rovepos == delaybuffersize)
+					rovepos = 0;
+			}
+			
+			ucount++;
+			if(ucount == 10)
+			{
+				ucount = 0;
+				for (int i = 0; i < delaybuffer.length; i++) {
+					double v = delaybuffer[i];
+					if (((v > 0.0) && (v < 1.0E-10))
+							|| ((v < 0.0) && (v > -1.0E-10)))
+						delaybuffer[i] = 0;					
+				}
+			}
+			
+		}
+
+	}
+
+	private class Comb {
+
+		private float[] delaybuffer;
+
+		private int delaybuffersize;
+
+		private int rovepos = 0;
+
+		private float feedback;
+
+		private float filtertemp = 0;
+
+		private float filtercoeff1 = 0;
+
+		private float filtercoeff2 = 1;
+
+		public Comb(int size) {
+			delaybuffer = new float[size];
+			delaybuffersize = size;
+		}
+
+		public void setFeedBack(float feedback) {
+			this.feedback = feedback;
+		}
+
+		int ucount = 0; 
+		public void processMix(float in[], float out[]) {
+			int len = in.length;
+			
+			float filtercoeff2 = this.filtercoeff2*feedback;
+			
+			for (int i = 0; i < len; i++) {
+				float delayout = delaybuffer[rovepos];
+
+				// One Pole Lowpass Filter
+				filtertemp = (delayout * filtercoeff2)
+						+ (filtertemp * filtercoeff1);
+
+				// undenormalise(filtertemp)
+				/*
+				if (((filtertemp > 0.0) && (filtertemp < 1.0E-10))
+						|| ((filtertemp < 0.0) && (filtertemp > -1.0E-10)))
+					filtertemp = 0;
+				*/
+				out[i] += delayout;
+				delaybuffer[rovepos] = in[i] + (filtertemp);// * feedback);
+				
+				if (++rovepos == delaybuffersize)
+					rovepos = 0;
+
+			}
+			ucount++;
+			if(ucount == 10)
+			{
+				ucount = 0;
+				if (((filtertemp > 0.0) && (filtertemp < 1.0E-10))
+						|| ((filtertemp < 0.0) && (filtertemp > -1.0E-10)))
+					filtertemp = 0;				
+				for (int i = 0; i < delaybuffer.length; i++) {
+					double v = delaybuffer[i];
+					if (((v > 0.0) && (v < 1.0E-10))
+							|| ((v < 0.0) && (v > -1.0E-10)))
+						delaybuffer[i] = 0;					
+				}
+			}
+			
+
+		}
+
+		public void setDamp(float val) {
+			filtercoeff1 = val;
+			filtercoeff2 = 1 - filtercoeff1;
+		}
+	}
+
+	private float roomsize;
+
+	private float damp;
+
+	private float gain = 1;
+
+	private Delay delay;
+
+	private Comb[] combL;
+
+	private Comb[] combR;
+
+	private AllPass[] allpassL;
+
+	private AllPass[] allpassR;
+
+	private float[] input;
+
+	private float[] outR;
+
+	private float[] outL;
+
+	private boolean mix = true;
+
+	private SoftAudioBuffer inputA;
+
+	private SoftAudioBuffer left;
+
+	private SoftAudioBuffer right;
+
+	private SoftSynthesizer synth;
+
+	private boolean dirty = true;
+
+	private float dirty_roomsize;
+
+	private float dirty_damp;
+
+	private float dirty_predelay;
+
+	private float dirty_gain;
+	
+	public void init(SoftSynthesizer synth) {
+		this.synth = synth;
+		double samplerate = synth.getFormat().getSampleRate();
+
+		double freqscale = ((double) samplerate) / 44100.0;
+		// freqscale = 1.0/ freqscale;
+
+		int stereospread = 23;
+
+		delay = new Delay();
+
+		combL = new Comb[8];
+		combR = new Comb[8];
+		combL[0] = new Comb((int) (freqscale * (1116)));
+		combR[0] = new Comb((int) (freqscale * (1116 + stereospread)));
+		combL[1] = new Comb((int) (freqscale * (1188)));
+		combR[1] = new Comb((int) (freqscale * (1188 + stereospread)));
+		combL[2] = new Comb((int) (freqscale * (1277)));
+		combR[2] = new Comb((int) (freqscale * (1277 + stereospread)));
+		combL[3] = new Comb((int) (freqscale * (1356)));
+		combR[3] = new Comb((int) (freqscale * (1356 + stereospread)));
+		combL[4] = new Comb((int) (freqscale * (1422)));
+		combR[4] = new Comb((int) (freqscale * (1422 + stereospread)));
+		combL[5] = new Comb((int) (freqscale * (1491)));
+		combR[5] = new Comb((int) (freqscale * (1491 + stereospread)));
+		combL[6] = new Comb((int) (freqscale * (1557)));
+		combR[6] = new Comb((int) (freqscale * (1557 + stereospread)));
+		combL[7] = new Comb((int) (freqscale * (1617)));
+		combR[7] = new Comb((int) (freqscale * (1617 + stereospread)));
+
+		allpassL = new AllPass[4];
+		allpassR = new AllPass[4];
+		allpassL[0] = new AllPass((int) (freqscale * (556)));
+		allpassR[0] = new AllPass((int) (freqscale * (556 + stereospread)));
+		allpassL[1] = new AllPass((int) (freqscale * (441)));
+		allpassR[1] = new AllPass((int) (freqscale * (441 + stereospread)));
+		allpassL[2] = new AllPass((int) (freqscale * (341)));
+		allpassR[2] = new AllPass((int) (freqscale * (341 + stereospread)));
+		allpassL[3] = new AllPass((int) (freqscale * (225)));
+		allpassR[3] = new AllPass((int) (freqscale * (225 + stereospread)));
+
+		for (int i = 0; i < allpassL.length; i++) {
+			allpassL[i].setFeedBack(0.5f);
+			allpassR[i].setFeedBack(0.5f);
+		}
+
+		/* Init other settings */
+		globalParameterControlChange(new int[] { 0x01 * 128 + 0x01 }, 0, 4);
+
+	}
+
+	public void setInput(int pin, SoftAudioBuffer input) {
+		if (pin == 0)
+			inputA = input;
+	}
+
+	public void setOutput(int pin, SoftAudioBuffer output) {
+		if (pin == 0)
+			left = output;
+		if (pin == 1)
+			right = output;
+	}
+
+	public void setMixMode(boolean mix) {
+		this.mix = mix;
+	}
+
+	private double silentcounter = 1000;
+	
+	public void processAudio() {
+		if (this.inputA.isSilent()) {
+			silentcounter += 1 / synth.getControlRate();
+
+			if (silentcounter > 60) {
+				if (!mix) {
+					left.clear();
+					right.clear();
+				}
+				return;
+			}
+		} else
+			silentcounter = 0;
+		
+		float[] inputA = this.inputA.array();
+		float[] left = this.left.array();
+		float[] right = this.right == null ? null : this.right.array();
+
+		int numsamples = inputA.length;
+		if (input == null || input.length < numsamples)
+			input = new float[numsamples];
+
+		float again = gain * 0.018f / 2;
+
+		for (int i = 0; i < numsamples; i++) 
+			input[i] = inputA[i] * again;
+		
+		delay.processReplace(input, input);
+		
+
+		
+		if (right != null)
+		{			
+			if (outR == null || outR.length < numsamples)
+				outR = new float[numsamples];
+			Arrays.fill(outR, 0);			
+			for (int i = 0; i < combR.length; i++) 
+				combR[i].processMix(input, outR);
+			for (int i = 0; i < allpassL.length; i++) 
+				allpassR[i].processReplace(outR, outR);
+			
+			if (mix) 
+				for (int i = 0; i < numsamples; i++) 
+					right[i] += outR[i];										
+			else
+				for (int i = 0; i < numsamples; i++) 
+					right[i] = outR[i];							
+		}
+		
+
+		if (outL == null || outL.length < numsamples)
+			outL = new float[numsamples];
+		Arrays.fill(outL, 0);
+		for (int i = 0; i < combL.length; i++)
+			combL[i].processMix(input, outL);
+		for (int i = 0; i < allpassL.length; i++) 
+			allpassL[i].processReplace(outL, outL);
+
+		if (mix) 
+			for (int i = 0; i < numsamples; i++) 
+				left[i] += outL[i];			
+		else 
+			for (int i = 0; i < numsamples; i++) 
+				left[i] = outL[i];
+
+		
+	}
+
+	public void globalParameterControlChange(int[] slothpath, long param,
+			long value) {
+		if (slothpath.length == 1)
+			if (slothpath[0] == 0x01 * 128 + 0x01) {
+
+				if (param == 0) {
+					if (value == 0) // Small Room A small size room with a
+									// length of 5m or so.
+					{
+						dirty_roomsize = (1.1f);
+						dirty_damp = (5000);
+						dirty_predelay = (0);
+						dirty_gain = (4);
+						dirty = true;
+					}
+					if (value == 1) // Medium Room A medium size room with a
+									// length of 10m or so.
+					{
+						dirty_roomsize = (1.3f);
+						dirty_damp = (5000);
+						dirty_predelay = (0);
+						dirty_gain = (3);
+						dirty = true;
+					}
+					if (value == 2) // Large Room A large size room suitable for
+									// live performances.
+					{
+						dirty_roomsize = (1.5f);
+						dirty_damp = (5000);
+						dirty_predelay = (0);
+						dirty_gain = (2);
+						dirty = true;
+					}
+					if (value == 3) // Medium Hall A medium size concert hall.
+					{
+						dirty_roomsize = (1.8f);
+						dirty_damp = (24000);
+						dirty_predelay = (0.02f);
+						dirty_gain = (1.5f);
+						dirty = true;
+					}
+					if (value == 4) // Large Hall A large size concert hall
+									// suitable for a full orchestra.
+					{
+						dirty_roomsize = (1.8f);
+						dirty_damp = (24000);
+						dirty_predelay = (0.03f);
+						dirty_gain = (1.5f);
+						dirty = true;
+					}
+					if (value == 8) // Plate A plate reverb simulation.
+					{
+						dirty_roomsize = (1.3f);
+						dirty_damp = (2500);
+						dirty_predelay = (0);
+						dirty_gain = (6);
+						dirty = true;
+					}
+				} else if (param == 1) {
+					dirty_roomsize = ((float) (Math.exp((value - 40) * 0.025)));
+					dirty = true;
+				}
+
+			}
+	}
+
+	public void processControlLogic() {
+		if (dirty) {
+			dirty = false;
+			setRoomSize(dirty_roomsize);
+			setDamp(dirty_damp);
+			setPreDelay(dirty_predelay);
+			setGain(dirty_gain);
+		}
+	}
+
+	public void setRoomSize(float value) {
+		roomsize = 1 - (0.17f / value);
+
+		for (int i = 0; i < 8; i++) {
+			combL[i].feedback = roomsize;
+			combR[i].feedback = roomsize;
+		}
+	}
+
+	public void setPreDelay(float value) {
+		delay.setDelay((int) (value * synth.getFormat().getSampleRate()));
+	}
+
+	public void setGain(float gain) {
+		this.gain = gain;
+	}
+
+	public void setDamp(float value) {
+		double x = (value / synth.getFormat().getSampleRate()) * (2 * Math.PI);
+		double cx = 2 - Math.cos(x);
+		damp = (float) (cx - Math.sqrt(cx * cx - 1));
+		if (damp > 1)
+			damp = 1;
+		if (damp < 0)
+			damp = 0;
+
+		// damp = value * 0.4f;
+		for (int i = 0; i < 8; i++) {
+			combL[i].setDamp(damp);
+			combR[i].setDamp(damp);
+		}
+
+	}
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftShortMessage.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.ShortMessage;
+
+/**
+ * 
+ * A short message class that support for than 16 midi channels.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftShortMessage extends ShortMessage {
+
+	int channel = 0;
+	
+	public int getChannel() {
+		return channel;
+	}
+
+	public void setMessage(int command, int channel, int data1, int data2) throws InvalidMidiDataException {
+		this.channel = channel;
+		super.setMessage(command, channel & 0xF, data1, data2);
+	}
+
+	public Object clone() {
+		SoftShortMessage clone = new SoftShortMessage();
+		try {
+			clone.setMessage(getCommand(), getChannel(), getData1(), getData2());
+		} catch (InvalidMidiDataException e) {
+			throw new IllegalArgumentException(e.getMessage());
+		}
+		return clone;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSincResampler.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+/**
+ * Hann windowed sinc interpolation resampler with anti-alias filtering.
+ * 
+ * Using 30 points for the interpolation.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftSincResampler extends SoftAbstractResampler {
+
+	double[] din;
+
+	float[][][] sinc_table;
+
+	int sinc_scale_size = 100;
+
+	int sinc_table_fsize = 800;
+
+	int sinc_table_size = 30;
+
+	int sinc_table_center = sinc_table_size / 2;
+
+	public SoftSincResampler() {
+		super();
+		sinc_table = new float[sinc_scale_size][sinc_table_fsize][];
+		for (int s = 0; s < sinc_scale_size; s++) {
+			float scale = (float) (1.0 / (1.0 + Math.pow(s, 1.1) / 10.0));
+			for (int i = 0; i < sinc_table_fsize; i++)
+				sinc_table[s][i] = sincTable(sinc_table_size, -i
+						/ ((float) sinc_table_fsize), scale);
+		}
+	}
+
+	// Normalized sinc function
+	public static double sinc(double x) {
+		return (x == 0.0) ? 1.0 : Math.sin(Math.PI * x) / (Math.PI * x);
+	}
+
+	// Generate hann window suitable for windowing sinc
+	public static float[] wHanning(int size, float offset) {
+		float[] window_table = new float[size];
+		for (int k = 0; k < size; k++)
+			window_table[k] = (float) (-0.5
+					* Math.cos(2.0 * Math.PI * (double) (k + offset)
+							/ (double) size) + 0.5);
+		return window_table;
+	}
+
+	// Generate sinc table
+	public static float[] sincTable(int size, float offset, float scale) {
+		int center = size / 2;
+		float[] w = wHanning(size, offset);
+		for (int k = 0; k < size; k++)
+			w[k] *= sinc((-center + k + offset) * scale) * scale;
+		return w;
+	}
+
+	public int getPadding() // must be at least half of sinc_table_size
+	{
+		return sinc_table_size / 2 + 2;
+	}
+
+	public void interpolate(float[] in, float[] in_offset, float in_end,
+			float[] startpitch, float pitchstep, float[] out, int[] out_offset,
+			int out_end) {
+		float pitch = startpitch[0];
+		float ix = in_offset[0];
+		int ox = out_offset[0];
+		float ix_end = in_end;
+		int ox_end = out_end;
+		int max_p = sinc_scale_size - 1;
+		if (pitchstep == 0) {
+
+			int p = (int) ((pitch - 1) * 10.0f);
+			if (p < 0)
+				p = 0;
+			else if (p > max_p)
+				p = max_p;
+			float[][] sinc_table_f = this.sinc_table[p];
+			while (ix < ix_end && ox < ox_end) {
+				int iix = (int) ix;
+				float[] sinc_table = sinc_table_f[(int) ((ix - iix) * sinc_table_fsize)];
+				int xx = iix - sinc_table_center;
+				float y = 0;
+				for (int i = 0; i < sinc_table_size; i++, xx++)
+					y += in[xx] * sinc_table[i];
+				out[ox++] = y;
+				ix += pitch;
+			}
+		} else {
+			while (ix < ix_end && ox < ox_end) {
+				int iix = (int) ix;
+				int p = (int) ((pitch - 1) * 10.0f);
+				if (p < 0)
+					p = 0;
+				else if (p > max_p)
+					p = max_p;
+				float[][] sinc_table_f = this.sinc_table[p];
+
+				float[] sinc_table = sinc_table_f[(int) ((ix - iix) * sinc_table_fsize)];
+				int xx = iix - sinc_table_center;
+				float y = 0;
+				for (int i = 0; i < sinc_table_size; i++, xx++)
+					y += in[xx] * sinc_table[i];
+				out[ox++] = y;
+
+				ix += pitch;
+				pitch += pitchstep;
+			}
+		}
+		in_offset[0] = ix;
+		out_offset[0] = ox;
+		startpitch[0] = pitch;
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,1006 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.Transmitter;
+import javax.sound.midi.VoiceStatus;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * 
+ * The software synthesizer class.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftSynthesizer implements AudioSynthesizer, ReferenceCountingDevice {
+	
+	private static class Info extends MidiDevice.Info {
+		public Info() {
+			super(INFO_NAME, INFO_VENDOR, INFO_DESCRIPTION, INFO_VERSION);
+		}
+	}
+
+	protected static final String INFO_NAME = "Gervill";
+
+	protected static final String INFO_VENDOR = "OpenJDK Proposal";
+
+	protected static final String INFO_DESCRIPTION = "Software MIDI Synthesizer";
+
+	protected static final String INFO_VERSION = "0.9";
+	
+	protected static MidiDevice.Info info = new Info();
+	
+	private static Soundbank defaultSoundBank = null;
+	
+	protected Object control_mutex = this;
+	
+	protected int voiceIDCounter = 0;	
+
+	protected int voice_allocation_mode = 0; // 0 (default) 
+	                                         // 1 (DLS Voice Allocation)
+	
+	protected boolean reverb_on = true;
+	
+	protected boolean chorus_on = true;
+	
+	protected boolean agc_on = true;
+
+	protected SoftChannel[] channels;
+	
+	protected SoftChannelProxy[] external_channels = null;
+
+	private boolean largemode = false;
+	
+	private int gmmode = 0; // 0:GM Mode off (default)
+							  // 1:GM Level 1, 2:GM Level 2
+
+	private int deviceid = 0;
+
+	private AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
+
+	private SourceDataLine sourceDataLine = null;
+	
+	private SoftAudioPusher pusher = null;
+	
+	private AudioInputStream pusher_stream = null;
+
+	private float controlrate = 147f;
+
+	private boolean open = false;
+	
+	private boolean implicitOpen = false;
+
+	private SoftResampler resampler = new SoftLinearResampler();
+	
+	private int number_of_midi_channels = 16;
+
+	private int maxpoly = 64;
+
+	private long latency = 200000; // 200 msec
+	
+	private boolean jitter_correction = false;
+	
+	private SoftMainMixer mainmixer;
+
+	private SoftVoice[] voices;
+
+	private Map<String, SoftTuning> tunings = new HashMap<String, SoftTuning>();
+
+	private Map<String, SoftInstrument> inslist = new HashMap<String, SoftInstrument>();
+
+	private Map<String, ModelInstrument> availlist = new HashMap<String, ModelInstrument>();
+
+	private Map<String, ModelInstrument> loadedlist = new HashMap<String, ModelInstrument>();
+
+	private ArrayList<Receiver> recvslist = new ArrayList<Receiver>();
+	
+	private void getBuffers(ModelInstrument instrument, List<ModelByteBuffer>buffers)
+	{
+		for(ModelPerformer performer : instrument.getPerformers())
+		{
+			if(performer.getOscillators() != null)
+			for(ModelOscillator osc : performer.getOscillators())
+			if(osc instanceof ModelByteBufferWavetable)
+			{
+				ModelByteBufferWavetable w = (ModelByteBufferWavetable)osc;
+				ModelByteBuffer buff = w.getBuffer();
+				if(buff != null) buffers.add(buff);
+				buff = w.get8BitExtensionBuffer();
+				if(buff != null) buffers.add(buff);
+			}
+		}				
+	}
+
+	private boolean loadSamples(List<ModelInstrument> instruments)
+	{
+		if(largemode) return true;
+		List<ModelByteBuffer>buffers = new ArrayList<ModelByteBuffer>();
+		for(ModelInstrument instrument : instruments)
+			getBuffers(instrument, buffers);
+		try {
+			ModelByteBuffer.loadAll(buffers);
+		} catch (IOException e) {
+			return false;
+		}
+		return true;
+	}	
+	
+	private boolean loadInstruments(List<ModelInstrument> instruments)
+	{
+		if(!isOpen())
+			return false;	
+		if(!loadSamples(instruments)) return false;
+		
+		synchronized (control_mutex) {
+			if (channels != null)
+				for (SoftChannel c : channels)
+					c.current_instrument = null;
+			for (Instrument instrument : instruments) {				
+				String pat = patchToString(instrument.getPatch());
+				availlist.remove(pat);
+				SoftInstrument softins = new SoftInstrument((ModelInstrument) instrument);
+				inslist.put(pat, softins);
+				loadedlist.put(pat, (ModelInstrument) instrument);				
+			}		
+		}
+			
+		return true;
+	}	
+	
+	private void processPropertyInfo(Map<String, Object> info)
+	{		
+		AudioSynthesizerPropertyInfo[] items = getPropertyInfo(info);
+
+		String resamplerType = (String)items[0].value;
+		if(resamplerType.equalsIgnoreCase("point")) this.resampler = new SoftPointResampler();
+		if(resamplerType.equalsIgnoreCase("linear")) this.resampler = new SoftLinearResampler2();
+		if(resamplerType.equalsIgnoreCase("linear1")) this.resampler = new SoftLinearResampler();
+		if(resamplerType.equalsIgnoreCase("linear2")) this.resampler = new SoftLinearResampler2();
+		if(resamplerType.equalsIgnoreCase("cubic")) this.resampler = new SoftCubicResampler();
+		if(resamplerType.equalsIgnoreCase("lanczos")) this.resampler = new SoftLanczosResampler();
+		if(resamplerType.equalsIgnoreCase("sinc")) this.resampler = new SoftSincResampler();
+		
+		setFormat((AudioFormat)items[2].value);
+		controlrate = (Float)items[1].value;
+		latency = (Long)items[3].value;
+		deviceid = (Integer)items[4].value;
+		maxpoly = (Integer)items[5].value;
+		reverb_on = (Boolean)items[6].value;
+		chorus_on = (Boolean)items[7].value;
+		agc_on = (Boolean)items[8].value;
+		largemode = (Boolean)items[9].value;
+		number_of_midi_channels = (Integer)items[10].value;
+		jitter_correction = (Boolean)items[11].value;
+	}
+		
+	private String patchToString(Patch patch) {
+		if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion())
+			return "p." + patch.getProgram() + "." + patch.getBank();
+		else
+			return patch.getProgram() + "." + patch.getBank();
+	}
+
+	private void setFormat(AudioFormat format) {
+		if (format.getChannels() > 2)
+			throw new IllegalArgumentException(
+					"Only mono and stereo audio supported.");
+		if (AudioFloatConverter.getConverter(format) == null)
+			throw new IllegalArgumentException("Audio format not supported.");
+		this.format = format;
+	}	
+	
+	protected void removeReceiver(Receiver recv)
+	{
+		boolean perform_close = false;
+		synchronized (control_mutex) {
+			if(recvslist.remove(recv))
+				if(implicitOpen && recvslist.isEmpty())
+				{
+					perform_close = true;
+				}				
+		}
+		if(perform_close)
+			close();
+	}
+	
+	protected SoftMainMixer getMainMixer() {
+		if (!isOpen())
+			return null;
+		return mainmixer;
+	}
+	
+	protected SoftInstrument findInstrument(int program, int bank, int channel) {
+
+		// Add support for GM2 banks 0x78 and 0x79
+		// as specified in DLS 2.2 in Section 1.4.6
+		// which allows using percussion and melodic instruments
+		// on all channels
+		if (bank >> 7 == 0x78 || bank >> 7 == 0x79) {
+			SoftInstrument current_instrument = inslist.get(program + "."
+					+ bank);
+			if (current_instrument != null)
+				return current_instrument;
+
+			String p_plaf;
+			if (bank >> 7 == 0x78)
+				p_plaf = "p.";
+			else
+				p_plaf = "";
+
+			// Instrument not found fallback to MSB:bank, LSB:0
+			current_instrument = inslist.get(p_plaf + program + "."
+					+ ((bank & 128) << 7));
+			if (current_instrument != null)
+				return current_instrument;
+			// Instrument not found fallback to MSB:0, LSB:bank
+			current_instrument = inslist.get(p_plaf + program + "."
+					+ (bank & 128));
+			if (current_instrument != null)
+				return current_instrument;
+			// Instrument not found fallback to MSB:0, LSB:0
+			current_instrument = inslist.get(p_plaf + program + ".0");
+			if (current_instrument != null)
+				return current_instrument;
+			// Instrument not found fallback to MSB:0, LSB:0, program=0
+			current_instrument = inslist.get(p_plaf + program + "0.0");
+			if (current_instrument != null)
+				return current_instrument;
+			return null;
+		}
+
+		// Channel 10 uses percussion instruments
+		String p_plaf;
+		if (channel == 9)
+			p_plaf = "p.";
+		else
+			p_plaf = "";
+
+		SoftInstrument current_instrument = inslist.get(p_plaf + program + "."
+				+ bank);
+		if (current_instrument != null)
+			return current_instrument;
+		// Instrument not found fallback to MSB:0, LSB:0
+		current_instrument = inslist.get(p_plaf + program + ".0");
+		if (current_instrument != null)
+			return current_instrument;
+		// Instrument not found fallback to MSB:0, LSB:0, program=0
+		current_instrument = inslist.get(p_plaf + "0.0");
+		if (current_instrument != null)
+			return current_instrument;
+		return null;
+	}
+
+	protected int getVoiceAllocationMode() {
+		return voice_allocation_mode;
+	}
+
+	protected int getGeneralMidiMode() {
+		return gmmode;
+	}
+	
+	protected void setGeneralMidiMode(int gmmode) {
+		this.gmmode = gmmode;
+	}	
+
+	protected int getDeviceID() {
+		return deviceid;
+	}
+
+	protected float getControlRate() {
+		return controlrate;
+	}
+
+	protected SoftVoice[] getVoices() {
+		return voices;
+	}
+	
+	protected SoftTuning getTuning(Patch patch) {
+		String t_id = patchToString(patch);
+		SoftTuning tuning = tunings.get(t_id);
+		if (tuning == null) {
+			tuning = new SoftTuning(patch);
+			tunings.put(t_id, tuning);
+		}
+		return tuning;
+	}
+
+	public long getLatency() {
+		synchronized (control_mutex) {
+			return latency;
+		}
+	}
+	
+	public AudioFormat getFormat() {
+		synchronized (control_mutex) {
+			return format;
+		}
+	}
+
+	public int getMaxPolyphony() {		
+		synchronized (control_mutex) {
+			return maxpoly;
+		}
+	}
+
+	public MidiChannel[] getChannels() {
+		
+		synchronized (control_mutex) {
+			
+			if(external_channels == null)				
+			{
+				external_channels = new SoftChannelProxy[16];
+				for (int i = 0; i < external_channels.length; i++) 
+					external_channels[i] = new SoftChannelProxy();
+			}			
+			MidiChannel[] ret;
+			if(isOpen())
+				ret = new MidiChannel[channels.length];
+			else
+				ret = new MidiChannel[16];
+			for (int i = 0; i < ret.length; i++)
+				ret[i] = external_channels[i];
+			return ret;
+		}
+	}
+	
+	public VoiceStatus[] getVoiceStatus() {
+		
+		if(!isOpen())
+		{
+			VoiceStatus[] tempVoiceStatusArray = new VoiceStatus[getMaxPolyphony()];
+			for (int i = 0; i < tempVoiceStatusArray.length; i++) {
+				VoiceStatus b = new VoiceStatus();
+				b.active = false;
+				b.bank = 0;
+				b.channel = 0;
+				b.note = 0;
+				b.program = 0;
+				b.volume = 0;
+				tempVoiceStatusArray[i] = b;
+			}
+			return tempVoiceStatusArray;
+		}
+		
+		synchronized (control_mutex)
+		{
+			VoiceStatus[] tempVoiceStatusArray = new VoiceStatus[voices.length];
+			for (int i = 0; i < voices.length; i++) {
+				VoiceStatus a = voices[i];
+				VoiceStatus b = new VoiceStatus();
+				b.active = a.active;
+				b.bank = a.bank;
+				b.channel = a.channel;
+				b.note = a.note;
+				b.program = a.program;
+				b.volume = a.volume;
+				tempVoiceStatusArray[i] = b;
+			}
+			return tempVoiceStatusArray;
+		}
+	}
+
+	public boolean isSoundbankSupported(Soundbank soundbank) {
+				
+		for (Instrument ins : soundbank.getInstruments())
+			if (!(ins instanceof ModelInstrument))
+				return false;
+		return true;
+	}
+
+	public boolean loadInstrument(Instrument instrument) {
+
+		if (instrument == null || (!(instrument instanceof ModelInstrument)))
+			throw new IllegalArgumentException("Unsupported instrument: " + instrument.toString());				
+		List<ModelInstrument> instruments = new ArrayList<ModelInstrument>();
+		instruments.add((ModelInstrument)instrument);
+		return loadInstruments(instruments);		
+	}
+	
+	public void unloadInstrument(Instrument instrument) {
+		
+		if (instrument == null || (!(instrument instanceof ModelInstrument)))
+			throw new IllegalArgumentException("Unsupported instrument: " + instrument.toString());
+		if(!isOpen())
+			return;		
+
+		String pat = patchToString(instrument.getPatch());
+		synchronized (control_mutex) {
+			for (SoftChannel c : channels)
+				c.current_instrument = null;
+			inslist.remove(pat);
+			loadedlist.remove(pat);
+			availlist.remove(pat);
+		}
+	}
+
+	public boolean remapInstrument(Instrument from, Instrument to) {
+
+		if (from == null)
+			throw new NullPointerException();
+		if (to == null)
+			throw new NullPointerException();		
+		if (!(from instanceof ModelInstrument))
+			throw new IllegalArgumentException("Unsupported instrument: " + from.toString());
+		if (!(to instanceof ModelInstrument))
+			throw new IllegalArgumentException("Unsupported instrument: " + to.toString());		
+		if(!isOpen())
+			return false;
+
+		synchronized (control_mutex) {
+			if (!loadedlist.containsValue(to) && !availlist.containsValue(to))
+				throw new IllegalArgumentException("Instrument to is not loaded.");
+			unloadInstrument(from);
+			ModelMappedInstrument mfrom = new ModelMappedInstrument(
+					(ModelInstrument) to, from.getPatch());
+			return loadInstrument(mfrom);
+		}
+	}
+	
+	public synchronized Soundbank getDefaultSoundbank() {
+		if (defaultSoundBank == null) {
+			try {
+
+				File javahome = new File(System.getProperties().getProperty(
+						"java.home"));
+				File libaudio = new File(new File(javahome, "lib"), "audio");
+
+				if (libaudio.exists()) {
+					File foundfile = null;
+					File[] files = libaudio.listFiles();
+					if (files != null) {
+						for (int i = 0; i < files.length; i++) {
+							File file = files[i];
+							if (file.isFile()) {
+								String lname = file.getName().toLowerCase();
+								if (lname.endsWith(".sf2")
+										|| lname.endsWith(".dls")) {
+									if (foundfile == null
+											|| (file.length() > foundfile
+													.length()))
+										foundfile = file;
+
+								}
+							}
+						}
+					}
+					if (foundfile != null) {
+						try {
+							Soundbank sbk = MidiSystem.getSoundbank(foundfile);
+							defaultSoundBank = sbk;
+							return defaultSoundBank;
+						} catch (Exception e) {
+							e.printStackTrace();
+						}
+					}
+				}
+
+				if (System.getProperties().getProperty("os.name").startsWith(
+						"Windows")) {
+					File gm_dls = new File(System.getenv("SystemRoot")
+							+ "\\system32\\drivers\\gm.dls");
+					if (gm_dls.exists()) {
+						try {
+							Soundbank sbk = MidiSystem.getSoundbank(gm_dls);
+							defaultSoundBank = sbk;
+							return defaultSoundBank;
+						} catch (Exception e) {
+							e.printStackTrace();
+						}
+					}
+				}
+
+			} catch (AccessControlException e) {	
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+
+			try {
+				defaultSoundBank = EmergencySoundbank.createSoundbank();
+			} catch (Exception e) {
+				e.printStackTrace();
+			}			
+
+		}
+		return defaultSoundBank;
+	}
+
+	public Instrument[] getAvailableInstruments() {
+		
+		if(!isOpen())
+		{
+			Soundbank defsbk = getDefaultSoundbank();
+			if(defsbk == null) return new Instrument[0];
+			return defsbk.getInstruments();
+		}
+		
+		synchronized (control_mutex) {
+			ModelInstrument[] inslist_array = new ModelInstrument[availlist
+					.values().size()];
+			availlist.values().toArray(inslist_array);
+			Arrays.sort(inslist_array, new ModelInstrumentComparator());
+			return inslist_array;
+		}
+	}
+
+	public Instrument[] getLoadedInstruments() {
+		
+		if(!isOpen())
+			return new Instrument[0];
+		
+		synchronized (control_mutex) {
+			ModelInstrument[] inslist_array = new ModelInstrument[loadedlist
+					.values().size()];
+			loadedlist.values().toArray(inslist_array);
+			Arrays.sort(inslist_array, new ModelInstrumentComparator());
+			return inslist_array;
+		}
+	}
+	
+	public boolean loadAllInstruments(Soundbank soundbank) {
+		
+		List<ModelInstrument> instruments = new ArrayList<ModelInstrument>(); 
+		for (Instrument ins : soundbank.getInstruments()) {
+			if (ins == null || !(ins instanceof ModelInstrument)) 
+				throw new IllegalArgumentException("Unsupported instrument: " + ins);
+			instruments.add((ModelInstrument)ins);
+		}			
+		return loadInstruments(instruments);		
+	}
+
+	public void unloadAllInstruments(Soundbank soundbank) {
+		
+		if(!isOpen())
+			return;
+		
+		for (Instrument ins : soundbank.getInstruments()) {
+			if (ins instanceof ModelInstrument) {
+				unloadInstrument(ins);
+			}
+		}
+	}
+
+	public boolean loadInstruments(Soundbank soundbank, Patch[] patchList) {
+		
+		List<ModelInstrument> instruments = new ArrayList<ModelInstrument>(); 
+		for (Patch patch : patchList) {
+			Instrument ins = soundbank.getInstrument(patch);
+			if (ins == null || !(ins instanceof ModelInstrument)) 
+				throw new IllegalArgumentException("Unsupported instrument: " + ins);
+			instruments.add((ModelInstrument)ins);
+		}			
+		return loadInstruments(instruments);		
+		
+	}
+
+	public void unloadInstruments(Soundbank soundbank, Patch[] patchList) {
+		
+		if(!isOpen())
+			return;
+		
+		for (Patch pat : patchList) {
+			Instrument ins = soundbank.getInstrument(pat);
+			if (ins instanceof ModelInstrument) {
+				unloadInstrument(ins);
+			}
+		}
+	}
+
+	public MidiDevice.Info getDeviceInfo() {
+		return info;
+	}
+
+	
+	public AudioSynthesizerPropertyInfo[] getPropertyInfo(Map<String, Object> info)
+	{
+		List<AudioSynthesizerPropertyInfo> list = new ArrayList<AudioSynthesizerPropertyInfo>();
+		
+		AudioSynthesizerPropertyInfo item;
+		
+		item = new AudioSynthesizerPropertyInfo("interpolation", "linear");
+		item.choices = new String[] {"linear", "linear1", "linear2", "cubic", "lanczos", "sinc", "point"};
+		item.description = "Interpolation method";
+		list.add(item);
+		
+		item = new AudioSynthesizerPropertyInfo("control rate", 147f);
+		item.description = "Control rate";
+		list.add(item);
+		
+		item = new AudioSynthesizerPropertyInfo("format", new AudioFormat(44100, 16, 2, true, false));
+		item.description = "Default audio format";
+		list.add(item);
+		
+		item = new AudioSynthesizerPropertyInfo("latency", 120000L);
+		item.description = "Default latency";
+		list.add(item);
+
+		item = new AudioSynthesizerPropertyInfo("device id", 0);
+		item.description = "Device ID for SysEx Messages";
+		list.add(item);
+		
+		item = new AudioSynthesizerPropertyInfo("max polyphony", 64);
+		item.description = "Maximum polyphony";
+		list.add(item);
+		
+		item = new AudioSynthesizerPropertyInfo("reverb", true);
+		item.description = "Turn reverb effect on or off";
+		list.add(item);
+		
+		item = new AudioSynthesizerPropertyInfo("chorus", true);
+		item.description = "Turn chorus effect on or off";
+		list.add(item);		
+
+		item = new AudioSynthesizerPropertyInfo("auto gain control", true);
+		item.description = "Turn auto gain control on or off";
+		list.add(item);
+		
+		item = new AudioSynthesizerPropertyInfo("large mode", false);
+		item.description = "Turn large mode on or off.";
+		list.add(item);		
+
+		item = new AudioSynthesizerPropertyInfo("midi channels", 16);
+		item.description = "Number of midi channels.";
+		list.add(item);		
+		
+		item = new AudioSynthesizerPropertyInfo("jitter correction", true);
+		item.description = "Turn jitter correction on or off.";
+		list.add(item);				
+
+		AudioSynthesizerPropertyInfo[] items;
+		items = list.toArray(new AudioSynthesizerPropertyInfo[list.size()]);
+		
+		if(info != null)
+		for(AudioSynthesizerPropertyInfo item2 : items)
+		{
+			Object v = info.get(item2.name);
+			Class c = (item2.valueClass);
+			if(v != null)
+			if(c.isInstance(v))
+				item2.value = v;
+		}
+		
+		return items;
+	}
+	
+	public void open() throws MidiUnavailableException {
+		if(isOpen())
+		{
+			synchronized (control_mutex) {
+				implicitOpen = false;
+			}
+			return;
+		}
+		open(null, null);
+	}
+
+	public void open(SourceDataLine line, Map<String, Object> info) throws MidiUnavailableException {
+		if(isOpen())
+		{
+			synchronized (control_mutex) {
+				implicitOpen = false;
+			}
+			return;
+		}
+		synchronized (control_mutex) {
+
+			try
+			{
+											
+				if(line != null)
+					setFormat(line.getFormat());
+			
+				AudioInputStream ais = openStream(getFormat(), info);
+			
+				if(line == null)
+					line = AudioSystem.getSourceDataLine(getFormat());
+				
+				double latency = this.latency;
+											
+				if(!line.isOpen())
+				{
+					int bufferSize = getFormat().getFrameSize() * (int)(getFormat().getFrameRate() * (latency / 1000000f));
+					line.open(getFormat(), bufferSize);
+					
+					// Remember that we opened that line 
+					// so we can close again in SoftSynthesizer.close()
+					sourceDataLine = line; 									
+				}
+				if(!line.isActive())
+					line.start();
+							
+				int controlbuffersize = 512;
+				try {
+					controlbuffersize = ais.available();
+				} catch (IOException e) {}
+				
+				// Tell mixer not fill read buffers fully.
+				// This lowers latency, and tells DataPusher
+				// to read in smaller amounts.
+				//mainmixer.readfully = false;
+				//pusher = new DataPusher(line, ais);
+								
+				int buffersize = line.getBufferSize();				
+				buffersize -= buffersize % controlbuffersize;
+				
+				if(buffersize < 3*controlbuffersize)
+					buffersize = 3*controlbuffersize;
+				
+				if(jitter_correction)
+				{
+					ais = new SoftJitterCorrector(ais, buffersize, controlbuffersize);
+				}
+				pusher = new SoftAudioPusher(line, ais, controlbuffersize);
+				pusher_stream = ais;
+				pusher.start();					
+				
+			
+			}
+			catch(LineUnavailableException e)
+			{
+				if(isOpen()) close();
+				throw new MidiUnavailableException(e.toString());
+			}
+				
+		}
+	}
+	
+	public AudioInputStream openStream(AudioFormat targetFormat, Map<String, Object> info) throws MidiUnavailableException {
+			
+		if(isOpen())
+			throw new MidiUnavailableException("Synthesizer is already open");
+		
+		synchronized (control_mutex) {
+					
+		open = true;		
+		implicitOpen = false;
+		
+		gmmode = 0;
+		voice_allocation_mode = 0;
+			
+		processPropertyInfo(info);
+		if(targetFormat != null)
+			setFormat(targetFormat);
+		
+		Soundbank defbank = getDefaultSoundbank();
+		if (defbank != null) {
+			loadAllInstruments(defbank);
+			availlist.putAll(loadedlist);
+			loadedlist.clear();
+		}
+
+		voices = new SoftVoice[maxpoly];
+		for (int i = 0; i < maxpoly; i++)
+			voices[i] = new SoftVoice(this);
+		
+		mainmixer = new SoftMainMixer(this);
+		
+		channels = new SoftChannel[number_of_midi_channels];
+		for (int i = 0; i < channels.length; i++)
+			channels[i] = new SoftChannel(this, i);
+		
+		if(external_channels == null)
+		{
+			// Always create external_channels array
+			// with 16 or more channels
+			// so getChannels works correctly
+			// when the synhtesizer is closed.
+			if(channels.length < 16)
+				external_channels = new SoftChannelProxy[16];
+			else
+				external_channels = new SoftChannelProxy[channels.length];
+			for (int i = 0; i < external_channels.length; i++) 
+				external_channels[i] = new SoftChannelProxy();			
+		}
+		else
+		{
+			// We must resize external_channels array
+			// but we must also copy the old SoftChannelProxy
+			// into the new one
+			if(channels.length > external_channels.length)
+			{
+				SoftChannelProxy[] new_external_channels = new SoftChannelProxy[channels.length];
+				for (int i = 0; i < external_channels.length; i++) 
+					new_external_channels[i] = external_channels[i];			
+				for (int i = external_channels.length; i < new_external_channels.length; i++)
+					new_external_channels[i] = new SoftChannelProxy();
+			}
+		}
+			
+		for (int i = 0; i < channels.length; i++) 
+			external_channels[i].setChannel(channels[i]);
+
+
+		for (SoftVoice voice : getVoices())
+			voice.resampler = resampler.openStreamer();
+		
+		for (Receiver recv : getReceivers())
+		{
+			SoftReceiver srecv = ((SoftReceiver)recv);
+			srecv.open = open;
+			srecv.mainmixer = mainmixer;
+			srecv.midimessages = mainmixer.midimessages;
+		}
+				
+		return mainmixer.getInputStream();
+		
+		}
+		
+	}
+
+	public void close() {
+		
+		if(!isOpen())
+			return;
+		
+		SoftAudioPusher pusher_to_be_closed = null;
+		AudioInputStream pusher_stream_to_be_closed = null;
+		synchronized (control_mutex) {
+			if(pusher != null)
+			{
+				pusher_to_be_closed = pusher;
+				pusher_stream_to_be_closed = pusher_stream;
+				pusher = null;
+				pusher_stream = null;
+			}
+		}
+		
+		if(pusher_to_be_closed != null)
+		{
+			// Pusher must not be closed synchronized against control_mutex			
+			// this may result in synchronized conflict between pusher and current thread.
+			pusher_to_be_closed.stop();
+
+			try {
+				pusher_stream_to_be_closed.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+		
+		synchronized (control_mutex) {
+									
+				if(mainmixer != null) mainmixer.close();
+				open = false;	
+				implicitOpen = false;
+				mainmixer = null;
+				voices = null;
+				channels = null;
+				
+				if(external_channels != null)				
+					for (int i = 0; i < external_channels.length; i++) 
+						external_channels[i].setChannel(null);
+												
+				if(sourceDataLine != null)
+				{
+					sourceDataLine.drain();
+					sourceDataLine.close();
+					sourceDataLine = null;					
+				}
+				
+				inslist.clear();
+				availlist.clear();
+				loadedlist.clear();
+				tunings.clear();
+				
+				while(recvslist.size() != 0)
+					recvslist.get(recvslist.size()-1).close();				
+
+		}
+	}
+
+	public boolean isOpen() {
+		synchronized (control_mutex) {
+			return open;
+		}
+	}
+
+	public long getMicrosecondPosition() {
+		
+		if(!isOpen())
+			return 0;
+		
+		synchronized (control_mutex) {
+			return mainmixer.getMicrosecondPosition();
+		}
+	}
+
+	public int getMaxReceivers() {
+		return -1;
+	}
+
+	public int getMaxTransmitters() {
+		return 0;
+	}
+
+	public Receiver getReceiver() throws MidiUnavailableException {
+		
+		synchronized (control_mutex) {
+			SoftReceiver receiver = new SoftReceiver(this);
+			receiver.open = open;
+			recvslist.add(receiver);
+			return receiver;
+		}				
+	}
+
+	public List<Receiver> getReceivers() {
+		
+		synchronized (control_mutex) {
+			ArrayList<Receiver> recvs = new ArrayList<Receiver>();
+			recvs.addAll(recvslist);
+			return recvs;
+		}
+	}
+
+	public Transmitter getTransmitter() throws MidiUnavailableException {
+		
+		throw new MidiUnavailableException("No transmitter available");
+	}
+
+	public List<Transmitter> getTransmitters() {
+		
+		return new ArrayList<Transmitter>();
+	}
+
+	public Receiver getReceiverReferenceCounting() throws MidiUnavailableException {
+		
+		if(!isOpen())
+		{
+			open();
+			synchronized (control_mutex) {
+				implicitOpen = true;
+			}
+		}
+		
+		return getReceiver();
+	}
+
+	public Transmitter getTransmitterReferenceCounting() throws MidiUnavailableException {
+
+		throw new MidiUnavailableException("No transmitter available");
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftTuning.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.UnsupportedEncodingException;
+
+import javax.sound.midi.Patch;
+
+/**
+ * 
+ * A tuning program container, for use with MIDI Tuning. see:
+ * http://www.midi.org
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftTuning {
+
+	private String name = null;
+
+	private double[] tuning = new double[128];
+
+	private Patch patch = null;
+
+	public SoftTuning() {
+		name = "12-TET";
+		for (int i = 0; i < tuning.length; i++)
+			tuning[i] = i * 100;
+	}
+
+	public SoftTuning(byte[] data) {
+		for (int i = 0; i < tuning.length; i++)
+			tuning[i] = i * 100;
+		load(data);
+	}
+
+	public SoftTuning(Patch patch) {
+		this.patch = patch;
+		name = "12-TET";
+		for (int i = 0; i < tuning.length; i++)
+			tuning[i] = i * 100;
+	}
+
+	public SoftTuning(Patch patch, byte[] data) {
+		this.patch = patch;
+		for (int i = 0; i < tuning.length; i++)
+			tuning[i] = i * 100;
+		load(data);
+	}
+
+	private boolean checksumOK(byte[] data) {
+		int x = data[1] & 0xFF;
+		for (int i = 2; i < data.length - 2; i++)
+			x = x ^ (data[i] & 0xFF);
+		return (data[data.length - 2] & 0xFF) == (x & 127);
+	}
+
+	/*
+	private boolean checksumOK2(byte[] data) {
+		int x = data[1] & 0xFF; // 7E
+		x = x ^ (data[2] & 0xFF); // <device ID>
+		x = x ^ (data[4] & 0xFF); // nn
+		x = x ^ (data[5] & 0xFF); // tt
+		for (int i = 22; i < data.length - 2; i++)
+			x = x ^ (data[i] & 0xFF);
+		return (data[data.length - 2] & 0xFF) == (x & 127);
+	}*/
+
+	public void load(byte[] data) {
+		// Universal Non-Real-Time / Real-Time SysEx
+		if ((data[1] & 0xFF) == 0x7E || (data[1] & 0xFF) == 0x7F) {
+			int subid1 = data[3] & 0xFF;
+			switch (subid1) {
+			case 0x08: // MIDI Tuning Standard
+				int subid2 = data[4] & 0xFF;
+				switch (subid2) {
+				case 0x01: // BULK TUNING DUMP (NON-REAL-TIME)
+				{
+					// http://www.midi.org/about-midi/tuning.shtml
+					//if (!checksumOK2(data))
+					//	break;
+					try {
+						name = new String(data, 6, 16, "ascii");
+					} catch (UnsupportedEncodingException e) {
+						name = null;
+					}
+					int r = 22;
+					for (int i = 0; i < 128; i++) {
+						int xx = data[r++] & 0xFF;
+						int yy = data[r++] & 0xFF;
+						int zz = data[r++] & 0xFF;
+						if (!(xx == 127 && yy == 127 && zz == 127))
+							tuning[i] = 100.0 * (((xx * 16384) + (yy * 128) + zz) / 16384.0);
+					}
+					break;
+				}
+				case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME)
+				{
+					// http://www.midi.org/about-midi/tuning.shtml
+					int ll = data[6] & 0xFF;
+					int r = 7;
+					for (int i = 0; i < ll; i++) {
+						int kk = data[r++] & 0xFF;
+						int xx = data[r++] & 0xFF;
+						int yy = data[r++] & 0xFF;
+						int zz = data[r++] & 0xFF;
+						if (!(xx == 127 && yy == 127 && zz == 127))
+							tuning[kk] = 100.0 * (((xx * 16384) + (yy * 128) + zz) / 16384.0);
+					}
+					break;
+				}
+				case 0x04: // KEY-BASED TUNING DUMP (NON-REAL-TIME)
+				{
+					// http://www.midi.org/about-midi/tuning_extens.shtml
+					if (!checksumOK(data))
+						break;
+					try {
+						name = new String(data, 7, 16, "ascii");
+					} catch (UnsupportedEncodingException e) {
+						name = null;
+					}
+					int r = 23;
+					for (int i = 0; i < 128; i++) {
+						int xx = data[r++] & 0xFF;
+						int yy = data[r++] & 0xFF;
+						int zz = data[r++] & 0xFF;
+						if (!(xx == 127 && yy == 127 && zz == 127))
+							tuning[i] = 100.0 * (((xx * 16384) + (yy * 128) + zz) / 16384.0);
+					}
+					break;
+				}
+				case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format
+							// (NON-REAL-TIME)
+				{
+					// http://www.midi.org/about-midi/tuning_extens.shtml
+					if (!checksumOK(data))
+						break;
+					try {
+						name = new String(data, 7, 16, "ascii");
+					} catch (UnsupportedEncodingException e) {
+						name = null;
+					}
+					int[] octave_tuning = new int[12];
+					for (int i = 0; i < 12; i++)
+						octave_tuning[i] = (data[i + 23] & 0xFF) - 64;
+					for (int i = 0; i < tuning.length; i++)
+						tuning[i] = i * 100 + octave_tuning[i % 12];
+					break;
+				}
+				case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format
+							// (NON-REAL-TIME)
+				{
+					// http://www.midi.org/about-midi/tuning_extens.shtml
+					if (!checksumOK(data))
+						break;
+					try {
+						name = new String(data, 7, 16, "ascii");
+					} catch (UnsupportedEncodingException e) {
+						name = null;
+					}
+					double[] octave_tuning = new double[12];
+					for (int i = 0; i < 12; i++) {
+						int v = (data[i * 2 + 23] & 0xFF) * 128
+								+ (data[i * 2 + 24] & 0xFF);
+						octave_tuning[i] = (v / 8192.0 - 1) * 100.0;
+					}
+					for (int i = 0; i < tuning.length; i++)
+						tuning[i] = i * 100 + octave_tuning[i % 12];
+					break;
+				}
+				case 0x07: // SINGLE NOTE TUNING CHANGE (NON
+							// REAL-TIME/REAL-TIME) (BANK)
+					// http://www.midi.org/about-midi/tuning_extens.shtml
+					int ll = data[7] & 0xFF;
+					int r = 8;
+					for (int i = 0; i < ll; i++) {
+						int kk = data[r++] & 0xFF;
+						int xx = data[r++] & 0xFF;
+						int yy = data[r++] & 0xFF;
+						int zz = data[r++] & 0xFF;
+						if (!(xx == 127 && yy == 127 && zz == 127))
+							tuning[kk] = 100.0 * (((xx * 16384) + (yy * 128) + zz) / 16384.0);
+					}
+					break;
+				case 0x08: // scale/octave tuning 1-byte form (Non
+							// Real-Time/REAL-TIME)
+				{
+					// http://www.midi.org/about-midi/tuning-scale.shtml
+					int[] octave_tuning = new int[12];
+					for (int i = 0; i < 12; i++)
+						octave_tuning[i] = (data[i + 8] & 0xFF) - 64;
+					for (int i = 0; i < tuning.length; i++)
+						tuning[i] = i * 100 + octave_tuning[i % 12];
+					break;
+				}
+				case 0x09: // scale/octave tuning 2-byte form (Non
+							// Real-Time/REAL-TIME)
+				{
+					// http://www.midi.org/about-midi/tuning-scale.shtml
+					double[] octave_tuning = new double[12];
+					for (int i = 0; i < 12; i++) {
+						int v = (data[i * 2 + 8] & 0xFF) * 128
+								+ (data[i * 2 + 9] & 0xFF);
+						octave_tuning[i] = (v / 8192.0 - 1) * 100.0;
+					}
+					for (int i = 0; i < tuning.length; i++)
+						tuning[i] = i * 100 + octave_tuning[i % 12];
+					break;
+				}
+				default:
+					break;
+				}
+			}
+		}
+	}
+
+	public double[] getTuning() {
+		return tuning;
+	}
+
+	public double getTuning(int noteNumber) {
+		return tuning[noteNumber];
+	}
+
+	public Patch getPatch() {
+		return patch;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,959 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.sound.midi.VoiceStatus;
+
+/**
+ * 
+ * Software synthesizer voice class.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+public class SoftVoice extends VoiceStatus {
+
+	public int exclusiveClass = 0;
+	
+	public boolean releaseTriggered = false;
+
+	private int noteOn_noteNumber = 0;
+
+	private int noteOn_velocity = 0;
+
+	private int noteOff_velocity = 0;
+	
+	protected ModelChannelMixer channelmixer = null;
+
+	protected double tunedKey = 0;
+
+	protected SoftTuning tuning = null;
+
+	protected SoftChannel stealer_channel = null;
+	
+	protected ModelConnectionBlock[] stealer_extendedConnectionBlocks = null;
+
+	protected SoftPerformer stealer_performer = null;
+	
+	protected ModelChannelMixer stealer_channelmixer = null;
+
+	protected int stealer_voiceID = -1;
+
+	protected int stealer_noteNumber = 0;
+
+	protected int stealer_velocity = 0;
+	
+	protected boolean stealer_releaseTriggered = false;
+
+	protected int voiceID = -1;
+
+	protected boolean sustain = false;
+
+	protected boolean sostenuto = false;
+
+	protected boolean portamento = false;
+
+	private SoftFilter filter_left;
+
+	private SoftFilter filter_right;
+
+	private SoftProcess eg = new SoftEnvelopeGenerator();
+
+	private SoftProcess lfo = new SoftLowFrequencyOscillator();
+
+	protected Map<String, SoftControl> objects = new HashMap<String, SoftControl>();
+
+	protected SoftSynthesizer synthesizer;
+
+	protected SoftInstrument instrument;
+
+	protected SoftPerformer performer;
+
+	protected SoftChannel softchannel = null;
+
+	protected boolean on = false;
+
+	private boolean audiostarted = false;
+
+	private boolean started = false;
+
+	private boolean stopping = false;
+
+	private float osc_attenuation = 0.0f;
+
+	private ModelOscillatorStream osc_stream;;
+
+	private int osc_stream_nrofchannels;
+
+	private float[][] osc_buff = new float[2][];
+
+	private boolean osc_stream_off_transmitted = false;
+
+	private boolean out_mixer_end = false;
+
+	private float out_mixer_left = 0;
+
+	private float out_mixer_right = 0;
+
+	private float out_mixer_effect1 = 0;
+
+	private float out_mixer_effect2 = 0;
+
+	private float last_out_mixer_left = 0;
+
+	private float last_out_mixer_right = 0;
+
+	private float last_out_mixer_effect1 = 0;
+
+	private float last_out_mixer_effect2 = 0;
+	
+	protected ModelConnectionBlock[] extendedConnectionBlocks = null;
+
+	private ModelConnectionBlock[] connections;
+
+	private double[] connections_last = new double[50]; // Last value added to
+														// destination
+
+	private double[][][] connections_src = new double[50][3][]; // Pointer to
+																// source value
+
+	private int[][] connections_src_kc = new int[50][3]; // Key-based
+															// override (if any)
+
+	private double[][] connections_dst = new double[50][]; // Pointer to
+															// destination value
+
+	private boolean soundoff = false;
+
+	private float lastMuteValue = 0;
+
+	private float lastSoloMuteValue = 0;
+
+	protected double[] co_noteon_keynumber = new double[1];
+
+	protected double[] co_noteon_velocity = new double[1];
+
+	protected double[] co_noteon_on = new double[1];
+
+	private SoftControl co_noteon = new SoftControl() {
+		double[] keynumber = co_noteon_keynumber;
+
+		double[] velocity = co_noteon_velocity;
+
+		double[] on = co_noteon_on;
+
+		public double[] get(int instance, String name) {
+			if (name == null)
+				return null;
+			if (name.equals("keynumber"))
+				return keynumber;
+			if (name.equals("velocity"))
+				return velocity;
+			if (name.equals("on"))
+				return on;
+			return null;
+		}
+	};
+
+	private double[] co_mixer_active = new double[1];
+
+	private double[] co_mixer_gain = new double[1];
+
+	private double[] co_mixer_pan = new double[1];
+
+	private double[] co_mixer_balance = new double[1];
+
+	private double[] co_mixer_reverb = new double[1];
+
+	private double[] co_mixer_chorus = new double[1];
+
+	private SoftControl co_mixer = new SoftControl() {
+		double[] active = co_mixer_active;
+
+		double[] gain = co_mixer_gain;
+
+		double[] pan = co_mixer_pan;
+
+		double[] balance = co_mixer_balance;
+
+		double[] reverb = co_mixer_reverb;
+
+		double[] chorus = co_mixer_chorus;
+
+		public double[] get(int instance, String name) {
+			if (name == null)
+				return null;
+			if (name.equals("active"))
+				return active;
+			if (name.equals("gain"))
+				return gain;
+			if (name.equals("pan"))
+				return pan;
+			if (name.equals("balance"))
+				return balance;
+			if (name.equals("reverb"))
+				return reverb;
+			if (name.equals("chorus"))
+				return chorus;
+			return null;
+		}
+	};
+
+	private double[] co_osc_pitch = new double[1];
+
+	private SoftControl co_osc = new SoftControl() {
+		double[] pitch = co_osc_pitch;
+
+		public double[] get(int instance, String name) {
+			if (name == null)
+				return null;
+			if (name.equals("pitch"))
+				return pitch;
+			return null;
+		}
+	};
+
+	private double[] co_filter_freq = new double[1];
+
+	private double[] co_filter_type = new double[1];
+
+	private double[] co_filter_q = new double[1];
+
+	private SoftControl co_filter = new SoftControl() {
+		double[] freq = co_filter_freq;
+
+		double[] ftype = co_filter_type;
+
+		double[] q = co_filter_q;
+
+		public double[] get(int instance, String name) {
+			if (name == null)
+				return null;
+			if (name.equals("freq"))
+				return freq;
+			if (name.equals("type"))
+				return ftype;
+			if (name.equals("q"))
+				return q;
+			return null;
+		}
+	};
+
+	protected SoftResamplerStreamer resampler;
+
+	private int nrofchannels;
+
+	public SoftVoice(SoftSynthesizer synth) {
+		synthesizer = synth;
+		filter_left = new SoftFilter(synth.getFormat().getSampleRate());
+		filter_right = new SoftFilter(synth.getFormat().getSampleRate());
+		nrofchannels = synth.getFormat().getChannels();
+	}
+
+	private int getValueKC(ModelIdentifier id) {
+		if (id.getObject().equals("midi_cc")) {
+			int ic = Integer.parseInt(id.getVariable());
+			if (ic != 0 && ic != 32)
+				if (ic < 120) {
+					return ic;
+				}
+		} else if (id.getObject().equals("midi_rpn")) {
+			if (id.getVariable().equals("1"))
+				return 120; // Fine tuning
+			if (id.getVariable().equals("2"))
+				return 121; // Coarse tuning
+		}
+		return -1;
+	}
+
+	private double[] getValue(ModelIdentifier id) {
+		SoftControl o = objects.get(id.getObject());
+		if (o == null)
+			return null;
+		return o.get(id.getInstance(), id.getVariable());
+	}
+
+	private double transformValue(double value, ModelSource src) {
+		if (src.getTransform() != null)
+			return src.getTransform().transform(value);
+		else
+			return value;
+	}
+
+	private double transformValue(double value, ModelDestination dst) {
+		if (dst.getTransform() != null)
+			return dst.getTransform().transform(value);
+		else
+			return value;
+	}
+
+	private double processKeyBasedController(double value, int keycontrol) {
+		if (keycontrol == -1)
+			return value;
+		if (softchannel.keybasedcontroller_active != null)
+			if (softchannel.keybasedcontroller_active[note] != null)
+				if (softchannel.keybasedcontroller_active[note][keycontrol]) {
+					double key_controlvalue = softchannel.keybasedcontroller_value[note][keycontrol];
+					if (keycontrol == 10 || keycontrol == 91
+							|| keycontrol == 93)
+						return key_controlvalue;
+					value += key_controlvalue * 2.0 - 1.0;
+					if (value > 1)
+						value = 1;
+					else if (value < 0)
+						value = 0;
+				}
+		return value;
+	}
+
+	private void processConnection(int ix) {
+		ModelConnectionBlock conn = connections[ix];
+		double[][] src = connections_src[ix];		
+		double[] dst = connections_dst[ix];
+		if (dst == null || Double.isInfinite(dst[0]))
+			return;
+
+		double value = conn.getScale();
+		if(softchannel.keybasedcontroller_active == null)
+		{
+			ModelSource[] srcs = conn.getSources();
+			for (int i = 0; i < srcs.length; i++) {
+				value *= transformValue(src[i][0], srcs[i]);
+				if(value == 0) break;
+			}
+		}
+		else
+		{
+			ModelSource[] srcs = conn.getSources();
+			int[] src_kc = connections_src_kc[ix];
+			for (int i = 0; i < srcs.length; i++) {
+				value *= transformValue(processKeyBasedController(src[i][0],
+					src_kc[i]), srcs[i]);
+				if(value == 0) break;
+			}
+		}
+
+		value = transformValue(value, conn.getDestination());
+		dst[0] = dst[0] - connections_last[ix] + value;
+		connections_last[ix] = value;
+		// co_mixer_gain[0] = 0;
+
+		
+	}
+
+	protected void updateTuning(SoftTuning newtuning) {
+		tunedKey = tuning.getTuning(note) / 100.0;
+		if (!portamento) {
+			co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
+			;
+			int[] c = performer.midi_connections[4];
+			if (c == null)
+				return;
+			for (int i = 0; i < c.length; i++)
+				processConnection(c[i]);
+		}
+	}
+
+	protected void setNote(int noteNumber) {
+		note = noteNumber;
+		tunedKey = tuning.getTuning(noteNumber) / 100.0;
+	}
+	
+	protected void noteOn(int noteNumber, int velocity) {
+		
+		sustain = false;
+		sostenuto = false;
+		portamento = false;
+
+		soundoff = false;
+		on = true;
+		active = true;
+		started = true;
+		// volume = velocity;
+
+		noteOn_noteNumber = noteNumber;
+		noteOn_velocity = velocity;
+
+		lastMuteValue = 0;
+		lastSoloMuteValue = 0;
+
+		setNote(noteNumber);
+
+		if (performer.forcedKeynumber)
+			co_noteon_keynumber[0] = 0;
+		else
+			co_noteon_keynumber[0] = tunedKey * (1f / 128f);
+		if (performer.forcedVelocity)
+			co_noteon_velocity[0] = 0;
+		else
+			co_noteon_velocity[0] = velocity * (1f / 128f);
+		co_mixer_active[0] = 0;
+		co_mixer_gain[0] = 0;
+		co_mixer_pan[0] = 0;
+		co_mixer_balance[0] = 0;
+		co_mixer_reverb[0] = 0;
+		co_mixer_chorus[0] = 0;
+		co_osc_pitch[0] = 0;
+		co_filter_freq[0] = 0;
+		co_filter_q[0] = 0;
+		co_filter_type[0] = 0;
+		co_noteon_on[0] = 1;
+
+		eg.reset();
+		lfo.reset();
+		filter_left.reset();
+		filter_right.reset();
+
+		objects.put("master", synthesizer.getMainMixer().co_master);
+		objects.put("eg", eg);
+		objects.put("lfo", lfo);
+		objects.put("noteon", co_noteon);
+		objects.put("osc", co_osc);
+		objects.put("mixer", co_mixer);
+		objects.put("filter", co_filter);
+
+		connections = performer.connections;
+
+		if (connections_last == null
+				|| connections_last.length < connections.length)
+			connections_last = new double[connections.length];
+		if (connections_src == null
+				|| connections_src.length < connections.length) {
+			connections_src = new double[connections.length][][];
+			connections_src_kc = new int[connections.length][];
+		}
+		if (connections_dst == null
+				|| connections_dst.length < connections.length)
+			connections_dst = new double[connections.length][];
+		for (int i = 0; i < connections.length; i++) {
+			ModelConnectionBlock conn = connections[i];
+			connections_last[i] = 0;
+			if (conn.getSources() != null) {
+				ModelSource[] srcs = conn.getSources();
+				if (connections_src[i] == null
+						|| connections_src[i].length < srcs.length) {
+					connections_src[i] = new double[srcs.length][];
+					connections_src_kc[i] = new int[srcs.length];
+				}
+				double[][] src = connections_src[i];
+				int[] src_kc = connections_src_kc[i];
+				connections_src[i] = src;
+				for (int j = 0; j < srcs.length; j++) {
+					src_kc[j] = getValueKC(srcs[j].getIdentifier());
+					src[j] = getValue(srcs[j].getIdentifier());
+				}
+			}
+
+			if (conn.getDestination() != null)
+				connections_dst[i] = getValue(conn.getDestination()
+						.getIdentifier());
+			else
+				connections_dst[i] = null;
+		}
+
+		for (int i = 0; i < connections.length; i++)
+			processConnection(i);
+		
+		
+		if(extendedConnectionBlocks != null)
+		{
+			for (ModelConnectionBlock connection : extendedConnectionBlocks) {
+				
+				double value = 0;
+				
+				if(softchannel.keybasedcontroller_active == null)
+				{					
+					for(ModelSource src : connection.getSources())
+					{
+						double x = getValue(src.getIdentifier())[0];
+						ModelTransform t = src.getTransform();
+						if(t == null)
+							value += x;
+						else
+							value += t.transform(x);
+					}
+				}
+				else
+				{
+					for(ModelSource src : connection.getSources())
+					{
+						double x = getValue(src.getIdentifier())[0];
+						x = processKeyBasedController(x, getValueKC(src.getIdentifier()));
+						ModelTransform t = src.getTransform();
+						if(t == null)
+							value += x;
+						else
+							value += t.transform(x);
+					}					
+				}
+
+				ModelDestination dest = connection.getDestination();
+				ModelTransform t = dest.getTransform();
+				if(t != null)
+					value = t.transform(value);
+				getValue(dest.getIdentifier())[0] += value;
+				
+			}
+		} 
+
+		eg.init(synthesizer);
+		lfo.init(synthesizer);
+
+	}
+
+	protected void setPolyPressure(int pressure) {
+		int[] c = performer.midi_connections[2];
+		if (c == null)
+			return;
+		for (int i = 0; i < c.length; i++)
+			processConnection(c[i]);
+	}
+
+	protected void setChannelPressure(int pressure) {
+		int[] c = performer.midi_connections[1];
+		if (c == null)
+			return;
+		for (int i = 0; i < c.length; i++)
+			processConnection(c[i]);
+	}
+
+	protected void controlChange(int controller, int value) {
+		int[] c = performer.midi_ctrl_connections[controller];
+		if (c == null)
+			return;
+		for (int i = 0; i < c.length; i++)
+			processConnection(c[i]);
+	}
+
+	protected void nrpnChange(int controller, int value) {
+		int[] c = performer.midi_nrpn_connections.get(controller);
+		if (c == null)
+			return;
+		for (int i = 0; i < c.length; i++)
+			processConnection(c[i]);
+
+	}
+
+	protected void rpnChange(int controller, int value) {
+		int[] c = performer.midi_rpn_connections.get(controller);
+		if (c == null)
+			return;
+		for (int i = 0; i < c.length; i++)
+			processConnection(c[i]);
+	}
+
+	protected void setPitchBend(int bend) {
+		int[] c = performer.midi_connections[0];
+		if (c == null)
+			return;
+		for (int i = 0; i < c.length; i++)
+			processConnection(c[i]);
+
+	}
+
+	protected void setMute(boolean mute) {
+		co_mixer_gain[0] -= lastMuteValue;
+		lastMuteValue = mute ? -960 : 0;
+		co_mixer_gain[0] += lastMuteValue;
+	}
+
+	protected void setSoloMute(boolean mute) {
+		co_mixer_gain[0] -= lastSoloMuteValue;
+		lastSoloMuteValue = mute ? -960 : 0;
+		co_mixer_gain[0] += lastSoloMuteValue;
+	}
+
+	protected void shutdown() {
+		if (co_noteon_on[0] < -0.5)
+			return;
+		on = false;
+
+		co_noteon_on[0] = -1;
+
+		int[] c = performer.midi_connections[3];
+		if (c == null)
+			return;
+		for (int i = 0; i < c.length; i++)
+			processConnection(c[i]);
+
+	}
+
+	protected void soundOff() {
+		on = false;
+		soundoff = true;
+	}
+
+	protected void noteOff(int velocity) {
+		if (!on)
+			return;
+		on = false;
+
+		noteOff_velocity = velocity;
+
+		if (softchannel.sustain) {
+			sustain = true;
+			return;
+		}
+		if (sostenuto)
+			return;
+
+		co_noteon_on[0] = 0;
+
+		int[] c = performer.midi_connections[3];
+		if (c == null)
+			return;
+		for (int i = 0; i < c.length; i++)
+			processConnection(c[i]);
+
+	}
+
+	protected void redamp() {
+		if (co_noteon_on[0] > 0.5)
+			return;
+		if (co_noteon_on[0] < -0.5)
+			return; // don't redamp notes in shutdown stage
+
+		sustain = true;
+		co_noteon_on[0] = 1;
+
+		int[] c = performer.midi_connections[3];
+		if (c == null)
+			return;
+		for (int i = 0; i < c.length; i++)
+			processConnection(c[i]);
+
+	}
+
+	protected void processControlLogic() {
+		
+		
+		
+		if (stopping) {
+			active = false;
+			stopping = false;
+			audiostarted = false;
+			if (osc_stream != null)
+				try {
+					osc_stream.close();
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+
+			if (stealer_channel != null) {
+				stealer_channel.initVoice(this, stealer_performer,
+				stealer_voiceID, stealer_noteNumber, stealer_velocity, stealer_extendedConnectionBlocks, stealer_channelmixer, stealer_releaseTriggered);
+				stealer_releaseTriggered = false;
+				stealer_channel = null;
+				stealer_performer = null;				
+				stealer_voiceID = -1;
+				stealer_noteNumber = 0;
+				stealer_velocity = 0;
+				stealer_extendedConnectionBlocks = null;
+				stealer_channelmixer = null;
+			}
+		}
+		if (started) {
+			audiostarted = true;
+			
+			ModelOscillator osc = performer.oscillators[0];
+
+			osc_stream_off_transmitted = false;
+			if (osc instanceof ModelWavetable) {
+				try {
+					resampler.open((ModelWavetable) osc, synthesizer
+							.getFormat().getSampleRate());
+					osc_stream = resampler;
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			} else {
+				osc_stream = osc.open(synthesizer.getFormat().getSampleRate());
+			}
+			osc_attenuation = osc.getAttenuation();
+			osc_stream_nrofchannels = osc.getChannels();
+			if (osc_buff == null || osc_buff.length < osc_stream_nrofchannels)
+				osc_buff = new float[osc_stream_nrofchannels][];
+
+			if (osc_stream != null)
+				osc_stream.noteOn(softchannel, this, noteOn_noteNumber,
+						noteOn_velocity);
+						
+
+		}
+		if (audiostarted) {
+			
+			if (portamento) {
+
+				double note_delta = tunedKey - (co_noteon_keynumber[0] * 128);
+				double note_delta_a = Math.abs(note_delta);
+				if (note_delta_a < 0.0000000001) {
+					co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
+					;
+					portamento = false;
+
+				} else {
+					if (note_delta_a > softchannel.portamento_time)
+						note_delta = Math.signum(note_delta)
+								* softchannel.portamento_time;
+					co_noteon_keynumber[0] += note_delta * (1.0 / 128.0);
+				}
+
+				int[] c = performer.midi_connections[4];
+				if (c == null)
+					return;
+				for (int i = 0; i < c.length; i++)
+					processConnection(c[i]);
+
+			}
+
+			eg.processControlLogic();			
+			lfo.processControlLogic();
+			
+			for (int i = 0; i < performer.ctrl_connections.length; i++)
+				processConnection(performer.ctrl_connections[i]);
+
+			osc_stream.setPitch((float) co_osc_pitch[0]);
+
+			int filter_type = (int) co_filter_type[0];
+			double filter_freq;
+			
+			if(co_filter_freq[0] == 13500.0)
+				filter_freq = 19912.126958213175;
+			else
+				filter_freq = 440.0 * Math.exp(
+						((co_filter_freq[0]) - 6900.0) * (Math.log(2.0)/ 1200.0));
+			/*
+				filter_freq = 440.0 * Math.pow(2.0,
+					((co_filter_freq[0]) - 6900.0) / 1200.0);*/
+			/*
+			 * double velocity = co_noteon_velocity[0]; if(velocity < 0.5)
+			 * filter_freq *= ((velocity * 2)*0.75 + 0.25);
+			 */
+			
+			double q = co_filter_q[0] / 10.0;
+			filter_left.setFilterType(filter_type);
+			filter_left.setFrequency(filter_freq);
+			filter_left.setResonance(q);
+			filter_right.setFilterType(filter_type);
+			filter_right.setFrequency(filter_freq);
+			filter_right.setResonance(q);
+			/*
+			float gain = (float) Math.pow(10,					
+					(-osc_attenuation + co_mixer_gain[0]) / 200.0);
+			*/
+			float gain = (float) Math.exp((					
+					(-osc_attenuation + co_mixer_gain[0]) * ( Math.log(10)/ 200.0))); 
+			
+			if (co_mixer_gain[0] <= -960)
+				gain = 0;
+
+			if (soundoff) {
+				stopping = true;
+				gain = 0;
+				/*
+				 * if(co_mixer_gain[0] > -960) co_mixer_gain[0] -= 960;
+				 */
+			}
+
+			volume = (int) (Math.sqrt(gain) * 128);
+
+			// gain *= 0.2;
+
+			double pan = co_mixer_pan[0] * (1.0 / 1000.0);
+			// System.out.println("pan = " + pan);
+			if (pan < 0)
+				pan = 0;
+			else if (pan > 1)
+				pan = 1;
+
+			if(pan == 0.5)
+			{
+				out_mixer_left = gain * 0.7071067811865476f;
+				out_mixer_right = out_mixer_left;				
+			}
+			else
+			{
+				out_mixer_left = gain * (float) Math.cos(pan * Math.PI * 0.5);
+				out_mixer_right = gain * (float) Math.sin(pan * Math.PI * 0.5);
+			}
+
+			double balance = co_mixer_balance[0] * (1.0 / 1000.0);
+			if(balance != 0.5)
+			{
+				if (balance > 0.5)
+					out_mixer_left *= (1 - balance) * 2;
+				else			
+					out_mixer_right *= balance * 2;
+			}
+
+			if(synthesizer.reverb_on)
+			{
+				out_mixer_effect1 = (float) (co_mixer_reverb[0] * (1.0 / 1000.0));
+				out_mixer_effect1 *= gain;
+			}
+			else
+				out_mixer_effect1 = 0;			
+			if(synthesizer.chorus_on)
+			{
+				out_mixer_effect2 = (float) (co_mixer_chorus[0] * (1.0 / 1000.0));
+				out_mixer_effect2 *= gain;
+			}
+			else
+				out_mixer_effect2 = 0;
+			out_mixer_end = co_mixer_active[0] < 0.5;
+
+			if (!on)
+				if (!osc_stream_off_transmitted) {
+					osc_stream_off_transmitted = true;
+					if (osc_stream != null)
+						osc_stream.noteOff(noteOff_velocity);
+				}
+			
+		}
+		if (started) {
+			last_out_mixer_left = out_mixer_left;
+			last_out_mixer_right = out_mixer_right;
+			last_out_mixer_effect1 = out_mixer_effect1;
+			last_out_mixer_effect2 = out_mixer_effect2;
+			started = false;
+		}
+				
+	}
+
+	protected void mixAudioStream(SoftAudioBuffer in, SoftAudioBuffer out,
+			float amp_from, float amp_to) {
+		int bufferlen = in.getSize();
+		if (amp_from < 0.000000001 && amp_to < 0.000000001)
+			return;
+		if (amp_from == amp_to) {
+			float[] fout = out.array();
+			float[] fin = in.array();
+			for (int i = 0; i < bufferlen; i++)
+				fout[i] += fin[i] * amp_to;
+		} else {
+			float amp = amp_from;
+			float amp_delta = (amp_to - amp_from) / bufferlen;
+			float[] fout = out.array();
+			float[] fin = in.array();
+			for (int i = 0; i < bufferlen; i++) {
+				amp += amp_delta;
+				fout[i] += fin[i] * amp;
+			}
+		}
+
+	}
+	
+	protected void processAudioLogic(SoftAudioBuffer[] buffer) {
+		if (!audiostarted)
+			return;
+		
+		int bufferlen = buffer[0].getSize();
+ 
+		try {
+			osc_buff[0] = buffer[SoftMainMixer.CHANNEL_LEFT_DRY].array();
+			if(nrofchannels != 1)
+				osc_buff[1] = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY].array();
+			int ret = osc_stream.read(osc_buff, 0, bufferlen);
+			if (ret == -1) {
+				stopping = true;
+				return;
+			}
+			if (ret != bufferlen) {				
+				Arrays.fill(osc_buff[0], ret, bufferlen, 0f);
+				if(nrofchannels != 1)
+					Arrays.fill(osc_buff[1], ret, bufferlen, 0f);
+			}
+
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		
+		SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT];
+		SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT];
+		SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1];
+		SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2];
+		SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY];
+		SoftAudioBuffer rightdry = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY];
+
+		if (osc_stream_nrofchannels == 1)
+			rightdry = null;
+
+		if (!Double.isInfinite(co_filter_freq[0])) {
+			filter_left.processAudio(leftdry);
+			if (rightdry != null)
+				filter_right.processAudio(rightdry);
+		}
+
+		if (nrofchannels == 1) {
+			out_mixer_left = (out_mixer_left + out_mixer_right) / 2;
+			mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
+			if (rightdry != null)
+				mixAudioStream(rightdry, left, last_out_mixer_left,
+						out_mixer_left);
+		} else {
+			mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
+			if (rightdry != null)
+				mixAudioStream(rightdry, right, last_out_mixer_right,
+						out_mixer_right);
+			else
+				mixAudioStream(leftdry, right, last_out_mixer_right,
+						out_mixer_right);
+		}
+
+		if (rightdry == null) {			
+			mixAudioStream(leftdry, eff1, last_out_mixer_effect1,
+					out_mixer_effect1);
+			mixAudioStream(leftdry, eff2, last_out_mixer_effect2,
+					out_mixer_effect2);
+		} else {
+			mixAudioStream(leftdry, eff1, last_out_mixer_effect1 * 0.5f,
+					out_mixer_effect1 * 0.5f);
+			mixAudioStream(leftdry, eff2, last_out_mixer_effect2 * 0.5f,
+					out_mixer_effect2 * 0.5f);
+			mixAudioStream(rightdry, eff1, last_out_mixer_effect1 * 0.5f,
+					out_mixer_effect1 * 0.5f);
+			mixAudioStream(rightdry, eff2, last_out_mixer_effect2 * 0.5f,
+					out_mixer_effect2 * 0.5f);
+		}
+
+		last_out_mixer_left = out_mixer_left;
+		last_out_mixer_right = out_mixer_right;
+		last_out_mixer_effect1 = out_mixer_effect1;
+		last_out_mixer_effect2 = out_mixer_effect2;
+
+		if (out_mixer_end) {
+			stopping = true;
+		}
+		
+
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.UnsupportedAudioFileException;
+import javax.sound.sampled.spi.AudioFileReader;
+
+/**
+ * Floating-point encoded (format 3) WAVE file loader.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class WaveFloatFileReader extends AudioFileReader {
+
+	public AudioFileFormat getAudioFileFormat(InputStream stream)
+			throws UnsupportedAudioFileException, IOException {
+
+		stream.mark(200);
+		AudioFileFormat format;
+		try {
+			format = internal_getAudioFileFormat(stream);
+		} finally {
+			stream.reset();
+		}
+		return format;
+	}
+
+	private AudioFileFormat internal_getAudioFileFormat(InputStream stream)
+			throws UnsupportedAudioFileException, IOException {
+
+		RIFFReader riffiterator = new RIFFReader(stream);
+		if (!riffiterator.getFormat().equals("RIFF"))
+			throw new UnsupportedAudioFileException();
+		if (!riffiterator.getType().equals("WAVE"))
+			throw new UnsupportedAudioFileException();
+
+		boolean fmt_found = false;
+		boolean data_found = false;
+
+		int channels = 1;
+		long samplerate = 1;
+		long framerate = 1;
+		int framesize = 1;
+		int bits = 1;
+
+		while (riffiterator.hasNextChunk()) {
+			RIFFReader chunk = riffiterator.nextChunk();
+
+			if (chunk.getFormat().equals("fmt ")) {
+				fmt_found = true;
+
+				int format = chunk.readUnsignedShort();
+				if (format != 3)
+					throw new UnsupportedAudioFileException(); // WAVE_FORMAT_IEEE_FLOAT
+																// only
+				channels = chunk.readUnsignedShort();
+				samplerate = chunk.readUnsignedInt();
+				framerate = chunk.readUnsignedInt();
+				framesize = chunk.readUnsignedShort();
+				bits = chunk.readUnsignedShort();
+
+			}
+			if (chunk.getFormat().equals("data")) {
+				data_found = true;
+				break;
+			}
+		}
+
+		if (!fmt_found)
+			throw new UnsupportedAudioFileException();
+		if (!data_found)
+			throw new UnsupportedAudioFileException();
+
+		AudioFormat audioformat = new AudioFormat(
+				AudioFloatConverter.PCM_FLOAT, samplerate, bits, channels,
+				framesize, framerate, false);
+		AudioFileFormat fileformat = new AudioFileFormat(
+				AudioFileFormat.Type.WAVE, audioformat,
+				AudioSystem.NOT_SPECIFIED);
+		return fileformat;
+	}
+
+	public AudioInputStream getAudioInputStream(InputStream stream)
+			throws UnsupportedAudioFileException, IOException {
+
+		AudioFileFormat format = getAudioFileFormat(stream);
+		RIFFReader riffiterator = new RIFFReader(stream);
+		if (!riffiterator.getFormat().equals("RIFF"))
+			throw new UnsupportedAudioFileException();
+		if (!riffiterator.getType().equals("WAVE"))
+			throw new UnsupportedAudioFileException();
+		while (riffiterator.hasNextChunk()) {
+			RIFFReader chunk = riffiterator.nextChunk();
+			if (chunk.getFormat().equals("data")) {
+				return new AudioInputStream(chunk, format.getFormat(), chunk
+						.getSize());
+			}
+		}
+		throw new UnsupportedAudioFileException();
+	}
+
+	public AudioFileFormat getAudioFileFormat(URL url)
+			throws UnsupportedAudioFileException, IOException {
+		InputStream stream = url.openStream();
+		AudioFileFormat format;
+		try {
+			format = getAudioFileFormat(new BufferedInputStream(stream));
+		} finally {
+			stream.close();
+		}
+		return format;
+	}
+
+	public AudioFileFormat getAudioFileFormat(File file)
+			throws UnsupportedAudioFileException, IOException {
+		InputStream stream = new FileInputStream(file);
+		AudioFileFormat format;
+		try {
+			format = getAudioFileFormat(new BufferedInputStream(stream));
+		} finally {
+			stream.close();
+		}
+		return format;
+	}
+
+	public AudioInputStream getAudioInputStream(URL url)
+			throws UnsupportedAudioFileException, IOException {
+		return getAudioInputStream(new BufferedInputStream(url.openStream()));
+	}
+
+	public AudioInputStream getAudioInputStream(File file)
+			throws UnsupportedAudioFileException, IOException {
+		return getAudioInputStream(new BufferedInputStream(new FileInputStream(
+				file)));
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/icedtea-gervill.patch	Wed Apr 30 22:09:08 2008 +0200
@@ -0,0 +1,30 @@
+# Adds the provides defined by gervill (and removes non-existing ones).
+# Gervill can be found in the overlays under
+# openjdk/jdk/src/share/classes/com/sun/media/sound
+--- openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider.orig	2008-04-30 16:12:37.000000000 +0200
++++ openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider	2008-04-30 16:06:18.000000000 +0200
+@@ -1,5 +1,5 @@
+ # Providers for midi devices
+-com.sun.media.sound.MixerSynthProvider
+ com.sun.media.sound.RealTimeSequencerProvider
+ com.sun.media.sound.MidiOutDeviceProvider
+ com.sun.media.sound.MidiInDeviceProvider
++com.sun.media.sound.SoftProvider
+--- openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader.orig	2008-04-30 16:13:18.000000000 +0200
++++ openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader	2008-04-30 16:07:16.000000000 +0200
+@@ -1,2 +1,6 @@
+ # Providers for Soundbanks
+-com.sun.media.sound.HsbParser
++com.sun.media.sound.PATSoundbankReader
++com.sun.media.sound.DLSSoundbankReader
++com.sun.media.sound.JARSoundbankReader
++com.sun.media.sound.AudioFileSoundbankReader
++com.sun.media.sound.SF2SoundbankReader
+--- openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader.orig	2008-04-30 16:13:58.000000000 +0200
++++ openjdk/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader	2008-04-30 16:01:27.000000000 +0200
+@@ -2,3 +2,5 @@
+ com.sun.media.sound.AuFileReader
+ com.sun.media.sound.AiffFileReader
+ com.sun.media.sound.WaveFileReader
++com.sun.media.sound.WaveFloatFileReader
++com.sun.media.sound.SoftMidiAudioFileReader