1 /*
   2  * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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.io.IOException;
  28 import java.util.Arrays;
  29 import java.util.HashMap;
  30 import java.util.Map;
  31 
  32 import javax.sound.midi.VoiceStatus;
  33 
  34 /**
  35  * Software synthesizer voice class.
  36  *
  37  * @author Karl Helgason
  38  */
  39 public final class SoftVoice extends VoiceStatus {
  40 
  41     public int exclusiveClass = 0;
  42     public boolean releaseTriggered = false;
  43     private int noteOn_noteNumber = 0;
  44     private int noteOn_velocity = 0;
  45     private int noteOff_velocity = 0;
  46     private int delay = 0;
  47     ModelChannelMixer channelmixer = null;
  48     double tunedKey = 0;
  49     SoftTuning tuning = null;
  50     SoftChannel stealer_channel = null;
  51     ModelConnectionBlock[] stealer_extendedConnectionBlocks = null;
  52     SoftPerformer stealer_performer = null;
  53     ModelChannelMixer stealer_channelmixer = null;
  54     int stealer_voiceID = -1;
  55     int stealer_noteNumber = 0;
  56     int stealer_velocity = 0;
  57     boolean stealer_releaseTriggered = false;
  58     int voiceID = -1;
  59     boolean sustain = false;
  60     boolean sostenuto = false;
  61     boolean portamento = false;
  62     private final SoftFilter filter_left;
  63     private final SoftFilter filter_right;
  64     private final SoftProcess eg = new SoftEnvelopeGenerator();
  65     private final SoftProcess lfo = new SoftLowFrequencyOscillator();
  66     Map<String, SoftControl> objects =
  67             new HashMap<String, SoftControl>();
  68     SoftSynthesizer synthesizer;
  69     SoftInstrument instrument;
  70     SoftPerformer performer;
  71     SoftChannel softchannel = null;
  72     boolean on = false;
  73     private boolean audiostarted = false;
  74     private boolean started = false;
  75     private boolean stopping = false;
  76     private float osc_attenuation = 0.0f;
  77     private ModelOscillatorStream osc_stream;
  78     private int osc_stream_nrofchannels;
  79     private float[][] osc_buff = new float[2][];
  80     private boolean osc_stream_off_transmitted = false;
  81     private boolean out_mixer_end = false;
  82     private float out_mixer_left = 0;
  83     private float out_mixer_right = 0;
  84     private float out_mixer_effect1 = 0;
  85     private float out_mixer_effect2 = 0;
  86     private float last_out_mixer_left = 0;
  87     private float last_out_mixer_right = 0;
  88     private float last_out_mixer_effect1 = 0;
  89     private float last_out_mixer_effect2 = 0;
  90     ModelConnectionBlock[] extendedConnectionBlocks = null;
  91     private ModelConnectionBlock[] connections;
  92     // Last value added to destination
  93     private double[] connections_last = new double[50];
  94     // Pointer to source value
  95     private double[][][] connections_src = new double[50][3][];
  96     // Key-based override (if any)
  97     private int[][] connections_src_kc = new int[50][3];
  98     // Pointer to destination value
  99     private double[][] connections_dst = new double[50][];
 100     private boolean soundoff = false;
 101     private float lastMuteValue = 0;
 102     private float lastSoloMuteValue = 0;
 103     double[] co_noteon_keynumber = new double[1];
 104     double[] co_noteon_velocity = new double[1];
 105     double[] co_noteon_on = new double[1];
 106     private final SoftControl co_noteon = new SoftControl() {
 107         double[] keynumber = co_noteon_keynumber;
 108         double[] velocity = co_noteon_velocity;
 109         double[] on = co_noteon_on;
 110         public double[] get(int instance, String name) {
 111             if (name == null)
 112                 return null;
 113             if (name.equals("keynumber"))
 114                 return keynumber;
 115             if (name.equals("velocity"))
 116                 return velocity;
 117             if (name.equals("on"))
 118                 return on;
 119             return null;
 120         }
 121     };
 122     private final double[] co_mixer_active = new double[1];
 123     private final double[] co_mixer_gain = new double[1];
 124     private final double[] co_mixer_pan = new double[1];
 125     private final double[] co_mixer_balance = new double[1];
 126     private final double[] co_mixer_reverb = new double[1];
 127     private final double[] co_mixer_chorus = new double[1];
 128     private final SoftControl co_mixer = new SoftControl() {
 129         double[] active = co_mixer_active;
 130         double[] gain = co_mixer_gain;
 131         double[] pan = co_mixer_pan;
 132         double[] balance = co_mixer_balance;
 133         double[] reverb = co_mixer_reverb;
 134         double[] chorus = co_mixer_chorus;
 135         public double[] get(int instance, String name) {
 136             if (name == null)
 137                 return null;
 138             if (name.equals("active"))
 139                 return active;
 140             if (name.equals("gain"))
 141                 return gain;
 142             if (name.equals("pan"))
 143                 return pan;
 144             if (name.equals("balance"))
 145                 return balance;
 146             if (name.equals("reverb"))
 147                 return reverb;
 148             if (name.equals("chorus"))
 149                 return chorus;
 150             return null;
 151         }
 152     };
 153     private final double[] co_osc_pitch = new double[1];
 154     private final SoftControl co_osc = new SoftControl() {
 155         double[] pitch = co_osc_pitch;
 156         public double[] get(int instance, String name) {
 157             if (name == null)
 158                 return null;
 159             if (name.equals("pitch"))
 160                 return pitch;
 161             return null;
 162         }
 163     };
 164     private final double[] co_filter_freq = new double[1];
 165     private final double[] co_filter_type = new double[1];
 166     private final double[] co_filter_q = new double[1];
 167     private final SoftControl co_filter = new SoftControl() {
 168         double[] freq = co_filter_freq;
 169         double[] ftype = co_filter_type;
 170         double[] q = co_filter_q;
 171         public double[] get(int instance, String name) {
 172             if (name == null)
 173                 return null;
 174             if (name.equals("freq"))
 175                 return freq;
 176             if (name.equals("type"))
 177                 return ftype;
 178             if (name.equals("q"))
 179                 return q;
 180             return null;
 181         }
 182     };
 183     SoftResamplerStreamer resampler;
 184     private final int nrofchannels;
 185 
 186     public SoftVoice(SoftSynthesizer synth) {
 187         synthesizer = synth;
 188         filter_left = new SoftFilter(synth.getFormat().getSampleRate());
 189         filter_right = new SoftFilter(synth.getFormat().getSampleRate());
 190         nrofchannels = synth.getFormat().getChannels();
 191     }
 192 
 193     private int getValueKC(ModelIdentifier id) {
 194         if (id.getObject().equals("midi_cc")) {
 195             int ic = Integer.parseInt(id.getVariable());
 196             if (ic != 0 && ic != 32) {
 197                 if (ic < 120)
 198                     return ic;
 199             }
 200         } else if (id.getObject().equals("midi_rpn")) {
 201             if (id.getVariable().equals("1"))
 202                 return 120; // Fine tuning
 203             if (id.getVariable().equals("2"))
 204                 return 121; // Coarse tuning
 205         }
 206         return -1;
 207     }
 208 
 209     private double[] getValue(ModelIdentifier id) {
 210         SoftControl o = objects.get(id.getObject());
 211         if (o == null)
 212             return null;
 213         return o.get(id.getInstance(), id.getVariable());
 214     }
 215 
 216     private double transformValue(double value, ModelSource src) {
 217         if (src.getTransform() != null)
 218             return src.getTransform().transform(value);
 219         else
 220             return value;
 221     }
 222 
 223     private double transformValue(double value, ModelDestination dst) {
 224         if (dst.getTransform() != null)
 225             return dst.getTransform().transform(value);
 226         else
 227             return value;
 228     }
 229 
 230     private double processKeyBasedController(double value, int keycontrol) {
 231         if (keycontrol == -1)
 232             return value;
 233         if (softchannel.keybasedcontroller_active != null)
 234             if (softchannel.keybasedcontroller_active[note] != null)
 235                 if (softchannel.keybasedcontroller_active[note][keycontrol]) {
 236                     double key_controlvalue =
 237                             softchannel.keybasedcontroller_value[note][keycontrol];
 238                     if (keycontrol == 10 || keycontrol == 91 || keycontrol == 93)
 239                         return key_controlvalue;
 240                     value += key_controlvalue * 2.0 - 1.0;
 241                     if (value > 1)
 242                         value = 1;
 243                     else if (value < 0)
 244                         value = 0;
 245                 }
 246         return value;
 247     }
 248 
 249     private void processConnection(int ix) {
 250         ModelConnectionBlock conn = connections[ix];
 251         double[][] src = connections_src[ix];
 252         double[] dst = connections_dst[ix];
 253         if (dst == null || Double.isInfinite(dst[0]))
 254             return;
 255 
 256         double value = conn.getScale();
 257         if (softchannel.keybasedcontroller_active == null) {
 258             ModelSource[] srcs = conn.getSources();
 259             for (int i = 0; i < srcs.length; i++) {
 260                 value *= transformValue(src[i][0], srcs[i]);
 261                 if (value == 0)
 262                     break;
 263             }
 264         } else {
 265             ModelSource[] srcs = conn.getSources();
 266             int[] src_kc = connections_src_kc[ix];
 267             for (int i = 0; i < srcs.length; i++) {
 268                 value *= transformValue(processKeyBasedController(src[i][0],
 269                         src_kc[i]), srcs[i]);
 270                 if (value == 0)
 271                     break;
 272             }
 273         }
 274 
 275         value = transformValue(value, conn.getDestination());
 276         dst[0] = dst[0] - connections_last[ix] + value;
 277         connections_last[ix] = value;
 278         // co_mixer_gain[0] = 0;
 279     }
 280 
 281     void updateTuning(SoftTuning newtuning) {
 282         tuning = newtuning;
 283         tunedKey = tuning.getTuning(note) / 100.0;
 284         if (!portamento) {
 285             co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
 286             if(performer == null)
 287                 return;
 288             int[] c = performer.midi_connections[4];
 289             if (c == null)
 290                 return;
 291             for (int i = 0; i < c.length; i++)
 292                 processConnection(c[i]);
 293         }
 294     }
 295 
 296     void setNote(int noteNumber) {
 297         note = noteNumber;
 298         tunedKey = tuning.getTuning(noteNumber) / 100.0;
 299     }
 300 
 301     void noteOn(int noteNumber, int velocity, int delay) {
 302 
 303         sustain = false;
 304         sostenuto = false;
 305         portamento = false;
 306 
 307         soundoff = false;
 308         on = true;
 309         active = true;
 310         started = true;
 311         // volume = velocity;
 312 
 313         noteOn_noteNumber = noteNumber;
 314         noteOn_velocity = velocity;
 315         this.delay = delay;
 316 
 317         lastMuteValue = 0;
 318         lastSoloMuteValue = 0;
 319 
 320         setNote(noteNumber);
 321 
 322         if (performer.forcedKeynumber)
 323             co_noteon_keynumber[0] = 0;
 324         else
 325             co_noteon_keynumber[0] = tunedKey * (1f / 128f);
 326         if (performer.forcedVelocity)
 327             co_noteon_velocity[0] = 0;
 328         else
 329             co_noteon_velocity[0] = velocity * (1f / 128f);
 330         co_mixer_active[0] = 0;
 331         co_mixer_gain[0] = 0;
 332         co_mixer_pan[0] = 0;
 333         co_mixer_balance[0] = 0;
 334         co_mixer_reverb[0] = 0;
 335         co_mixer_chorus[0] = 0;
 336         co_osc_pitch[0] = 0;
 337         co_filter_freq[0] = 0;
 338         co_filter_q[0] = 0;
 339         co_filter_type[0] = 0;
 340         co_noteon_on[0] = 1;
 341 
 342         eg.reset();
 343         lfo.reset();
 344         filter_left.reset();
 345         filter_right.reset();
 346 
 347         objects.put("master", synthesizer.getMainMixer().co_master);
 348         objects.put("eg", eg);
 349         objects.put("lfo", lfo);
 350         objects.put("noteon", co_noteon);
 351         objects.put("osc", co_osc);
 352         objects.put("mixer", co_mixer);
 353         objects.put("filter", co_filter);
 354 
 355         connections = performer.connections;
 356 
 357         if (connections_last == null
 358                 || connections_last.length < connections.length) {
 359             connections_last = new double[connections.length];
 360         }
 361         if (connections_src == null
 362                 || connections_src.length < connections.length) {
 363             connections_src = new double[connections.length][][];
 364             connections_src_kc = new int[connections.length][];
 365         }
 366         if (connections_dst == null
 367                 || connections_dst.length < connections.length) {
 368             connections_dst = new double[connections.length][];
 369         }
 370         for (int i = 0; i < connections.length; i++) {
 371             ModelConnectionBlock conn = connections[i];
 372             connections_last[i] = 0;
 373             if (conn.getSources() != null) {
 374                 ModelSource[] srcs = conn.getSources();
 375                 if (connections_src[i] == null
 376                         || connections_src[i].length < srcs.length) {
 377                     connections_src[i] = new double[srcs.length][];
 378                     connections_src_kc[i] = new int[srcs.length];
 379                 }
 380                 double[][] src = connections_src[i];
 381                 int[] src_kc = connections_src_kc[i];
 382                 connections_src[i] = src;
 383                 for (int j = 0; j < srcs.length; j++) {
 384                     src_kc[j] = getValueKC(srcs[j].getIdentifier());
 385                     src[j] = getValue(srcs[j].getIdentifier());
 386                 }
 387             }
 388 
 389             if (conn.getDestination() != null)
 390                 connections_dst[i] = getValue(conn.getDestination()
 391                         .getIdentifier());
 392             else
 393                 connections_dst[i] = null;
 394         }
 395 
 396         for (int i = 0; i < connections.length; i++)
 397             processConnection(i);
 398 
 399         if (extendedConnectionBlocks != null) {
 400             for (ModelConnectionBlock connection: extendedConnectionBlocks) {
 401                 double value = 0;
 402 
 403                 if (softchannel.keybasedcontroller_active == null) {
 404                     for (ModelSource src: connection.getSources()) {
 405                         double x = getValue(src.getIdentifier())[0];
 406                         ModelTransform t = src.getTransform();
 407                         if (t == null)
 408                             value += x;
 409                         else
 410                             value += t.transform(x);
 411                     }
 412                 } else {
 413                     for (ModelSource src: connection.getSources()) {
 414                         double x = getValue(src.getIdentifier())[0];
 415                         x = processKeyBasedController(x,
 416                                 getValueKC(src.getIdentifier()));
 417                         ModelTransform t = src.getTransform();
 418                         if (t == null)
 419                             value += x;
 420                         else
 421                             value += t.transform(x);
 422                     }
 423                 }
 424 
 425                 ModelDestination dest = connection.getDestination();
 426                 ModelTransform t = dest.getTransform();
 427                 if (t != null)
 428                     value = t.transform(value);
 429                 getValue(dest.getIdentifier())[0] += value;
 430             }
 431         }
 432 
 433         eg.init(synthesizer);
 434         lfo.init(synthesizer);
 435 
 436     }
 437 
 438     void setPolyPressure(int pressure) {
 439         if(performer == null)
 440             return;
 441         int[] c = performer.midi_connections[2];
 442         if (c == null)
 443             return;
 444         for (int i = 0; i < c.length; i++)
 445             processConnection(c[i]);
 446     }
 447 
 448     void setChannelPressure(int pressure) {
 449         if(performer == null)
 450             return;
 451         int[] c = performer.midi_connections[1];
 452         if (c == null)
 453             return;
 454         for (int i = 0; i < c.length; i++)
 455             processConnection(c[i]);
 456     }
 457 
 458     void controlChange(int controller, int value) {
 459         if(performer == null)
 460             return;
 461         int[] c = performer.midi_ctrl_connections[controller];
 462         if (c == null)
 463             return;
 464         for (int i = 0; i < c.length; i++)
 465             processConnection(c[i]);
 466     }
 467 
 468     void nrpnChange(int controller, int value) {
 469         if(performer == null)
 470             return;
 471         int[] c = performer.midi_nrpn_connections.get(controller);
 472         if (c == null)
 473             return;
 474         for (int i = 0; i < c.length; i++)
 475             processConnection(c[i]);
 476     }
 477 
 478     void rpnChange(int controller, int value) {
 479         if(performer == null)
 480             return;
 481         int[] c = performer.midi_rpn_connections.get(controller);
 482         if (c == null)
 483             return;
 484         for (int i = 0; i < c.length; i++)
 485             processConnection(c[i]);
 486     }
 487 
 488     void setPitchBend(int bend) {
 489         if(performer == null)
 490             return;
 491         int[] c = performer.midi_connections[0];
 492         if (c == null)
 493             return;
 494         for (int i = 0; i < c.length; i++)
 495             processConnection(c[i]);
 496     }
 497 
 498     void setMute(boolean mute) {
 499         co_mixer_gain[0] -= lastMuteValue;
 500         lastMuteValue = mute ? -960 : 0;
 501         co_mixer_gain[0] += lastMuteValue;
 502     }
 503 
 504     void setSoloMute(boolean mute) {
 505         co_mixer_gain[0] -= lastSoloMuteValue;
 506         lastSoloMuteValue = mute ? -960 : 0;
 507         co_mixer_gain[0] += lastSoloMuteValue;
 508     }
 509 
 510     void shutdown() {
 511         if (co_noteon_on[0] < -0.5)
 512             return;
 513         on = false;
 514 
 515         co_noteon_on[0] = -1;
 516 
 517         if(performer == null)
 518             return;
 519         int[] c = performer.midi_connections[3];
 520         if (c == null)
 521             return;
 522         for (int i = 0; i < c.length; i++)
 523             processConnection(c[i]);
 524     }
 525 
 526     void soundOff() {
 527         on = false;
 528         soundoff = true;
 529     }
 530 
 531     void noteOff(int velocity) {
 532         if (!on)
 533             return;
 534         on = false;
 535 
 536         noteOff_velocity = velocity;
 537 
 538         if (softchannel.sustain) {
 539             sustain = true;
 540             return;
 541         }
 542         if (sostenuto)
 543             return;
 544 
 545         co_noteon_on[0] = 0;
 546 
 547         if(performer == null)
 548             return;
 549         int[] c = performer.midi_connections[3];
 550         if (c == null)
 551             return;
 552         for (int i = 0; i < c.length; i++)
 553             processConnection(c[i]);
 554     }
 555 
 556     void redamp() {
 557         if (co_noteon_on[0] > 0.5)
 558             return;
 559         if (co_noteon_on[0] < -0.5)
 560             return; // don't redamp notes in shutdown stage
 561 
 562         sustain = true;
 563         co_noteon_on[0] = 1;
 564 
 565         if(performer == null)
 566             return;
 567         int[] c = performer.midi_connections[3];
 568         if (c == null)
 569             return;
 570         for (int i = 0; i < c.length; i++)
 571             processConnection(c[i]);
 572     }
 573 
 574     void processControlLogic() {
 575         if (stopping) {
 576             active = false;
 577             stopping = false;
 578             audiostarted = false;
 579             instrument = null;
 580             performer = null;
 581             connections = null;
 582             extendedConnectionBlocks = null;
 583             channelmixer = null;
 584             if (osc_stream != null)
 585                 try {
 586                     osc_stream.close();
 587                 } catch (IOException e) {
 588                     //e.printStackTrace();
 589                 }
 590 
 591             if (stealer_channel != null) {
 592                 stealer_channel.initVoice(this, stealer_performer,
 593                         stealer_voiceID, stealer_noteNumber, stealer_velocity, 0,
 594                         stealer_extendedConnectionBlocks, stealer_channelmixer,
 595                         stealer_releaseTriggered);
 596                 stealer_releaseTriggered = false;
 597                 stealer_channel = null;
 598                 stealer_performer = null;
 599                 stealer_voiceID = -1;
 600                 stealer_noteNumber = 0;
 601                 stealer_velocity = 0;
 602                 stealer_extendedConnectionBlocks = null;
 603                 stealer_channelmixer = null;
 604             }
 605         }
 606         if (started) {
 607             audiostarted = true;
 608 
 609             ModelOscillator osc = performer.oscillators[0];
 610 
 611             osc_stream_off_transmitted = false;
 612             if (osc instanceof ModelWavetable) {
 613                 try {
 614                     resampler.open((ModelWavetable)osc,
 615                             synthesizer.getFormat().getSampleRate());
 616                     osc_stream = resampler;
 617                 } catch (IOException e) {
 618                     //e.printStackTrace();
 619                 }
 620             } else {
 621                 osc_stream = osc.open(synthesizer.getFormat().getSampleRate());
 622             }
 623             osc_attenuation = osc.getAttenuation();
 624             osc_stream_nrofchannels = osc.getChannels();
 625             if (osc_buff == null || osc_buff.length < osc_stream_nrofchannels)
 626                 osc_buff = new float[osc_stream_nrofchannels][];
 627 
 628             if (osc_stream != null)
 629                 osc_stream.noteOn(softchannel, this, noteOn_noteNumber,
 630                         noteOn_velocity);
 631 
 632 
 633         }
 634         if (audiostarted) {
 635             if (portamento) {
 636                 double note_delta = tunedKey - (co_noteon_keynumber[0] * 128);
 637                 double note_delta_a = Math.abs(note_delta);
 638                 if (note_delta_a < 0.0000000001) {
 639                     co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
 640                     portamento = false;
 641                 } else {
 642                     if (note_delta_a > softchannel.portamento_time)
 643                         note_delta = Math.signum(note_delta)
 644                                 * softchannel.portamento_time;
 645                     co_noteon_keynumber[0] += note_delta * (1.0 / 128.0);
 646                 }
 647 
 648                 int[] c = performer.midi_connections[4];
 649                 if (c == null)
 650                     return;
 651                 for (int i = 0; i < c.length; i++)
 652                     processConnection(c[i]);
 653             }
 654 
 655             eg.processControlLogic();
 656             lfo.processControlLogic();
 657 
 658             for (int i = 0; i < performer.ctrl_connections.length; i++)
 659                 processConnection(performer.ctrl_connections[i]);
 660 
 661             osc_stream.setPitch((float)co_osc_pitch[0]);
 662 
 663             int filter_type = (int)co_filter_type[0];
 664             double filter_freq;
 665 
 666             if (co_filter_freq[0] == 13500.0)
 667                 filter_freq = 19912.126958213175;
 668             else
 669                 filter_freq = 440.0 * Math.exp(
 670                         ((co_filter_freq[0]) - 6900.0) *
 671                         (Math.log(2.0) / 1200.0));
 672             /*
 673             filter_freq = 440.0 * Math.pow(2.0,
 674             ((co_filter_freq[0]) - 6900.0) / 1200.0);*/
 675             /*
 676              * double velocity = co_noteon_velocity[0]; if(velocity < 0.5)
 677              * filter_freq *= ((velocity * 2)*0.75 + 0.25);
 678              */
 679 
 680             double q = co_filter_q[0] / 10.0;
 681             filter_left.setFilterType(filter_type);
 682             filter_left.setFrequency(filter_freq);
 683             filter_left.setResonance(q);
 684             filter_right.setFilterType(filter_type);
 685             filter_right.setFrequency(filter_freq);
 686             filter_right.setResonance(q);
 687             /*
 688             float gain = (float) Math.pow(10,
 689             (-osc_attenuation + co_mixer_gain[0]) / 200.0);
 690              */
 691             float gain = (float)Math.exp(
 692                     (-osc_attenuation + co_mixer_gain[0])*(Math.log(10) / 200.0));
 693 
 694             if (co_mixer_gain[0] <= -960)
 695                 gain = 0;
 696 
 697             if (soundoff) {
 698                 stopping = true;
 699                 gain = 0;
 700                 /*
 701                  * if(co_mixer_gain[0] > -960)
 702                  *   co_mixer_gain[0] -= 960;
 703                  */
 704             }
 705 
 706             volume = (int)(Math.sqrt(gain) * 128);
 707 
 708             // gain *= 0.2;
 709 
 710             double pan = co_mixer_pan[0] * (1.0 / 1000.0);
 711             // System.out.println("pan = " + pan);
 712             if (pan < 0)
 713                 pan = 0;
 714             else if (pan > 1)
 715                 pan = 1;
 716 
 717             if (pan == 0.5) {
 718                 out_mixer_left = gain * 0.7071067811865476f;
 719                 out_mixer_right = out_mixer_left;
 720             } else {
 721                 out_mixer_left = gain * (float)Math.cos(pan * Math.PI * 0.5);
 722                 out_mixer_right = gain * (float)Math.sin(pan * Math.PI * 0.5);
 723             }
 724 
 725             double balance = co_mixer_balance[0] * (1.0 / 1000.0);
 726             if (balance != 0.5) {
 727                 if (balance > 0.5)
 728                     out_mixer_left *= (1 - balance) * 2;
 729                 else
 730                     out_mixer_right *= balance * 2;
 731             }
 732 
 733             if (synthesizer.reverb_on) {
 734                 out_mixer_effect1 = (float)(co_mixer_reverb[0] * (1.0 / 1000.0));
 735                 out_mixer_effect1 *= gain;
 736             } else
 737                 out_mixer_effect1 = 0;
 738             if (synthesizer.chorus_on) {
 739                 out_mixer_effect2 = (float)(co_mixer_chorus[0] * (1.0 / 1000.0));
 740                 out_mixer_effect2 *= gain;
 741             } else
 742                 out_mixer_effect2 = 0;
 743             out_mixer_end = co_mixer_active[0] < 0.5;
 744 
 745             if (!on)
 746                 if (!osc_stream_off_transmitted) {
 747                     osc_stream_off_transmitted = true;
 748                     if (osc_stream != null)
 749                         osc_stream.noteOff(noteOff_velocity);
 750                 }
 751 
 752         }
 753         if (started) {
 754             last_out_mixer_left = out_mixer_left;
 755             last_out_mixer_right = out_mixer_right;
 756             last_out_mixer_effect1 = out_mixer_effect1;
 757             last_out_mixer_effect2 = out_mixer_effect2;
 758             started = false;
 759         }
 760 
 761     }
 762 
 763     void mixAudioStream(SoftAudioBuffer in, SoftAudioBuffer out,
 764                                 SoftAudioBuffer dout, float amp_from,
 765                                 float amp_to) {
 766         int bufferlen = in.getSize();
 767         if (amp_from < 0.000000001 && amp_to < 0.000000001)
 768             return;
 769         if(dout != null && delay != 0)
 770         {
 771             if (amp_from == amp_to) {
 772                 float[] fout = out.array();
 773                 float[] fin = in.array();
 774                 int j = 0;
 775                 for (int i = delay; i < bufferlen; i++)
 776                     fout[i] += fin[j++] * amp_to;
 777                 fout = dout.array();
 778                 for (int i = 0; i < delay; i++)
 779                     fout[i] += fin[j++] * amp_to;
 780             } else {
 781                 float amp = amp_from;
 782                 float amp_delta = (amp_to - amp_from) / bufferlen;
 783                 float[] fout = out.array();
 784                 float[] fin = in.array();
 785                 int j = 0;
 786                 for (int i = delay; i < bufferlen; i++) {
 787                     amp += amp_delta;
 788                     fout[i] += fin[j++] * amp;
 789                 }
 790                 fout = dout.array();
 791                 for (int i = 0; i < delay; i++) {
 792                     amp += amp_delta;
 793                     fout[i] += fin[j++] * amp;
 794                 }
 795             }
 796         }
 797         else
 798         {
 799             if (amp_from == amp_to) {
 800                 float[] fout = out.array();
 801                 float[] fin = in.array();
 802                 for (int i = 0; i < bufferlen; i++)
 803                     fout[i] += fin[i] * amp_to;
 804             } else {
 805                 float amp = amp_from;
 806                 float amp_delta = (amp_to - amp_from) / bufferlen;
 807                 float[] fout = out.array();
 808                 float[] fin = in.array();
 809                 for (int i = 0; i < bufferlen; i++) {
 810                     amp += amp_delta;
 811                     fout[i] += fin[i] * amp;
 812                 }
 813             }
 814         }
 815 
 816     }
 817 
 818     void processAudioLogic(SoftAudioBuffer[] buffer) {
 819         if (!audiostarted)
 820             return;
 821 
 822         int bufferlen = buffer[0].getSize();
 823 
 824         try {
 825             osc_buff[0] = buffer[SoftMainMixer.CHANNEL_LEFT_DRY].array();
 826             if (nrofchannels != 1)
 827                 osc_buff[1] = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY].array();
 828             int ret = osc_stream.read(osc_buff, 0, bufferlen);
 829             if (ret == -1) {
 830                 stopping = true;
 831                 return;
 832             }
 833             if (ret != bufferlen) {
 834                 Arrays.fill(osc_buff[0], ret, bufferlen, 0f);
 835                 if (nrofchannels != 1)
 836                     Arrays.fill(osc_buff[1], ret, bufferlen, 0f);
 837             }
 838 
 839         } catch (IOException e) {
 840             //e.printStackTrace();
 841         }
 842 
 843         SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT];
 844         SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT];
 845         SoftAudioBuffer mono = buffer[SoftMainMixer.CHANNEL_MONO];
 846         SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1];
 847         SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2];
 848 
 849         SoftAudioBuffer dleft = buffer[SoftMainMixer.CHANNEL_DELAY_LEFT];
 850         SoftAudioBuffer dright = buffer[SoftMainMixer.CHANNEL_DELAY_RIGHT];
 851         SoftAudioBuffer dmono = buffer[SoftMainMixer.CHANNEL_DELAY_MONO];
 852         SoftAudioBuffer deff1 = buffer[SoftMainMixer.CHANNEL_DELAY_EFFECT1];
 853         SoftAudioBuffer deff2 = buffer[SoftMainMixer.CHANNEL_DELAY_EFFECT2];
 854 
 855         SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY];
 856         SoftAudioBuffer rightdry = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY];
 857 
 858         if (osc_stream_nrofchannels == 1)
 859             rightdry = null;
 860 
 861         if (!Double.isInfinite(co_filter_freq[0])) {
 862             filter_left.processAudio(leftdry);
 863             if (rightdry != null)
 864                 filter_right.processAudio(rightdry);
 865         }
 866 
 867         if (nrofchannels == 1) {
 868             out_mixer_left = (out_mixer_left + out_mixer_right) / 2;
 869             mixAudioStream(leftdry, left, dleft, last_out_mixer_left, out_mixer_left);
 870             if (rightdry != null)
 871                 mixAudioStream(rightdry, left, dleft, last_out_mixer_left,
 872                         out_mixer_left);
 873         } else {
 874             if(rightdry == null &&
 875                     last_out_mixer_left == last_out_mixer_right &&
 876                     out_mixer_left == out_mixer_right)
 877             {
 878                 mixAudioStream(leftdry, mono, dmono, last_out_mixer_left, out_mixer_left);
 879             }
 880             else
 881             {
 882                 mixAudioStream(leftdry, left, dleft, last_out_mixer_left, out_mixer_left);
 883                 if (rightdry != null)
 884                     mixAudioStream(rightdry, right, dright, last_out_mixer_right,
 885                         out_mixer_right);
 886                 else
 887                     mixAudioStream(leftdry, right, dright, last_out_mixer_right,
 888                         out_mixer_right);
 889             }
 890         }
 891 
 892         if (rightdry == null) {
 893             mixAudioStream(leftdry, eff1, deff1, last_out_mixer_effect1,
 894                     out_mixer_effect1);
 895             mixAudioStream(leftdry, eff2, deff2, last_out_mixer_effect2,
 896                     out_mixer_effect2);
 897         } else {
 898             mixAudioStream(leftdry, eff1, deff1, last_out_mixer_effect1 * 0.5f,
 899                     out_mixer_effect1 * 0.5f);
 900             mixAudioStream(leftdry, eff2, deff2, last_out_mixer_effect2 * 0.5f,
 901                     out_mixer_effect2 * 0.5f);
 902             mixAudioStream(rightdry, eff1, deff1, last_out_mixer_effect1 * 0.5f,
 903                     out_mixer_effect1 * 0.5f);
 904             mixAudioStream(rightdry, eff2, deff2, last_out_mixer_effect2 * 0.5f,
 905                     out_mixer_effect2 * 0.5f);
 906         }
 907 
 908         last_out_mixer_left = out_mixer_left;
 909         last_out_mixer_right = out_mixer_right;
 910         last_out_mixer_effect1 = out_mixer_effect1;
 911         last_out_mixer_effect2 = out_mixer_effect2;
 912 
 913         if (out_mixer_end) {
 914             stopping = true;
 915         }
 916 
 917     }
 918 }