6821030: Merge OpenJDK Gervill with upstream sources, Q1CY2009
Reviewed-by: darcy, amenkov
--- a/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java Fri Apr 17 15:15:20 2009 +0400
+++ b/jdk/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/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java Fri Apr 17 15:15:20 2009 +0400
+++ b/jdk/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/jdk/src/share/classes/com/sun/media/sound/SoftChorus.java Fri Apr 17 15:15:20 2009 +0400
+++ b/jdk/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/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java Fri Apr 17 15:15:20 2009 +0400
+++ b/jdk/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/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java Fri Apr 17 15:15:20 2009 +0400
+++ b/jdk/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/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java Fri Apr 17 15:15:20 2009 +0400
+++ b/jdk/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/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java Fri Apr 17 15:15:20 2009 +0400
+++ b/jdk/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/jdk/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/jdk/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();
+ }
+
+ }
+
+}