changeset 2713:903f44341e34

6941027: Gervill update, April 2010 Reviewed-by: amenkov
author kalli
date Mon, 13 Sep 2010 15:12:31 +0400
parents ee4d92fb6df3
children 3fa6114faa54
files src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java src/share/classes/com/sun/media/sound/ModelInstrument.java src/share/classes/com/sun/media/sound/ModelStandardIndexedDirector.java src/share/classes/com/sun/media/sound/SoftChannel.java src/share/classes/com/sun/media/sound/SoftSynthesizer.java src/share/classes/com/sun/media/sound/SoftVoice.java test/javax/sound/midi/Gervill/AudioFloatFormatConverter/SkipTest.java test/javax/sound/midi/Gervill/ModelByteBufferWavetable/OpenStream.java test/javax/sound/midi/Gervill/SoftSynthesizer/GetAvailableInstruments2.java test/javax/sound/midi/Gervill/SoftSynthesizer/GetLoadedInstruments2.java test/javax/sound/midi/Gervill/SoftSynthesizer/GetPropertyInfo.java test/javax/sound/midi/Gervill/SoftSynthesizer/LoadAllInstruments.java test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstrument.java test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstruments.java test/javax/sound/midi/Gervill/SoftSynthesizer/RemapInstrument.java test/javax/sound/midi/Gervill/SoftSynthesizer/TestDisableLoadDefaultSoundbank.java test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadAllInstruments.java test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstrument.java test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstruments.java test/javax/sound/midi/Gervill/SoftTuning/RealTimeTuning.java
diffstat 22 files changed, 1218 insertions(+), 129 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java	Mon Sep 13 15:12:31 2010 +0400
@@ -175,7 +175,6 @@
                 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) {
@@ -186,7 +185,6 @@
                 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);
@@ -390,6 +388,7 @@
                 return -1;
             if (len < 0)
                 return 0;
+            int offlen = off + len;
             int remain = len / nrofchannels;
             int destPos = 0;
             int in_end = ibuffer_len;
@@ -423,7 +422,7 @@
             for (int c = 0; c < nrofchannels; c++) {
                 int ix = 0;
                 float[] buff = cbuffer[c];
-                for (int i = c; i < b.length; i += nrofchannels) {
+                for (int i = c + off; i < offlen; i += nrofchannels) {
                     b[i] = buff[ix++];
                 }
             }
@@ -447,7 +446,7 @@
         }
 
         public long skip(long len) throws IOException {
-            if (len > 0)
+            if (len < 0)
                 return 0;
             if (skipbuffer == null)
                 skipbuffer = new float[1024 * targetFormat.getFrameSize()];
--- a/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java	Mon Sep 13 15:12:31 2010 +0400
@@ -42,11 +42,14 @@
      */
     public AudioSynthesizerPropertyInfo(String name, Object value) {
         this.name = name;
-        this.value = value;
         if (value instanceof Class)
             valueClass = (Class)value;
-        else if (value != null)
-            valueClass = value.getClass();
+        else
+        {
+            this.value = value;
+            if (value != null)
+                valueClass = value.getClass();
+        }
     }
     /**
      * The name of the property.
--- a/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java	Mon Sep 13 15:12:31 2010 +0400
@@ -205,7 +205,8 @@
         }
         if (buffer.array() == null) {
             return AudioFloatInputStream.getInputStream(new AudioInputStream(
-                    buffer.getInputStream(), format, buffer.capacity()));
+                    buffer.getInputStream(), format,
+                    buffer.capacity() / format.getFrameSize()));
         }
         if (buffer8 != null) {
             if (format.getEncoding().equals(Encoding.PCM_SIGNED)
--- a/src/share/classes/com/sun/media/sound/ModelInstrument.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/src/share/classes/com/sun/media/sound/ModelInstrument.java	Mon Sep 13 15:12:31 2010 +0400
@@ -56,7 +56,7 @@
 
     public ModelDirector getDirector(ModelPerformer[] performers,
             MidiChannel channel, ModelDirectedPlayer player) {
-        return new ModelStandardDirector(performers, player);
+        return new ModelStandardIndexedDirector(performers, player);
     }
 
     public ModelPerformer[] getPerformers() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/media/sound/ModelStandardIndexedDirector.java	Mon Sep 13 15:12:31 2010 +0400
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.media.sound;
+
+/**
+ * A standard indexed director who chooses performers
+ * by there keyfrom,keyto,velfrom,velto properties.
+ *
+ * @author Karl Helgason
+ */
+public class ModelStandardIndexedDirector implements ModelDirector {
+
+    ModelPerformer[] performers;
+    ModelDirectedPlayer player;
+    boolean noteOnUsed = false;
+    boolean noteOffUsed = false;
+
+    // Variables needed for index
+    byte[][] trantables;
+    int[] counters;
+    int[][] mat;
+
+    public ModelStandardIndexedDirector(ModelPerformer[] performers,
+            ModelDirectedPlayer player) {
+        this.performers = performers;
+        this.player = player;
+        for (int i = 0; i < performers.length; i++) {
+            ModelPerformer p = performers[i];
+            if (p.isReleaseTriggered()) {
+                noteOffUsed = true;
+            } else {
+                noteOnUsed = true;
+            }
+        }
+        buildindex();
+    }
+
+    private int[] lookupIndex(int x, int y)
+    {
+        if ((x >= 0) && (x < 128) && (y >= 0) && (y < 128)) {
+            int xt = trantables[0][x];
+            int yt = trantables[1][y];
+            if (xt != -1 && yt != -1) {
+                return mat[xt + yt * counters[0]];
+            }
+        }
+        return null;
+    }
+
+    private void buildindex() {
+        trantables = new byte[2][129];
+        counters = new int[trantables.length];
+        for (ModelPerformer performer : performers) {
+            trantables[0][performer.getKeyFrom()] = 1;
+            trantables[0][performer.getKeyTo() + 1] = 1;
+            trantables[1][performer.getVelFrom()] = 1;
+            trantables[1][performer.getVelTo() + 1] = 1;
+        }
+        for (int d = 0; d < trantables.length; d++) {
+            byte[] trantable = trantables[d];
+            int transize = trantable.length;
+            for (int i = transize - 1; i >= 0; i--) {
+                if (trantable[i] == 1) {
+                    trantable[i] = -1;
+                    break;
+                }
+                trantable[i] = -1;
+            }
+            int counter = -1;
+            for (int i = 0; i < transize; i++) {
+                if (trantable[i] != 0) {
+                    counter++;
+                    if (trantable[i] == -1)
+                        break;
+                }
+                trantable[i] = (byte) counter;
+            }
+            counters[d] = counter;
+        }
+        mat = new int[counters[0] * counters[1]][];
+        int ix = 0;
+        for (ModelPerformer performer : performers) {
+            int x_from = trantables[0][performer.getKeyFrom()];
+            int x_to = trantables[0][performer.getKeyTo() + 1];
+            int y_from = trantables[1][performer.getVelFrom()];
+            int y_to = trantables[1][performer.getVelTo() + 1];
+            if (x_to == -1)
+                x_to = counters[0];
+            if (y_to == -1)
+                y_to = counters[1];
+            for (int y = y_from; y < y_to; y++) {
+                int i = x_from + y * counters[0];
+                for (int x = x_from; x < x_to; x++) {
+                    int[] mprev = mat[i];
+                    if (mprev == null) {
+                        mat[i] = new int[] { ix };
+                    } else {
+                        int[] mnew = new int[mprev.length + 1];
+                        mnew[mnew.length - 1] = ix;
+                        for (int k = 0; k < mprev.length; k++)
+                            mnew[k] = mprev[k];
+                        mat[i] = mnew;
+                    }
+                    i++;
+                }
+            }
+            ix++;
+        }
+    }
+
+    public void close() {
+    }
+
+    public void noteOff(int noteNumber, int velocity) {
+        if (!noteOffUsed)
+            return;
+        int[] plist = lookupIndex(noteNumber, velocity);
+        if(plist == null) return;
+        for (int i : plist) {
+            ModelPerformer p = performers[i];
+            if (p.isReleaseTriggered()) {
+                player.play(i, null);
+            }
+        }
+    }
+
+    public void noteOn(int noteNumber, int velocity) {
+        if (!noteOnUsed)
+            return;
+        int[] plist = lookupIndex(noteNumber, velocity);
+        if(plist == null) return;
+        for (int i : plist) {
+            ModelPerformer p = performers[i];
+            if (!p.isReleaseTriggered()) {
+                player.play(i, null);
+            }
+        }
+    }
+}
--- a/src/share/classes/com/sun/media/sound/SoftChannel.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/src/share/classes/com/sun/media/sound/SoftChannel.java	Mon Sep 13 15:12:31 2010 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. 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
@@ -116,7 +116,7 @@
     protected int tuning_program = 0;
     protected SoftInstrument current_instrument = null;
     protected ModelChannelMixer current_mixer = null;
-    private ModelDirector current_director = null;
+    protected ModelDirector current_director = null;
 
     // Controller Destination Settings
     protected int cds_control_number = -1;
@@ -1268,9 +1268,12 @@
         program = restrict7Bit(program);
         synchronized (control_mutex) {
             mainmixer.activity();
-            this.bank = bank;
-            this.program = program;
-            current_instrument = null;
+            if(this.bank != bank || this.program != program)
+            {
+                this.bank = bank;
+                this.program = program;
+                current_instrument = null;
+            }
         }
     }
 
--- a/src/share/classes/com/sun/media/sound/SoftSynthesizer.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/src/share/classes/com/sun/media/sound/SoftSynthesizer.java	Mon Sep 13 15:12:31 2010 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. 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
@@ -25,16 +25,25 @@
 
 package com.sun.media.sound;
 
+import java.io.BufferedInputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.lang.ref.WeakReference;
-import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
 
 import javax.sound.midi.Instrument;
 import javax.sound.midi.MidiChannel;
@@ -182,6 +191,7 @@
     // 1: DLS Voice Allocation
     protected int voice_allocation_mode = 0;
 
+    protected boolean load_default_soundbank = false;
     protected boolean reverb_light = true;
     protected boolean reverb_on = true;
     protected boolean chorus_on = true;
@@ -226,8 +236,6 @@
             = new HashMap<String, SoftTuning>();
     private Map<String, SoftInstrument> inslist
             = new HashMap<String, SoftInstrument>();
-    private Map<String, ModelInstrument> availlist
-            = new HashMap<String, ModelInstrument>();
     private Map<String, ModelInstrument> loadedlist
             = new HashMap<String, ModelInstrument>();
 
@@ -275,10 +283,12 @@
         synchronized (control_mutex) {
             if (channels != null)
                 for (SoftChannel c : channels)
+                {
                     c.current_instrument = null;
+                    c.current_director = null;
+                }
             for (Instrument instrument : instruments) {
                 String pat = patchToString(instrument.getPatch());
-                availlist.remove(pat);
                 SoftInstrument softins
                         = new SoftInstrument((ModelInstrument) instrument);
                 inslist.put(pat, softins);
@@ -341,6 +351,7 @@
         number_of_midi_channels = (Integer)items[10].value;
         jitter_correction = (Boolean)items[11].value;
         reverb_light = (Boolean)items[12].value;
+        load_default_soundbank = (Boolean)items[13].value;
     }
 
     private String patchToString(Patch patch) {
@@ -578,7 +589,9 @@
                 c.current_instrument = null;
             inslist.remove(pat);
             loadedlist.remove(pat);
-            availlist.remove(pat);
+            for (int i = 0; i < channels.length; i++) {
+                channels[i].allSoundOff();
+            }
         }
     }
 
@@ -600,7 +613,7 @@
             return false;
 
         synchronized (control_mutex) {
-            if (!loadedlist.containsValue(to) && !availlist.containsValue(to))
+            if (!loadedlist.containsValue(to))
                 throw new IllegalArgumentException("Instrument to is not loaded.");
             unloadInstrument(from);
             ModelMappedInstrument mfrom = new ModelMappedInstrument(
@@ -609,118 +622,155 @@
         }
     }
 
-    public synchronized Soundbank getDefaultSoundbank() {
-        if (defaultSoundBank == null) {
-            try {
-                File javahome = new File(System.getProperties().getProperty(
-                        "java.home"));
-                File libaudio = new File(new File(javahome, "lib"), "audio");
+    public Soundbank getDefaultSoundbank() {
+        synchronized (SoftSynthesizer.class) {
+            if (defaultSoundBank != null)
+                return defaultSoundBank;
 
-                if (libaudio.exists()) {
-                    File foundfile = null;
-                    File[] files = libaudio.listFiles();
-                    if (files != null) {
-                        for (int i = 0; i < files.length; i++) {
-                            File file = files[i];
-                            if (file.isFile()) {
-                                String lname = file.getName().toLowerCase();
-                                if (lname.endsWith(".sf2") ||
-                                        lname.endsWith(".dls")) {
-                                    if (foundfile == null || (file.length() >
-                                            foundfile.length())) {
-                                        foundfile = file;
+            List<PrivilegedAction<InputStream>> actions =
+                new ArrayList<PrivilegedAction<InputStream>>();
+
+            actions.add(new PrivilegedAction<InputStream>() {
+                public InputStream run() {
+                    File javahome = new File(System.getProperties()
+                            .getProperty("java.home"));
+                    File libaudio = new File(new File(javahome, "lib"), "audio");
+                    if (libaudio.exists()) {
+                        File foundfile = null;
+                        File[] files = libaudio.listFiles();
+                        if (files != null) {
+                            for (int i = 0; i < files.length; i++) {
+                                File file = files[i];
+                                if (file.isFile()) {
+                                    String lname = file.getName().toLowerCase();
+                                    if (lname.endsWith(".sf2")
+                                            || lname.endsWith(".dls")) {
+                                        if (foundfile == null
+                                                || (file.length() > foundfile
+                                                        .length())) {
+                                            foundfile = file;
+                                        }
                                     }
                                 }
                             }
                         }
-                    }
-                    if (foundfile != null) {
-                        try {
-                            Soundbank sbk = MidiSystem.getSoundbank(foundfile);
-                            defaultSoundBank = sbk;
-                            return defaultSoundBank;
-                        } catch (Exception e) {
-                            //e.printStackTrace();
+                        if (foundfile != null) {
+                            try {
+                                return new FileInputStream(foundfile);
+                            } catch (IOException e) {
+                            }
                         }
                     }
+                    return null;
                 }
+            });
 
-                if (System.getProperties().getProperty("os.name")
-                        .startsWith("Windows")) {
-                    File gm_dls = new File(System.getenv("SystemRoot")
-                            + "\\system32\\drivers\\gm.dls");
-                    if (gm_dls.exists()) {
-                        try {
-                            Soundbank sbk = MidiSystem.getSoundbank(gm_dls);
-                            defaultSoundBank = sbk;
-                            return defaultSoundBank;
-                        } catch (Exception e) {
-                            //e.printStackTrace();
+            actions.add(new PrivilegedAction<InputStream>() {
+                public InputStream run() {
+                    if (System.getProperties().getProperty("os.name")
+                            .startsWith("Windows")) {
+                        File gm_dls = new File(System.getenv("SystemRoot")
+                                + "\\system32\\drivers\\gm.dls");
+                        if (gm_dls.exists()) {
+                            try {
+                                return new FileInputStream(gm_dls);
+                            } catch (IOException e) {
+                            }
                         }
                     }
+                    return null;
                 }
-            } catch (AccessControlException e) {
-            } catch (Exception e) {
-                //e.printStackTrace();
-            }
+            });
 
-            File userhome = null;
-            File emg_soundbank_file = null;
+            actions.add(new PrivilegedAction<InputStream>() {
+                public InputStream run() {
+                    /*
+                     * Try to load saved generated soundbank
+                     */
+                    File userhome = new File(System.getProperty("user.home"),
+                            ".gervill");
+                    File emg_soundbank_file = new File(userhome,
+                            "soundbank-emg.sf2");
+                    if (emg_soundbank_file.exists()) {
+                        try {
+                            return new FileInputStream(emg_soundbank_file);
+                        } catch (IOException e) {
+                        }
+                    }
+                    return 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();
+            for (PrivilegedAction<InputStream> action : actions) {
+                try {
+                    InputStream is = AccessController.doPrivileged(action);
+                    if(is == null) continue;
+                    Soundbank sbk;
+                    try {
+                        sbk = MidiSystem.getSoundbank(new BufferedInputStream(is));
+                    } finally {
+                        is.close();
+                    }
+                    if (sbk != null) {
+                        defaultSoundBank = sbk;
+                        return defaultSoundBank;
+                    }
+                } catch (Exception e) {
+                }
             }
 
             try {
-
                 /*
-                 *  Generate emergency soundbank
+                 * 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();
             }
 
+            if (defaultSoundBank != null) {
+                /*
+                 * Save generated soundbank to disk for faster future use.
+                 */
+                OutputStream out = AccessController
+                        .doPrivileged(new PrivilegedAction<OutputStream>() {
+                            public OutputStream run() {
+                                try {
+                                    File userhome = new File(System
+                                            .getProperty("user.home"),
+                                            ".gervill");
+                                    if (!userhome.exists())
+                                        userhome.mkdirs();
+                                    File emg_soundbank_file = new File(
+                                            userhome, "soundbank-emg.sf2");
+                                    if (emg_soundbank_file.exists())
+                                        return null;
+                                    return new FileOutputStream(
+                                            emg_soundbank_file);
+                                } catch (IOException e) {
+                                } catch (SecurityException e) {
+                                }
+                                return null;
+                            }
+                        });
+                if (out != null) {
+                    try {
+                        ((SF2Soundbank) defaultSoundBank).save(out);
+                        out.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
         }
         return defaultSoundBank;
     }
 
     public Instrument[] getAvailableInstruments() {
-        if (!isOpen()) {
-            Soundbank defsbk = getDefaultSoundbank();
-            if (defsbk == null)
-                return new Instrument[0];
-            return defsbk.getInstruments();
-        }
-
-        synchronized (control_mutex) {
-            ModelInstrument[] inslist_array =
-                    new ModelInstrument[availlist.values().size()];
-            availlist.values().toArray(inslist_array);
-            Arrays.sort(inslist_array, new ModelInstrumentComparator());
-            return inslist_array;
-        }
+        Soundbank defsbk = getDefaultSoundbank();
+        if (defsbk == null)
+            return new Instrument[0];
+        Instrument[] inslist_array = defsbk.getInstruments();
+        Arrays.sort(inslist_array, new ModelInstrumentComparator());
+        return inslist_array;
     }
 
     public Instrument[] getLoadedInstruments() {
@@ -794,6 +844,31 @@
         return info;
     }
 
+    private Properties getStoredProperties() {
+        return AccessController
+                .doPrivileged(new PrivilegedAction<Properties>() {
+                    public Properties run() {
+                        Properties p = new Properties();
+                        String notePath = "/com/sun/media/sound/softsynthesizer";
+                        try {
+                            Preferences prefroot = Preferences.userRoot();
+                            if (prefroot.nodeExists(notePath)) {
+                                Preferences prefs = prefroot.node(notePath);
+                                String[] prefs_keys = prefs.keys();
+                                for (String prefs_key : prefs_keys) {
+                                    String val = prefs.get(prefs_key, null);
+                                    if (val != null)
+                                        p.setProperty(prefs_key, val);
+                                }
+                            }
+                        } catch (BackingStoreException e) {
+                        } catch (SecurityException e) {
+                        }
+                        return p;
+                    }
+                });
+    }
+
     public AudioSynthesizerPropertyInfo[] getPropertyInfo(Map<String, Object> info) {
         List<AudioSynthesizerPropertyInfo> list =
                 new ArrayList<AudioSynthesizerPropertyInfo>();
@@ -861,17 +936,92 @@
         item.description = "Turn light reverb mode on or off";
         list.add(item);
 
+        item = new AudioSynthesizerPropertyInfo("load default soundbank", o?load_default_soundbank:true);
+        item.description = "Enabled/disable loading default soundbank";
+        list.add(item);
+
         AudioSynthesizerPropertyInfo[] items;
         items = list.toArray(new AudioSynthesizerPropertyInfo[list.size()]);
 
-        if (info != null)
-            for (AudioSynthesizerPropertyInfo item2: items) {
-                Object v = info.get(item2.name);
+        Properties storedProperties = getStoredProperties();
+
+        for (AudioSynthesizerPropertyInfo item2 : items) {
+            Object v = (info == null) ? null : info.get(item2.name);
+            v = (v != null) ? v : storedProperties.getProperty(item2.name);
+            if (v != null) {
                 Class c = (item2.valueClass);
-                if (v != null)
-                    if (c.isInstance(v))
-                        item2.value = v;
+                if (c.isInstance(v))
+                    item2.value = v;
+                else if (v instanceof String) {
+                    String s = (String) v;
+                    if (c == Boolean.class) {
+                        if (s.equalsIgnoreCase("true"))
+                            item2.value = Boolean.TRUE;
+                        if (s.equalsIgnoreCase("false"))
+                            item2.value = Boolean.FALSE;
+                    } else if (c == AudioFormat.class) {
+                        int channels = 2;
+                        boolean signed = true;
+                        boolean bigendian = false;
+                        int bits = 16;
+                        float sampleRate = 44100f;
+                        try {
+                            StringTokenizer st = new StringTokenizer(s, ", ");
+                            String prevToken = "";
+                            while (st.hasMoreTokens()) {
+                                String token = st.nextToken().toLowerCase();
+                                if (token.equals("mono"))
+                                    channels = 1;
+                                if (token.startsWith("channel"))
+                                    channels = Integer.parseInt(prevToken);
+                                if (token.contains("unsigned"))
+                                    signed = false;
+                                if (token.equals("big-endian"))
+                                    bigendian = true;
+                                if (token.equals("bit"))
+                                    bits = Integer.parseInt(prevToken);
+                                if (token.equals("hz"))
+                                    sampleRate = Float.parseFloat(prevToken);
+                                prevToken = token;
+                            }
+                            item2.value = new AudioFormat(sampleRate, bits,
+                                    channels, signed, bigendian);
+                        } catch (NumberFormatException e) {
+                        }
+
+                    } else
+                        try {
+                            if (c == Byte.class)
+                                item2.value = Byte.valueOf(s);
+                            else if (c == Short.class)
+                                item2.value = Short.valueOf(s);
+                            else if (c == Integer.class)
+                                item2.value = Integer.valueOf(s);
+                            else if (c == Long.class)
+                                item2.value = Long.valueOf(s);
+                            else if (c == Float.class)
+                                item2.value = Float.valueOf(s);
+                            else if (c == Double.class)
+                                item2.value = Double.valueOf(s);
+                        } catch (NumberFormatException e) {
+                        }
+                } else if (v instanceof Number) {
+                    Number n = (Number) v;
+                    if (c == Byte.class)
+                        item2.value = Byte.valueOf(n.byteValue());
+                    if (c == Short.class)
+                        item2.value = Short.valueOf(n.shortValue());
+                    if (c == Integer.class)
+                        item2.value = Integer.valueOf(n.intValue());
+                    if (c == Long.class)
+                        item2.value = Long.valueOf(n.longValue());
+                    if (c == Float.class)
+                        item2.value = Float.valueOf(n.floatValue());
+                    if (c == Double.class)
+                        item2.value = Double.valueOf(n.doubleValue());
+                }
             }
+        }
 
         return items;
     }
@@ -1007,11 +1157,12 @@
             if (targetFormat != null)
                 setFormat(targetFormat);
 
-            Soundbank defbank = getDefaultSoundbank();
-            if (defbank != null) {
-                loadAllInstruments(defbank);
-                availlist.putAll(loadedlist);
-                loadedlist.clear();
+            if (load_default_soundbank)
+            {
+                Soundbank defbank = getDefaultSoundbank();
+                if (defbank != null) {
+                    loadAllInstruments(defbank);
+                }
             }
 
             voices = new SoftVoice[maxpoly];
@@ -1117,7 +1268,6 @@
             }
 
             inslist.clear();
-            availlist.clear();
             loadedlist.clear();
             tunings.clear();
 
--- a/src/share/classes/com/sun/media/sound/SoftVoice.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/src/share/classes/com/sun/media/sound/SoftVoice.java	Mon Sep 13 15:12:31 2010 +0400
@@ -279,9 +279,12 @@
     }
 
     protected void updateTuning(SoftTuning newtuning) {
+        tuning = newtuning;
         tunedKey = tuning.getTuning(note) / 100.0;
         if (!portamento) {
             co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
+            if(performer == null)
+                return;
             int[] c = performer.midi_connections[4];
             if (c == null)
                 return;
@@ -433,6 +436,8 @@
     }
 
     protected void setPolyPressure(int pressure) {
+        if(performer == null)
+            return;
         int[] c = performer.midi_connections[2];
         if (c == null)
             return;
@@ -441,6 +446,8 @@
     }
 
     protected void setChannelPressure(int pressure) {
+        if(performer == null)
+            return;
         int[] c = performer.midi_connections[1];
         if (c == null)
             return;
@@ -449,6 +456,8 @@
     }
 
     protected void controlChange(int controller, int value) {
+        if(performer == null)
+            return;
         int[] c = performer.midi_ctrl_connections[controller];
         if (c == null)
             return;
@@ -457,6 +466,8 @@
     }
 
     protected void nrpnChange(int controller, int value) {
+        if(performer == null)
+            return;
         int[] c = performer.midi_nrpn_connections.get(controller);
         if (c == null)
             return;
@@ -465,6 +476,8 @@
     }
 
     protected void rpnChange(int controller, int value) {
+        if(performer == null)
+            return;
         int[] c = performer.midi_rpn_connections.get(controller);
         if (c == null)
             return;
@@ -473,6 +486,8 @@
     }
 
     protected void setPitchBend(int bend) {
+        if(performer == null)
+            return;
         int[] c = performer.midi_connections[0];
         if (c == null)
             return;
@@ -499,6 +514,8 @@
 
         co_noteon_on[0] = -1;
 
+        if(performer == null)
+            return;
         int[] c = performer.midi_connections[3];
         if (c == null)
             return;
@@ -527,6 +544,8 @@
 
         co_noteon_on[0] = 0;
 
+        if(performer == null)
+            return;
         int[] c = performer.midi_connections[3];
         if (c == null)
             return;
@@ -543,6 +562,8 @@
         sustain = true;
         co_noteon_on[0] = 1;
 
+        if(performer == null)
+            return;
         int[] c = performer.midi_connections[3];
         if (c == null)
             return;
@@ -555,6 +576,11 @@
             active = false;
             stopping = false;
             audiostarted = false;
+            instrument = null;
+            performer = null;
+            connections = null;
+            extendedConnectionBlocks = null;
+            channelmixer = null;
             if (osc_stream != null)
                 try {
                     osc_stream.close();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/sound/midi/Gervill/AudioFloatFormatConverter/SkipTest.java	Mon Sep 13 15:12:31 2010 +0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @summary Test skip method returned from AudioFloatFormatConverter.getAudioInputStream */
+
+import java.io.ByteArrayInputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+
+import com.sun.media.sound.AudioFloatFormatConverter;
+
+public class SkipTest {
+
+    public static void main(String[] args) throws Exception {
+        AudioFloatFormatConverter converter = new AudioFloatFormatConverter();
+        byte[] data = { 10, 20, 30, 40, 30, 20, 10 };
+        AudioFormat format = new AudioFormat(8000, 8, 1, true, false);
+        AudioFormat format2 = new AudioFormat(16000, 8, 1, true, false);
+        AudioInputStream ais = new AudioInputStream(new ByteArrayInputStream(
+                data), format, data.length);
+        AudioInputStream ais2 = converter.getAudioInputStream(format2, ais);
+        byte[] data2 = new byte[30];
+        int ret = ais2.read(data2, 0, data2.length);
+        ais.reset();
+        AudioInputStream ais3 = converter.getAudioInputStream(format2, ais);
+        byte[] data3 = new byte[100];
+        ais3.skip(7);
+        int ret2 = ais3.read(data3, 7, data3.length);
+        if (ret2 != ret - 7)
+            throw new Exception("Skip doesn't work correctly (" + ret2 + " != "
+                    + (ret - 7) + ")");
+        for (int i = 7; i < ret2 + 7; i++) {
+            if (data3[i] != data2[i])
+                throw new Exception("Skip doesn't work correctly (" + data3[i]
+                        + " != " + data2[i] + ")");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/OpenStream.java	Mon Sep 13 15:12:31 2010 +0400
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @summary Test AudioFloatInputStream.getFrameLength() returned from
+ ModelByteBufferWavetable openStream method */
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+
+import javax.sound.sampled.*;
+
+import com.sun.media.sound.*;
+
+public class OpenStream {
+
+    static float[] testarray;
+
+    static byte[] test_byte_array;
+
+    static byte[] test_byte_array_8ext;
+
+    static AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
+
+    static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false);
+
+    static ModelByteBuffer buffer;
+
+    static ModelByteBuffer buffer_wave;
+
+    static ModelByteBuffer buffer8;
+
+    static ModelByteBuffer buffer16_8;
+
+    static ModelByteBuffer buffer24;
+
+    static File test_file;
+
+    static ModelByteBuffer buffer_wave_ondisk;
+
+    static void setUp() throws Exception {
+        testarray = new float[1024];
+        for (int i = 0; i < 1024; i++) {
+            double ii = i / 1024.0;
+            ii = ii * ii;
+            testarray[i] = (float) Math.sin(10 * ii * 2 * Math.PI);
+            testarray[i] += (float) Math.sin(1.731 + 2 * ii * 2 * Math.PI);
+            testarray[i] += (float) Math.sin(0.231 + 6.3 * ii * 2 * Math.PI);
+            testarray[i] *= 0.3;
+        }
+        test_byte_array = new byte[testarray.length * 2];
+        AudioFloatConverter.getConverter(format).toByteArray(testarray,
+                test_byte_array);
+        buffer = new ModelByteBuffer(test_byte_array);
+
+        byte[] test_byte_array2 = new byte[testarray.length * 3];
+        buffer24 = new ModelByteBuffer(test_byte_array2);
+        test_byte_array_8ext = new byte[testarray.length];
+        byte[] test_byte_array_8_16 = new byte[testarray.length * 2];
+        AudioFloatConverter.getConverter(format24).toByteArray(testarray,
+                test_byte_array2);
+        int ix = 0;
+        int x = 0;
+        for (int i = 0; i < test_byte_array_8ext.length; i++) {
+            test_byte_array_8ext[i] = test_byte_array2[ix++];
+            test_byte_array_8_16[x++] = test_byte_array2[ix++];
+            test_byte_array_8_16[x++] = test_byte_array2[ix++];
+        }
+        buffer16_8 = new ModelByteBuffer(test_byte_array_8_16);
+        buffer8 = new ModelByteBuffer(test_byte_array_8ext);
+
+        AudioInputStream ais = new AudioInputStream(buffer.getInputStream(),
+                format, testarray.length);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos);
+        buffer_wave = new ModelByteBuffer(baos.toByteArray());
+
+        test_file = File.createTempFile("test", ".raw");
+        FileOutputStream fos = new FileOutputStream(test_file);
+        fos.write(baos.toByteArray());
+        fos.close();
+        buffer_wave_ondisk = new ModelByteBuffer(test_file);
+
+    }
+
+    static void tearDown() throws Exception {
+        if (!test_file.delete())
+            test_file.deleteOnExit();
+    }
+
+    public static void testOpenStream(ModelByteBufferWavetable wavetable)
+            throws Exception {
+        AudioFloatInputStream ais = wavetable.openStream();
+        long frames = wavetable.getBuffer().capacity()
+                / wavetable.getFormat().getFrameSize();
+        long framelength = ais.getFrameLength();
+        ais.close();
+        if (frames != framelength) {
+            throw new Exception("Incorrect framelength returned (" + frames
+                    + " != " + framelength + ")");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        setUp();
+
+        try {
+            testOpenStream(new ModelByteBufferWavetable(buffer, format));
+            testOpenStream(new ModelByteBufferWavetable(buffer_wave, format));
+            testOpenStream(new ModelByteBufferWavetable(buffer_wave_ondisk,
+                    format));
+        } finally {
+            tearDown();
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/GetAvailableInstruments2.java	Mon Sep 13 15:12:31 2010 +0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @summary Test SoftSynthesizer getAvailableInstruments method */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.sampled.*;
+import javax.sound.midi.MidiDevice.Info;
+
+import com.sun.media.sound.*;
+
+public class GetAvailableInstruments2 {
+
+    private static void assertEquals(Object a, Object b) throws Exception {
+        if (!a.equals(b))
+            throw new RuntimeException("assertEquals fails!");
+    }
+
+    private static void assertTrue(boolean value) throws Exception {
+        if (!value)
+            throw new RuntimeException("assertTrue fails!");
+    }
+
+    public static void main(String[] args) throws Exception {
+        AudioSynthesizer synth = new SoftSynthesizer();
+        synth.openStream(null, null);
+        Soundbank defsbk = synth.getDefaultSoundbank();
+        if (defsbk != null) {
+            synth.unloadAllInstruments(defsbk);
+            assertTrue(defsbk.getInstruments().length == synth
+                    .getAvailableInstruments().length);
+        }
+        synth.close();
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/GetLoadedInstruments2.java	Mon Sep 13 15:12:31 2010 +0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @summary Test SoftSynthesizer getLoadedInstruments method */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.sampled.*;
+import javax.sound.midi.MidiDevice.Info;
+
+import com.sun.media.sound.*;
+
+public class GetLoadedInstruments2 {
+
+    private static void assertEquals(Object a, Object b) throws Exception {
+        if (!a.equals(b))
+            throw new RuntimeException("assertEquals fails!");
+    }
+
+    private static void assertTrue(boolean value) throws Exception {
+        if (!value)
+            throw new RuntimeException("assertTrue fails!");
+    }
+
+    public static void main(String[] args) throws Exception {
+        AudioSynthesizer synth = new SoftSynthesizer();
+        synth.openStream(null, null);
+        Soundbank defsbk = synth.getDefaultSoundbank();
+        if (defsbk != null) {
+            assertTrue(defsbk.getInstruments().length == synth
+                    .getLoadedInstruments().length);
+        }
+        synth.close();
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/GetPropertyInfo.java	Mon Sep 13 15:12:31 2010 +0400
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @summary Test SoftSynthesizer getPropertyInfo method */
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.sampled.*;
+import javax.sound.sampled.AudioFormat.Encoding;
+import javax.sound.midi.MidiDevice.Info;
+
+import com.sun.media.sound.*;
+
+public class GetPropertyInfo {
+
+    private static void assertTrue(boolean value) throws Exception {
+        if (!value)
+            throw new RuntimeException("assertTrue fails!");
+    }
+
+    public static void main(String[] args) throws Exception {
+        SoftSynthesizer synth = new SoftSynthesizer();
+        Map<String, Object> p = new HashMap<String, Object>();
+        p.put("format", "8000 HZ 24 BIT MONO UNSIGNED BIG-ENDIAN");
+        p.put("control rate", 125);
+        p.put("reverb", false);
+        p.put("auto gain control", "false");
+        AudioSynthesizerPropertyInfo[] ap = synth.getPropertyInfo(p);
+        for (int i = 0; i < ap.length; i++) {
+            if (ap[i].name.equals("control rate"))
+                assertTrue(Math.abs((Float) ap[i].value - 125.0) < 0.001);
+            if (ap[i].name.equals("reverb"))
+                assertTrue((Boolean) ap[i].value == false);
+            if (ap[i].name.equals("auto gain control"))
+                assertTrue((Boolean) ap[i].value == false);
+            if (ap[i].name.equals("format")) {
+                AudioFormat format = (AudioFormat) ap[i].value;
+                assertTrue(format.getChannels() == 1);
+                assertTrue(format.getSampleSizeInBits() == 24);
+                assertTrue(format.isBigEndian());
+                assertTrue(Math.abs(format.getSampleRate() - 8000) < 0.001);
+                assertTrue(format.getEncoding() == Encoding.PCM_UNSIGNED);
+            }
+        }
+        p = new HashMap<String, Object>();
+        p.put("format", "9000 Hz, 8 bit, 4 channels");
+        ap = synth.getPropertyInfo(p);
+        for (int i = 0; i < ap.length; i++) {
+            if (ap[i].name.equals("format")) {
+                AudioFormat format = (AudioFormat) ap[i].value;
+                assertTrue(format.getChannels() == 4);
+                assertTrue(format.getSampleSizeInBits() == 8);
+                assertTrue(!format.isBigEndian());
+                assertTrue(Math.abs(format.getSampleRate() - 9000) < 0.001);
+                assertTrue(format.getEncoding() == Encoding.PCM_SIGNED);
+            }
+        }
+
+        p = new HashMap<String, Object>();
+        p.put("format", "PCM_UNSIGNED 44100.0 Hz, 16 bit, 3 channels, 6 bytes/frame, big-endian");
+        ap = synth.getPropertyInfo(p);
+        for (int i = 0; i < ap.length; i++) {
+            if (ap[i].name.equals("format")) {
+                AudioFormat format = (AudioFormat) ap[i].value;
+                assertTrue(format.getChannels() == 3);
+                assertTrue(format.getSampleSizeInBits() == 16);
+                assertTrue(format.isBigEndian());
+                assertTrue(Math.abs(format.getSampleRate() - 44100) < 0.001);
+                assertTrue(format.getEncoding() == Encoding.PCM_UNSIGNED);
+            }
+        }
+
+
+    }
+}
--- a/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadAllInstruments.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadAllInstruments.java	Mon Sep 13 15:12:31 2010 +0400
@@ -55,7 +55,6 @@
         Soundbank defsbk = synth.getDefaultSoundbank();
         if(defsbk != null)
         {
-            assertTrue(synth.getLoadedInstruments().length == 0);
             synth.unloadAllInstruments(defsbk);
             SimpleSoundbank sbk = new SimpleSoundbank();
             SimpleInstrument ins = new SimpleInstrument();
--- a/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstrument.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstrument.java	Mon Sep 13 15:12:31 2010 +0400
@@ -55,7 +55,6 @@
         Soundbank defsbk = synth.getDefaultSoundbank();
         if(defsbk != null)
         {
-            assertTrue(synth.getLoadedInstruments().length == 0);
             synth.unloadAllInstruments(defsbk);
             SimpleSoundbank sbk = new SimpleSoundbank();
             SimpleInstrument ins = new SimpleInstrument();
--- a/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstruments.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstruments.java	Mon Sep 13 15:12:31 2010 +0400
@@ -55,7 +55,6 @@
         Soundbank defsbk = synth.getDefaultSoundbank();
         if(defsbk != null)
         {
-            assertTrue(synth.getLoadedInstruments().length == 0);
             synth.unloadAllInstruments(defsbk);
             SimpleSoundbank sbk = new SimpleSoundbank();
             SimpleInstrument ins = new SimpleInstrument();
--- a/test/javax/sound/midi/Gervill/SoftSynthesizer/RemapInstrument.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/RemapInstrument.java	Mon Sep 13 15:12:31 2010 +0400
@@ -56,15 +56,15 @@
         Soundbank defsbk = synth.getDefaultSoundbank();
         if(defsbk != null)
         {
-            Instrument ins0 = defsbk.getInstrument(new Patch(0,0));
+            Instrument ins3 = defsbk.getInstrument(new Patch(0,3));
             Instrument ins10 = defsbk.getInstrument(new Patch(0,10));
-            assertTrue(synth.remapInstrument(ins0, ins10));
+            assertTrue(synth.remapInstrument(ins3, ins10));
             Instrument[] loaded = synth.getLoadedInstruments();
             for (int i = 0; i < loaded.length; i++) {
-                if(loaded[i].getPatch().getBank() == 0)
-                if(loaded[i].getPatch().getProgram() == 10)
+                if(loaded[i].getPatch().getBank() == ins3.getPatch().getBank())
+                if(loaded[i].getPatch().getProgram() == ins3.getPatch().getProgram())
                 {
-                    assertEquals(loaded[i].getName(), ins0.getName());
+                    assertEquals(loaded[i].getName(), ins10.getName());
                     break;
                 }
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/TestDisableLoadDefaultSoundbank.java	Mon Sep 13 15:12:31 2010 +0400
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @summary Test Disable/enable loading default soundbank in SoftSynthesizer */
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Patch;
+import javax.sound.midi.Soundbank;
+import javax.sound.sampled.*;
+import javax.sound.midi.MidiDevice.Info;
+
+import com.sun.media.sound.*;
+
+public class TestDisableLoadDefaultSoundbank {
+
+    private static void assertEquals(Object a, Object b) throws Exception {
+        if (!a.equals(b))
+            throw new RuntimeException("assertEquals fails!");
+    }
+
+    private static void assertTrue(boolean value) throws Exception {
+        if (!value)
+            throw new RuntimeException("assertTrue fails!");
+    }
+
+    public static void main(String[] args) throws Exception {
+        AudioSynthesizer synth = new SoftSynthesizer();
+        synth.openStream(null, null);
+        Soundbank defsbk = synth.getDefaultSoundbank();
+        if (defsbk != null) {
+            assertTrue(defsbk.getInstruments().length == synth
+                    .getLoadedInstruments().length);
+        }
+        synth.close();
+        Map<String, Object> p = new HashMap<String, Object>();
+        p.put("load default soundbank", false);
+        synth.openStream(null, p);
+        if (defsbk != null) {
+            assertTrue(synth.getLoadedInstruments().length == 0);
+        }
+        synth.close();
+
+    }
+}
--- a/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadAllInstruments.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadAllInstruments.java	Mon Sep 13 15:12:31 2010 +0400
@@ -55,9 +55,8 @@
         Soundbank defsbk = synth.getDefaultSoundbank();
         if(defsbk != null)
         {
+            synth.unloadAllInstruments(defsbk);
             assertTrue(synth.getLoadedInstruments().length == 0);
-            synth.unloadAllInstruments(defsbk);
-            assertTrue(synth.getAvailableInstruments().length == 0);
             synth.loadAllInstruments(defsbk);
             assertTrue(synth.getLoadedInstruments().length != 0);
             synth.unloadAllInstruments(defsbk);
--- a/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstrument.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstrument.java	Mon Sep 13 15:12:31 2010 +0400
@@ -55,7 +55,6 @@
         Soundbank defsbk = synth.getDefaultSoundbank();
         if(defsbk != null)
         {
-            assertTrue(synth.getLoadedInstruments().length == 0);
             synth.unloadAllInstruments(defsbk);
             SimpleSoundbank sbk = new SimpleSoundbank();
             SimpleInstrument ins = new SimpleInstrument();
--- a/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstruments.java	Fri Sep 10 15:29:40 2010 -0700
+++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstruments.java	Mon Sep 13 15:12:31 2010 +0400
@@ -55,7 +55,6 @@
         Soundbank defsbk = synth.getDefaultSoundbank();
         if(defsbk != null)
         {
-            assertTrue(synth.getLoadedInstruments().length == 0);
             synth.unloadAllInstruments(defsbk);
             SimpleSoundbank sbk = new SimpleSoundbank();
             SimpleInstrument ins = new SimpleInstrument();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/sound/midi/Gervill/SoftTuning/RealTimeTuning.java	Mon Sep 13 15:12:31 2010 +0400
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ @summary Test RealTime-tunings using SoftReciver.send method */
+
+import java.io.IOException;
+
+import javax.sound.midi.*;
+import javax.sound.sampled.*;
+
+import com.sun.media.sound.*;
+
+public class RealTimeTuning {
+
+    private static class PitchSpy {
+        public float pitch = 0;
+
+        public Soundbank getSoundBank() {
+            ModelOscillator osc = new ModelOscillator() {
+                public float getAttenuation() {
+                    return 0;
+                }
+
+                public int getChannels() {
+                    return 0;
+                }
+
+                public ModelOscillatorStream open(float samplerate) {
+                    return new ModelOscillatorStream() {
+                        public void close() throws IOException {
+                            pitch = 0;
+                        }
+
+                        public void noteOff(int velocity) {
+                            pitch = 0;
+                        }
+
+                        public void noteOn(MidiChannel channel,
+                                VoiceStatus voice, int noteNumber, int velocity) {
+                            pitch = noteNumber * 100;
+                        }
+
+                        public int read(float[][] buffer, int offset, int len)
+                                throws IOException {
+                            return len;
+                        }
+
+                        public void setPitch(float ipitch) {
+                            pitch = ipitch;
+                        }
+                    };
+                }
+            };
+            ModelPerformer performer = new ModelPerformer();
+            performer.getOscillators().add(osc);
+            SimpleInstrument testinstrument = new SimpleInstrument();
+            testinstrument.setPatch(new Patch(0, 0));
+            testinstrument.add(performer);
+            SimpleSoundbank testsoundbank = new SimpleSoundbank();
+            testsoundbank.addInstrument(testinstrument);
+            return testsoundbank;
+        }
+    }
+
+    public static void sendTuningChange(Receiver recv, int channel,
+            int tuningpreset, int tuningbank) throws InvalidMidiDataException {
+        // Data Entry
+        ShortMessage sm1 = new ShortMessage();
+        sm1.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 04);
+        ShortMessage sm2 = new ShortMessage();
+        sm2.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);
+
+        // Tuning Bank
+        ShortMessage sm3 = new ShortMessage();
+        sm3.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06, tuningbank);
+        // Data Increment
+        ShortMessage sm4 = new ShortMessage();
+        sm4.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);
+        // Data Decrement
+        ShortMessage sm5 = new ShortMessage();
+        sm5.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);
+
+        // Data Entry
+        ShortMessage sm6 = new ShortMessage();
+        sm6.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 03);
+        ShortMessage sm7 = new ShortMessage();
+        sm7.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);
+
+        // Tuning program
+        ShortMessage sm8 = new ShortMessage();
+        sm8
+                .setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06,
+                        tuningpreset);
+        // Data Increment
+        ShortMessage sm9 = new ShortMessage();
+        sm9.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);
+        // Data Decrement
+        ShortMessage sm10 = new ShortMessage();
+        sm10.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);
+
+        recv.send(sm1, -1);
+        recv.send(sm2, -1);
+        recv.send(sm3, -1);
+        recv.send(sm4, -1);
+        recv.send(sm5, -1);
+        recv.send(sm6, -1);
+        recv.send(sm7, -1);
+        recv.send(sm8, -1);
+        recv.send(sm9, -1);
+        recv.send(sm10, -1);
+
+    }
+
+    private static void assertTrue(boolean value) throws Exception {
+        if (!value)
+            throw new RuntimeException("assertTrue fails!");
+    }
+
+    public static void testTunings(int[] msg, int tuningProgram,
+            int tuningBank, int targetNote, float targetPitch, boolean realtime)
+            throws Exception {
+        AudioSynthesizer synth = new SoftSynthesizer();
+        AudioInputStream stream = synth.openStream(null, null);
+        Receiver recv = synth.getReceiver();
+        MidiChannel channel = synth.getChannels()[0];
+        byte[] buff = new byte[2048];
+
+        // Create test instrument which we can use to monitor pitch changes
+        PitchSpy pitchspy = new PitchSpy();
+
+        synth.unloadAllInstruments(synth.getDefaultSoundbank());
+        synth.loadAllInstruments(pitchspy.getSoundBank());
+
+        SysexMessage sysex = null;
+
+        // Send tuning changes
+        if (msg != null) {
+            byte[] bmsg = new byte[msg.length];
+            for (int i = 0; i < bmsg.length; i++)
+                bmsg[i] = (byte) msg[i];
+            sysex = new SysexMessage();
+            sysex.setMessage(bmsg, bmsg.length);
+            if (targetPitch == 0) {
+                targetPitch = (float) new SoftTuning(bmsg)
+                        .getTuning(targetNote);
+                // Check if targetPitch != targetNote * 100
+                assertTrue(Math.abs(targetPitch - targetNote * 100.0) > 0.001);
+            }
+        }
+
+        if (tuningProgram != -1)
+            sendTuningChange(recv, 0, tuningProgram, tuningBank);
+
+        // First test without tunings
+        channel.noteOn(targetNote, 64);
+        stream.read(buff, 0, buff.length);
+        assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);
+
+        // Test if realtime/non-realtime works
+        if (sysex != null)
+            recv.send(sysex, -1);
+        stream.read(buff, 0, buff.length);
+        if (realtime)
+            assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);
+        else
+            assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);
+
+        // Test if tunings works
+        channel.noteOn(targetNote, 0);
+        stream.read(buff, 0, buff.length);
+        assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);
+
+        channel.noteOn(targetNote, 64);
+        stream.read(buff, 0, buff.length);
+        assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);
+
+        channel.noteOn(targetNote, 0);
+        stream.read(buff, 0, buff.length);
+        assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);
+
+        stream.close();
+    }
+
+    public static void main(String[] args) throws Exception {
+        // Test with no-tunings
+        testTunings(null, -1, -1, 60, 6000, false);
+
+        int[] msg;
+        // 0x02 SINGLE NOTE TUNING CHANGE (REAL-TIME)
+        msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x02, 0x10, 0x02, 36, 36, 64,
+                0, 60, 70, 0, 0, 0xf7 };
+        testTunings(msg, 0x10, 0, 60, 7000, true);
+
+        // 0x07 SINGLE NOTE TUNING CHANGE (NON REAL-TIME) (BANK)
+        msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,
+                36, 64, 0, 60, 80, 0, 0, 0xf7 };
+        testTunings(msg, 0x07, 0x05, 60, 8000, false);
+
+        // 0x07 SINGLE NOTE TUNING CHANGE (REAL-TIME) (BANK)
+        msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,
+                36, 64, 0, 60, 80, 0, 0, 0xf7 };
+        testTunings(msg, 0x07, 0x05, 60, 8000, true);
+
+        // 0x08 scale/octave tuning 1-byte form (Non Real-Time)
+        msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,
+                10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };
+        testTunings(msg, -1, -1, 60, 0, false);
+
+        // 0x08 scale/octave tuning 1-byte form (REAL-TIME)
+        msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,
+                10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };
+        testTunings(msg, -1, -1, 60, 0, true);
+
+        // 0x09 scale/octave tuning 2-byte form (Non Real-Time)
+        msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,
+                10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,
+                30, 35, 40, 45, 50, 51, 52, 0xf7 };
+        testTunings(msg, -1, -1, 60, 0, false);
+
+        // 0x09 scale/octave tuning 2-byte form (REAL-TIME)
+        msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,
+                10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,
+                30, 35, 40, 45, 50, 51, 52, 0xf7 };
+        testTunings(msg, -1, -1, 60, 0, true);
+
+    }
+}