changeset 1170:923a730165bf

6821030: Merge OpenJDK Gervill with upstream sources, Q1CY2009 Reviewed-by: darcy, amenkov
author kalli
date Fri, 17 Apr 2009 16:13:43 +0400
parents a301fb619494
children e61cd67602bd
files src/share/classes/com/sun/media/sound/SoftAudioPusher.java src/share/classes/com/sun/media/sound/SoftChannel.java src/share/classes/com/sun/media/sound/SoftChorus.java src/share/classes/com/sun/media/sound/SoftFilter.java src/share/classes/com/sun/media/sound/SoftJitterCorrector.java src/share/classes/com/sun/media/sound/SoftMainMixer.java src/share/classes/com/sun/media/sound/SoftVoice.java test/javax/sound/midi/Gervill/SoftChannel/NoteOverFlowTest.java test/javax/sound/midi/Gervill/SoftFilter/TestProcessAudio.java
diffstat 9 files changed, 283 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/media/sound/SoftAudioPusher.java	Fri Apr 17 15:15:20 2009 +0400
+++ b/src/share/classes/com/sun/media/sound/SoftAudioPusher.java	Fri Apr 17 16:13:43 2009 +0400
@@ -54,6 +54,7 @@
             return;
         active = true;
         audiothread = new Thread(this);
+        audiothread.setDaemon(true);
         audiothread.setPriority(Thread.MAX_PRIORITY);
         audiothread.start();
     }
--- a/src/share/classes/com/sun/media/sound/SoftChannel.java	Fri Apr 17 15:15:20 2009 +0400
+++ b/src/share/classes/com/sun/media/sound/SoftChannel.java	Fri Apr 17 16:13:43 2009 +0400
@@ -67,6 +67,7 @@
         dontResetControls[77] = true;  // Sound Controller 8 (GM2 default: Vibrato Depth)
         dontResetControls[78] = true;  // Sound Controller 9 (GM2 default: Vibrato Delay)
         dontResetControls[79] = true;  // Sound Controller 10 (GM2 default: Undefined)
+        dontResetControls[84] = true;  // Portamento Controller
         dontResetControls[120] = true; // All Sound Off
         dontResetControls[121] = true; // Reset All Controllers
         dontResetControls[122] = true; // Local Control On/Off
@@ -556,6 +557,18 @@
                         && voices[i].releaseTriggered == false) {
                     voices[i].noteOff(velocity);
                 }
+                // We must also check stolen voices
+                if (voices[i].stealer_channel == this && voices[i].stealer_noteNumber == noteNumber) {
+                    SoftVoice v = voices[i];
+                    v.stealer_releaseTriggered = false;
+                    v.stealer_channel = null;
+                    v.stealer_performer = null;
+                    v.stealer_voiceID = -1;
+                    v.stealer_noteNumber = 0;
+                    v.stealer_velocity = 0;
+                    v.stealer_extendedConnectionBlocks = null;
+                    v.stealer_channelmixer = null;
+                }
             }
 
             // Try play back note-off triggered voices,
@@ -1385,6 +1398,10 @@
                     controlChange(i, 0);
             }
 
+            // Portamento Controller (0x54) has to reset
+            // to -1 which mean that Portamento Controller is off
+            portamento_control_note = -1;
+
             controlChange(71, 64); // Filter Resonance
             controlChange(72, 64); // Release Time
             controlChange(73, 64); // Attack Time
--- a/src/share/classes/com/sun/media/sound/SoftChorus.java	Fri Apr 17 15:15:20 2009 +0400
+++ b/src/share/classes/com/sun/media/sound/SoftChorus.java	Fri Apr 17 16:13:43 2009 +0400
@@ -38,11 +38,11 @@
 
         private float[] delaybuffer;
         private int rovepos = 0;
-        private volatile float gain = 1;
-        private volatile float rgain = 0;
-        private volatile float delay = 0;
+        private float gain = 1;
+        private float rgain = 0;
+        private float delay = 0;
         private float lastdelay = 0;
-        private volatile float feedback = 0;
+        private float feedback = 0;
 
         public VariableDelay(int maxbuffersize) {
             delaybuffer = new float[maxbuffersize];
@@ -115,10 +115,8 @@
 
     private static class LFODelay {
 
-        private volatile double c_cos_delta;
-        private volatile double c_sin_delta;
-        private double c_cos = 1;
-        private double c_sin = 0;
+        private double phase = 1;
+        private double phase_step = 0;
         private double depth = 0;
         private VariableDelay vdelay;
         private double samplerate;
@@ -139,13 +137,11 @@
 
         public void setRate(double rate) {
             double g = (Math.PI * 2) * (rate / controlrate);
-            c_cos_delta = Math.cos(g);
-            c_sin_delta = Math.sin(g);
+            phase_step = g;
         }
 
         public void setPhase(double phase) {
-            c_cos = Math.cos(phase);
-            c_sin = Math.sin(phase);
+            this.phase = phase;
         }
 
         public void setFeedBack(float feedback) {
@@ -161,16 +157,16 @@
         }
 
         public void processMix(float[] in, float[] out, float[] rout) {
-            c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta;
-            c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta;
-            vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2)));
+            phase += phase_step;
+            while(phase > (Math.PI * 2)) phase -= (Math.PI * 2);
+            vdelay.setDelay((float) (depth * 0.5 * (Math.cos(phase) + 2)));
             vdelay.processMix(in, out, rout);
         }
 
         public void processReplace(float[] in, float[] out, float[] rout) {
-            c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta;
-            c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta;
-            vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2)));
+            phase += phase_step;
+            while(phase > (Math.PI * 2)) phase -= (Math.PI * 2);
+            vdelay.setDelay((float) (depth * 0.5 * (Math.cos(phase) + 2)));
             vdelay.processReplace(in, out, rout);
 
         }
--- a/src/share/classes/com/sun/media/sound/SoftFilter.java	Fri Apr 17 15:15:20 2009 +0400
+++ b/src/share/classes/com/sun/media/sound/SoftFilter.java	Fri Apr 17 16:13:43 2009 +0400
@@ -543,8 +543,6 @@
 
     public void filter1(SoftAudioBuffer sbuffer) {
 
-        float[] buffer = sbuffer.array();
-
         if (dirty) {
             filter1calc();
             dirty = false;
@@ -559,6 +557,7 @@
 
         if (wet > 0 || last_wet > 0) {
 
+            float[] buffer = sbuffer.array();
             int len = buffer.length;
             float a0 = this.last_a0;
             float q = this.last_q;
@@ -577,14 +576,16 @@
                     q += q_delta;
                     gain += gain_delta;
                     wet += wet_delta;
-                    y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
-                    y2 = (1 - q * a0) * y2 + (a0) * y1;
+                    float ga0 = (1 - q * a0);
+                    y1 = ga0 * y1 + (a0) * (buffer[i] - y2);
+                    y2 = ga0 * y2 + (a0) * y1;
                     buffer[i] = y2 * gain * wet + buffer[i] * (1 - wet);
                 }
             } else if (a0_delta == 0 && q_delta == 0) {
+                float ga0 = (1 - q * a0);
                 for (int i = 0; i < len; i++) {
-                    y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
-                    y2 = (1 - q * a0) * y2 + (a0) * y1;
+                    y1 = ga0 * y1 + (a0) * (buffer[i] - y2);
+                    y2 = ga0 * y2 + (a0) * y1;
                     buffer[i] = y2 * gain;
                 }
             } else {
@@ -592,8 +593,9 @@
                     a0 += a0_delta;
                     q += q_delta;
                     gain += gain_delta;
-                    y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i];
-                    y2 = (1 - q * a0) * y2 + (a0) * y1;
+                    float ga0 = (1 - q * a0);
+                    y1 = ga0 * y1 + (a0) * (buffer[i] - y2);
+                    y2 = ga0 * y2 + (a0) * y1;
                     buffer[i] = y2 * gain;
                 }
             }
--- a/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java	Fri Apr 17 15:15:20 2009 +0400
+++ b/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java	Fri Apr 17 16:13:43 2009 +0400
@@ -216,6 +216,7 @@
             };
 
             thread = new Thread(runnable);
+            thread.setDaemon(true);
             thread.setPriority(Thread.MAX_PRIORITY);
             thread.start();
         }
--- a/src/share/classes/com/sun/media/sound/SoftMainMixer.java	Fri Apr 17 15:15:20 2009 +0400
+++ b/src/share/classes/com/sun/media/sound/SoftMainMixer.java	Fri Apr 17 16:13:43 2009 +0400
@@ -48,16 +48,18 @@
 
     public final static int CHANNEL_LEFT = 0;
     public final static int CHANNEL_RIGHT = 1;
-    public final static int CHANNEL_EFFECT1 = 2;
-    public final static int CHANNEL_EFFECT2 = 3;
-    public final static int CHANNEL_EFFECT3 = 4;
-    public final static int CHANNEL_EFFECT4 = 5;
+    public final static int CHANNEL_MONO = 2;
+    public final static int CHANNEL_EFFECT1 = 3;
+    public final static int CHANNEL_EFFECT2 = 4;
+    public final static int CHANNEL_EFFECT3 = 5;
+    public final static int CHANNEL_EFFECT4 = 6;
     public final static int CHANNEL_LEFT_DRY = 10;
     public final static int CHANNEL_RIGHT_DRY = 11;
     public final static int CHANNEL_SCRATCH1 = 12;
     public final static int CHANNEL_SCRATCH2 = 13;
     public final static int CHANNEL_CHANNELMIXER_LEFT = 14;
     public final static int CHANNEL_CHANNELMIXER_RIGHT = 15;
+    public final static int CHANNEL_CHANNELMIXER_MONO = 16;
     protected boolean active_sensing_on = false;
     private long msec_last_activity = -1;
     private boolean pusher_silent = false;
@@ -485,8 +487,10 @@
             // to channelmixer left,right input/output
             SoftAudioBuffer leftbak = buffers[CHANNEL_LEFT];
             SoftAudioBuffer rightbak = buffers[CHANNEL_RIGHT];
+            SoftAudioBuffer monobak = buffers[CHANNEL_MONO];
             buffers[CHANNEL_LEFT] = buffers[CHANNEL_CHANNELMIXER_LEFT];
-            buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_LEFT];
+            buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_RIGHT];
+            buffers[CHANNEL_MONO] = buffers[CHANNEL_CHANNELMIXER_MONO];
 
             int bufferlen = buffers[CHANNEL_LEFT].getSize();
 
@@ -503,6 +507,7 @@
             for (ModelChannelMixer cmixer : act_registeredMixers) {
                 for (int i = 0; i < cbuffer.length; i++)
                     Arrays.fill(cbuffer[i], 0);
+                buffers[CHANNEL_MONO].clear();
                 boolean hasactivevoices = false;
                 for (int i = 0; i < voicestatus.length; i++)
                     if (voicestatus[i].active)
@@ -517,6 +522,26 @@
                     }
                 }
 
+                if(!buffers[CHANNEL_MONO].isSilent())
+                {
+                    float[] mono = buffers[CHANNEL_MONO].array();
+                    float[] left = buffers[CHANNEL_LEFT].array();
+                    if (nrofchannels != 1) {
+                        float[] right = buffers[CHANNEL_RIGHT].array();
+                        for (int i = 0; i < bufferlen; i++) {
+                            float v = mono[i];
+                            left[i] += v;
+                            right[i] += v;
+                        }
+                    }
+                    else
+                    {
+                        for (int i = 0; i < bufferlen; i++) {
+                            left[i] += mono[i];
+                        }
+                    }
+                }
+
                 for (int i = 0; i < cbuffer.length; i++) {
                     float[] cbuff = cbuffer[i];
                     float[] obuff = obuffer[i];
@@ -539,6 +564,7 @@
 
             buffers[CHANNEL_LEFT] = leftbak;
             buffers[CHANNEL_RIGHT] = rightbak;
+            buffers[CHANNEL_MONO] = monobak;
 
         }
 
@@ -547,6 +573,27 @@
                 if (voicestatus[i].channelmixer == null)
                     voicestatus[i].processAudioLogic(buffers);
 
+        if(!buffers[CHANNEL_MONO].isSilent())
+        {
+            float[] mono = buffers[CHANNEL_MONO].array();
+            float[] left = buffers[CHANNEL_LEFT].array();
+            int bufferlen = buffers[CHANNEL_LEFT].getSize();
+            if (nrofchannels != 1) {
+                float[] right = buffers[CHANNEL_RIGHT].array();
+                for (int i = 0; i < bufferlen; i++) {
+                    float v = mono[i];
+                    left[i] += v;
+                    right[i] += v;
+                }
+            }
+            else
+            {
+                for (int i = 0; i < bufferlen; i++) {
+                    left[i] += mono[i];
+                }
+            }
+        }
+
         // Run effects
         if (synth.chorus_on)
             chorus.processAudio();
@@ -665,7 +712,7 @@
                                 / synth.getControlRate());
 
         control_mutex = synth.control_mutex;
-        buffers = new SoftAudioBuffer[16];
+        buffers = new SoftAudioBuffer[17];
         for (int i = 0; i < buffers.length; i++) {
             buffers[i] = new SoftAudioBuffer(buffersize, synth.getFormat());
         }
--- a/src/share/classes/com/sun/media/sound/SoftVoice.java	Fri Apr 17 15:15:20 2009 +0400
+++ b/src/share/classes/com/sun/media/sound/SoftVoice.java	Fri Apr 17 16:13:43 2009 +0400
@@ -782,6 +782,7 @@
 
         SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT];
         SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT];
+        SoftAudioBuffer mono = buffer[SoftMainMixer.CHANNEL_MONO];
         SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1];
         SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2];
         SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY];
@@ -803,13 +804,22 @@
                 mixAudioStream(rightdry, left, last_out_mixer_left,
                         out_mixer_left);
         } else {
-            mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
-            if (rightdry != null)
-                mixAudioStream(rightdry, right, last_out_mixer_right,
+            if(rightdry == null &&
+                    last_out_mixer_left == last_out_mixer_right &&
+                    out_mixer_left == out_mixer_right)
+            {
+                mixAudioStream(leftdry, mono, last_out_mixer_left, out_mixer_left);
+            }
+            else
+            {
+                mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
+                if (rightdry != null)
+                    mixAudioStream(rightdry, right, last_out_mixer_right,
                         out_mixer_right);
-            else
-                mixAudioStream(leftdry, right, last_out_mixer_right,
+                else
+                    mixAudioStream(leftdry, right, last_out_mixer_right,
                         out_mixer_right);
+            }
         }
 
         if (rightdry == null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/sound/midi/Gervill/SoftChannel/NoteOverFlowTest.java	Fri Apr 17 16:13:43 2009 +0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+   @summary Test SoftChannel noteOn/noteOff overflow test */
+
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.VoiceStatus;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+
+import com.sun.media.sound.AudioSynthesizer;
+import com.sun.media.sound.SoftSynthesizer;
+
+public class NoteOverFlowTest {
+
+    public static void main(String[] args) throws Exception
+    {
+        AudioSynthesizer synth = new SoftSynthesizer();
+        AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
+        AudioInputStream stream = synth.openStream(format, null);
+
+        // Make all voices busy, e.g.
+        // send midi on and midi off on all available voices
+        MidiChannel ch1 = synth.getChannels()[0];
+        ch1.programChange(48); // Use contionus instrument like string ensemble
+        for (int i = 0; i < synth.getMaxPolyphony(); i++) {
+            ch1.noteOn(64, 64);
+            ch1.noteOff(64);
+        }
+
+        // Now send single midi on, and midi off message
+        ch1.noteOn(64, 64);
+        ch1.noteOff(64);
+
+        // Read 10 sec from stream, by this time all voices should be inactvie
+        stream.skip(format.getFrameSize() * ((int)(format.getFrameRate() * 20)));
+
+        // If no voice are active, then this test will pass
+        VoiceStatus[] v = synth.getVoiceStatus();
+        for (int i = 0; i < v.length; i++) {
+            if(v[i].active)
+            {
+                throw new RuntimeException("Not all voices are inactive!");
+            }
+        }
+
+        // Close the synthesizer after use
+        synth.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/sound/midi/Gervill/SoftFilter/TestProcessAudio.java	Fri Apr 17 16:13:43 2009 +0400
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+   @summary Test SoftFilter processAudio method */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Random;
+
+import javax.sound.sampled.*;
+
+import com.sun.media.sound.*;
+
+public class TestProcessAudio {
+
+    public static void main(String[] args) throws Exception {
+        AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
+        SoftAudioBuffer sbuffer = new SoftAudioBuffer(3600, format);
+        SoftFilter filter = new SoftFilter(format.getSampleRate());
+        Random random = new Random(42);
+
+
+        for (int t = 0; t <= 6; t++)
+        {
+            if(t == 0) filter.setFilterType(SoftFilter.FILTERTYPE_BP12);
+            if(t == 1) filter.setFilterType(SoftFilter.FILTERTYPE_HP12);
+            if(t == 2) filter.setFilterType(SoftFilter.FILTERTYPE_HP24);
+            if(t == 3) filter.setFilterType(SoftFilter.FILTERTYPE_LP12);
+            if(t == 4) filter.setFilterType(SoftFilter.FILTERTYPE_LP24);
+            if(t == 5) filter.setFilterType(SoftFilter.FILTERTYPE_LP6);
+            if(t == 6) filter.setFilterType(SoftFilter.FILTERTYPE_NP12);
+
+
+            // Try first by reseting always
+            for (int f = 1200; f < 3600; f+=100)
+                for (int r = 0; r <= 30; r+=5) {
+                    filter.reset();
+                    filter.setResonance(r);
+                    filter.setFrequency(f);
+                    float[] data = sbuffer.array();
+                    int len = sbuffer.getSize();
+                    for (int i = 0; i < len; i++)
+                        data[i] = random.nextFloat() - 0.5f;
+                    filter.processAudio(sbuffer);
+                }
+
+            // Now we skip reseting
+            // to test how changing frequency and resonance
+            // affect active filter
+            for (int f = 100; f < 12800; f+=1200)
+            for (int r = 0; r <= 30; r+=5) {
+                filter.setResonance(r);
+                filter.setFrequency(f);
+                float[] data = sbuffer.array();
+                int len = sbuffer.getSize();
+                for (int i = 0; i < len; i++)
+                    data[i] = random.nextFloat() - 0.5f;
+                filter.processAudio(sbuffer);
+            }
+            for (int f = 12800; f >= 100; f-=1200)
+                for (int r = 30; r >= 0; r-=5) {
+                    filter.setResonance(r);
+                    filter.setFrequency(f);
+                    float[] data = sbuffer.array();
+                    int len = sbuffer.getSize();
+                    for (int i = 0; i < len; i++)
+                        data[i] = random.nextFloat() - 0.5f;
+                    filter.processAudio(sbuffer);
+                }
+            filter.reset();
+        }
+
+    }
+
+}