< prev index next >

src/java.desktop/share/classes/com/sun/media/sound/SoftChorus.java

Print this page




   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */

  25 package com.sun.media.sound;
  26 
  27 import java.util.Arrays;
  28 
  29 /**
  30  * A chorus effect made using LFO and variable delay. One for each channel
  31  * (left,right), with different starting phase for stereo effect.
  32  *
  33  * @author Karl Helgason
  34  */
  35 public final class SoftChorus implements SoftAudioProcessor {
  36 
  37     private static class VariableDelay {
  38 
  39         private final float[] delaybuffer;
  40         private int rovepos = 0;
  41         private float gain = 1;
  42         private float rgain = 0;
  43         private float delay = 0;
  44         private float lastdelay = 0;


 173     }
 174     private boolean mix = true;
 175     private SoftAudioBuffer inputA;
 176     private SoftAudioBuffer left;
 177     private SoftAudioBuffer right;
 178     private SoftAudioBuffer reverb;
 179     private LFODelay vdelay1L;
 180     private LFODelay vdelay1R;
 181     private float rgain = 0;
 182     private boolean dirty = true;
 183     private double dirty_vdelay1L_rate;
 184     private double dirty_vdelay1R_rate;
 185     private double dirty_vdelay1L_depth;
 186     private double dirty_vdelay1R_depth;
 187     private float dirty_vdelay1L_feedback;
 188     private float dirty_vdelay1R_feedback;
 189     private float dirty_vdelay1L_reverbsendgain;
 190     private float dirty_vdelay1R_reverbsendgain;
 191     private float controlrate;
 192 

 193     public void init(float samplerate, float controlrate) {
 194         this.controlrate = controlrate;
 195         vdelay1L = new LFODelay(samplerate, controlrate);
 196         vdelay1R = new LFODelay(samplerate, controlrate);
 197         vdelay1L.setGain(1.0f); // %
 198         vdelay1R.setGain(1.0f); // %
 199         vdelay1L.setPhase(0.5 * Math.PI);
 200         vdelay1R.setPhase(0);
 201 
 202         globalParameterControlChange(new int[]{0x01 * 128 + 0x02}, 0, 2);
 203     }
 204 

 205     public void globalParameterControlChange(int[] slothpath, long param,
 206             long value) {
 207         if (slothpath.length == 1) {
 208             if (slothpath[0] == 0x01 * 128 + 0x02) {
 209                 if (param == 0) { // Chorus Type
 210                     switch ((int)value) {
 211                     case 0: // Chorus 1 0 (0%) 3 (0.4Hz) 5 (1.9ms) 0 (0%)
 212                         globalParameterControlChange(slothpath, 3, 0);
 213                         globalParameterControlChange(slothpath, 1, 3);
 214                         globalParameterControlChange(slothpath, 2, 5);
 215                         globalParameterControlChange(slothpath, 4, 0);
 216                         break;
 217                     case 1: // Chorus 2 5 (4%) 9 (1.1Hz) 19 (6.3ms) 0 (0%)
 218                         globalParameterControlChange(slothpath, 3, 5);
 219                         globalParameterControlChange(slothpath, 1, 9);
 220                         globalParameterControlChange(slothpath, 2, 19);
 221                         globalParameterControlChange(slothpath, 4, 0);
 222                         break;
 223                     case 2: // Chorus 3 8 (6%) 3 (0.4Hz) 19 (6.3ms) 0 (0%)
 224                         globalParameterControlChange(slothpath, 3, 8);


 254                 } else if (param == 2) { // Mod Depth
 255                     dirty_vdelay1L_depth = ((value + 1) / 3200.0);
 256                     dirty_vdelay1R_depth = ((value + 1) / 3200.0);
 257                     dirty = true;
 258                 } else if (param == 3) { // Feedback
 259                     dirty_vdelay1L_feedback = (value * 0.00763f);
 260                     dirty_vdelay1R_feedback = (value * 0.00763f);
 261                     dirty = true;
 262                 }
 263                 if (param == 4) { // Send to Reverb
 264                     rgain = value * 0.00787f;
 265                     dirty_vdelay1L_reverbsendgain = (value * 0.00787f);
 266                     dirty_vdelay1R_reverbsendgain = (value * 0.00787f);
 267                     dirty = true;
 268                 }
 269 
 270             }
 271         }
 272     }
 273 

 274     public void processControlLogic() {
 275         if (dirty) {
 276             dirty = false;
 277             vdelay1L.setRate(dirty_vdelay1L_rate);
 278             vdelay1R.setRate(dirty_vdelay1R_rate);
 279             vdelay1L.setDepth(dirty_vdelay1L_depth);
 280             vdelay1R.setDepth(dirty_vdelay1R_depth);
 281             vdelay1L.setFeedBack(dirty_vdelay1L_feedback);
 282             vdelay1R.setFeedBack(dirty_vdelay1R_feedback);
 283             vdelay1L.setReverbSendGain(dirty_vdelay1L_reverbsendgain);
 284             vdelay1R.setReverbSendGain(dirty_vdelay1R_reverbsendgain);
 285         }
 286     }
 287     double silentcounter = 1000;
 288 

 289     public void processAudio() {
 290 
 291         if (inputA.isSilent()) {
 292             silentcounter += 1 / controlrate;
 293 
 294             if (silentcounter > 1) {
 295                 if (!mix) {
 296                     left.clear();
 297                     right.clear();
 298                 }
 299                 return;
 300             }
 301         } else
 302             silentcounter = 0;
 303 
 304         float[] inputA = this.inputA.array();
 305         float[] left = this.left.array();
 306         float[] right = this.right == null ? null : this.right.array();
 307         float[] reverb = rgain != 0 ? this.reverb.array() : null;
 308 
 309         if (mix) {
 310             vdelay1L.processMix(inputA, left, reverb);
 311             if (right != null)
 312                 vdelay1R.processMix(inputA, right, reverb);
 313         } else {
 314             vdelay1L.processReplace(inputA, left, reverb);
 315             if (right != null)
 316                 vdelay1R.processReplace(inputA, right, reverb);
 317         }
 318     }
 319 

 320     public void setInput(int pin, SoftAudioBuffer input) {
 321         if (pin == 0)
 322             inputA = input;
 323     }
 324 

 325     public void setMixMode(boolean mix) {
 326         this.mix = mix;
 327     }
 328 

 329     public void setOutput(int pin, SoftAudioBuffer output) {
 330         if (pin == 0)
 331             left = output;
 332         if (pin == 1)
 333             right = output;
 334         if (pin == 2)
 335             reverb = output;
 336     }
 337 }


   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.media.sound;
  27 
  28 import java.util.Arrays;
  29 
  30 /**
  31  * A chorus effect made using LFO and variable delay. One for each channel
  32  * (left,right), with different starting phase for stereo effect.
  33  *
  34  * @author Karl Helgason
  35  */
  36 public final class SoftChorus implements SoftAudioProcessor {
  37 
  38     private static class VariableDelay {
  39 
  40         private final float[] delaybuffer;
  41         private int rovepos = 0;
  42         private float gain = 1;
  43         private float rgain = 0;
  44         private float delay = 0;
  45         private float lastdelay = 0;


 174     }
 175     private boolean mix = true;
 176     private SoftAudioBuffer inputA;
 177     private SoftAudioBuffer left;
 178     private SoftAudioBuffer right;
 179     private SoftAudioBuffer reverb;
 180     private LFODelay vdelay1L;
 181     private LFODelay vdelay1R;
 182     private float rgain = 0;
 183     private boolean dirty = true;
 184     private double dirty_vdelay1L_rate;
 185     private double dirty_vdelay1R_rate;
 186     private double dirty_vdelay1L_depth;
 187     private double dirty_vdelay1R_depth;
 188     private float dirty_vdelay1L_feedback;
 189     private float dirty_vdelay1R_feedback;
 190     private float dirty_vdelay1L_reverbsendgain;
 191     private float dirty_vdelay1R_reverbsendgain;
 192     private float controlrate;
 193 
 194     @Override
 195     public void init(float samplerate, float controlrate) {
 196         this.controlrate = controlrate;
 197         vdelay1L = new LFODelay(samplerate, controlrate);
 198         vdelay1R = new LFODelay(samplerate, controlrate);
 199         vdelay1L.setGain(1.0f); // %
 200         vdelay1R.setGain(1.0f); // %
 201         vdelay1L.setPhase(0.5 * Math.PI);
 202         vdelay1R.setPhase(0);
 203 
 204         globalParameterControlChange(new int[]{0x01 * 128 + 0x02}, 0, 2);
 205     }
 206 
 207     @Override
 208     public void globalParameterControlChange(int[] slothpath, long param,
 209                                              long value) {
 210         if (slothpath.length == 1) {
 211             if (slothpath[0] == 0x01 * 128 + 0x02) {
 212                 if (param == 0) { // Chorus Type
 213                     switch ((int)value) {
 214                     case 0: // Chorus 1 0 (0%) 3 (0.4Hz) 5 (1.9ms) 0 (0%)
 215                         globalParameterControlChange(slothpath, 3, 0);
 216                         globalParameterControlChange(slothpath, 1, 3);
 217                         globalParameterControlChange(slothpath, 2, 5);
 218                         globalParameterControlChange(slothpath, 4, 0);
 219                         break;
 220                     case 1: // Chorus 2 5 (4%) 9 (1.1Hz) 19 (6.3ms) 0 (0%)
 221                         globalParameterControlChange(slothpath, 3, 5);
 222                         globalParameterControlChange(slothpath, 1, 9);
 223                         globalParameterControlChange(slothpath, 2, 19);
 224                         globalParameterControlChange(slothpath, 4, 0);
 225                         break;
 226                     case 2: // Chorus 3 8 (6%) 3 (0.4Hz) 19 (6.3ms) 0 (0%)
 227                         globalParameterControlChange(slothpath, 3, 8);


 257                 } else if (param == 2) { // Mod Depth
 258                     dirty_vdelay1L_depth = ((value + 1) / 3200.0);
 259                     dirty_vdelay1R_depth = ((value + 1) / 3200.0);
 260                     dirty = true;
 261                 } else if (param == 3) { // Feedback
 262                     dirty_vdelay1L_feedback = (value * 0.00763f);
 263                     dirty_vdelay1R_feedback = (value * 0.00763f);
 264                     dirty = true;
 265                 }
 266                 if (param == 4) { // Send to Reverb
 267                     rgain = value * 0.00787f;
 268                     dirty_vdelay1L_reverbsendgain = (value * 0.00787f);
 269                     dirty_vdelay1R_reverbsendgain = (value * 0.00787f);
 270                     dirty = true;
 271                 }
 272 
 273             }
 274         }
 275     }
 276 
 277     @Override
 278     public void processControlLogic() {
 279         if (dirty) {
 280             dirty = false;
 281             vdelay1L.setRate(dirty_vdelay1L_rate);
 282             vdelay1R.setRate(dirty_vdelay1R_rate);
 283             vdelay1L.setDepth(dirty_vdelay1L_depth);
 284             vdelay1R.setDepth(dirty_vdelay1R_depth);
 285             vdelay1L.setFeedBack(dirty_vdelay1L_feedback);
 286             vdelay1R.setFeedBack(dirty_vdelay1R_feedback);
 287             vdelay1L.setReverbSendGain(dirty_vdelay1L_reverbsendgain);
 288             vdelay1R.setReverbSendGain(dirty_vdelay1R_reverbsendgain);
 289         }
 290     }
 291     double silentcounter = 1000;
 292 
 293     @Override
 294     public void processAudio() {
 295 
 296         if (inputA.isSilent()) {
 297             silentcounter += 1 / controlrate;
 298 
 299             if (silentcounter > 1) {
 300                 if (!mix) {
 301                     left.clear();
 302                     right.clear();
 303                 }
 304                 return;
 305             }
 306         } else
 307             silentcounter = 0;
 308 
 309         float[] inputA = this.inputA.array();
 310         float[] left = this.left.array();
 311         float[] right = this.right == null ? null : this.right.array();
 312         float[] reverb = rgain != 0 ? this.reverb.array() : null;
 313 
 314         if (mix) {
 315             vdelay1L.processMix(inputA, left, reverb);
 316             if (right != null)
 317                 vdelay1R.processMix(inputA, right, reverb);
 318         } else {
 319             vdelay1L.processReplace(inputA, left, reverb);
 320             if (right != null)
 321                 vdelay1R.processReplace(inputA, right, reverb);
 322         }
 323     }
 324 
 325     @Override
 326     public void setInput(int pin, SoftAudioBuffer input) {
 327         if (pin == 0)
 328             inputA = input;
 329     }
 330 
 331     @Override
 332     public void setMixMode(boolean mix) {
 333         this.mix = mix;
 334     }
 335 
 336     @Override
 337     public void setOutput(int pin, SoftAudioBuffer output) {
 338         if (pin == 0)
 339             left = output;
 340         if (pin == 1)
 341             right = output;
 342         if (pin == 2)
 343             reverb = output;
 344     }
 345 }
< prev index next >