changeset 851:4706d355d973

Import new Gervill CVS. 2008-05-04 Mark Wielaard <mark@klomp.org> * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound: Import new Gervill CVS. See CHANGES.txt. Changed: AudioFloatConverter.java, DLSSoundbank.java, SoftChannel.java, WaveFloatFileReader.java. Added: AudioFloatFormatConverter.java, WaveExtensibleFileReader.java, WaveFloatFileWriter.java. Deleted: PATInstrument.java, PATSample.java, PATSoundbankReader.java.
author Mark Wielaard <mark@klomp.org>
date Mon, 05 May 2008 00:31:45 +0200
parents a952ab0e58fb
children dce24bd81691
files ChangeLog overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.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/SoftChannel.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileWriter.java
diffstat 12 files changed, 1426 insertions(+), 973 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun May 04 23:35:04 2008 +0200
+++ b/ChangeLog	Mon May 05 00:31:45 2008 +0200
@@ -1,3 +1,12 @@
+2008-05-04  Mark Wielaard  <mark@klomp.org>
+
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound:
+	Import new Gervill CVS. See CHANGES.txt. Changed:
+	AudioFloatConverter.java, DLSSoundbank.java, SoftChannel.java,
+	WaveFloatFileReader.java. Added: AudioFloatFormatConverter.java,
+	WaveExtensibleFileReader.java, WaveFloatFileWriter.java. Deleted:
+	PATInstrument.java, PATSample.java, PATSoundbankReader.java.
+
 2008-05-04  Mark Wielaard  <mark@klomp.org>
 
 	* Makefile.am (EXTRA_DIST): Add patches/icedtea-hat-spl-gpl.patch.
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java	Sun May 04 23:35:04 2008 +0200
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java	Mon May 05 00:31:45 2008 +0200
@@ -27,13 +27,14 @@
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.nio.DoubleBuffer;
 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
+ * This class is used to convert between 8,16,24,32,32+ bit signed/unsigned
  * big/litle endian fixed/floating point byte buffers and float buffers.
  * 
  * @version %I%, %E%
@@ -43,6 +44,173 @@
 public abstract class AudioFloatConverter {
 
 	public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");
+	
+	/***************************************************************************
+	 * 
+	 * LSB Filter, used filter least significant byte in samples arrays.
+	 * 
+	 * Is used filter out data in lsb byte 
+	 * when SampleSizeInBits is not dividable by 8.
+	 * 
+	 **************************************************************************/
+	
+	private static class AudioFloatLSBFilter extends AudioFloatConverter {
+		
+		private AudioFloatConverter converter;
+		final private int offset;
+		final private int stepsize;
+		final private byte mask;		
+		private byte[] mask_buffer;
+		
+		public AudioFloatLSBFilter(AudioFloatConverter converter, AudioFormat format)
+		{
+			int bits = format.getSampleSizeInBits();
+			boolean bigEndian = format.isBigEndian();
+			this.converter = converter;
+			stepsize = (bits + 7) / 8;
+			offset = bigEndian?(stepsize - 1):0;
+			int lsb_bits = bits % 8;
+			if(lsb_bits == 0) mask = (byte)0x00;
+			else if(lsb_bits == 1) mask = (byte)0x80;
+			else if(lsb_bits == 2) mask = (byte)0xC0;
+			else if(lsb_bits == 3) mask = (byte)0xE0;
+			else if(lsb_bits == 4) mask = (byte)0xF0;
+			else if(lsb_bits == 5) mask = (byte)0xF8;
+			else if(lsb_bits == 6) mask = (byte)0xFC;
+			else if(lsb_bits == 7) mask = (byte)0xFE;
+			else mask = (byte)0xFF;
+		}
+
+		public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, byte[] out_buff, int out_offset) {
+			byte[] ret = converter.toByteArray(in_buff, in_offset, in_len, out_buff, out_offset);
+			
+			int out_offset_end = in_len*stepsize;
+			for (int i = out_offset+offset; i < out_offset_end; i+=stepsize) {
+				out_buff[i] = (byte)(out_buff[i] & mask); 
+			}
+			
+			return ret;
+		}
+
+		public float[] toFloatArray(byte[] in_buff, int in_offset, float[] out_buff, int out_offset, int out_len) {
+			if(mask_buffer == null || mask_buffer.length < in_buff.length)
+				mask_buffer = new byte[in_buff.length];
+			System.arraycopy(in_buff, 0, mask_buffer, 0, in_buff.length);
+			int in_offset_end = out_len*stepsize;
+			for (int i = in_offset+offset; i < in_offset_end; i+=stepsize) {
+				mask_buffer[i] = (byte)(mask_buffer[i] & mask); 
+			}
+			float[] ret = converter.toFloatArray(mask_buffer, in_offset, out_buff, out_offset, out_len);
+			return ret;
+		}
+		
+	}
+	
+	/***************************************************************************
+	 * 
+	 * 64 bit float, little/big-endian
+	 * 
+	 **************************************************************************/
+
+	// PCM 64 bit float, little-endian
+	private static class AudioFloatConversion64L extends AudioFloatConverter {
+		ByteBuffer bytebuffer = null;
+
+		DoubleBuffer floatbuffer = null;
+		double[] double_buff = null;
+
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int in_len = out_len * 8;
+			if (bytebuffer == null || bytebuffer.capacity() < in_len) {
+				bytebuffer = ByteBuffer.allocate(in_len).order(
+						ByteOrder.LITTLE_ENDIAN);
+				floatbuffer = bytebuffer.asDoubleBuffer();
+			}
+			bytebuffer.position(0);
+			floatbuffer.position(0);
+			bytebuffer.put(in_buff, in_offset, in_len);
+			if(double_buff == null || double_buff.length < out_len+out_offset)
+				double_buff = new double[out_len+out_offset];
+			floatbuffer.get(double_buff, out_offset, out_len);
+			int out_offset_end = out_offset + out_len;
+			for (int i = out_offset; i < out_offset_end; i++) {
+				out_buff[i] = (float)double_buff[i];
+			}
+			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 * 8;
+			if (bytebuffer == null || bytebuffer.capacity() < out_len) {
+				bytebuffer = ByteBuffer.allocate(out_len).order(
+						ByteOrder.LITTLE_ENDIAN);
+				floatbuffer = bytebuffer.asDoubleBuffer();
+			}
+			floatbuffer.position(0);
+			bytebuffer.position(0);
+			if(double_buff == null || double_buff.length < in_offset+in_len)
+				double_buff = new double[in_offset+in_len];
+			int in_offset_end = in_offset+in_len;
+			for (int i = in_offset; i < in_offset_end; i++) {
+				double_buff[i] = in_buff[i];
+			}			
+			floatbuffer.put(double_buff, in_offset, in_len);
+			bytebuffer.get(out_buff, out_offset, out_len);
+			return out_buff;
+		}
+	}
+
+	// PCM 64 bit float, big-endian
+	private static class AudioFloatConversion64B extends AudioFloatConverter {
+		ByteBuffer bytebuffer = null;
+
+		DoubleBuffer floatbuffer = null;
+		double[] double_buff = null;
+
+		public float[] toFloatArray(byte[] in_buff, int in_offset,
+				float[] out_buff, int out_offset, int out_len) {
+			int in_len = out_len * 8;
+			if (bytebuffer == null || bytebuffer.capacity() < in_len) {
+				bytebuffer = ByteBuffer.allocate(in_len).order(
+						ByteOrder.BIG_ENDIAN);
+				floatbuffer = bytebuffer.asDoubleBuffer();
+			}
+			bytebuffer.position(0);
+			floatbuffer.position(0);
+			bytebuffer.put(in_buff, in_offset, in_len);
+			if(double_buff == null || double_buff.length < out_len+out_offset)
+				double_buff = new double[out_len+out_offset];
+			floatbuffer.get(double_buff, out_offset, out_len);
+			int out_offset_end = out_offset + out_len;
+			for (int i = out_offset; i < out_offset_end; i++) {
+				out_buff[i] = (float)double_buff[i];
+			}
+			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 * 8;
+			if (bytebuffer == null || bytebuffer.capacity() < out_len) {
+				bytebuffer = ByteBuffer.allocate(out_len).order(
+						ByteOrder.BIG_ENDIAN);
+				floatbuffer = bytebuffer.asDoubleBuffer();
+			}
+			floatbuffer.position(0);
+			bytebuffer.position(0);
+			if(double_buff == null || double_buff.length < in_offset+in_len)
+				double_buff = new double[in_offset+in_len];
+			int in_offset_end = in_offset+in_len;
+			for (int i = in_offset; i < in_offset_end; i++) {
+				double_buff[i] = in_buff[i];
+			}						
+			floatbuffer.put(double_buff, in_offset, in_len);
+			bytebuffer.get(out_buff, out_offset, out_len);
+			return out_buff;
+		}
+	}
 
 	/***************************************************************************
 	 * 
@@ -549,14 +717,196 @@
 		}
 	}
 
+	/***************************************************************************
+	 * 
+	 * 32+ bit signed/unsigned, little/big-endian
+	 * 
+	 **************************************************************************/
+
+	// PCM 32+ bit, signed, little-endian
+	private static class AudioFloatConversion32xSL extends AudioFloatConverter {
+
+		final int xbytes;
+
+		public AudioFloatConversion32xSL(int xbytes)
+		{
+			this.xbytes = xbytes;
+		}
+
+		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++) {
+				ix += xbytes;
+				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);
+				for (int j = 0; j < xbytes; j++) {
+					out_buff[ox++] = 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 AudioFloatConversion32xSB extends AudioFloatConverter {
+
+		final int xbytes;
+
+		public AudioFloatConversion32xSB(int xbytes)
+		{
+			this.xbytes = xbytes;
+		}
+
+		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);
+				ix += xbytes;				
+				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;
+				for (int j = 0; j < xbytes; j++) {
+					out_buff[ox++] = 0;	
+				}				
+			}
+			return out_buff;
+		}
+	}
+
+	// PCM 32+ bit, unsigned, little-endian
+	private static class AudioFloatConversion32xUL extends AudioFloatConverter {
+
+		final int xbytes;
+
+		public AudioFloatConversion32xUL(int xbytes)
+		{
+			this.xbytes = xbytes;
+		}
+
+		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++) {
+				ix += xbytes;				
+				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;
+				for (int j = 0; j < xbytes; j++) {
+					out_buff[ox++] = 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, unsigned, big-endian
+	private static class AudioFloatConversion32xUB extends AudioFloatConverter {
+
+		final int xbytes;
+
+		public AudioFloatConversion32xUB(int xbytes)
+		{
+			this.xbytes = xbytes;
+		}
+
+		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);
+				ix += xbytes;
+				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;
+				for (int j = 0; j < xbytes; j++) {
+					out_buff[ox++] = 0;	
+				}				
+			}
+			return out_buff;
+		}
+	}
+	
+	
 	public static AudioFloatConverter getConverter(AudioFormat format) {
 		AudioFloatConverter conv = null;
-		if (format.getFrameSize() != (format.getSampleSizeInBits() / 8)
+		if (format.getFrameSize() == 0) return null;
+		if (format.getFrameSize() != ((format.getSampleSizeInBits()+7) / 8)
 				* format.getChannels())
 			return null;
 		if (format.getEncoding().equals(Encoding.PCM_SIGNED)) {
 			if (format.isBigEndian()) {
-				if (format.getSampleSizeInBits() == 8)
+				if (format.getSampleSizeInBits() <= 8)
 					conv = new AudioFloatConversion8S();
 				else if (format.getSampleSizeInBits() > 8
 						&& format.getSampleSizeInBits() <= 16)
@@ -567,8 +917,10 @@
 				else if (format.getSampleSizeInBits() > 24
 						&& format.getSampleSizeInBits() <= 32)
 					conv = new AudioFloatConversion32SB();
+				else if (format.getSampleSizeInBits() > 32)
+					conv = new AudioFloatConversion32xSB(((format.getSampleSizeInBits()+7)/8)-4);
 			} else {
-				if (format.getSampleSizeInBits() == 8)
+				if (format.getSampleSizeInBits() <= 8)
 					conv = new AudioFloatConversion8S();
 				else if (format.getSampleSizeInBits() > 8
 						& format.getSampleSizeInBits() <= 16)
@@ -579,10 +931,12 @@
 				else if (format.getSampleSizeInBits() > 24
 						&& format.getSampleSizeInBits() <= 32)
 					conv = new AudioFloatConversion32SL();
+				else if (format.getSampleSizeInBits() > 32)
+					conv = new AudioFloatConversion32xSL(((format.getSampleSizeInBits()+7)/8)-4);				
 			}
 		} else if (format.getEncoding().equals(Encoding.PCM_UNSIGNED)) {
 			if (format.isBigEndian()) {
-				if (format.getSampleSizeInBits() == 8)
+				if (format.getSampleSizeInBits() <= 8)
 					conv = new AudioFloatConversion8U();
 				else if (format.getSampleSizeInBits() > 8
 						&& format.getSampleSizeInBits() <= 16)
@@ -593,8 +947,10 @@
 				else if (format.getSampleSizeInBits() > 24
 						&& format.getSampleSizeInBits() <= 32)
 					conv = new AudioFloatConversion32UB();
+				else if (format.getSampleSizeInBits() > 32)
+					conv = new AudioFloatConversion32xUB(((format.getSampleSizeInBits()+7)/8)-4);				
 			} else {
-				if (format.getSampleSizeInBits() == 8)
+				if (format.getSampleSizeInBits() <= 8)
 					conv = new AudioFloatConversion8U();
 				else if (format.getSampleSizeInBits() > 8
 						&& format.getSampleSizeInBits() <= 16)
@@ -605,6 +961,8 @@
 				else if (format.getSampleSizeInBits() > 24
 						&& format.getSampleSizeInBits() <= 32)
 					conv = new AudioFloatConversion32UL();
+				else if (format.getSampleSizeInBits() > 32)
+					conv = new AudioFloatConversion32xUL(((format.getSampleSizeInBits()+7)/8)-4);				
 			}
 		} else if (format.getEncoding().equals(PCM_FLOAT)) {
 			if (format.getSampleSizeInBits() == 32) {
@@ -613,6 +971,20 @@
 				else
 					conv = new AudioFloatConversion32L();
 			}
+			else
+				if (format.getSampleSizeInBits() == 64) {
+					if (format.isBigEndian())
+						conv = new AudioFloatConversion64B();
+					else
+						conv = new AudioFloatConversion64L();
+				}
+				
+		}
+		
+		if ((format.getEncoding().equals(Encoding.PCM_SIGNED) ||
+			format.getEncoding().equals(Encoding.PCM_UNSIGNED)) 
+		   && (format.getSampleSizeInBits() % 8 != 0)) {
+			conv = new AudioFloatLSBFilter(conv, format);
 		}
 
 		if (conv != null)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java	Mon May 05 00:31:45 2008 +0200
@@ -0,0 +1,523 @@
+/*
+ * 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.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.AudioFormat.Encoding;
+import javax.sound.sampled.spi.FormatConversionProvider;
+
+/**
+ * This class is used to convert between 8,16,24,32 bit signed/unsigned
+ * big/litle endian fixed/floating stereo/mono/multi-channel audio streams
+ * and perform sample-rate conversion if needed.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class AudioFloatFormatConverter extends FormatConversionProvider {
+
+	private class AudioFloatFormatConverterInputStream extends InputStream
+	{
+		private AudioFloatConverter converter;
+		private AudioFloatInputStream stream;
+		private float[] readfloatbuffer;
+		private int fsize = 0;
+		
+		public AudioFloatFormatConverterInputStream(AudioFormat targetFormat, AudioFloatInputStream stream)
+		{
+			this.stream = stream;
+			converter = AudioFloatConverter.getConverter(targetFormat);
+			fsize = ((targetFormat.getSampleSizeInBits()+7) / 8);
+		}
+
+		public int read() throws IOException {
+			byte[] b = new byte[1];
+			int ret = read(b);
+			if(ret < 0) return ret;
+			return b[0] & 0xFF;
+		}
+		
+		public int read(byte[] b, int off, int len) throws IOException {
+			
+			int flen = len / fsize; 
+			if(readfloatbuffer == null || readfloatbuffer.length < flen)
+				readfloatbuffer = new float[flen];		
+			int ret = stream.read(readfloatbuffer, 0, flen);
+			if(ret < 0) return ret;			
+			converter.toByteArray(readfloatbuffer, 0, ret, b, off);			
+			return ret*fsize;
+		}
+
+		public int available() throws IOException {
+			int ret = stream.available();
+			if(ret < 0) return ret;
+			return ret * fsize;
+		}
+
+		public void close() throws IOException {
+			stream.close();
+		}
+
+		public synchronized void mark(int readlimit) {
+			stream.mark(readlimit*fsize);
+		}
+
+		public boolean markSupported() {
+			return stream.markSupported();
+		}
+
+		public synchronized void reset() throws IOException {
+			stream.reset();
+		}
+
+		public long skip(long n) throws IOException {
+			long ret = stream.skip(n/fsize);
+			if(ret < 0) return ret;
+			return ret*fsize;
+		}
+		
+	}
+	
+	private class AudioFloatInputStreamChannelMixer extends AudioFloatInputStream
+	{
+		
+		private int targetChannels;
+		private int sourceChannels;
+		private AudioFloatInputStream ais;
+		private AudioFormat targetFormat;
+		private float[] conversion_buffer;
+		
+		public AudioFloatInputStreamChannelMixer(AudioFloatInputStream ais, int targetChannels)
+		{
+			this.sourceChannels = ais.getFormat().getChannels();
+			this.targetChannels = targetChannels;
+			this.ais = ais;
+			AudioFormat format = ais.getFormat();
+			targetFormat = new AudioFormat(format.getEncoding(), format.getSampleRate(), 
+					format.getSampleSizeInBits(), targetChannels,
+					(format.getFrameSize()/sourceChannels)*targetChannels, format.getFrameRate(), format.isBigEndian());			
+		}
+
+		public int available() throws IOException {
+			return (ais.available()/sourceChannels)*targetChannels;
+		}
+
+		public void close() throws IOException {
+			ais.close();
+		}
+
+		public AudioFormat getFormat() {
+			return targetFormat;
+		}
+
+		public long getFrameLength() {
+			return ais.getFrameLength();
+		}
+
+		public void mark(int readlimit) {
+			ais.mark((readlimit/targetChannels)*sourceChannels);			
+		}
+
+		public boolean markSupported() {
+			return ais.markSupported();
+		}
+
+		public int read(float[] b, int off, int len) throws IOException {			
+			int len2 = (len / targetChannels)*sourceChannels;
+			if(conversion_buffer == null || conversion_buffer.length < len2)
+				conversion_buffer = new float[len2];
+			int ret = ais.read(conversion_buffer, 0, len2);
+			if(ret < 0) return ret;
+			if(sourceChannels == 1)
+			{
+				int cs = targetChannels;
+				for (int c = 0; c < targetChannels; c++) {
+					for (int i = 0, ix = off+c; i < len2; i++, ix+=cs) {
+						b[ix] = conversion_buffer[i];;
+					}
+				}
+			}
+			else
+			if(targetChannels == 1)
+			{
+				int cs = sourceChannels;
+				for (int i = 0, ix = off; i < len2; i+=cs, ix++) {
+					b[ix] = conversion_buffer[i];
+				}
+				for (int c = 1; c < sourceChannels; c++) {
+					for (int i = c, ix = off; i < len2; i+=cs, ix++) {
+						b[ix] += conversion_buffer[i];;
+					}
+				}
+				float vol = 1f / ((float)sourceChannels);
+				for (int i = 0, ix = off; i < len2; i+=cs, ix++) {
+					b[ix] *= vol;
+				}
+			}
+			else
+			{
+				int minChannels = Math.min(sourceChannels, targetChannels);
+				int off_len = off + len;
+				int ct = targetChannels;
+				int cs = sourceChannels;
+				for (int c = 0; c < minChannels; c++) {
+					for (int i = off+c, ix = c; i < off_len; i+=ct, ix+=cs) {
+						b[i] = conversion_buffer[ix];
+					}
+				}
+				for (int c = minChannels; c < targetChannels; c++) {
+					for (int i = off+c; i < off_len; i+=ct) {
+						b[i] = 0;
+					}
+				}
+			}
+			return (ret / sourceChannels)*targetChannels;
+		}
+
+		public void reset() throws IOException {
+			ais.reset();
+		}
+
+		public long skip(long len) throws IOException {
+			long ret = ais.skip((len / targetChannels)*sourceChannels);
+			if(ret < 0) return ret;
+			return (ret / sourceChannels)*targetChannels;
+		}
+		
+	}
+	
+	private class AudioFloatInputStreamResampler extends AudioFloatInputStream
+	{
+		
+		private AudioFloatInputStream ais;
+		private AudioFormat targetFormat;
+		private float[] skipbuffer;		
+		private SoftAbstractResampler resampler;		
+		private float[] pitch = new float[1];
+		private float[] ibuffer2;
+		private float[][] ibuffer;
+		private float ibuffer_index = 0;
+		private int ibuffer_len = 0;
+		private int nrofchannels = 0;
+		private float[][] cbuffer;
+
+		private int buffer_len = 512;
+		private int pad;
+		private int pad2;
+		
+		private float[] ix = new float[1];
+		private int[] ox = new int[1];
+
+		private float[][] mark_ibuffer = null;
+		private float mark_ibuffer_index = 0;
+		private int mark_ibuffer_len = 0;		
+		
+		public AudioFloatInputStreamResampler(AudioFloatInputStream ais, AudioFormat format)
+		{
+			this.ais = ais;
+			AudioFormat sourceFormat = ais.getFormat();
+			targetFormat = new AudioFormat(sourceFormat.getEncoding(), format.getSampleRate(), 
+					sourceFormat.getSampleSizeInBits(), sourceFormat.getChannels(),
+					sourceFormat.getFrameSize(), format.getSampleRate(), sourceFormat.isBigEndian());
+			nrofchannels = targetFormat.getChannels();			
+			Object interpolation = format.getProperty("interpolation");
+			if(interpolation != null && (interpolation instanceof String))
+			{
+				String resamplerType = (String)interpolation;			
+				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();
+			}
+			if(resampler == null) resampler = new SoftLinearResampler2(); // new SoftLinearResampler2();
+			pitch[0] = sourceFormat.getSampleRate() / format.getSampleRate();
+			pad = resampler.getPadding();
+			pad2 = pad*2;
+			ibuffer = new float[nrofchannels][buffer_len + pad2];
+			ibuffer2 = new float[nrofchannels*buffer_len];
+			ibuffer_index = buffer_len + pad;		
+			ibuffer_len = buffer_len;
+		}
+
+		public int available() throws IOException {
+			return 0;
+		}
+
+		public void close() throws IOException {
+			ais.close();			
+		}
+
+		public AudioFormat getFormat() {
+			return targetFormat;
+		}
+
+		public long getFrameLength() {
+			return AudioSystem.NOT_SPECIFIED; // ais.getFrameLength();
+		}
+
+		public void mark(int readlimit) {
+			ais.mark((int)(readlimit*pitch[0]));			
+			mark_ibuffer_index = ibuffer_index;
+			mark_ibuffer_len = ibuffer_len;			
+			if(mark_ibuffer == null)
+			{
+				mark_ibuffer = new float[ibuffer.length][ibuffer[0].length];
+			}
+			for (int c = 0; c < ibuffer.length; c++) {				
+				float[] from = ibuffer[c] ;
+				float[] to = mark_ibuffer[c] ;
+				for (int i = 0; i < to.length; i++) {
+					to[i] = from[i];
+				}
+			}						
+		}
+
+		public boolean markSupported() {
+			return ais.markSupported();
+		}
+		
+		
+		private void readNextBuffer() throws IOException
+		{
+			
+			if(ibuffer_len == -1) return;
+			
+			for (int c = 0; c < nrofchannels; c++) {				
+				float[] buff = ibuffer[c] ;
+				int buffer_len_pad = ibuffer_len+pad2;
+				for (int i = ibuffer_len, ix = 0; i < buffer_len_pad; i++, ix++) {
+					buff[ix] = buff[i];
+				}
+			}			
+
+			ibuffer_index -= (ibuffer_len);
+			
+			ibuffer_len = ais.read(ibuffer2);
+			if(ibuffer_len >= 0) 
+			{
+				while(ibuffer_len < ibuffer2.length)
+				{
+				   int ret = ais.read(ibuffer2, ibuffer_len, ibuffer2.length - ibuffer_len);
+				   if(ret == -1) break;
+				   ibuffer_len += ret;
+				}
+				Arrays.fill(ibuffer2, ibuffer_len, ibuffer2.length, 0);
+				ibuffer_len /= nrofchannels;				
+			}
+			else
+			{
+				Arrays.fill(ibuffer2, 0, ibuffer2.length, 0);
+			}
+						
+			int ibuffer2_len = ibuffer2.length;
+			for (int c = 0; c < nrofchannels; c++) {				
+				float[] buff = ibuffer[c] ;
+				for (int i = c, ix = pad2; i < ibuffer2_len; i+=nrofchannels, ix++) {
+					buff[ix] = ibuffer2[i];
+				}
+			}
+						
+		}		
+		
+		public int read(float[] b, int off, int len) throws IOException {
+			
+			if(cbuffer == null || cbuffer[0].length < len/nrofchannels)
+			{
+				cbuffer = new float[nrofchannels][len / nrofchannels]; 
+			}
+			if(ibuffer_len == -1) return -1;
+			if(len < 0) return 0;
+			int remain = len/nrofchannels;
+			int destPos = 0;			
+			int in_end = ibuffer_len;
+			while(remain > 0)
+			{
+				if(ibuffer_len < 0)
+				{
+					in_end = pad2;
+					if(ibuffer_index > in_end) break;	
+				}
+				else
+				{
+					if(ibuffer_index >= (ibuffer_len+pad)) 
+						readNextBuffer();
+					in_end = ibuffer_len+pad;
+				}
+				if(ibuffer_index < 0) 
+					break;
+				int preDestPos = destPos;
+				for (int c = 0; c < nrofchannels; c++) {
+					ix[0] = ibuffer_index;
+					ox[0] = destPos;
+					float[] buff = ibuffer[c] ;
+					resampler.interpolate(buff, ix, in_end, pitch, 0, cbuffer[c], ox, len / nrofchannels);
+				}
+				ibuffer_index = ix[0];
+				destPos = ox[0];	
+				remain -= destPos - preDestPos;
+			}			
+			for (int c = 0; c < nrofchannels; c++) {
+				int ix = 0;
+				float[] buff = cbuffer[c] ;
+				for (int i = c; i < b.length; i+=nrofchannels) {
+					b[i] = buff[ix++];
+				}
+			}
+			return len - remain*nrofchannels;
+		}
+
+		public void reset() throws IOException {			
+			ais.reset();			
+			if(mark_ibuffer == null) return;
+			ibuffer_index = mark_ibuffer_index;
+			ibuffer_len = mark_ibuffer_len;					
+			for (int c = 0; c < ibuffer.length; c++) {				
+				float[] from = mark_ibuffer[c] ;
+				float[] to = ibuffer[c] ;
+				for (int i = 0; i < to.length; i++) {
+					to[i] = from[i];
+				}
+			}						
+			
+		}
+
+		public long skip(long len) throws IOException {
+			if(len > 0) return 0;
+			if(skipbuffer == null)
+			   skipbuffer = new float[1024*targetFormat.getFrameSize()];
+			float[] l_skipbuffer = skipbuffer;
+			long remain = len;
+			while(remain > 0)
+			{
+				int ret = read(l_skipbuffer, 0, (int)Math.min(remain, skipbuffer.length));
+				if(ret < 0) 
+				{
+					if(remain == len) return ret;
+					break;
+				}
+				remain -= ret;
+			}			
+			return len - remain;
+			
+		}
+		
+	}
+	
+	private Encoding[] formats = {Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED, AudioFloatConverter.PCM_FLOAT}; 
+	
+	public AudioInputStream getAudioInputStream(Encoding targetEncoding, AudioInputStream sourceStream) {
+		if(sourceStream.getFormat().getEncoding().equals(targetEncoding)) return sourceStream;
+		AudioFormat format = sourceStream.getFormat();
+		int channels = format.getChannels();
+		Encoding encoding = targetEncoding;
+		float samplerate = format.getSampleRate();
+		int bits = format.getSampleSizeInBits();
+		boolean bigendian = format.isBigEndian(); 
+		if(targetEncoding.equals(AudioFloatConverter.PCM_FLOAT)) bits = 32;
+		AudioFormat targetFormat = new AudioFormat(encoding, samplerate, bits, 
+				channels, channels*bits/8, samplerate, bigendian);  
+		return getAudioInputStream(targetFormat, sourceStream);
+	}
+	
+	public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream) {
+		if(!isConversionSupported(targetFormat, sourceStream.getFormat()))
+			throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetFormat.toString());		
+		return getAudioInputStream(targetFormat, AudioFloatInputStream.getInputStream(sourceStream));
+	}
+	
+	public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioFloatInputStream sourceStream) {
+		
+		if(!isConversionSupported(targetFormat, sourceStream.getFormat()))
+			throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetFormat.toString());
+		if(targetFormat.getChannels() != sourceStream.getFormat().getChannels())
+			sourceStream = new AudioFloatInputStreamChannelMixer(sourceStream, targetFormat.getChannels());
+		if(Math.abs(targetFormat.getSampleRate() - sourceStream.getFormat().getSampleRate()) > 0.000001)
+			sourceStream = new AudioFloatInputStreamResampler(sourceStream, targetFormat);
+		return new AudioInputStream(
+				new AudioFloatFormatConverterInputStream(targetFormat, sourceStream), 
+				targetFormat, sourceStream.getFrameLength());  
+	}	
+
+	public Encoding[] getSourceEncodings() {
+		return formats;
+	}
+
+	public Encoding[] getTargetEncodings() {
+		return formats;
+	}
+
+	public Encoding[] getTargetEncodings(AudioFormat sourceFormat) {
+		if(AudioFloatConverter.getConverter(sourceFormat) == null) return new Encoding[0]; 
+		return formats;
+	}
+
+	public AudioFormat[] getTargetFormats(Encoding targetEncoding, AudioFormat sourceFormat) {
+		if(AudioFloatConverter.getConverter(sourceFormat) == null) return new AudioFormat[0];
+		int channels = sourceFormat.getChannels();
+		ArrayList<AudioFormat> formats = new ArrayList<AudioFormat>();
+		formats.add(new AudioFormat(Encoding.PCM_SIGNED, AudioSystem.NOT_SPECIFIED, 8, channels, channels, AudioSystem.NOT_SPECIFIED, false));
+		formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, AudioSystem.NOT_SPECIFIED, 8, channels, channels, AudioSystem.NOT_SPECIFIED, false));
+		for (int bits = 16; bits < 32; bits+=8) {			
+			formats.add(new AudioFormat(Encoding.PCM_SIGNED, AudioSystem.NOT_SPECIFIED, bits, channels, channels*bits/8, AudioSystem.NOT_SPECIFIED, false));
+			formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, AudioSystem.NOT_SPECIFIED, bits, channels, channels*bits/8, AudioSystem.NOT_SPECIFIED, false));
+			formats.add(new AudioFormat(Encoding.PCM_SIGNED, AudioSystem.NOT_SPECIFIED, bits, channels, channels*bits/8, AudioSystem.NOT_SPECIFIED, true));
+			formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, AudioSystem.NOT_SPECIFIED, bits, channels, channels*bits/8, AudioSystem.NOT_SPECIFIED, true));
+		}
+		formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, AudioSystem.NOT_SPECIFIED, 32, channels, channels*4, AudioSystem.NOT_SPECIFIED, false));
+		formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, AudioSystem.NOT_SPECIFIED, 32, channels, channels*4, AudioSystem.NOT_SPECIFIED, true));
+		formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, AudioSystem.NOT_SPECIFIED, 64, channels, channels*8, AudioSystem.NOT_SPECIFIED, false));
+		formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, AudioSystem.NOT_SPECIFIED, 64, channels, channels*8, AudioSystem.NOT_SPECIFIED, true));
+		return formats.toArray(new AudioFormat[formats.size()]);
+	}
+
+	public boolean isConversionSupported(AudioFormat targetFormat, AudioFormat sourceFormat) {
+		if(AudioFloatConverter.getConverter(sourceFormat) == null) return false;
+		if(AudioFloatConverter.getConverter(targetFormat) == null) return false;
+		if(sourceFormat.getChannels() <= 0) return false;
+		if(targetFormat.getChannels() <= 0) return false;
+		return true;
+	}
+
+	public boolean isConversionSupported(Encoding targetEncoding, AudioFormat sourceFormat) {
+		if(AudioFloatConverter.getConverter(sourceFormat) == null) return false;
+		for (int i = 0; i < formats.length; i++) {
+			if(targetEncoding.equals(formats[i])) return true;
+		}
+		return false;
+	}
+
+}
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt	Sun May 04 23:35:04 2008 +0200
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt	Mon May 05 00:31:45 2008 +0200
@@ -1,3 +1,22 @@
+  - Removed: PATSoundBankReader removed because no format license is available.
+             It is also undocumented format. 
+  - Added: AudioFloatFormatConverter, used to convert 
+           between PCM_SIGNED, PCM_UNSIGNED, PCM_FLOAT in 8/16/24/32 bit (big/little endian),
+           and resample using (linear/cubic/sinc...) if needed.
+  - Added: WaveExtensibleReader, used to read WAV files using WAVE_FORMAT_EXTENSIBLE format.
+  - Added: WaveFloatFileWriter, used to writing WAV files with PCM_FLOAT encoding.
+  - Fix: AudioFloatConverter tests incorrectly AudioFormat frameSize against SampleSizeInBits
+         Support for 64-byte float added, and support for 32+ bit PCM samples.  
+         SampleSizeInBits  not dividable by 8 are now handled correctly.
+  - Fix: DLSID(GUID) values incorrectly read from files in DLSSoundBank.
+  - Fix: WaveFloatFileReader incorrectly sets framrate.
+  - Fix: DLSSoundbank writes avgBytesPerSec incorrectly if SampleSizeInBits is not dividable by 8.
+  - Fix: SoftChannel didn't reset concept of LSB control to 0 when MSB control value is set
+         (according to MIDI 1.0 Detailed Spec. page 12)
+  - Fix: SoftChannel, added check for illegal noteNumbers.
+         If illegal notenumber was used in NoteOn/NoteOff
+         a ArrayOutOfIndex exception was thrown.
+         
   - 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
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java	Sun May 04 23:35:04 2008 +0200
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java	Mon May 05 00:31:45 2008 +0200
@@ -100,14 +100,14 @@
 			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();
+			d.x1 = riff.readUnsignedByte();
+			d.x2 = riff.readUnsignedByte();
+			d.x3 = riff.readUnsignedByte();
+			d.x4 = riff.readUnsignedByte();
+			d.x5 = riff.readUnsignedByte();
+			d.x6 = riff.readUnsignedByte();
+			d.x7 = riff.readUnsignedByte();
+			d.x8 = riff.readUnsignedByte();
 			return d;
 		}
 		
@@ -1006,11 +1006,13 @@
 		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.writeUnsignedInt(srate);*/
+		fmt_chunk.writeUnsignedInt(((long)audioformat.getFrameRate())*audioformat.getFrameSize());
 		fmt_chunk.writeUnsignedShort(audioformat.getFrameSize());
 		fmt_chunk.writeUnsignedShort(audioformat.getSampleSizeInBits());
 		fmt_chunk.write(0);
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATInstrument.java	Sun May 04 23:35:04 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,536 +0,0 @@
-/*
- * 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;
-	}
-
-}
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSample.java	Sun May 04 23:35:04 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * 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;
-
-}
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/PATSoundbankReader.java	Sun May 04 23:35:04 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/*
- * 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;
-		} catch (IOException ioe) {
-			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;
-	}
-
-
-}
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java	Sun May 04 23:35:04 2008 +0200
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java	Mon May 05 00:31:45 2008 +0200
@@ -423,6 +423,7 @@
 	
 	public void noteOn(int noteNumber, int velocity) {
 
+		if(noteNumber < 0 || noteNumber > 127) return;
 		noteOn_internal(noteNumber, velocity);
 		if(current_mixer != null) current_mixer.noteOn(noteNumber, velocity);
 	}
@@ -551,6 +552,7 @@
 	
 	public void noteOff(int noteNumber, int velocity) {
 		
+		if(noteNumber < 0 || noteNumber > 127) return;
 		noteOff_internal(noteNumber, velocity);
 
 		if(current_mixer != null) current_mixer.noteOff(noteNumber, velocity);
@@ -644,6 +646,7 @@
 	}
 
 	public void noteOff(int noteNumber) {
+		if(noteNumber < 0 || noteNumber > 127) return;
 		noteOff_internal(noteNumber, 64);
 	}
 
@@ -1044,7 +1047,7 @@
 				}
 				
 				if(controller == 6)
-					val = (val & 127) + (value << 7);
+					val = /*(val & 127) +*/ (value << 7);
 				else if(controller == 38)
 					val = (val & (127 << 7)) + value;
 				else if(controller == 96 || controller == 97)
@@ -1161,7 +1164,7 @@
 			
 			
 			if (controller == 0x00) {
-				bank = (bank & 127) + (value << 7);
+				bank = /*(bank & 127) +*/ (value << 7);
 				return;
 			}
 
@@ -1170,13 +1173,9 @@
 				return;
 			}			
 
-			// Keep track of values (capped to 7 bit).
-			// Reset least significant (32 through 63)
-			// controller value when most significant
-			// (0 through 31) is set.
-			this.controller[controller] = value & 127;
-			if (controller < 32)
-				this.controller[controller + 32] = 0;
+			this.controller[controller] = value;
+			if(controller < 0x20)
+				this.controller[controller + 0x20] = 0;	
 
 			for (int i = 0; i < voices.length; i++)
 				if (voices[i].active)
@@ -1188,7 +1187,9 @@
 
 	public int getController(int controller) {
 		synchronized (control_mutex) {
-			return this.controller[controller];
+			// Should only return lower 7 bits,
+			// even when controller is "boosted" higher.
+			return this.controller[controller] & 127;
 		}
 	}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java	Mon May 05 00:31:45 2008 +0200
@@ -0,0 +1,331 @@
+/*
+ * 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 java.util.HashMap;
+import java.util.Map;
+
+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.AudioFormat.Encoding;
+import javax.sound.sampled.spi.AudioFileReader;
+
+/**
+ * WAVE file reader for files using format WAVE_FORMAT_EXTENSIBLE (0xFFFE).
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class WaveExtensibleFileReader extends AudioFileReader {
+
+	
+	static private class GUID
+	{
+		long i1;
+		int s1;
+		int s2;
+		int x1;
+		int x2;
+		int x3;
+		int x4;
+		int x5;
+		int x6;
+		int x7;
+		int x8;
+		
+		private GUID()
+		{			
+		}
+		public GUID(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 GUID read(RIFFReader riff) throws IOException
+		{
+			GUID d = new GUID();
+			d.i1 = riff.readUnsignedInt();
+			d.s1 = riff.readUnsignedShort();
+			d.s2 = riff.readUnsignedShort();
+			d.x1 = riff.readUnsignedByte();
+			d.x2 = riff.readUnsignedByte();
+			d.x3 = riff.readUnsignedByte();
+			d.x4 = riff.readUnsignedByte();
+			d.x5 = riff.readUnsignedByte();
+			d.x6 = riff.readUnsignedByte();
+			d.x7 = riff.readUnsignedByte();
+			d.x8 = riff.readUnsignedByte();
+			return d;
+		}
+		
+		public boolean equals(Object obj) {
+			if(!(obj instanceof GUID)) return false;
+			GUID t = (GUID)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 String[] channelnames = 
+	   { "FL", "FR", "FC", "LF", "BL", "BR", // 5.1 
+		 "FLC", "FLR", "BC", "SL", "SR",
+		 "TC", "TFL", "TFC", "TFR", "TBL", "TBC", "TBR"};	
+	
+	private static String[] allchannelnames = 
+	   { "w1",  "w2",  "w3",  "w4",  "w5",  "w6",  "w7",  "w8",  "w9", "w10",
+		"w11", "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20",
+		"w21", "w22", "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30",
+		"w31", "w32", "w33", "w34", "w35", "w36", "w37", "w38", "w39", "w40",
+		"w41", "w42", "w43", "w44", "w45", "w46", "w47", "w48", "w49", "w50",
+		"w51", "w52", "w53", "w54", "w55", "w56", "w57", "w58", "w59", "w60",
+		"w61", "w62", "w63", "w64"};
+	
+	private static GUID SUBTYPE_PCM        =  new GUID(0x00000001,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
+	private static GUID SUBTYPE_IEEE_FLOAT =  new GUID(0x00000003,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
+
+	private String decodeChannelMask(long channelmask)
+	{
+		StringBuffer sb = new StringBuffer();
+		long m = 1;
+		for (int i = 0; i < allchannelnames.length; i++) {
+			if((channelmask & m) != 0L)
+			{
+				if(i < channelnames.length)
+				{
+					sb.append(channelnames[i] + " ");
+				}
+				else
+				{
+					sb.append(allchannelnames[i] + " ");				
+				}	
+			}
+			m *= 2L;
+		}
+		if(sb.length() == 0) return null;
+		return sb.substring(0, sb.length() - 1);
+		
+	}
+
+	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;
+		int validBitsPerSample = 1;
+		long channelMask = 0;
+		GUID subFormat = null;
+
+		while (riffiterator.hasNextChunk()) {
+			RIFFReader chunk = riffiterator.nextChunk();
+
+			if (chunk.getFormat().equals("fmt ")) {
+				fmt_found = true;
+
+				int format = chunk.readUnsignedShort();
+				if (format != 0xFFFE)
+					throw new UnsupportedAudioFileException(); // WAVE_FORMAT_EXTENSIBLE
+																// only
+				channels = chunk.readUnsignedShort();
+				samplerate = chunk.readUnsignedInt();
+				/*framerate =*/ chunk.readUnsignedInt();
+				framesize = chunk.readUnsignedShort();
+				bits = chunk.readUnsignedShort();
+				int cbSize = chunk.readUnsignedShort();
+				if (cbSize != 22)
+					throw new UnsupportedAudioFileException();				
+				validBitsPerSample = chunk.readUnsignedShort();
+				if(validBitsPerSample > bits)
+					throw new UnsupportedAudioFileException();
+				channelMask = chunk.readUnsignedInt();
+				subFormat = GUID.read(chunk);
+
+			}
+			if (chunk.getFormat().equals("data")) {
+				data_found = true;
+				break;
+			}
+		}
+
+		if (!fmt_found)
+			throw new UnsupportedAudioFileException();
+		if (!data_found)
+			throw new UnsupportedAudioFileException();
+
+		Map<String, Object> p = new HashMap<String, Object>();
+		String s_channelmask = decodeChannelMask(channelMask);
+		if(s_channelmask != null)
+			p.put("channelOrder", s_channelmask);
+		if(channelMask != 0)
+			p.put("channelMask", channelMask);
+		// validBitsPerSample is only informational for PCM data,
+		// data is still encode according to SampleSizeInBits.
+		p.put("validBitsPerSample", validBitsPerSample);
+		
+		AudioFormat audioformat = null;
+		if(subFormat.equals(SUBTYPE_PCM))
+		{
+			if(bits == 8)
+			{
+				audioformat = new AudioFormat(
+						Encoding.PCM_UNSIGNED, samplerate, bits, channels,
+						framesize, samplerate, false, p );
+			}
+			else
+			{
+				audioformat = new AudioFormat(
+						Encoding.PCM_SIGNED, samplerate, bits, channels,
+						framesize, samplerate, false, p );
+			}
+		}
+		else
+		if(subFormat.equals(SUBTYPE_IEEE_FLOAT))
+		{
+			audioformat = new AudioFormat(
+					AudioFloatConverter.PCM_FLOAT, samplerate, bits, channels,
+					framesize, samplerate, false, p );			
+		}
+		else
+			throw new UnsupportedAudioFileException();
+		
+
+		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)));
+	}
+
+}
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java	Sun May 04 23:35:04 2008 +0200
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java	Mon May 05 00:31:45 2008 +0200
@@ -75,7 +75,7 @@
 
 		int channels = 1;
 		long samplerate = 1;
-		long framerate = 1;
+		//long framerate = 1;
 		int framesize = 1;
 		int bits = 1;
 
@@ -91,7 +91,7 @@
 																// only
 				channels = chunk.readUnsignedShort();
 				samplerate = chunk.readUnsignedInt();
-				framerate = chunk.readUnsignedInt();
+				/*framerate =*/ chunk.readUnsignedInt();
 				framesize = chunk.readUnsignedShort();
 				bits = chunk.readUnsignedShort();
 
@@ -109,7 +109,7 @@
 
 		AudioFormat audioformat = new AudioFormat(
 				AudioFloatConverter.PCM_FLOAT, samplerate, bits, channels,
-				framesize, framerate, false);
+				framesize, samplerate, false);
 		AudioFileFormat fileformat = new AudioFileFormat(
 				AudioFileFormat.Type.WAVE, audioformat,
 				AudioSystem.NOT_SPECIFIED);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileWriter.java	Mon May 05 00:31:45 2008 +0200
@@ -0,0 +1,141 @@
+/*
+ * 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.io.OutputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.AudioFileFormat.Type;
+import javax.sound.sampled.spi.AudioFileWriter;
+
+/**
+ * Floating-point encoded (format 3) WAVE file writer.
+ * 
+ * @version %I%, %E%
+ * @author Karl Helgason
+ */
+
+public class WaveFloatFileWriter extends AudioFileWriter {
+	
+	private Type[] filetypes = {Type.WAVE};
+
+	public Type[] getAudioFileTypes() {
+		return filetypes;
+	}
+
+	public Type[] getAudioFileTypes(AudioInputStream stream) {
+		
+	    if(!stream.getFormat().getEncoding().equals(AudioFloatConverter.PCM_FLOAT)) return new Type[0]; 
+		return filetypes;
+	}
+	
+    private void checkFormat(AudioFileFormat.Type type, AudioInputStream stream) 
+   	{    	    	
+    	if (!Type.WAVE.equals(type)) 
+    		throw new IllegalArgumentException("File type " + type + " not supported.");
+    	if(!stream.getFormat().getEncoding().equals(AudioFloatConverter.PCM_FLOAT)) 
+    		throw new IllegalArgumentException("File format " + stream.getFormat() + " not supported.");        	
+   	}
+
+	public void write(AudioInputStream stream, RIFFWriter writer) throws IOException {
+					
+		RIFFWriter fmt_chunk = writer.writeChunk("fmt ");
+		
+		AudioFormat format = stream.getFormat();
+		fmt_chunk.writeUnsignedShort(3); // WAVE_FORMAT_IEEE_FLOAT
+		fmt_chunk.writeUnsignedShort(format.getChannels());
+		fmt_chunk.writeUnsignedInt((int)format.getSampleRate());
+		fmt_chunk.writeUnsignedInt(((int)format.getFrameRate())*format.getFrameSize());
+		fmt_chunk.writeUnsignedShort(format.getFrameSize());
+		fmt_chunk.writeUnsignedShort(format.getSampleSizeInBits());
+		fmt_chunk.close();
+		RIFFWriter data_chunk = writer.writeChunk("data");
+		byte[] buff = new byte[1024];
+		int len;
+		while((len = stream.read(buff, 0, buff.length)) != -1)
+			data_chunk.write(buff, 0, len);
+		data_chunk.close();		
+	}
+	
+	private class NoCloseOutputStream extends OutputStream
+	{
+		OutputStream out;
+		public NoCloseOutputStream(OutputStream out)
+		{
+			this.out = out;
+		}
+		public void write(int b) throws IOException {
+			out.write(b);
+		}
+		public void flush() throws IOException {
+			out.flush();
+		}
+		public void write(byte[] b, int off, int len) throws IOException {
+			out.write(b, off, len);
+		}
+		public void write(byte[] b) throws IOException {
+			out.write(b);
+		}		
+	}
+	
+	private AudioInputStream toLittleEndian(AudioInputStream ais)
+	{
+		AudioFormat format = ais.getFormat();
+		AudioFormat targetFormat = new AudioFormat(
+				format.getEncoding(), format.getSampleRate(), format.getSampleSizeInBits(),
+				format.getChannels(), format.getFrameSize(), format.getFrameRate(), false);
+		return AudioSystem.getAudioInputStream(targetFormat, ais);
+	}
+
+	public int write(AudioInputStream stream, Type fileType, OutputStream out) throws IOException {
+		
+		checkFormat(fileType, stream);
+		if(stream.getFormat().isBigEndian())
+			stream = toLittleEndian(stream);
+		RIFFWriter writer = new RIFFWriter(new NoCloseOutputStream(out), "WAVE");
+		write(stream, writer);
+		int fpointer = (int)writer.getFilePointer();
+		writer.close();
+		return fpointer;
+	}
+
+	public int write(AudioInputStream stream, Type fileType, File out) throws IOException {
+		checkFormat(fileType, stream);
+		if(stream.getFormat().isBigEndian())
+			stream = toLittleEndian(stream);		
+		RIFFWriter writer = new RIFFWriter(out, "WAVE");
+		write(stream, writer);
+		int fpointer = (int)writer.getFilePointer();
+		writer.close();
+		return fpointer;
+	}
+
+}