changeset 1035:8b0e11483252

Updated Gervill from upstream CVS (September 1, 2008) 2008-09-11 Mark Wielaard <mark@klomp.org> * patches/icedtea-gervill.patch: Updated patch for old tests. * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/*: New Gervill files (sept 1). - Add: More JTreg tests added: EmergencySoundbank SoftFilter AudioFloatConverter.ToFloatArray (improved) - Change: SoftReverb optimized, about 2 times faster. - Fix: ModelByteBuffer.skip called super.skip instead to call to RandomAccessFile directly. JTreg tests added: ModelByteBuffer/RandomFileInputStream/*.java - Fix: ModelByteBuffer.len was being modified in inner class RandomFileInputStream. The variable was made final and RandomFileInputStream.read methods where fixed. - Fix: ArrayOutOfException error in ModelInstrument.getKeys(), Keys array was to small, it couldn't hold all possible midi notes (0..127). Version 1.0.1 - Fix: Created dummy SourceDataline so that following jtreg test can be tested without using a real Audio Device SourceDataLine. javax/sound/midi/Gervill/SoftAudioSynthesizer/Open.java javax/sound/midi/Gervill/SoftSynthesizer/GetLatency.java javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver.java javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver2.java javax/sound/midi/Gervill/SoftSynthesizer/GetReceivers.java javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitter.java javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitters.java javax/sound/midi/Gervill/SoftSynthesizer/ImplicitOpenClose.java javax/sound/midi/Gervill/SoftSynthesizer/Open.java - Fix: Make open SoftSynthesizer garbage-collectable when user don't have reference to it and it is not producing any sound. - Fix: SoftReverb silent detection improved. - Added: SoftSynthesizer.getPropertyInfo returns current properties values if it is open. - Fix: Restrict input values in SoftChannel to 7 and 14 bit in these methods: noteOn noteOff setPolyPressure setChannelPressure controlChange programChange(program) programChange(bank, program) setPitchBend - Fix: Store generated soundbank to disk for faster future use.
author Mark Wielaard <mark@klomp.org>
date Thu, 11 Sep 2008 20:47:50 +0200
parents aacc3e8a8e16
children 8306580ee906
files ChangeLog overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMixingMixer.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java overlays/openjdk/jdk/test/com/sun/media/sound/AudioFloatConverter/ToFloatArray.java overlays/openjdk/jdk/test/com/sun/media/sound/SoftAudioSynthesizer/Open.java overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetLatency.java overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetReceiver.java overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetReceiver2.java overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetReceivers.java overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetTransmitter.java overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetTransmitters.java overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/ImplicitOpenClose.java overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/Open.java patches/icedtea-gervill.patch
diffstat 21 files changed, 707 insertions(+), 198 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Sep 10 13:37:08 2008 -0400
+++ b/ChangeLog	Thu Sep 11 20:47:50 2008 +0200
@@ -1,3 +1,9 @@
+2008-09-11  Mark Wielaard  <mark@klomp.org>
+
+	* patches/icedtea-gervill.patch: Updated patch for old tests.
+	* overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/*:
+	New Gervill files (sept 1).
+
 2008-09-10  Lillian Angel  <langel@redhat.com>
 
 	* patches/icedtea-lc_ctype.patch: New patch to fix this issue:
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/CHANGES.txt	Thu Sep 11 20:47:50 2008 +0200
@@ -1,3 +1,47 @@
+  - Add: More JTreg tests added:
+           EmergencySoundbank
+           SoftFilter
+           AudioFloatConverter.ToFloatArray (improved)
+  - Change: SoftReverb optimized, about 2 times faster.
+  - Fix: ModelByteBuffer.skip called super.skip
+         instead to call to RandomAccessFile directly.
+         JTreg tests added: ModelByteBuffer/RandomFileInputStream/*.java
+  - Fix: ModelByteBuffer.len was being modified in inner
+         class RandomFileInputStream. The variable was made final
+         and RandomFileInputStream.read methods where fixed.
+  - Fix: ArrayOutOfException error in ModelInstrument.getKeys(),
+         Keys array was to small, it couldn't
+         hold all possible midi notes (0..127).
+
+Version 1.0.1
+  - Fix: Created dummy SourceDataline so that following 
+         jtreg test can be tested without using
+         a real Audio Device SourceDataLine.  
+            javax/sound/midi/Gervill/SoftAudioSynthesizer/Open.java
+            javax/sound/midi/Gervill/SoftSynthesizer/GetLatency.java
+            javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver.java
+            javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver2.java
+            javax/sound/midi/Gervill/SoftSynthesizer/GetReceivers.java
+            javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitter.java
+            javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitters.java
+            javax/sound/midi/Gervill/SoftSynthesizer/ImplicitOpenClose.java
+            javax/sound/midi/Gervill/SoftSynthesizer/Open.java
+  - Fix: Make open SoftSynthesizer garbage-collectable
+         when user don't have reference to it and it is not
+         producing any sound.
+  - Fix: SoftReverb silent detection improved.
+  - Added: SoftSynthesizer.getPropertyInfo returns
+           current properties values if it is open.        
+  - Fix: Restrict input values in SoftChannel to 7 and 14 bit in these methods:
+            noteOn 
+            noteOff
+            setPolyPressure
+            setChannelPressure
+            controlChange
+            programChange(program)
+            programChange(bank, program)
+            setPitchBend
+  - Fix: Store generated soundbank to disk for faster future use.         
   - Cleanup: Make inner classes static 
               AudioFloatFormatConverter.AudioFloatFormatConverterInputStream
               AudioFloatFormatConverter.AudioFloatInputStreamChannelMixer
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java	Thu Sep 11 20:47:50 2008 +0200
@@ -45,7 +45,7 @@
     private long fileoffset;
     private byte[] buffer;
     private long offset;
-    private long len;
+    private final long len;
 
     private class RandomFileInputStream extends InputStream {
 
@@ -85,11 +85,12 @@
         }
 
         public long skip(long n) throws IOException {
+            if( n < 0)
+                return 0;
             if (n > left)
                 n = left;
-            n = super.skip(n);
-            if (n == -1)
-                return -1;
+            long p = raf.getFilePointer();
+            raf.seek(p + n);
             left -= n;
             return n;
         }
@@ -107,11 +108,12 @@
         }
 
         public int read(byte[] b) throws IOException {
+            int len = b.length;
             if (len > left)
                 len = (int)left;
             if (left == 0)
                 return -1;
-            int len = raf.read(b);
+            len = raf.read(b, 0, len);
             if (len == -1)
                 return -1;
             left -= len;
@@ -119,12 +121,12 @@
         }
 
         public int read() throws IOException {
-            if (len == 0)
+            if (left == 0)
                 return -1;
             int b = raf.read();
             if (b == -1)
                 return -1;
-            len--;
+            left--;
             return b;
         }
 
@@ -137,15 +139,15 @@
             long beginIndex, long endIndex, boolean independent) {
         this.root = parent.root;
         this.offset = 0;
-        this.len = parent.len;
+        long parent_len = parent.len;
         if (beginIndex < 0)
             beginIndex = 0;
-        if (beginIndex > len)
-            beginIndex = len;
+        if (beginIndex > parent_len)
+            beginIndex = parent_len;
         if (endIndex < 0)
             endIndex = 0;
-        if (endIndex > len)
-            endIndex = len;
+        if (endIndex > parent_len)
+            endIndex = parent_len;
         if (beginIndex > endIndex)
             beginIndex = endIndex;
         offset = beginIndex;
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java	Thu Sep 11 20:47:50 2008 +0200
@@ -88,10 +88,10 @@
     // This information is generated from ModelPerformer.getName()
     // returned from getPerformers().
     public String[] getKeys() {
-        String[] keys = new String[127];
+        String[] keys = new String[128];
         for (ModelPerformer performer : getPerformers()) {
             for (int k = performer.getKeyFrom(); k <= performer.getKeyTo(); k++) {
-                if (keys[k] == null) {
+                if (k >= 0 && k < 128 && keys[k] == null) {
                     String name = performer.getName();
                     if (name == null)
                         name = "untitled";
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java	Thu Sep 11 20:47:50 2008 +0200
@@ -194,6 +194,20 @@
             return v;
         }
     };
+    
+    private static int restrict7Bit(int value)
+    {
+        if(value < 0) return 0;
+        if(value > 127) return 127;
+        return value;
+    }
+    
+    private static int restrict14Bit(int value)
+    {
+        if(value < 0) return 0;
+        if(value > 16256) return 16256;
+        return value;
+    }
 
     public SoftChannel(SoftSynthesizer synth, int channel) {
         this.channel = channel;
@@ -386,8 +400,8 @@
     }
 
     public void noteOn(int noteNumber, int velocity) {
-
-        if(noteNumber < 0 || noteNumber > 127) return;
+        noteNumber = restrict7Bit(noteNumber);
+        velocity = restrict7Bit(velocity);        
         noteOn_internal(noteNumber, velocity);
         if (current_mixer != null)
             current_mixer.noteOn(noteNumber, velocity);
@@ -415,7 +429,7 @@
                 sustain = true;
             }
 
-            mainmixer.msec_last_activity = mainmixer.msec_pos;
+            mainmixer.activity();
 
             if (mono) {
                 if (portamento) {
@@ -515,7 +529,8 @@
     }
 
     public void noteOff(int noteNumber, int velocity) {
-        if(noteNumber < 0 || noteNumber > 127) return;
+        noteNumber = restrict7Bit(noteNumber);
+        velocity = restrict7Bit(velocity);        
         noteOff_internal(noteNumber, velocity);
 
         if (current_mixer != null)
@@ -534,7 +549,7 @@
                 }
             }
 
-            mainmixer.msec_last_activity = mainmixer.msec_pos;
+            mainmixer.activity();
             for (int i = 0; i < voices.length; i++) {
                 if (voices[i].on && voices[i].channel == channel
                         && voices[i].note == noteNumber
@@ -617,11 +632,14 @@
     }
 
     public void setPolyPressure(int noteNumber, int pressure) {
+        noteNumber = restrict7Bit(noteNumber);
+        pressure = restrict7Bit(pressure);        
+
         if (current_mixer != null)
             current_mixer.setPolyPressure(noteNumber, pressure);
 
         synchronized (control_mutex) {
-            mainmixer.msec_last_activity = mainmixer.msec_pos;
+            mainmixer.activity();
             co_midi[noteNumber].get(0, "poly_pressure")[0] = pressure*(1.0/128.0);
             polypressure[noteNumber] = pressure;
             for (int i = 0; i < voices.length; i++) {
@@ -637,11 +655,12 @@
         }
     }
 
-    public void setChannelPressure(int pressure) {
+    public void setChannelPressure(int pressure) {        
+        pressure = restrict7Bit(pressure);                
         if (current_mixer != null)
             current_mixer.setChannelPressure(pressure);
         synchronized (control_mutex) {
-            mainmixer.msec_last_activity = mainmixer.msec_pos;
+            mainmixer.activity();
             co_midi_channel_pressure[0] = pressure * (1.0 / 128.0);
             channelpressure = pressure;
             for (int i = 0; i < voices.length; i++) {
@@ -1006,6 +1025,8 @@
     }
 
     public void controlChange(int controller, int value) {
+        controller = restrict7Bit(controller);
+        value = restrict7Bit(value);
         if (current_mixer != null)
             current_mixer.controlChange(controller, value);
 
@@ -1210,13 +1231,15 @@
         }
     }
 
-    public void programChange(int program) {
+    public void programChange(int program) {        
         programChange(bank, program);
     }
 
     public void programChange(int bank, int program) {
+        bank = restrict7Bit(bank);
+        program = restrict7Bit(program);        
         synchronized (control_mutex) {
-            mainmixer.msec_last_activity = mainmixer.msec_pos;
+            mainmixer.activity();
             this.bank = bank;
             this.program = program;
             current_instrument = null;
@@ -1230,10 +1253,11 @@
     }
 
     public void setPitchBend(int bend) {
-        if (current_mixer != null)
+        bend = restrict14Bit(bend);
+        if (current_mixer != null)            
             current_mixer.setPitchBend(bend);
         synchronized (control_mutex) {
-            mainmixer.msec_last_activity = mainmixer.msec_pos;
+            mainmixer.activity();
             co_midi_pitch[0] = bend * (1.0 / 16384.0);
             pitchbend = bend;
             for (int i = 0; i < voices.length; i++)
@@ -1349,7 +1373,7 @@
 
     public void resetAllControllers(boolean allControls) {
         synchronized (control_mutex) {
-            mainmixer.msec_last_activity = mainmixer.msec_pos;
+            mainmixer.activity();
 
             for (int i = 0; i < 128; i++) {
                 setPolyPressure(i, 0);
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java	Thu Sep 11 20:47:50 2008 +0200
@@ -5,7 +5,7 @@
  * 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 suabject to the "Classpath" exception as provided
+ * 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
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java	Thu Sep 11 20:47:50 2008 +0200
@@ -59,15 +59,17 @@
     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;
+    private long msec_last_activity = -1;
+    private boolean pusher_silent = false;
+    private int pusher_silent_count = 0;
+    private 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 SoftReverb reverb;
     private SoftAudioProcessor chorus;
     private SoftAudioProcessor agc;
     private long msec_buffer_len = 0;
@@ -106,7 +108,7 @@
 
     private void processSystemExclusiveMessage(byte[] data) {
         synchronized (synth.control_mutex) {
-            msec_last_activity = msec_pos;
+            activity();
 
             // Universal Non-Real-Time SysEx
             if ((data[1] & 0xFF) == 0x7E) {
@@ -597,11 +599,40 @@
 
             }
         }
+        
+        if(buffers[CHANNEL_LEFT].isSilent()
+            && buffers[CHANNEL_RIGHT].isSilent())
+        {            
+            pusher_silent_count++;
+            if(pusher_silent_count > 5)
+            {
+                pusher_silent_count = 0;
+                synchronized (control_mutex) {
+                    pusher_silent = true;
+                    if(synth.weakstream != null)
+                        synth.weakstream.setInputStream(null);
+                }                    
+            }
+        }
+        else
+            pusher_silent_count = 0;
 
         if (synth.agc_on)
             agc.processAudio();
 
     }
+        
+    // Must only we called within control_mutex synchronization
+    public void activity()
+    {        
+        msec_last_activity = msec_pos;
+        if(pusher_silent)
+        {
+            pusher_silent = false;
+            if(synth.weakstream != null)
+                synth.weakstream.setInputStream(ais);
+        }
+    }
 
     public void stopMixer(ModelChannelMixer mixer) {
         if (stoppedMixers == null)
@@ -650,6 +681,8 @@
         chorus.init(samplerate, controlrate);
         agc.init(samplerate, controlrate);
 
+        reverb.setLightMode(synth.reverb_light);
+        
         reverb.setMixMode(true);
         chorus.setMixMode(true);
         agc.setMixMode(false);
@@ -686,7 +719,13 @@
             private byte[] single = new byte[1];
 
             public void fillBuffer() {
-                processAudioBuffers();
+                /*
+                boolean pusher_silent2;
+                synchronized (control_mutex) {
+                    pusher_silent2 = pusher_silent;
+                }
+                if(!pusher_silent2)*/
+                processAudioBuffers(); 
                 for (int i = 0; i < nrofchannels; i++)
                     buffers[i].get(bbuffer, i);
                 bbuffer_pos = 0;
@@ -884,7 +923,7 @@
 
     public void processMessage(int ch, int cmd, int data1, int data2) {
         synchronized (synth.control_mutex) {
-            msec_last_activity = msec_pos;
+            activity();
         }
 
         if (cmd == 0xF0) {
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMixingMixer.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftMixingMixer.java	Thu Sep 11 20:47:50 2008 +0200
@@ -62,7 +62,7 @@
 
     protected static final String INFO_DESCRIPTION = "Software Sound Mixer";
 
-    protected static final String INFO_VERSION = "0.9";
+    protected static final String INFO_VERSION = "1.0";
 
     protected final static Mixer.Info info = new Info();
 
@@ -354,9 +354,6 @@
                 AudioInputStream ais = openStream(getFormat());
 
                 if (line == null) {
-                    DataLine.Info info = new DataLine.Info(
-                            SourceDataLine.class, format);
-
                     synchronized (SoftMixingMixerProvider.mutex) {
                         SoftMixingMixerProvider.lockthread = Thread
                                 .currentThread();
@@ -365,8 +362,55 @@
                     try {
                         Mixer defaultmixer = AudioSystem.getMixer(null);
                         if (defaultmixer != null)
-                            line = (SourceDataLine) defaultmixer.getLine(info);
-                        else
+                        {
+                            // Search for suitable line
+                            
+                            DataLine.Info idealinfo = null;
+                            AudioFormat idealformat = null;
+                            
+                            Line.Info[] lineinfos = defaultmixer.getSourceLineInfo();
+                            idealFound:
+                            for (int i = 0; i < lineinfos.length; i++) {
+                                if(lineinfos[i].getLineClass() == SourceDataLine.class)
+                                {
+                                    DataLine.Info info = (DataLine.Info)lineinfos[i];
+                                    AudioFormat[] formats = info.getFormats();
+                                    for (int j = 0; j < formats.length; j++) {
+                                        AudioFormat format = formats[j];
+                                        if(format.getChannels() == 2 || 
+                                                format.getChannels() == AudioSystem.NOT_SPECIFIED)
+                                        if(format.getEncoding().equals(Encoding.PCM_SIGNED) || 
+                                                format.getEncoding().equals(Encoding.PCM_UNSIGNED))
+                                        if(format.getSampleRate() == AudioSystem.NOT_SPECIFIED || 
+                                                format.getSampleRate() == 48000.0)
+                                        if(format.getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED || 
+                                                format.getSampleSizeInBits() == 16)
+                                        {
+                                            idealinfo = info;
+                                            int ideal_channels = format.getChannels();
+                                            boolean ideal_signed = format.getEncoding().equals(Encoding.PCM_SIGNED); 
+                                            float ideal_rate = format.getSampleRate();
+                                            boolean ideal_endian = format.isBigEndian();                                            
+                                            int ideal_bits = format.getSampleSizeInBits();                                            
+                                            if(ideal_bits == AudioSystem.NOT_SPECIFIED) ideal_bits = 16;
+                                            if(ideal_channels == AudioSystem.NOT_SPECIFIED) ideal_channels = 2;
+                                            if(ideal_rate == AudioSystem.NOT_SPECIFIED) ideal_rate = 48000;
+                                            idealformat = new AudioFormat(ideal_rate, ideal_bits, 
+                                                    ideal_channels, ideal_signed, ideal_endian);
+                                            break idealFound;
+                                        }
+                                    }
+                                }                                    
+                            }
+                            
+                            if(idealformat != null)
+                            {
+                                format = idealformat;
+                                line = (SourceDataLine) defaultmixer.getLine(idealinfo);
+                            }
+                        }
+                        
+                        if(line == null)
                             line = AudioSystem.getSourceDataLine(format);
                     } finally {
                         synchronized (SoftMixingMixerProvider.mutex) {
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java	Thu Sep 11 20:47:50 2008 +0200
@@ -35,7 +35,7 @@
  */
 public class SoftReverb implements SoftAudioProcessor {
 
-    private static class Delay {
+    private final static class Delay {
 
         private float[] delaybuffer;
         private int rovepos = 0;
@@ -52,31 +52,28 @@
             rovepos = 0;
         }
 
-        public void processReplace(float[] in, float[] out) {
-            float[] delaybuffer = this.delaybuffer;
+        public void processReplace(float[] inout) {
             if (delaybuffer == null)
                 return;
-            int len = in.length;
+            int len = inout.length;
             int rnlen = delaybuffer.length;
             int rovepos = this.rovepos;
 
             for (int i = 0; i < len; i++) {
-                float x = in[i];
-                out[i] = delaybuffer[rovepos];
+                float x = inout[i];
+                inout[i] = delaybuffer[rovepos];
                 delaybuffer[rovepos] = x;
-                rovepos = rovepos + 1;
-                if (rovepos == rnlen)
+                if (++rovepos == rnlen)
                     rovepos = 0;
-                //rovepos = (rovepos + 1) % rnlen;
             }
             this.rovepos = rovepos;
         }
     }
 
-    private static class AllPass {
+    private final static class AllPass {
 
-        private float[] delaybuffer;
-        private int delaybuffersize;
+        private final float[] delaybuffer;
+        private final int delaybuffersize;
         private int rovepos = 0;
         private float feedback;
 
@@ -88,47 +85,42 @@
         public void setFeedBack(float feedback) {
             this.feedback = feedback;
         }
-        int ucount = 0;
 
-        public void processReplace(float in[], float out[]) {
-            int len = in.length;
+        public void processReplace(float inout[]) {
+            int len = inout.length;
+            int delaybuffersize = this.delaybuffersize;
+            int rovepos = this.rovepos;            
             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;
+                float input = inout[i];
+                inout[i] = delayout - input;
                 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;
-                    }
-                }
+            this.rovepos = rovepos;                        
+        }
+        
+        public void processReplace(float in[], float out[]) {
+            int len = in.length;
+            int delaybuffersize = this.delaybuffersize;
+            int rovepos = this.rovepos;            
+            for (int i = 0; i < len; i++) {
+                float delayout = delaybuffer[rovepos];
+                float input = in[i];
+                out[i] = delayout - input;
+                delaybuffer[rovepos] = input + delayout * feedback;
+                if (++rovepos == delaybuffersize)
+                    rovepos = 0;
             }
-
-        }
+            this.rovepos = rovepos;                        
+        }        
     }
 
-    private static class Comb {
+    private final static class Comb {
 
-        private float[] delaybuffer;
-        private int delaybuffersize;
+        private final float[] delaybuffer;
+        private final int delaybuffersize;
         private int rovepos = 0;
         private float feedback;
         private float filtertemp = 0;
@@ -142,56 +134,54 @@
 
         public void setFeedBack(float feedback) {
             this.feedback = feedback;
+            filtercoeff2 = (1 - filtercoeff1)* feedback;
         }
-        int ucount = 0;
 
         public void processMix(float in[], float out[]) {
-            int len = in.length;
-
-            float filtercoeff2 = this.filtercoeff2 * feedback;
-
+            int len = in.length;            
+            int delaybuffersize = this.delaybuffersize;
+            int rovepos = this.rovepos;
+            float filtertemp = this.filtertemp;
+            float filtercoeff1 = this.filtercoeff1;
+            float filtercoeff2 = this.filtercoeff2;
             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);
-
+                delaybuffer[rovepos] = in[i] + filtertemp;
                 if (++rovepos == delaybuffersize)
                     rovepos = 0;
+            }            
+            this.filtertemp  = filtertemp;
+            this.rovepos = rovepos;
+        }
 
-            }
-            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 processReplace(float in[], float out[]) {
+            int len = in.length;            
+            int delaybuffersize = this.delaybuffersize;
+            int rovepos = this.rovepos;
+            float filtertemp = this.filtertemp;
+            float filtercoeff1 = this.filtercoeff1;
+            float filtercoeff2 = this.filtercoeff2;
+            for (int i = 0; i < len; i++) {
+                float delayout = delaybuffer[rovepos];
+                // One Pole Lowpass Filter
+                filtertemp = (delayout * filtercoeff2)
+                        + (filtertemp * filtercoeff1);
+                out[i] = delayout;
+                delaybuffer[rovepos] = in[i] + filtertemp;
+                if (++rovepos == delaybuffersize)
+                    rovepos = 0;
+            }            
+            this.filtertemp  = filtertemp;
+            this.rovepos = rovepos;
         }
 
         public void setDamp(float val) {
             filtercoeff1 = val;
-            filtercoeff2 = 1 - filtercoeff1;
+            filtercoeff2 = (1 - filtercoeff1)* feedback;
         }
     }
     private float roomsize;
@@ -203,8 +193,11 @@
     private AllPass[] allpassL;
     private AllPass[] allpassR;
     private float[] input;
-    private float[] outR;
-    private float[] outL;
+    private float[] out;
+    private float[] pre1;
+    private float[] pre2;
+    private float[] pre3;
+    private boolean denormal_flip = false;
     private boolean mix = true;
     private SoftAudioBuffer inputA;
     private SoftAudioBuffer left;
@@ -214,11 +207,10 @@
     private float dirty_damp;
     private float dirty_predelay;
     private float dirty_gain;
-    private float controlrate;
-    private float samplerate;
+    private float samplerate;    
+    private boolean light = true;
 
     public void init(float samplerate, float controlrate) {
-        this.controlrate = controlrate;		
         this.samplerate = samplerate;
 
         double freqscale = ((double) samplerate) / 44100.0;
@@ -239,7 +231,7 @@
         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)));
+        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)));
@@ -283,21 +275,21 @@
     public void setMixMode(boolean mix) {
         this.mix = mix;
     }
-    private double silentcounter = 1000;
+    
+    private boolean silent = true;
 
     public void processAudio() {
-        if (this.inputA.isSilent()) {
-            silentcounter += 1 / controlrate;
-
-            if (silentcounter > 60) {
-                if (!mix) {
-                    left.clear();
-                    right.clear();
-                }
-                return;
+        boolean silent_input = this.inputA.isSilent();
+        if(!silent_input)
+            silent = false;
+        if(silent)
+        {
+            if (!mix) {
+                left.clear();
+                right.clear();
             }
-        } else
-            silentcounter = 0;
+            return;            
+        }
 
         float[] inputA = this.inputA.array();
         float[] left = this.left.array();
@@ -308,49 +300,100 @@
             input = new float[numsamples];
 
         float again = gain * 0.018f / 2;
+        
+        denormal_flip = !denormal_flip;
+        if(denormal_flip)
+            for (int i = 0; i < numsamples; i++) 
+                input[i] = inputA[i] * again + 1E-20f;
+        else
+            for (int i = 0; i < numsamples; i++) 
+                input[i] = inputA[i] * again - 1E-20f;
 
-        for (int i = 0; i < numsamples; i++)
-            input[i] = inputA[i] * again;
-
-        delay.processReplace(input, input);
-
+        delay.processReplace(input);
+                      
+        if(light && (right != null))
+        {
+            if (pre1 == null || pre1.length < numsamples)
+            {
+                pre1 = new float[numsamples];
+                pre2 = new float[numsamples];
+                pre3 = new float[numsamples];
+            }
+            
+            for (int i = 0; i < allpassL.length; i++)
+                allpassL[i].processReplace(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);
+            combL[0].processReplace(input, pre3);
+            combL[1].processReplace(input, pre3);
 
-            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];
+            combL[2].processReplace(input, pre1);
+            for (int i = 4; i < combL.length-2; i+=2)
+                combL[i].processMix(input, pre1); 
+            
+            combL[3].processReplace(input, pre2);;
+            for (int i = 5; i < combL.length-2; i+=2)            
+                combL[i].processMix(input, pre2);
+                                        
+            if (!mix)
+            {
+                Arrays.fill(right, 0);            
+                Arrays.fill(left, 0);
+            }
+            for (int i = combR.length-2; i < combR.length; i++)
+                combR[i].processMix(input, right);            
+            for (int i = combL.length-2; i < combL.length; i++)
+                combL[i].processMix(input, left);
+            
+            for (int i = 0; i < numsamples; i++) 
+            {
+                float p = pre1[i] - pre2[i];
+                float m = pre3[i];
+                left[i] += m + p;
+                right[i] += m - p;
             }
         }
-
-
-        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);
+        else
+        {
+            if (out == null || out.length < numsamples)
+                out = new float[numsamples];
+            
+            if (right != null) {
+                if (!mix)            
+                    Arrays.fill(right, 0);                        
+                allpassR[0].processReplace(input, out);
+                for (int i = 1; i < allpassR.length; i++)
+                    allpassR[i].processReplace(out);
+                for (int i = 0; i < combR.length; i++)
+                    combR[i].processMix(out, right);
+            }
 
-        if (mix) {
-            for (int i = 0; i < numsamples; i++)
-                left[i] += outL[i];
-        } else {
+            if (!mix)            
+                Arrays.fill(left, 0);                    
+            allpassL[0].processReplace(input, out);
+            for (int i = 1; i < allpassL.length; i++)
+                allpassL[i].processReplace(out);
+            for (int i = 0; i < combL.length; i++)
+                combL[i].processMix(out, left);            
+        }
+        
+        
+        
+        
+        
+
+        if (silent_input) {
+            silent = true;
             for (int i = 0; i < numsamples; i++)
-                left[i] = outL[i];
+            {
+                float v = left[i];
+                if(v > 1E-10 || v < -1E-10)
+                {
+                    silent = false;
+                    break;
+                }
+            }
         }
-
-
+        
     }
 
     public void globalParameterControlChange(int[] slothpath, long param,
@@ -433,7 +476,7 @@
     public void setRoomSize(float value) {
         roomsize = 1 - (0.17f / value);
 
-        for (int i = 0; i < 8; i++) {
+        for (int i = 0; i < combL.length; i++) {
             combL[i].feedback = roomsize;
             combR[i].feedback = roomsize;
         }
@@ -457,10 +500,16 @@
             damp = 0;
 
         // damp = value * 0.4f;
-        for (int i = 0; i < 8; i++) {
+        for (int i = 0; i < combL.length; i++) {
             combL[i].setDamp(damp);
             combR[i].setDamp(damp);
         }
 
     }
+    
+    public void setLightMode(boolean light)
+    {
+        this.light = light;
+    }
 }
+
--- a/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java	Thu Sep 11 20:47:50 2008 +0200
@@ -27,6 +27,8 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.WeakReference;
 import java.security.AccessControlException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -57,6 +59,97 @@
  */
 public class SoftSynthesizer implements AudioSynthesizer,
         ReferenceCountingDevice {
+    
+    protected static class WeakAudioStream extends InputStream 
+    {
+        private volatile AudioInputStream stream;
+        public SoftAudioPusher pusher = null;
+        public AudioInputStream jitter_stream = null;       
+        public SourceDataLine sourceDataLine = null;
+        private WeakReference<AudioInputStream> weak_stream_link;
+        private AudioFloatConverter converter;
+        private float[] silentbuffer = null;
+        private int samplesize;
+        
+        public void setInputStream(AudioInputStream stream)
+        {
+            this.stream = stream;
+        }
+            
+        public int available() throws IOException {
+            AudioInputStream local_stream = stream;
+            if(local_stream != null)
+                return local_stream.available();
+            return 0;
+        }
+
+        public int read() throws IOException {
+             byte[] b = new byte[1];
+             if (read(b) == -1)
+                  return -1;
+             return b[0] & 0xFF;
+        }
+            
+        public int read(byte[] b, int off, int len) throws IOException {
+             AudioInputStream local_stream = stream;
+             if(local_stream != null)
+                 return local_stream.read(b, off, len);
+             else
+             {
+                 int flen = len / samplesize;
+                 if(silentbuffer == null || silentbuffer.length < flen)
+                     silentbuffer = new float[flen];
+                 converter.toByteArray(silentbuffer, flen, b, off);
+                 
+                 if(pusher != null)
+                 if(weak_stream_link.get() == null)
+                 {
+                     Runnable runnable = new Runnable()
+                     {
+                         SoftAudioPusher _pusher = pusher;
+                         AudioInputStream _jitter_stream = jitter_stream;
+                         SourceDataLine _sourceDataLine = sourceDataLine;
+                         public void run()
+                         {
+                             _pusher.stop();
+                             if(_jitter_stream != null)
+                                try {
+                                    _jitter_stream.close();
+                                } catch (IOException e) {
+                                    e.printStackTrace();
+                                } 
+                             if(_sourceDataLine != null)
+                                 _sourceDataLine.close();
+                         }
+                     };
+                     pusher = null;
+                     jitter_stream = null;
+                     sourceDataLine = null;
+                     new Thread(runnable).start();
+                 }
+                 return len;
+             }
+        }            
+            
+        public WeakAudioStream(AudioInputStream stream) {
+            this.stream = stream;
+            weak_stream_link = new WeakReference<AudioInputStream>(stream);
+            converter = AudioFloatConverter.getConverter(stream.getFormat());
+            samplesize = stream.getFormat().getFrameSize() / stream.getFormat().getChannels();             
+        }        
+        
+        public AudioInputStream getAudioInputStream()
+        {
+            return new AudioInputStream(this, stream.getFormat(), AudioSystem.NOT_SPECIFIED);
+        }
+        
+        public void close() throws IOException
+        {
+            AudioInputStream astream  = weak_stream_link.get();
+            if(astream != null)
+                astream.close();
+        }
+    }
 
     private static class Info extends MidiDevice.Info {
         public Info() {
@@ -69,9 +162,13 @@
     protected static final String INFO_DESCRIPTION = "Software MIDI Synthesizer";
     protected static final String INFO_VERSION = "1.0";
     protected final static MidiDevice.Info info = new Info();
+    
+    private static SourceDataLine testline = null;
 
     private static Soundbank defaultSoundBank = null;
 
+    protected WeakAudioStream weakstream = null;
+    
     protected Object control_mutex = this;
 
     protected int voiceIDCounter = 0;
@@ -80,6 +177,7 @@
     // 1: DLS Voice Allocation
     protected int voice_allocation_mode = 0;
 
+    protected boolean reverb_light = true;
     protected boolean reverb_on = true;
     protected boolean chorus_on = true;
     protected boolean agc_on = true;
@@ -108,6 +206,7 @@
     private boolean open = false;
     private boolean implicitOpen = false;
 
+    private String resamplerType = "linear";
     private SoftResampler resampler = new SoftLinearResampler();
 
     private int number_of_midi_channels = 16;
@@ -190,19 +289,40 @@
 
         String resamplerType = (String)items[0].value;
         if (resamplerType.equalsIgnoreCase("point"))
+        {
             this.resampler = new SoftPointResampler();
+            this.resamplerType = "point";
+        }
         else if (resamplerType.equalsIgnoreCase("linear"))
+        {
             this.resampler = new SoftLinearResampler2();
+            this.resamplerType = "linear";
+        }
         else if (resamplerType.equalsIgnoreCase("linear1"))
+        {
             this.resampler = new SoftLinearResampler();
+            this.resamplerType = "linear1";
+        }
         else if (resamplerType.equalsIgnoreCase("linear2"))
+        {
             this.resampler = new SoftLinearResampler2();
+            this.resamplerType = "linear2";
+        }
         else if (resamplerType.equalsIgnoreCase("cubic"))
+        {
             this.resampler = new SoftCubicResampler();
+            this.resamplerType = "cubic";
+        }
         else if (resamplerType.equalsIgnoreCase("lanczos"))
+        {
             this.resampler = new SoftLanczosResampler();
+            this.resamplerType = "lanczos";
+        }
         else if (resamplerType.equalsIgnoreCase("sinc"))
+        {
             this.resampler = new SoftSincResampler();
+            this.resamplerType = "sinc";
+        }
 
         setFormat((AudioFormat)items[2].value);
         controlrate = (Float)items[1].value;
@@ -215,6 +335,7 @@
         largemode = (Boolean)items[9].value;
         number_of_midi_channels = (Integer)items[10].value;
         jitter_correction = (Boolean)items[11].value;
+        reverb_light = (Boolean)items[12].value;
     }
 
     private String patchToString(Patch patch) {
@@ -538,8 +659,40 @@
                 //e.printStackTrace();
             }
 
+            File userhome = null;
+            File emg_soundbank_file = null;
+            
+            /*
+             *  Try to load saved generated soundbank 
+             */                
             try {
+                userhome = new File(System.getProperty("user.home"),
+                     ".gervill");
+                emg_soundbank_file = new File(userhome, "soundbank-emg.sf2");
+                Soundbank sbk = MidiSystem.getSoundbank(emg_soundbank_file);
+                defaultSoundBank = sbk;
+                return defaultSoundBank;                
+            } catch (AccessControlException e) {
+            } catch (Exception e) {
+                //e.printStackTrace();
+            }
+            
+            try {
+                
+                /*
+                 *  Generate emergency soundbank 
+                 */
                 defaultSoundBank = EmergencySoundbank.createSoundbank();
+                
+                /*
+                 *  Save generated soundbank to disk for faster future use. 
+                 */
+                if(defaultSoundBank != null)
+                {
+                    if(!userhome.exists()) userhome.mkdirs();
+                    if(!emg_soundbank_file.exists())
+                        ((SF2Soundbank)defaultSoundBank).save(emg_soundbank_file);
+                }
             } catch (Exception e) {
                 //e.printStackTrace();
             }
@@ -641,58 +794,68 @@
                 new ArrayList<AudioSynthesizerPropertyInfo>();
 
         AudioSynthesizerPropertyInfo item;
+        
+        // If info != null or synthesizer is closed
+        //   we return how the synthesizer will be set on next open
+        // If info == null and synthesizer is open
+        //   we return current synthesizer properties.
+        boolean o = info == null && open;
 
-        item = new AudioSynthesizerPropertyInfo("interpolation", "linear");
+        item = new AudioSynthesizerPropertyInfo("interpolation", o?resamplerType:"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 = new AudioSynthesizerPropertyInfo("control rate", o?controlrate:147f);
         item.description = "Control rate";
         list.add(item);
 
         item = new AudioSynthesizerPropertyInfo("format",
-                new AudioFormat(44100, 16, 2, true, false));
+                o?format:new AudioFormat(44100, 16, 2, true, false));
         item.description = "Default audio format";
         list.add(item);
 
-        item = new AudioSynthesizerPropertyInfo("latency", 120000L);
+        item = new AudioSynthesizerPropertyInfo("latency", o?latency:120000L);
         item.description = "Default latency";
         list.add(item);
 
-        item = new AudioSynthesizerPropertyInfo("device id", 0);
+        item = new AudioSynthesizerPropertyInfo("device id", o?deviceid:0);
         item.description = "Device ID for SysEx Messages";
         list.add(item);
 
-        item = new AudioSynthesizerPropertyInfo("max polyphony", 64);
+        item = new AudioSynthesizerPropertyInfo("max polyphony", o?maxpoly:64);
         item.description = "Maximum polyphony";
         list.add(item);
 
-        item = new AudioSynthesizerPropertyInfo("reverb", true);
+        item = new AudioSynthesizerPropertyInfo("reverb", o?reverb_on:true);
         item.description = "Turn reverb effect on or off";
         list.add(item);
 
-        item = new AudioSynthesizerPropertyInfo("chorus", true);
+        item = new AudioSynthesizerPropertyInfo("chorus", o?chorus_on:true);
         item.description = "Turn chorus effect on or off";
         list.add(item);
 
-        item = new AudioSynthesizerPropertyInfo("auto gain control", true);
+        item = new AudioSynthesizerPropertyInfo("auto gain control", o?agc_on:true);
         item.description = "Turn auto gain control on or off";
         list.add(item);
 
-        item = new AudioSynthesizerPropertyInfo("large mode", false);
+        item = new AudioSynthesizerPropertyInfo("large mode", o?largemode:false);
         item.description = "Turn large mode on or off.";
         list.add(item);
 
-        item = new AudioSynthesizerPropertyInfo("midi channels", 16);
+        item = new AudioSynthesizerPropertyInfo("midi channels", o?channels.length:16);
         item.description = "Number of midi channels.";
         list.add(item);
 
-        item = new AudioSynthesizerPropertyInfo("jitter correction", true);
+        item = new AudioSynthesizerPropertyInfo("jitter correction", o?jitter_correction:true);
         item.description = "Turn jitter correction on or off.";
         list.add(item);
 
+        item = new AudioSynthesizerPropertyInfo("light reverb", o?reverb_light:true);
+        item.description = "Turn light reverb mode on or off";
+        list.add(item);
+        
         AudioSynthesizerPropertyInfo[] items;
         items = list.toArray(new AudioSynthesizerPropertyInfo[list.size()]);
 
@@ -731,9 +894,17 @@
                     setFormat(line.getFormat());
 
                 AudioInputStream ais = openStream(getFormat(), info);
+                
+                weakstream = new WeakAudioStream(ais);
+                ais = weakstream.getAudioInputStream();
 
                 if (line == null)
-                    line = AudioSystem.getSourceDataLine(getFormat());
+                {
+                    if(testline != null)
+                        line = testline;
+                    else
+                        line = AudioSystem.getSourceDataLine(getFormat());
+                }                    
 
                 double latency = this.latency;
 
@@ -770,11 +941,20 @@
                 if (jitter_correction) {
                     ais = new SoftJitterCorrector(ais, buffersize,
                             controlbuffersize);
+                    if(weakstream != null)
+                        weakstream.jitter_stream = ais;
                 }
                 pusher = new SoftAudioPusher(line, ais, controlbuffersize);
                 pusher_stream = ais;
                 pusher.start();
 
+                if(weakstream != null)
+                {
+                    weakstream.pusher = pusher;
+                    weakstream.sourceDataLine = sourceDataLine;
+                }
+                
+
 
             } catch (LineUnavailableException e) {
                 if (isOpen())
@@ -793,13 +973,15 @@
             throw new MidiUnavailableException("Synthesizer is already open");
 
         synchronized (control_mutex) {
-            open = true;
-            implicitOpen = false;
 
             gmmode = 0;
             voice_allocation_mode = 0;
 
             processPropertyInfo(info);
+            
+            open = true;
+            implicitOpen = false;
+            
             if (targetFormat != null)
                 setFormat(targetFormat);
 
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/AudioFloatConverter/ToFloatArray.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/AudioFloatConverter/ToFloatArray.java	Thu Sep 11 20:47:50 2008 +0200
@@ -43,11 +43,30 @@
 			testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI);
 			testarray[i] *= 0.3;
 		}		
+        
+        // Check conversion using PCM_FLOAT
+        for (int big = 0; big < 2; big+=1)
+        for (int bits = 32; bits <= 64; bits+=32) {
+            AudioFormat frm = new AudioFormat(
+                    AudioFloatConverter.PCM_FLOAT,
+                    44100, bits, 1, bits/8,
+                    44100, big==1);
+            byte[] buff = new byte[testarray.length * frm.getFrameSize()];
+            float[] testarray2 = new float[testarray.length];
+            AudioFloatConverter conv = AudioFloatConverter.getConverter(frm);
+            conv.toByteArray(testarray, buff);
+            conv.toFloatArray(buff, testarray2);
+            for (int i = 0; i < testarray2.length; i++) {
+                if(Math.abs(testarray[i] - testarray2[i]) > 0.05)
+                    throw new RuntimeException("Conversion failed for " + frm  +" , arrays not equal enough!\n");
+            }               
+            
+        }
 		
 		// Check conversion from float2byte and byte2float.
 		for (int big = 0; big < 2; big+=1) 
 		for (int signed = 0; signed < 2; signed+=1) 
-		for (int bits = 8; bits <= 32; bits+=8) {					
+		for (int bits = 6; bits <= 40; bits+=2) {					
 			AudioFormat frm = new AudioFormat(44100, bits, 1, signed==1, big==1);
 			byte[] buff = new byte[testarray.length * frm.getFrameSize()];
 			float[] testarray2 = new float[testarray.length];
@@ -63,7 +82,7 @@
 		// Check big/little
 		for (int big = 0; big < 2; big+=1) 
 		for (int signed = 0; signed < 2; signed+=1)
-		for (int bits = 8; bits <= 32; bits+=8) {					
+		for (int bits = 6; bits <= 40; bits+=2) {					
 			AudioFormat frm = new AudioFormat(44100, bits, 1, signed==1, big==1);
 			byte[] buff = new byte[testarray.length * frm.getFrameSize()];
 			AudioFloatConverter conv = AudioFloatConverter.getConverter(frm);
@@ -89,7 +108,7 @@
 		// Check signed/unsigned 
 		for (int big = 0; big < 2; big+=1) 
 		for (int signed = 0; signed < 2; signed+=1)
-		for (int bits = 8; bits <= 32; bits+=8) {					
+		for (int bits = 6; bits <= 40; bits+=2) {					
 			AudioFormat frm = new AudioFormat(44100, bits, 1, signed==1, big==1);
 			byte[] b = new byte[testarray.length * frm.getFrameSize()];
 			AudioFloatConverter conv = AudioFloatConverter.getConverter(frm);
@@ -117,10 +136,10 @@
 		}
 		
 		// Check if conversion 32->24, 24->16, 16->8 result in same float data
-		AudioFormat frm = new AudioFormat(44100, 32, 1, true, true);
+		AudioFormat frm = new AudioFormat(44100, 40, 1, true, true);
 		byte[] b = new byte[testarray.length * frm.getFrameSize()];
 		AudioFloatConverter.getConverter(frm).toByteArray(testarray, b);
-		for (int bits = 8; bits <= 32; bits+=8) {
+		for (int bits = 6; bits <= 40; bits+=2) {
 			AudioFormat frm2 = new AudioFormat(44100, bits, 1, true, true);
 			byte[] b2 = new byte[testarray.length * frm2.getFrameSize()];
 			int fs1 = frm.getFrameSize();
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/SoftAudioSynthesizer/Open.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/SoftAudioSynthesizer/Open.java	Thu Sep 11 20:47:50 2008 +0200
@@ -47,7 +47,7 @@
 		
 	public static void main(String[] args) throws Exception {
 		AudioSynthesizer synth = new SoftSynthesizer();
-		SourceDataLine line = AudioSystem.getSourceDataLine(new AudioFormat(44100, 16, 2, true, false));
+		SourceDataLine line = new DummySourceDataLine(); //AudioSystem.getSourceDataLine(new AudioFormat(44100, 16, 2, true, false));
 		synth.open(line, null);
 		synth.close();		
 	}
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetLatency.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetLatency.java	Thu Sep 11 20:47:50 2008 +0200
@@ -50,7 +50,7 @@
 		
 	public static void main(String[] args) throws Exception {
 		AudioSynthesizer synth = new SoftSynthesizer();
-		synth.open();
+        synth.open(new DummySourceDataLine(), null);
 		assertTrue(synth.getLatency() != -1);
 		synth.close();
 		
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetReceiver.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetReceiver.java	Thu Sep 11 20:47:50 2008 +0200
@@ -51,7 +51,7 @@
 		
 	public static void main(String[] args) throws Exception {
 		AudioSynthesizer synth = new SoftSynthesizer();
-		synth.open(null,null);
+        synth.open(new DummySourceDataLine(), null);
 		Receiver recv = synth.getReceiver();
 		assertTrue(recv != null);
 		Receiver recv2 = synth.getReceiver();
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetReceiver2.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetReceiver2.java	Thu Sep 11 20:47:50 2008 +0200
@@ -46,7 +46,7 @@
 		assertTrue(recv != null);
 		ShortMessage sm = new ShortMessage();
 		sm.setMessage(ShortMessage.NOTE_OFF, 0, 64, 64);
-		synth.open(null,null);
+        synth.open(new DummySourceDataLine(), null);
 		recv.send(sm, -1);		
 		synth.close();			
 		try
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetReceivers.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetReceivers.java	Thu Sep 11 20:47:50 2008 +0200
@@ -51,7 +51,7 @@
 		
 	public static void main(String[] args) throws Exception {
 		AudioSynthesizer synth = new SoftSynthesizer();
-		synth.open(null,null);
+        synth.open(new DummySourceDataLine(), null);
 		assertTrue(synth.getReceivers().size() == 0);
 		Receiver recv = synth.getReceiver();
 		assertTrue(synth.getReceivers().size() == 1);
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetTransmitter.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetTransmitter.java	Thu Sep 11 20:47:50 2008 +0200
@@ -50,7 +50,7 @@
 		
 	public static void main(String[] args) throws Exception {
 		AudioSynthesizer synth = new SoftSynthesizer();
-		synth.open(null,null);
+        synth.open(new DummySourceDataLine(), null);
 		try
 		{
 			synth.getTransmitter();
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetTransmitters.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/GetTransmitters.java	Thu Sep 11 20:47:50 2008 +0200
@@ -50,7 +50,7 @@
 		
 	public static void main(String[] args) throws Exception {
 		AudioSynthesizer synth = new SoftSynthesizer();
-		synth.open(null,null);
+        synth.open(new DummySourceDataLine(), null);
 		assertTrue(synth.getTransmitters().size() == 0);
 		synth.close();			
 		
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/ImplicitOpenClose.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/ImplicitOpenClose.java	Thu Sep 11 20:47:50 2008 +0200
@@ -26,6 +26,8 @@
 /* @test
    @summary Test SoftSynthesizer implicit open/close using getReceiver. */
 
+import java.lang.reflect.Field;
+
 import javax.sound.midi.MidiDevice;
 import javax.sound.midi.MidiSystem;
 import javax.sound.midi.MidiUnavailableException;
@@ -40,6 +42,10 @@
 public class ImplicitOpenClose {
 			
 	public static void main(String[] args) throws Exception {
+        Field f = SoftSynthesizer.class.getDeclaredField("testline");
+        f.setAccessible(true);
+        f.set(null, new DummySourceDataLine());
+        
 		Synthesizer synth = new SoftSynthesizer();
 				
 		ReferenceCountingDevice rcd = (ReferenceCountingDevice)synth;		
--- a/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/Open.java	Wed Sep 10 13:37:08 2008 -0400
+++ b/overlays/openjdk/jdk/test/com/sun/media/sound/SoftSynthesizer/Open.java	Thu Sep 11 20:47:50 2008 +0200
@@ -26,6 +26,8 @@
 /* @test
    @summary Test SoftSynthesizer open method */
 
+import java.lang.reflect.Field;
+
 import javax.sound.midi.MidiDevice;
 import javax.sound.midi.MidiUnavailableException;
 import javax.sound.midi.Patch;
@@ -49,6 +51,10 @@
 	}
 		
 	public static void main(String[] args) throws Exception {
+        Field f = SoftSynthesizer.class.getDeclaredField("testline");
+        f.setAccessible(true);
+        f.set(null, new DummySourceDataLine());
+        
 		AudioSynthesizer synth = new SoftSynthesizer();
 		synth.open();
 		assertTrue(synth.isOpen());
--- a/patches/icedtea-gervill.patch	Wed Sep 10 13:37:08 2008 -0400
+++ b/patches/icedtea-gervill.patch	Thu Sep 11 20:47:50 2008 +0200
@@ -9,3 +9,91 @@
  com.sun.media.sound.AlawCodec
  com.sun.media.sound.PCMtoPCMCodec
 +com.sun.media.sound.AudioFloatFormatConverter
+--- openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix.java	2008-07-10 22:02:36.000000000 +0200
++++ openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix.java	2008-09-11 16:16:23.000000000 +0200
+@@ -71,7 +71,7 @@
+ 		}
+ 		
+ 		SoftLimiter limiter = new SoftLimiter();
+-		limiter.init(synth);
++		limiter.init(44100, 147);
+ 		limiter.setMixMode(true);
+ 		limiter.setInput(0, in1);
+ 		limiter.setInput(1, in2);
+--- openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono.java	2008-07-10 22:02:36.000000000 +0200
++++ openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono.java	2008-09-11 16:16:23.000000000 +0200
+@@ -63,7 +63,7 @@
+ 		}
+ 		
+ 		SoftLimiter limiter = new SoftLimiter();
+-		limiter.init(synth);
++		limiter.init(44100, 147);
+ 		limiter.setMixMode(true);
+ 		limiter.setInput(0, in1);
+ 		limiter.setOutput(0, out1);
+--- openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono_overdrive.java	2008-07-10 22:02:36.000000000 +0200
++++ openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono_overdrive.java	2008-09-11 16:16:23.000000000 +0200
+@@ -64,7 +64,7 @@
+ 		}
+ 		
+ 		SoftLimiter limiter = new SoftLimiter();
+-		limiter.init(synth);
++		limiter.init(44100, 147);
+ 		limiter.setMixMode(true);
+ 		limiter.setInput(0, in1);
+ 		limiter.setOutput(0, out1);
+--- openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_overdrive.java	2008-07-10 22:02:36.000000000 +0200
++++ openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_overdrive.java	2008-09-11 16:16:23.000000000 +0200
+@@ -71,7 +71,7 @@
+ 		}
+ 		
+ 		SoftLimiter limiter = new SoftLimiter();
+-		limiter.init(synth);
++		limiter.init(44100, 147);
+ 		limiter.setMixMode(true);
+ 		limiter.setInput(0, in1);
+ 		limiter.setInput(1, in2);
+--- openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal.java	2008-07-10 22:02:36.000000000 +0200
++++ openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal.java	2008-09-11 16:16:23.000000000 +0200
+@@ -71,7 +71,7 @@
+ 		}
+ 		
+ 		SoftLimiter limiter = new SoftLimiter();
+-		limiter.init(synth);
++		limiter.init(44100, 147);
+ 		limiter.setMixMode(false);
+ 		limiter.setInput(0, in1);
+ 		limiter.setInput(1, in2);
+--- openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal_mono.java	2008-07-10 22:02:36.000000000 +0200
++++ openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal_mono.java	2008-09-11 16:16:23.000000000 +0200
+@@ -63,7 +63,7 @@
+ 		}
+ 		
+ 		SoftLimiter limiter = new SoftLimiter();
+-		limiter.init(synth);
++		limiter.init(44100, 147);
+ 		limiter.setMixMode(false);
+ 		limiter.setInput(0, in1);
+ 		limiter.setOutput(0, out1);
+--- openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive.java	2008-07-10 22:02:36.000000000 +0200
++++ openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive.java	2008-09-11 16:16:23.000000000 +0200
+@@ -71,7 +71,7 @@
+ 		}
+ 		
+ 		SoftLimiter limiter = new SoftLimiter();
+-		limiter.init(synth);
++		limiter.init(44100, 147);
+ 		limiter.setMixMode(false);
+ 		limiter.setInput(0, in1);
+ 		limiter.setInput(1, in2);
+--- openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive_mono.java	2008-07-10 22:02:36.000000000 +0200
++++ openjdk/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive_mono.java	2008-09-11 16:16:23.000000000 +0200
+@@ -63,7 +63,7 @@
+ 		}
+ 		
+ 		SoftLimiter limiter = new SoftLimiter();
+-		limiter.init(synth);
++		limiter.init(44100, 147);
+ 		limiter.setMixMode(false);
+ 		limiter.setInput(0, in1);
+ 		limiter.setOutput(0, out1);