From 969560f07efcb6630b8a6f16c440f9cde0e35a2e Mon Sep 17 00:00:00 2001 From: kalli Date: Fri, 17 Apr 2009 16:13:43 +0400 Subject: [PATCH] 6821030: Merge OpenJDK Gervill with upstream sources, Q1CY2009 Reviewed-by: darcy, amenkov --- .../com/sun/media/sound/SoftAudioPusher.java | 1 + .../com/sun/media/sound/SoftChannel.java | 17 ++++ .../com/sun/media/sound/SoftChorus.java | 32 +++--- .../com/sun/media/sound/SoftFilter.java | 18 ++-- .../sun/media/sound/SoftJitterCorrector.java | 1 + .../com/sun/media/sound/SoftMainMixer.java | 59 +++++++++-- .../com/sun/media/sound/SoftVoice.java | 20 +++- .../Gervill/SoftChannel/NoteOverFlowTest.java | 73 ++++++++++++++ .../Gervill/SoftFilter/TestProcessAudio.java | 99 +++++++++++++++++++ 9 files changed, 283 insertions(+), 37 deletions(-) create mode 100644 test/javax/sound/midi/Gervill/SoftChannel/NoteOverFlowTest.java create mode 100644 test/javax/sound/midi/Gervill/SoftFilter/TestProcessAudio.java diff --git a/src/share/classes/com/sun/media/sound/SoftAudioPusher.java b/src/share/classes/com/sun/media/sound/SoftAudioPusher.java index d19ff412b..43773347a 100644 --- a/src/share/classes/com/sun/media/sound/SoftAudioPusher.java +++ b/src/share/classes/com/sun/media/sound/SoftAudioPusher.java @@ -54,6 +54,7 @@ public class SoftAudioPusher implements Runnable { return; active = true; audiothread = new Thread(this); + audiothread.setDaemon(true); audiothread.setPriority(Thread.MAX_PRIORITY); audiothread.start(); } diff --git a/src/share/classes/com/sun/media/sound/SoftChannel.java b/src/share/classes/com/sun/media/sound/SoftChannel.java index 8bb5f2ef6..57bb3b85d 100644 --- a/src/share/classes/com/sun/media/sound/SoftChannel.java +++ b/src/share/classes/com/sun/media/sound/SoftChannel.java @@ -67,6 +67,7 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer { 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 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer { && 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 @@ public class SoftChannel implements MidiChannel, ModelDirectedPlayer { 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 diff --git a/src/share/classes/com/sun/media/sound/SoftChorus.java b/src/share/classes/com/sun/media/sound/SoftChorus.java index 0a9f64439..59778cdbb 100644 --- a/src/share/classes/com/sun/media/sound/SoftChorus.java +++ b/src/share/classes/com/sun/media/sound/SoftChorus.java @@ -38,11 +38,11 @@ public class SoftChorus implements SoftAudioProcessor { 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 @@ public class SoftChorus implements SoftAudioProcessor { 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 class SoftChorus implements SoftAudioProcessor { 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 class SoftChorus implements SoftAudioProcessor { } 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); } diff --git a/src/share/classes/com/sun/media/sound/SoftFilter.java b/src/share/classes/com/sun/media/sound/SoftFilter.java index 0468f15be..c7ed4872b 100644 --- a/src/share/classes/com/sun/media/sound/SoftFilter.java +++ b/src/share/classes/com/sun/media/sound/SoftFilter.java @@ -543,8 +543,6 @@ public class SoftFilter { public void filter1(SoftAudioBuffer sbuffer) { - float[] buffer = sbuffer.array(); - if (dirty) { filter1calc(); dirty = false; @@ -559,6 +557,7 @@ public class SoftFilter { 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 @@ public class SoftFilter { 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 @@ public class SoftFilter { 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; } } diff --git a/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java b/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java index 98d205b6d..b647ba779 100644 --- a/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java +++ b/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java @@ -216,6 +216,7 @@ public class SoftJitterCorrector extends AudioInputStream { }; thread = new Thread(runnable); + thread.setDaemon(true); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); } diff --git a/src/share/classes/com/sun/media/sound/SoftMainMixer.java b/src/share/classes/com/sun/media/sound/SoftMainMixer.java index 1f38058b0..b62d1d480 100644 --- a/src/share/classes/com/sun/media/sound/SoftMainMixer.java +++ b/src/share/classes/com/sun/media/sound/SoftMainMixer.java @@ -48,16 +48,18 @@ public class SoftMainMixer { 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 @@ public class SoftMainMixer { // 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 @@ public class SoftMainMixer { 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 @@ public class SoftMainMixer { } } + 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 @@ public class SoftMainMixer { buffers[CHANNEL_LEFT] = leftbak; buffers[CHANNEL_RIGHT] = rightbak; + buffers[CHANNEL_MONO] = monobak; } @@ -547,6 +573,27 @@ public class SoftMainMixer { 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 @@ public class SoftMainMixer { / 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()); } diff --git a/src/share/classes/com/sun/media/sound/SoftVoice.java b/src/share/classes/com/sun/media/sound/SoftVoice.java index 49662b787..cec2e3047 100644 --- a/src/share/classes/com/sun/media/sound/SoftVoice.java +++ b/src/share/classes/com/sun/media/sound/SoftVoice.java @@ -782,6 +782,7 @@ public class SoftVoice extends VoiceStatus { 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 @@ public class SoftVoice extends VoiceStatus { 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, - 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, right, last_out_mixer_right, + { + 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, + out_mixer_right); + } } if (rightdry == null) { diff --git a/test/javax/sound/midi/Gervill/SoftChannel/NoteOverFlowTest.java b/test/javax/sound/midi/Gervill/SoftChannel/NoteOverFlowTest.java new file mode 100644 index 000000000..fdb33571b --- /dev/null +++ b/test/javax/sound/midi/Gervill/SoftChannel/NoteOverFlowTest.java @@ -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(); + } +} diff --git a/test/javax/sound/midi/Gervill/SoftFilter/TestProcessAudio.java b/test/javax/sound/midi/Gervill/SoftFilter/TestProcessAudio.java new file mode 100644 index 000000000..032f66762 --- /dev/null +++ b/test/javax/sound/midi/Gervill/SoftFilter/TestProcessAudio.java @@ -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(); + } + + } + +} -- GitLab