Save This Page
Home » openjdk-7 » com.sun.media » sound » [javadoc | source]
    1   /*
    2    * Copyright (c) 2007, 2010, 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.util.ArrayList;
   28   import java.util.Arrays;
   29   import java.util.HashMap;
   30   import java.util.Iterator;
   31   import java.util.List;
   32   import java.util.Map;
   33   
   34   import javax.sound.midi.MidiChannel;
   35   import javax.sound.midi.Patch;
   36   
   37   /**
   38    * Software Synthesizer MIDI channel class.
   39    *
   40    * @author Karl Helgason
   41    */
   42   public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
   43   
   44       private static boolean[] dontResetControls = new boolean[128];
   45       static {
   46           for (int i = 0; i < dontResetControls.length; i++)
   47               dontResetControls[i] = false;
   48   
   49           dontResetControls[0] = true;   // Bank Select (MSB)
   50           dontResetControls[32] = true;  // Bank Select (LSB)
   51           dontResetControls[7] = true;   // Channel Volume (MSB)
   52           dontResetControls[8] = true;   // Balance (MSB)
   53           dontResetControls[10] = true;  // Pan (MSB)
   54           dontResetControls[11] = true;  // Expression (MSB)
   55           dontResetControls[91] = true;  // Effects 1 Depth (default: Reverb Send)
   56           dontResetControls[92] = true;  // Effects 2 Depth (default: Tremolo Depth)
   57           dontResetControls[93] = true;  // Effects 3 Depth (default: Chorus Send)
   58           dontResetControls[94] = true;  // Effects 4 Depth (default: Celeste [Detune] Depth)
   59           dontResetControls[95] = true;  // Effects 5 Depth (default: Phaser Depth)
   60           dontResetControls[70] = true;  // Sound Controller 1 (default: Sound Variation)
   61           dontResetControls[71] = true;  // Sound Controller 2 (default: Timbre / Harmonic Quality)
   62           dontResetControls[72] = true;  // Sound Controller 3 (default: Release Time)
   63           dontResetControls[73] = true;  // Sound Controller 4 (default: Attack Time)
   64           dontResetControls[74] = true;  // Sound Controller 5 (default: Brightness)
   65           dontResetControls[75] = true;  // Sound Controller 6 (GM2 default: Decay Time)
   66           dontResetControls[76] = true;  // Sound Controller 7 (GM2 default: Vibrato Rate)
   67           dontResetControls[77] = true;  // Sound Controller 8 (GM2 default: Vibrato Depth)
   68           dontResetControls[78] = true;  // Sound Controller 9 (GM2 default: Vibrato Delay)
   69           dontResetControls[79] = true;  // Sound Controller 10 (GM2 default: Undefined)
   70           dontResetControls[120] = true; // All Sound Off
   71           dontResetControls[121] = true; // Reset All Controllers
   72           dontResetControls[122] = true; // Local Control On/Off
   73           dontResetControls[123] = true; // All Notes Off
   74           dontResetControls[124] = true; // Omni Mode Off
   75           dontResetControls[125] = true; // Omni Mode On
   76           dontResetControls[126] = true; // Poly Mode Off
   77           dontResetControls[127] = true; // Poly Mode On
   78   
   79           dontResetControls[6] = true;   // Data Entry (MSB)
   80           dontResetControls[38] = true;  // Data Entry (LSB)
   81           dontResetControls[96] = true;  // Data Increment
   82           dontResetControls[97] = true;  // Data Decrement
   83           dontResetControls[98] = true;  // Non-Registered Parameter Number (LSB)
   84           dontResetControls[99] = true;  // Non-Registered Parameter Number(MSB)
   85           dontResetControls[100] = true; // RPN = Null
   86           dontResetControls[101] = true; // RPN = Null
   87   
   88       }
   89   
   90       private static final int RPN_NULL_VALUE = (127 << 7) + 127;
   91       private int rpn_control = RPN_NULL_VALUE;
   92       private int nrpn_control = RPN_NULL_VALUE;
   93       protected double portamento_time = 1; // keyschanges per control buffer time
   94       protected int[] portamento_lastnote = new int[128];
   95       protected int portamento_lastnote_ix = 0;
   96       private boolean portamento = false;
   97       private boolean mono = false;
   98       private boolean mute = false;
   99       private boolean solo = false;
  100       private boolean solomute = false;
  101       private Object control_mutex;
  102       private int channel;
  103       private SoftVoice[] voices;
  104       private int bank;
  105       private int program;
  106       private SoftSynthesizer synthesizer;
  107       private SoftMainMixer mainmixer;
  108       private int[] polypressure = new int[128];
  109       private int channelpressure = 0;
  110       private int[] controller = new int[128];
  111       private int pitchbend;
  112       private double[] co_midi_pitch = new double[1];
  113       private double[] co_midi_channel_pressure = new double[1];
  114       protected SoftTuning tuning = new SoftTuning();
  115       protected int tuning_bank = 0;
  116       protected int tuning_program = 0;
  117       protected SoftInstrument current_instrument = null;
  118       protected ModelChannelMixer current_mixer = null;
  119       protected ModelDirector current_director = null;
  120   
  121       // Controller Destination Settings
  122       protected int cds_control_number = -1;
  123       protected ModelConnectionBlock[] cds_control_connections = null;
  124       protected ModelConnectionBlock[] cds_channelpressure_connections = null;
  125       protected ModelConnectionBlock[] cds_polypressure_connections = null;
  126       protected boolean sustain = false;
  127       protected boolean[][] keybasedcontroller_active = null;
  128       protected double[][] keybasedcontroller_value = null;
  129   
  130       private class MidiControlObject implements SoftControl {
  131           double[] pitch = co_midi_pitch;
  132           double[] channel_pressure = co_midi_channel_pressure;
  133           double[] poly_pressure = new double[1];
  134   
  135           public double[] get(int instance, String name) {
  136               if (name == null)
  137                   return null;
  138               if (name.equals("pitch"))
  139                   return pitch;
  140               if (name.equals("channel_pressure"))
  141                   return channel_pressure;
  142               if (name.equals("poly_pressure"))
  143                   return poly_pressure;
  144               return null;
  145           }
  146       }
  147   
  148       private SoftControl[] co_midi = new SoftControl[128];
  149       {
  150           for (int i = 0; i < co_midi.length; i++) {
  151               co_midi[i] = new MidiControlObject();
  152           }
  153       }
  154   
  155       private double[][] co_midi_cc_cc = new double[128][1];
  156       private SoftControl co_midi_cc = new SoftControl() {
  157           double[][] cc = co_midi_cc_cc;
  158           public double[] get(int instance, String name) {
  159               if (name == null)
  160                   return null;
  161               return cc[Integer.parseInt(name)];
  162           }
  163       };
  164       Map<Integer, int[]> co_midi_rpn_rpn_i = new HashMap<Integer, int[]>();
  165       Map<Integer, double[]> co_midi_rpn_rpn = new HashMap<Integer, double[]>();
  166       private SoftControl co_midi_rpn = new SoftControl() {
  167           Map<Integer, double[]> rpn = co_midi_rpn_rpn;
  168           public double[] get(int instance, String name) {
  169               if (name == null)
  170                   return null;
  171               int iname = Integer.parseInt(name);
  172               double[] v = rpn.get(iname);
  173               if (v == null) {
  174                   v = new double[1];
  175                   rpn.put(iname, v);
  176               }
  177               return v;
  178           }
  179       };
  180       Map<Integer, int[]> co_midi_nrpn_nrpn_i = new HashMap<Integer, int[]>();
  181       Map<Integer, double[]> co_midi_nrpn_nrpn = new HashMap<Integer, double[]>();
  182       private SoftControl co_midi_nrpn = new SoftControl() {
  183           Map<Integer, double[]> nrpn = co_midi_nrpn_nrpn;
  184           public double[] get(int instance, String name) {
  185               if (name == null)
  186                   return null;
  187               int iname = Integer.parseInt(name);
  188               double[] v = nrpn.get(iname);
  189               if (v == null) {
  190                   v = new double[1];
  191                   nrpn.put(iname, v);
  192               }
  193               return v;
  194           }
  195       };
  196   
  197       private static int restrict7Bit(int value)
  198       {
  199           if(value < 0) return 0;
  200           if(value > 127) return 127;
  201           return value;
  202       }
  203   
  204       private static int restrict14Bit(int value)
  205       {
  206           if(value < 0) return 0;
  207           if(value > 16256) return 16256;
  208           return value;
  209       }
  210   
  211       public SoftChannel(SoftSynthesizer synth, int channel) {
  212           this.channel = channel;
  213           this.voices = synth.getVoices();
  214           this.synthesizer = synth;
  215           this.mainmixer = synth.getMainMixer();
  216           control_mutex = synth.control_mutex;
  217           resetAllControllers(true);
  218       }
  219   
  220       private int findFreeVoice(int x) {
  221           if(x == -1)
  222           {
  223               // x = -1 means that there where no available voice
  224               // last time we called findFreeVoice
  225               // and it hasn't changed because no audio has been
  226               // rendered in the meantime.
  227               // Therefore we have to return -1.
  228               return -1;
  229           }
  230           for (int i = x; i < voices.length; i++)
  231               if (!voices[i].active)
  232                   return i;
  233   
  234           // No free voice was found, we must steal one
  235   
  236           int vmode = synthesizer.getVoiceAllocationMode();
  237           if (vmode == 1) {
  238               // DLS Static Voice Allocation
  239   
  240               //  * priority ( 10, 1-9, 11-16)
  241               // Search for channel to steal from
  242               int steal_channel = channel;
  243               for (int j = 0; j < voices.length; j++) {
  244                   if (voices[j].stealer_channel == null) {
  245                       if (steal_channel == 9) {
  246                           steal_channel = voices[j].channel;
  247                       } else {
  248                           if (voices[j].channel != 9) {
  249                               if (voices[j].channel > steal_channel)
  250                                   steal_channel = voices[j].channel;
  251                           }
  252                       }
  253                   }
  254               }
  255   
  256               int voiceNo = -1;
  257   
  258               SoftVoice v = null;
  259               // Search for oldest voice in off state on steal_channel
  260               for (int j = 0; j < voices.length; j++) {
  261                   if (voices[j].channel == steal_channel) {
  262                       if (voices[j].stealer_channel == null && !voices[j].on) {
  263                           if (v == null) {
  264                               v = voices[j];
  265                               voiceNo = j;
  266                           }
  267                           if (voices[j].voiceID < v.voiceID) {
  268                               v = voices[j];
  269                               voiceNo = j;
  270                           }
  271                       }
  272                   }
  273               }
  274               // Search for oldest voice in on state on steal_channel
  275               if (voiceNo == -1) {
  276                   for (int j = 0; j < voices.length; j++) {
  277                       if (voices[j].channel == steal_channel) {
  278                           if (voices[j].stealer_channel == null) {
  279                               if (v == null) {
  280                                   v = voices[j];
  281                                   voiceNo = j;
  282                               }
  283                               if (voices[j].voiceID < v.voiceID) {
  284                                   v = voices[j];
  285                                   voiceNo = j;
  286                               }
  287                           }
  288                       }
  289                   }
  290               }
  291   
  292               return voiceNo;
  293   
  294           } else {
  295               // Default Voice Allocation
  296               //  * Find voice that is on
  297               //    and Find voice which has lowest voiceID ( oldest voice)
  298               //  * Or find voice that is off
  299               //    and Find voice which has lowest voiceID ( oldest voice)
  300   
  301               int voiceNo = -1;
  302   
  303               SoftVoice v = null;
  304               // Search for oldest voice in off state
  305               for (int j = 0; j < voices.length; j++) {
  306                   if (voices[j].stealer_channel == null && !voices[j].on) {
  307                       if (v == null) {
  308                           v = voices[j];
  309                           voiceNo = j;
  310                       }
  311                       if (voices[j].voiceID < v.voiceID) {
  312                           v = voices[j];
  313                           voiceNo = j;
  314                       }
  315                   }
  316               }
  317               // Search for oldest voice in on state
  318               if (voiceNo == -1) {
  319   
  320                   for (int j = 0; j < voices.length; j++) {
  321                       if (voices[j].stealer_channel == null) {
  322                           if (v == null) {
  323                               v = voices[j];
  324                               voiceNo = j;
  325                           }
  326                           if (voices[j].voiceID < v.voiceID) {
  327                               v = voices[j];
  328                               voiceNo = j;
  329                           }
  330                       }
  331                   }
  332               }
  333   
  334               return voiceNo;
  335           }
  336   
  337       }
  338   
  339       protected void initVoice(SoftVoice voice, SoftPerformer p, int voiceID,
  340               int noteNumber, int velocity, int delay, ModelConnectionBlock[] connectionBlocks,
  341               ModelChannelMixer channelmixer, boolean releaseTriggered) {
  342           if (voice.active) {
  343               // Voice is active , we must steal the voice
  344               voice.stealer_channel = this;
  345               voice.stealer_performer = p;
  346               voice.stealer_voiceID = voiceID;
  347               voice.stealer_noteNumber = noteNumber;
  348               voice.stealer_velocity = velocity;
  349               voice.stealer_extendedConnectionBlocks = connectionBlocks;
  350               voice.stealer_channelmixer = channelmixer;
  351               voice.stealer_releaseTriggered = releaseTriggered;
  352               for (int i = 0; i < voices.length; i++)
  353                   if (voices[i].active && voices[i].voiceID == voice.voiceID)
  354                       voices[i].soundOff();
  355               return;
  356           }
  357   
  358           voice.extendedConnectionBlocks = connectionBlocks;
  359           voice.channelmixer = channelmixer;
  360           voice.releaseTriggered = releaseTriggered;
  361           voice.voiceID = voiceID;
  362           voice.tuning = tuning;
  363           voice.exclusiveClass = p.exclusiveClass;
  364           voice.softchannel = this;
  365           voice.channel = channel;
  366           voice.bank = bank;
  367           voice.program = program;
  368           voice.instrument = current_instrument;
  369           voice.performer = p;
  370           voice.objects.clear();
  371           voice.objects.put("midi", co_midi[noteNumber]);
  372           voice.objects.put("midi_cc", co_midi_cc);
  373           voice.objects.put("midi_rpn", co_midi_rpn);
  374           voice.objects.put("midi_nrpn", co_midi_nrpn);
  375           voice.noteOn(noteNumber, velocity, delay);
  376           voice.setMute(mute);
  377           voice.setSoloMute(solomute);
  378           if (releaseTriggered)
  379               return;
  380           if (controller[84] != 0) {
  381               voice.co_noteon_keynumber[0]
  382                       = (tuning.getTuning(controller[84]) / 100.0)
  383                       * (1f / 128f);
  384               voice.portamento = true;
  385               controlChange(84, 0);
  386           } else if (portamento) {
  387               if (mono) {
  388                   if (portamento_lastnote[0] != -1) {
  389                       voice.co_noteon_keynumber[0]
  390                               = (tuning.getTuning(portamento_lastnote[0]) / 100.0)
  391                               * (1f / 128f);
  392                       voice.portamento = true;
  393                       controlChange(84, 0);
  394                   }
  395                   portamento_lastnote[0] = noteNumber;
  396               } else {
  397                   if (portamento_lastnote_ix != 0) {
  398                       portamento_lastnote_ix--;
  399                       voice.co_noteon_keynumber[0]
  400                               = (tuning.getTuning(
  401                                       portamento_lastnote[portamento_lastnote_ix])
  402                                   / 100.0)
  403                               * (1f / 128f);
  404                       voice.portamento = true;
  405                   }
  406               }
  407           }
  408       }
  409   
  410       public void noteOn(int noteNumber, int velocity) {
  411           noteOn(noteNumber, velocity, 0);
  412       }
  413   
  414       /* A special noteOn with delay parameter, which is used to
  415        * start note within control buffers.
  416        */
  417       protected void noteOn(int noteNumber, int velocity, int delay) {
  418           noteNumber = restrict7Bit(noteNumber);
  419           velocity = restrict7Bit(velocity);
  420           noteOn_internal(noteNumber, velocity, delay);
  421           if (current_mixer != null)
  422               current_mixer.noteOn(noteNumber, velocity);
  423       }
  424   
  425       private void noteOn_internal(int noteNumber, int velocity, int delay) {
  426   
  427           if (velocity == 0) {
  428               noteOff_internal(noteNumber, 64);
  429               return;
  430           }
  431   
  432           synchronized (control_mutex) {
  433               if (sustain) {
  434                   sustain = false;
  435                   for (int i = 0; i < voices.length; i++) {
  436                       if ((voices[i].sustain || voices[i].on)
  437                               && voices[i].channel == channel && voices[i].active
  438                               && voices[i].note == noteNumber) {
  439                           voices[i].sustain = false;
  440                           voices[i].on = true;
  441                           voices[i].noteOff(0);
  442                       }
  443                   }
  444                   sustain = true;
  445               }
  446   
  447               mainmixer.activity();
  448   
  449               if (mono) {
  450                   if (portamento) {
  451                       boolean n_found = false;
  452                       for (int i = 0; i < voices.length; i++) {
  453                           if (voices[i].on && voices[i].channel == channel
  454                                   && voices[i].active
  455                                   && voices[i].releaseTriggered == false) {
  456                               voices[i].portamento = true;
  457                               voices[i].setNote(noteNumber);
  458                               n_found = true;
  459                           }
  460                       }
  461                       if (n_found) {
  462                           portamento_lastnote[0] = noteNumber;
  463                           return;
  464                       }
  465                   }
  466   
  467                   if (controller[84] != 0) {
  468                       boolean n_found = false;
  469                       for (int i = 0; i < voices.length; i++) {
  470                           if (voices[i].on && voices[i].channel == channel
  471                                   && voices[i].active
  472                                   && voices[i].note == controller[84]
  473                                   && voices[i].releaseTriggered == false) {
  474                               voices[i].portamento = true;
  475                               voices[i].setNote(noteNumber);
  476                               n_found = true;
  477                           }
  478                       }
  479                       controlChange(84, 0);
  480                       if (n_found)
  481                           return;
  482                   }
  483               }
  484   
  485               if (mono)
  486                   allNotesOff();
  487   
  488               if (current_instrument == null) {
  489                   current_instrument
  490                           = synthesizer.findInstrument(program, bank, channel);
  491                   if (current_instrument == null)
  492                       return;
  493                   if (current_mixer != null)
  494                       mainmixer.stopMixer(current_mixer);
  495                   current_mixer = current_instrument.getSourceInstrument()
  496                           .getChannelMixer(this, synthesizer.getFormat());
  497                   if (current_mixer != null)
  498                       mainmixer.registerMixer(current_mixer);
  499                   current_director = current_instrument.getDirector(this, this);
  500                   applyInstrumentCustomization();
  501               }
  502               prevVoiceID = synthesizer.voiceIDCounter++;
  503               firstVoice = true;
  504               voiceNo = 0;
  505   
  506               int tunedKey = (int)(Math.round(tuning.getTuning(noteNumber)/100.0));
  507               play_noteNumber = noteNumber;
  508               play_velocity = velocity;
  509               play_delay = delay;
  510               play_releasetriggered = false;
  511               lastVelocity[noteNumber] = velocity;
  512               current_director.noteOn(tunedKey, velocity);
  513   
  514               /*
  515               SoftPerformer[] performers = current_instrument.getPerformers();
  516               for (int i = 0; i < performers.length; i++) {
  517                   SoftPerformer p = performers[i];
  518                   if (p.keyFrom <= tunedKey && p.keyTo >= tunedKey) {
  519                       if (p.velFrom <= velocity && p.velTo >= velocity) {
  520                           if (firstVoice) {
  521                               firstVoice = false;
  522                               if (p.exclusiveClass != 0) {
  523                                   int x = p.exclusiveClass;
  524                                   for (int j = 0; j < voices.length; j++) {
  525                                       if (voices[j].active
  526                                               && voices[j].channel == channel
  527                                               && voices[j].exclusiveClass == x) {
  528                                           if (!(p.selfNonExclusive
  529                                                   && voices[j].note == noteNumber))
  530                                               voices[j].shutdown();
  531                                       }
  532                                   }
  533                               }
  534                           }
  535                           voiceNo = findFreeVoice(voiceNo);
  536                           if (voiceNo == -1)
  537                               return;
  538                           initVoice(voices[voiceNo], p, prevVoiceID, noteNumber,
  539                                   velocity);
  540                       }
  541                   }
  542               }
  543               */
  544           }
  545       }
  546   
  547       public void noteOff(int noteNumber, int velocity) {
  548           noteNumber = restrict7Bit(noteNumber);
  549           velocity = restrict7Bit(velocity);
  550           noteOff_internal(noteNumber, velocity);
  551   
  552           if (current_mixer != null)
  553               current_mixer.noteOff(noteNumber, velocity);
  554       }
  555   
  556       private void noteOff_internal(int noteNumber, int velocity) {
  557           synchronized (control_mutex) {
  558   
  559               if (!mono) {
  560                   if (portamento) {
  561                       if (portamento_lastnote_ix != 127) {
  562                           portamento_lastnote[portamento_lastnote_ix] = noteNumber;
  563                           portamento_lastnote_ix++;
  564                       }
  565                   }
  566               }
  567   
  568               mainmixer.activity();
  569               for (int i = 0; i < voices.length; i++) {
  570                   if (voices[i].on && voices[i].channel == channel
  571                           && voices[i].note == noteNumber
  572                           && voices[i].releaseTriggered == false) {
  573                       voices[i].noteOff(velocity);
  574                   }
  575                   // We must also check stolen voices
  576                   if (voices[i].stealer_channel == this && voices[i].stealer_noteNumber == noteNumber) {
  577                       SoftVoice v = voices[i];
  578                       v.stealer_releaseTriggered = false;
  579                       v.stealer_channel = null;
  580                       v.stealer_performer = null;
  581                       v.stealer_voiceID = -1;
  582                       v.stealer_noteNumber = 0;
  583                       v.stealer_velocity = 0;
  584                       v.stealer_extendedConnectionBlocks = null;
  585                       v.stealer_channelmixer = null;
  586                   }
  587               }
  588   
  589               // Try play back note-off triggered voices,
  590   
  591               if (current_instrument == null) {
  592                   current_instrument
  593                           = synthesizer.findInstrument(program, bank, channel);
  594                   if (current_instrument == null)
  595                       return;
  596                   if (current_mixer != null)
  597                       mainmixer.stopMixer(current_mixer);
  598                   current_mixer = current_instrument.getSourceInstrument()
  599                           .getChannelMixer(this, synthesizer.getFormat());
  600                   if (current_mixer != null)
  601                       mainmixer.registerMixer(current_mixer);
  602                   current_director = current_instrument.getDirector(this, this);
  603                   applyInstrumentCustomization();
  604   
  605               }
  606               prevVoiceID = synthesizer.voiceIDCounter++;
  607               firstVoice = true;
  608               voiceNo = 0;
  609   
  610               int tunedKey = (int)(Math.round(tuning.getTuning(noteNumber)/100.0));
  611               play_noteNumber = noteNumber;
  612               play_velocity = lastVelocity[noteNumber];
  613               play_releasetriggered = true;
  614               play_delay = 0;
  615               current_director.noteOff(tunedKey, velocity);
  616   
  617           }
  618       }
  619       private int[] lastVelocity = new int[128];
  620       private int prevVoiceID;
  621       private boolean firstVoice = true;
  622       private int voiceNo = 0;
  623       private int play_noteNumber = 0;
  624       private int play_velocity = 0;
  625       private int play_delay = 0;
  626       private boolean play_releasetriggered = false;
  627   
  628       public void play(int performerIndex, ModelConnectionBlock[] connectionBlocks) {
  629   
  630           int noteNumber = play_noteNumber;
  631           int velocity = play_velocity;
  632           int delay = play_delay;
  633           boolean releasetriggered = play_releasetriggered;
  634   
  635           SoftPerformer p = current_instrument.getPerformer(performerIndex);
  636   
  637           if (firstVoice) {
  638               firstVoice = false;
  639               if (p.exclusiveClass != 0) {
  640                   int x = p.exclusiveClass;
  641                   for (int j = 0; j < voices.length; j++) {
  642                       if (voices[j].active && voices[j].channel == channel
  643                               && voices[j].exclusiveClass == x) {
  644                           if (!(p.selfNonExclusive && voices[j].note == noteNumber))
  645                               voices[j].shutdown();
  646                       }
  647                   }
  648               }
  649           }
  650   
  651           voiceNo = findFreeVoice(voiceNo);
  652   
  653           if (voiceNo == -1)
  654               return;
  655   
  656           initVoice(voices[voiceNo], p, prevVoiceID, noteNumber, velocity, delay,
  657                   connectionBlocks, current_mixer, releasetriggered);
  658       }
  659   
  660       public void noteOff(int noteNumber) {
  661           if(noteNumber < 0 || noteNumber > 127) return;
  662           noteOff_internal(noteNumber, 64);
  663       }
  664   
  665       public void setPolyPressure(int noteNumber, int pressure) {
  666           noteNumber = restrict7Bit(noteNumber);
  667           pressure = restrict7Bit(pressure);
  668   
  669           if (current_mixer != null)
  670               current_mixer.setPolyPressure(noteNumber, pressure);
  671   
  672           synchronized (control_mutex) {
  673               mainmixer.activity();
  674               co_midi[noteNumber].get(0, "poly_pressure")[0] = pressure*(1.0/128.0);
  675               polypressure[noteNumber] = pressure;
  676               for (int i = 0; i < voices.length; i++) {
  677                   if (voices[i].active && voices[i].note == noteNumber)
  678                       voices[i].setPolyPressure(pressure);
  679               }
  680           }
  681       }
  682   
  683       public int getPolyPressure(int noteNumber) {
  684           synchronized (control_mutex) {
  685               return polypressure[noteNumber];
  686           }
  687       }
  688   
  689       public void setChannelPressure(int pressure) {
  690           pressure = restrict7Bit(pressure);
  691           if (current_mixer != null)
  692               current_mixer.setChannelPressure(pressure);
  693           synchronized (control_mutex) {
  694               mainmixer.activity();
  695               co_midi_channel_pressure[0] = pressure * (1.0 / 128.0);
  696               channelpressure = pressure;
  697               for (int i = 0; i < voices.length; i++) {
  698                   if (voices[i].active)
  699                       voices[i].setChannelPressure(pressure);
  700               }
  701           }
  702       }
  703   
  704       public int getChannelPressure() {
  705           synchronized (control_mutex) {
  706               return channelpressure;
  707           }
  708       }
  709   
  710       protected void applyInstrumentCustomization() {
  711           if (cds_control_connections == null
  712                   && cds_channelpressure_connections == null
  713                   && cds_polypressure_connections == null) {
  714               return;
  715           }
  716   
  717           ModelInstrument src_instrument = current_instrument.getSourceInstrument();
  718           ModelPerformer[] performers = src_instrument.getPerformers();
  719           ModelPerformer[] new_performers = new ModelPerformer[performers.length];
  720           for (int i = 0; i < new_performers.length; i++) {
  721               ModelPerformer performer = performers[i];
  722               ModelPerformer new_performer = new ModelPerformer();
  723               new_performer.setName(performer.getName());
  724               new_performer.setExclusiveClass(performer.getExclusiveClass());
  725               new_performer.setKeyFrom(performer.getKeyFrom());
  726               new_performer.setKeyTo(performer.getKeyTo());
  727               new_performer.setVelFrom(performer.getVelFrom());
  728               new_performer.setVelTo(performer.getVelTo());
  729               new_performer.getOscillators().addAll(performer.getOscillators());
  730               new_performer.getConnectionBlocks().addAll(
  731                       performer.getConnectionBlocks());
  732               new_performers[i] = new_performer;
  733   
  734               List<ModelConnectionBlock> connblocks =
  735                       new_performer.getConnectionBlocks();
  736   
  737               if (cds_control_connections != null) {
  738                   String cc = Integer.toString(cds_control_number);
  739                   Iterator<ModelConnectionBlock> iter = connblocks.iterator();
  740                   while (iter.hasNext()) {
  741                       ModelConnectionBlock conn = iter.next();
  742                       ModelSource[] sources = conn.getSources();
  743                       boolean removeok = false;
  744                       if (sources != null) {
  745                           for (int j = 0; j < sources.length; j++) {
  746                               ModelSource src = sources[j];
  747                               if ("midi_cc".equals(src.getIdentifier().getObject())
  748                                       && cc.equals(src.getIdentifier().getVariable())) {
  749                                   removeok = true;
  750                               }
  751                           }
  752                       }
  753                       if (removeok)
  754                           iter.remove();
  755                   }
  756                   for (int j = 0; j < cds_control_connections.length; j++)
  757                       connblocks.add(cds_control_connections[j]);
  758               }
  759   
  760               if (cds_polypressure_connections != null) {
  761                   Iterator<ModelConnectionBlock> iter = connblocks.iterator();
  762                   while (iter.hasNext()) {
  763                       ModelConnectionBlock conn = iter.next();
  764                       ModelSource[] sources = conn.getSources();
  765                       boolean removeok = false;
  766                       if (sources != null) {
  767                           for (int j = 0; j < sources.length; j++) {
  768                               ModelSource src = sources[j];
  769                               if ("midi".equals(src.getIdentifier().getObject())
  770                                       && "poly_pressure".equals(
  771                                           src.getIdentifier().getVariable())) {
  772                                   removeok = true;
  773                               }
  774                           }
  775                       }
  776                       if (removeok)
  777                           iter.remove();
  778                   }
  779                   for (int j = 0; j < cds_polypressure_connections.length; j++)
  780                       connblocks.add(cds_polypressure_connections[j]);
  781               }
  782   
  783   
  784               if (cds_channelpressure_connections != null) {
  785                   Iterator<ModelConnectionBlock> iter = connblocks.iterator();
  786                   while (iter.hasNext()) {
  787                       ModelConnectionBlock conn = iter.next();
  788                       ModelSource[] sources = conn.getSources();
  789                       boolean removeok = false;
  790                       if (sources != null) {
  791                           for (int j = 0; j < sources.length; j++) {
  792                               ModelIdentifier srcid = sources[j].getIdentifier();
  793                               if ("midi".equals(srcid.getObject()) &&
  794                                       "channel_pressure".equals(srcid.getVariable())) {
  795                                   removeok = true;
  796                               }
  797                           }
  798                       }
  799                       if (removeok)
  800                           iter.remove();
  801                   }
  802                   for (int j = 0; j < cds_channelpressure_connections.length; j++)
  803                       connblocks.add(cds_channelpressure_connections[j]);
  804               }
  805   
  806           }
  807   
  808           current_instrument = new SoftInstrument(src_instrument, new_performers);
  809   
  810       }
  811   
  812       private ModelConnectionBlock[] createModelConnections(ModelIdentifier sid,
  813               int[] destination, int[] range) {
  814   
  815           /*
  816           controlled parameter (pp)|range (rr)| Description             |Default
  817           -------------------------|----------|-------------------------|-------
  818           00 Pitch Control         | 28H..58H | -24..+24 semitones      | 40H
  819           01 Filter Cutoff Control | 00H..7FH | -9600..+9450 cents      | 40H
  820           02 Amplitude Control     | 00H..7FH | 0..(127/64)*100 percent | 40H
  821           03 LFO Pitch Depth       | 00H..7FH | 0..600 cents            |  0
  822           04 LFO Filter Depth      | 00H..7FH | 0..2400 cents           |  0
  823           05 LFO Amplitude Depth   | 00H..7FH | 0..100 percent          |  0
  824           */
  825   
  826           List<ModelConnectionBlock> conns = new ArrayList<ModelConnectionBlock>();
  827   
  828           for (int i = 0; i < destination.length; i++) {
  829               int d = destination[i];
  830               int r = range[i];
  831               if (d == 0) {
  832                   double scale = (r - 64) * 100;
  833                   ModelConnectionBlock conn = new ModelConnectionBlock(
  834                           new ModelSource(sid,
  835                               ModelStandardTransform.DIRECTION_MIN2MAX,
  836                               ModelStandardTransform.POLARITY_UNIPOLAR,
  837                               ModelStandardTransform.TRANSFORM_LINEAR),
  838                           scale,
  839                           new ModelDestination(
  840                               new ModelIdentifier("osc", "pitch")));
  841                   conns.add(conn);
  842   
  843               }
  844               if (d == 1) {
  845                   double scale = (r / 64.0 - 1.0) * 9600.0;
  846                   ModelConnectionBlock conn;
  847                   if (scale > 0) {
  848                       conn = new ModelConnectionBlock(
  849                               new ModelSource(sid,
  850                                   ModelStandardTransform.DIRECTION_MAX2MIN,
  851                                   ModelStandardTransform.POLARITY_UNIPOLAR,
  852                                   ModelStandardTransform.TRANSFORM_LINEAR),
  853                               -scale,
  854                               new ModelDestination(
  855                                   ModelDestination.DESTINATION_FILTER_FREQ));
  856                   } else {
  857                       conn = new ModelConnectionBlock(
  858                               new ModelSource(sid,
  859                                   ModelStandardTransform.DIRECTION_MIN2MAX,
  860                                   ModelStandardTransform.POLARITY_UNIPOLAR,
  861                                   ModelStandardTransform.TRANSFORM_LINEAR),
  862                               scale,
  863                               new ModelDestination(
  864                                   ModelDestination.DESTINATION_FILTER_FREQ));
  865                   }
  866                   conns.add(conn);
  867               }
  868               if (d == 2) {
  869                   final double scale = (r / 64.0);
  870                   ModelTransform mt = new ModelTransform() {
  871                       double s = scale;
  872                       public double transform(double value) {
  873                           if (s < 1)
  874                               value = s + (value * (1.0 - s));
  875                           else if (s > 1)
  876                               value = 1 + (value * (s - 1.0));
  877                           else
  878                               return 0;
  879                           return -((5.0 / 12.0) / Math.log(10)) * Math.log(value);
  880                       }
  881                   };
  882   
  883                   ModelConnectionBlock conn = new ModelConnectionBlock(
  884                           new ModelSource(sid, mt), -960,
  885                           new ModelDestination(ModelDestination.DESTINATION_GAIN));
  886                   conns.add(conn);
  887   
  888               }
  889               if (d == 3) {
  890                   double scale = (r / 64.0 - 1.0) * 9600.0;
  891                   ModelConnectionBlock conn = new ModelConnectionBlock(
  892                           new ModelSource(ModelSource.SOURCE_LFO1,
  893                               ModelStandardTransform.DIRECTION_MIN2MAX,
  894                               ModelStandardTransform.POLARITY_BIPOLAR,
  895                               ModelStandardTransform.TRANSFORM_LINEAR),
  896                           new ModelSource(sid,
  897                               ModelStandardTransform.DIRECTION_MIN2MAX,
  898                               ModelStandardTransform.POLARITY_UNIPOLAR,
  899                               ModelStandardTransform.TRANSFORM_LINEAR),
  900                           scale,
  901                           new ModelDestination(
  902                               ModelDestination.DESTINATION_PITCH));
  903                   conns.add(conn);
  904               }
  905               if (d == 4) {
  906                   double scale = (r / 128.0) * 2400.0;
  907                   ModelConnectionBlock conn = new ModelConnectionBlock(
  908                           new ModelSource(ModelSource.SOURCE_LFO1,
  909                               ModelStandardTransform.DIRECTION_MIN2MAX,
  910                               ModelStandardTransform.POLARITY_BIPOLAR,
  911                               ModelStandardTransform.TRANSFORM_LINEAR),
  912                           new ModelSource(sid,
  913                               ModelStandardTransform.DIRECTION_MIN2MAX,
  914                               ModelStandardTransform.POLARITY_UNIPOLAR,
  915                               ModelStandardTransform.TRANSFORM_LINEAR),
  916                           scale,
  917                           new ModelDestination(
  918                               ModelDestination.DESTINATION_FILTER_FREQ));
  919                   conns.add(conn);
  920               }
  921               if (d == 5) {
  922                   final double scale = (r / 127.0);
  923   
  924                   ModelTransform mt = new ModelTransform() {
  925                       double s = scale;
  926                       public double transform(double value) {
  927                           return -((5.0 / 12.0) / Math.log(10))
  928                                   * Math.log(1 - value * s);
  929                       }
  930                   };
  931   
  932                   ModelConnectionBlock conn = new ModelConnectionBlock(
  933                           new ModelSource(ModelSource.SOURCE_LFO1,
  934                               ModelStandardTransform.DIRECTION_MIN2MAX,
  935                               ModelStandardTransform.POLARITY_UNIPOLAR,
  936                               ModelStandardTransform.TRANSFORM_LINEAR),
  937                           new ModelSource(sid, mt),
  938                           -960,
  939                           new ModelDestination(
  940                               ModelDestination.DESTINATION_GAIN));
  941                   conns.add(conn);
  942               }
  943           }
  944   
  945           return conns.toArray(new ModelConnectionBlock[conns.size()]);
  946       }
  947   
  948       public void mapPolyPressureToDestination(int[] destination, int[] range) {
  949           current_instrument = null;
  950           if (destination.length == 0) {
  951               cds_polypressure_connections = null;
  952               return;
  953           }
  954           cds_polypressure_connections
  955                   = createModelConnections(
  956                       new ModelIdentifier("midi", "poly_pressure"),
  957                       destination, range);
  958       }
  959   
  960       public void mapChannelPressureToDestination(int[] destination, int[] range) {
  961           current_instrument = null;
  962           if (destination.length == 0) {
  963               cds_channelpressure_connections = null;
  964               return;
  965           }
  966           cds_channelpressure_connections
  967                   = createModelConnections(
  968                       new ModelIdentifier("midi", "channel_pressure"),
  969                       destination, range);
  970       }
  971   
  972       public void mapControlToDestination(int control, int[] destination, int[] range) {
  973   
  974           if (!((control >= 0x01 && control <= 0x1F)
  975                   || (control >= 0x40 && control <= 0x5F))) {
  976               cds_control_connections = null;
  977               return;
  978           }
  979   
  980           current_instrument = null;
  981           cds_control_number = control;
  982           if (destination.length == 0) {
  983               cds_control_connections = null;
  984               return;
  985           }
  986           cds_control_connections
  987                   = createModelConnections(
  988                       new ModelIdentifier("midi_cc", Integer.toString(control)),
  989                       destination, range);
  990       }
  991   
  992       public void controlChangePerNote(int noteNumber, int controller, int value) {
  993   
  994   /*
  995    CC# | nn   | Name                    | vv             | default    | description
  996   -----|------|-------------------------|----------------|------------|-------------------------------
  997   7    |07H   |Note Volume              |00H-40H-7FH     |40H         |0-100-(127/64)*100(%)(Relative)
  998   10   |0AH   |*Pan                     |00H-7FH absolute|Preset Value|Left-Center-Right (absolute)
  999   33-63|21-3FH|LSB for                  |01H-1FH         |            |
 1000   71   |47H   |Timbre/Harmonic Intensity|00H-40H-7FH     |40H (???)   |
 1001   72   |48H   |Release Time             |00H-40H-7FH     |40H (???)   |
 1002   73   |49H   |Attack Time              |00H-40H-7FH     |40H (???)   |
 1003   74   |4AH   |Brightness               |00H-40H-7FH     |40H (???)   |
 1004   75   |4BH   |Decay Time               |00H-40H-7FH     |40H (???)   |
 1005   76   |4CH   |Vibrato Rate             |00H-40H-7FH     |40H (???)   |
 1006   77   |4DH   |Vibrato Depth            |00H-40H-7FH     |40H (???)   |
 1007   78   |4EH   |Vibrato Delay            |00H-40H-7FH     |40H (???)   |
 1008   91   |5BH   |*Reverb Send             |00H-7FH absolute|Preset Value|Left-Center-Right (absolute)
 1009   93   |5DH   |*Chorus Send             |00H-7FH absolute|Preset Value|Left-Center-Right (absolute)
 1010   120  |78H   |**Fine Tuning            |00H-40H-7FH     |40H (???)   |
 1011   121  |79H   |**Coarse Tuning          |00H-40H-7FH     |40H (???)   |
 1012   */
 1013   
 1014           if (keybasedcontroller_active == null) {
 1015               keybasedcontroller_active = new boolean[128][];
 1016               keybasedcontroller_value = new double[128][];
 1017           }
 1018           if (keybasedcontroller_active[noteNumber] == null) {
 1019               keybasedcontroller_active[noteNumber] = new boolean[128];
 1020               Arrays.fill(keybasedcontroller_active[noteNumber], false);
 1021               keybasedcontroller_value[noteNumber] = new double[128];
 1022               Arrays.fill(keybasedcontroller_value[noteNumber], 0);
 1023           }
 1024   
 1025           if (value == -1) {
 1026               keybasedcontroller_active[noteNumber][controller] = false;
 1027           } else {
 1028               keybasedcontroller_active[noteNumber][controller] = true;
 1029               keybasedcontroller_value[noteNumber][controller] = value / 128.0;
 1030           }
 1031   
 1032           if (controller < 120) {
 1033               for (int i = 0; i < voices.length; i++)
 1034                   if (voices[i].active)
 1035                       voices[i].controlChange(controller, -1);
 1036           } else if (controller == 120) {
 1037               for (int i = 0; i < voices.length; i++)
 1038                   if (voices[i].active)
 1039                       voices[i].rpnChange(1, -1);
 1040           } else if (controller == 121) {
 1041               for (int i = 0; i < voices.length; i++)
 1042                   if (voices[i].active)
 1043                       voices[i].rpnChange(2, -1);
 1044           }
 1045   
 1046       }
 1047   
 1048       public int getControlPerNote(int noteNumber, int controller) {
 1049           if (keybasedcontroller_active == null)
 1050               return -1;
 1051           if (keybasedcontroller_active[noteNumber] == null)
 1052               return -1;
 1053           if (!keybasedcontroller_active[noteNumber][controller])
 1054               return -1;
 1055           return (int)(keybasedcontroller_value[noteNumber][controller] * 128);
 1056       }
 1057   
 1058       public void controlChange(int controller, int value) {
 1059           controller = restrict7Bit(controller);
 1060           value = restrict7Bit(value);
 1061           if (current_mixer != null)
 1062               current_mixer.controlChange(controller, value);
 1063   
 1064           synchronized (control_mutex) {
 1065               switch (controller) {
 1066               /*
 1067               Map<String, int[]>co_midi_rpn_rpn_i = new HashMap<String, int[]>();
 1068               Map<String, double[]>co_midi_rpn_rpn = new HashMap<String, double[]>();
 1069               Map<String, int[]>co_midi_nrpn_nrpn_i = new HashMap<String, int[]>();
 1070               Map<String, double[]>co_midi_nrpn_nrpn = new HashMap<String, double[]>();
 1071                */
 1072   
 1073               case 5:
 1074                   // This produce asin-like curve
 1075                   // as described in General Midi Level 2 Specification, page 6
 1076                   double x = -Math.asin((value / 128.0) * 2 - 1) / Math.PI + 0.5;
 1077                   x = Math.pow(100000.0, x) / 100.0;  // x is now cent/msec
 1078                   // Convert x from cent/msec to key/controlbuffertime
 1079                   x = x / 100.0;                      // x is now keys/msec
 1080                   x = x * 1000.0;                     // x is now keys/sec
 1081                   x = x / synthesizer.getControlRate(); // x is now keys/controlbuffertime
 1082                   portamento_time = x;
 1083                   break;
 1084               case 6:
 1085               case 38:
 1086               case 96:
 1087               case 97:
 1088                   int val = 0;
 1089                   if (nrpn_control != RPN_NULL_VALUE) {
 1090                       int[] val_i = co_midi_nrpn_nrpn_i.get(nrpn_control);
 1091                       if (val_i != null)
 1092                           val = val_i[0];
 1093                   }
 1094                   if (rpn_control != RPN_NULL_VALUE) {
 1095                       int[] val_i = co_midi_rpn_rpn_i.get(rpn_control);
 1096                       if (val_i != null)
 1097                           val = val_i[0];
 1098                   }
 1099   
 1100                   if (controller == 6)
 1101                       val = (val & 127) + (value << 7);
 1102                   else if (controller == 38)
 1103                       val = (val & (127 << 7)) + value;
 1104                   else if (controller == 96 || controller == 97) {
 1105                       int step = 1;
 1106                       if (rpn_control == 2 || rpn_control == 3 || rpn_control == 4)
 1107                           step = 128;
 1108                       if (controller == 96)
 1109                           val += step;
 1110                       if (controller == 97)
 1111                           val -= step;
 1112                   }
 1113   
 1114                   if (nrpn_control != RPN_NULL_VALUE)
 1115                       nrpnChange(nrpn_control, val);
 1116                   if (rpn_control != RPN_NULL_VALUE)
 1117                       rpnChange(rpn_control, val);
 1118   
 1119                   break;
 1120               case 64: // Hold1 (Damper) (cc#64)
 1121                   boolean on = value >= 64;
 1122                   if (sustain != on) {
 1123                       sustain = on;
 1124                       if (!on) {
 1125                           for (int i = 0; i < voices.length; i++) {
 1126                               if (voices[i].active && voices[i].sustain &&
 1127                                       voices[i].channel == channel) {
 1128                                   voices[i].sustain = false;
 1129                                   if (!voices[i].on) {
 1130                                       voices[i].on = true;
 1131                                       voices[i].noteOff(0);
 1132                                   }
 1133                               }
 1134                           }
 1135                       } else {
 1136                           for (int i = 0; i < voices.length; i++)
 1137                               if (voices[i].active && voices[i].channel == channel)
 1138                                   voices[i].redamp();
 1139                       }
 1140                   }
 1141                   break;
 1142               case 65:
 1143                   //allNotesOff();
 1144                   portamento = value >= 64;
 1145                   portamento_lastnote[0] = -1;
 1146                   /*
 1147                   for (int i = 0; i < portamento_lastnote.length; i++)
 1148                       portamento_lastnote[i] = -1;
 1149                    */
 1150                   portamento_lastnote_ix = 0;
 1151                   break;
 1152               case 66: // Sostenuto (cc#66)
 1153                   on = value >= 64;
 1154                   if (on) {
 1155                       for (int i = 0; i < voices.length; i++) {
 1156                           if (voices[i].active && voices[i].on &&
 1157                                   voices[i].channel == channel) {
 1158                               voices[i].sostenuto = true;
 1159                           }
 1160                       }
 1161                   }
 1162                   if (!on) {
 1163                       for (int i = 0; i < voices.length; i++) {
 1164                           if (voices[i].active && voices[i].sostenuto &&
 1165                                   voices[i].channel == channel) {
 1166                               voices[i].sostenuto = false;
 1167                               if (!voices[i].on) {
 1168                                   voices[i].on = true;
 1169                                   voices[i].noteOff(0);
 1170                               }
 1171                           }
 1172                       }
 1173                   }
 1174                   break;
 1175               case 98:
 1176                   nrpn_control = (nrpn_control & (127 << 7)) + value;
 1177                   rpn_control = RPN_NULL_VALUE;
 1178                   break;
 1179               case 99:
 1180                   nrpn_control = (nrpn_control & 127) + (value << 7);
 1181                   rpn_control = RPN_NULL_VALUE;
 1182                   break;
 1183               case 100:
 1184                   rpn_control = (rpn_control & (127 << 7)) + value;
 1185                   nrpn_control = RPN_NULL_VALUE;
 1186                   break;
 1187               case 101:
 1188                   rpn_control = (rpn_control & 127) + (value << 7);
 1189                   nrpn_control = RPN_NULL_VALUE;
 1190                   break;
 1191               case 120:
 1192                   allSoundOff();
 1193                   break;
 1194               case 121:
 1195                   resetAllControllers(value == 127);
 1196                   break;
 1197               case 122:
 1198                   localControl(value >= 64);
 1199                   break;
 1200               case 123:
 1201                   allNotesOff();
 1202                   break;
 1203               case 124:
 1204                   setOmni(false);
 1205                   break;
 1206               case 125:
 1207                   setOmni(true);
 1208                   break;
 1209               case 126:
 1210                   if (value == 1)
 1211                       setMono(true);
 1212                   break;
 1213               case 127:
 1214                   setMono(false);
 1215                   break;
 1216   
 1217               default:
 1218                   break;
 1219               }
 1220   
 1221               co_midi_cc_cc[controller][0] = value * (1.0 / 128.0);
 1222   
 1223               if (controller == 0x00) {
 1224                   bank = /*(bank & 127) +*/ (value << 7);
 1225                   return;
 1226               }
 1227   
 1228               if (controller == 0x20) {
 1229                   bank = (bank & (127 << 7)) + value;
 1230                   return;
 1231               }
 1232   
 1233               this.controller[controller] = value;
 1234               if(controller < 0x20)
 1235                   this.controller[controller + 0x20] = 0;
 1236   
 1237               for (int i = 0; i < voices.length; i++)
 1238                   if (voices[i].active)
 1239                       voices[i].controlChange(controller, value);
 1240   
 1241           }
 1242       }
 1243   
 1244       public int getController(int controller) {
 1245           synchronized (control_mutex) {
 1246               // Should only return lower 7 bits,
 1247               // even when controller is "boosted" higher.
 1248               return this.controller[controller] & 127;
 1249           }
 1250       }
 1251   
 1252       public void tuningChange(int program) {
 1253           tuningChange(0, program);
 1254       }
 1255   
 1256       public void tuningChange(int bank, int program) {
 1257           synchronized (control_mutex) {
 1258               tuning = synthesizer.getTuning(new Patch(bank, program));
 1259           }
 1260       }
 1261   
 1262       public void programChange(int program) {
 1263           programChange(bank, program);
 1264       }
 1265   
 1266       public void programChange(int bank, int program) {
 1267           bank = restrict14Bit(bank);
 1268           program = restrict7Bit(program);
 1269           synchronized (control_mutex) {
 1270               mainmixer.activity();
 1271               if(this.bank != bank || this.program != program)
 1272               {
 1273                   this.bank = bank;
 1274                   this.program = program;
 1275                   current_instrument = null;
 1276               }
 1277           }
 1278       }
 1279   
 1280       public int getProgram() {
 1281           synchronized (control_mutex) {
 1282               return program;
 1283           }
 1284       }
 1285   
 1286       public void setPitchBend(int bend) {
 1287           bend = restrict14Bit(bend);
 1288           if (current_mixer != null)
 1289               current_mixer.setPitchBend(bend);
 1290           synchronized (control_mutex) {
 1291               mainmixer.activity();
 1292               co_midi_pitch[0] = bend * (1.0 / 16384.0);
 1293               pitchbend = bend;
 1294               for (int i = 0; i < voices.length; i++)
 1295                   if (voices[i].active)
 1296                       voices[i].setPitchBend(bend);
 1297           }
 1298       }
 1299   
 1300       public int getPitchBend() {
 1301           synchronized (control_mutex) {
 1302               return pitchbend;
 1303           }
 1304       }
 1305   
 1306       public void nrpnChange(int controller, int value) {
 1307   
 1308           /*
 1309           System.out.println("(" + channel + ").nrpnChange("
 1310                   + Integer.toHexString(controller >> 7)
 1311                   + " " + Integer.toHexString(controller & 127)
 1312                   + ", " + Integer.toHexString(value >> 7)
 1313                   + " " + Integer.toHexString(value & 127) + ")");
 1314            */
 1315   
 1316           if (synthesizer.getGeneralMidiMode() == 0) {
 1317               if (controller == (0x01 << 7) + (0x08)) // Vibrato Rate
 1318                   controlChange(76, value >> 7);
 1319               if (controller == (0x01 << 7) + (0x09)) // Vibrato Depth
 1320                   controlChange(77, value >> 7);
 1321               if (controller == (0x01 << 7) + (0x0A)) // Vibrato Delay
 1322                   controlChange(78, value >> 7);
 1323               if (controller == (0x01 << 7) + (0x20)) // Brightness
 1324                   controlChange(74, value >> 7);
 1325               if (controller == (0x01 << 7) + (0x21)) // Filter Resonance
 1326                   controlChange(71, value >> 7);
 1327               if (controller == (0x01 << 7) + (0x63)) // Attack Time
 1328                   controlChange(73, value >> 7);
 1329               if (controller == (0x01 << 7) + (0x64)) // Decay Time
 1330                   controlChange(75, value >> 7);
 1331               if (controller == (0x01 << 7) + (0x66)) // Release Time
 1332                   controlChange(72, value >> 7);
 1333   
 1334               if (controller >> 7 == 0x18) // Pitch coarse
 1335                   controlChangePerNote(controller % 128, 120, value >> 7);
 1336               if (controller >> 7 == 0x1A) // Volume
 1337                   controlChangePerNote(controller % 128, 7, value >> 7);
 1338               if (controller >> 7 == 0x1C) // Panpot
 1339                   controlChangePerNote(controller % 128, 10, value >> 7);
 1340               if (controller >> 7 == 0x1D) // Reverb
 1341                   controlChangePerNote(controller % 128, 91, value >> 7);
 1342               if (controller >> 7 == 0x1E) // Chorus
 1343                   controlChangePerNote(controller % 128, 93, value >> 7);
 1344           }
 1345   
 1346           int[] val_i = co_midi_nrpn_nrpn_i.get(controller);
 1347           double[] val_d = co_midi_nrpn_nrpn.get(controller);
 1348           if (val_i == null) {
 1349               val_i = new int[1];
 1350               co_midi_nrpn_nrpn_i.put(controller, val_i);
 1351           }
 1352           if (val_d == null) {
 1353               val_d = new double[1];
 1354               co_midi_nrpn_nrpn.put(controller, val_d);
 1355           }
 1356           val_i[0] = value;
 1357           val_d[0] = val_i[0] * (1.0 / 16384.0);
 1358   
 1359           for (int i = 0; i < voices.length; i++)
 1360               if (voices[i].active)
 1361                   voices[i].nrpnChange(controller, val_i[0]);
 1362   
 1363       }
 1364   
 1365       public void rpnChange(int controller, int value) {
 1366   
 1367           /*
 1368           System.out.println("(" + channel + ").rpnChange("
 1369                   + Integer.toHexString(controller >> 7)
 1370                   + " " + Integer.toHexString(controller & 127)
 1371                   + ", " + Integer.toHexString(value >> 7)
 1372                   + " " + Integer.toHexString(value & 127) + ")");
 1373            */
 1374   
 1375           if (controller == 3) {
 1376               tuning_program = (value >> 7) & 127;
 1377               tuningChange(tuning_bank, tuning_program);
 1378           }
 1379           if (controller == 4) {
 1380               tuning_bank = (value >> 7) & 127;
 1381           }
 1382   
 1383           int[] val_i = co_midi_rpn_rpn_i.get(controller);
 1384           double[] val_d = co_midi_rpn_rpn.get(controller);
 1385           if (val_i == null) {
 1386               val_i = new int[1];
 1387               co_midi_rpn_rpn_i.put(controller, val_i);
 1388           }
 1389           if (val_d == null) {
 1390               val_d = new double[1];
 1391               co_midi_rpn_rpn.put(controller, val_d);
 1392           }
 1393           val_i[0] = value;
 1394           val_d[0] = val_i[0] * (1.0 / 16384.0);
 1395   
 1396           for (int i = 0; i < voices.length; i++)
 1397               if (voices[i].active)
 1398                   voices[i].rpnChange(controller, val_i[0]);
 1399       }
 1400   
 1401       public void resetAllControllers() {
 1402           resetAllControllers(false);
 1403       }
 1404   
 1405       public void resetAllControllers(boolean allControls) {
 1406           synchronized (control_mutex) {
 1407               mainmixer.activity();
 1408   
 1409               for (int i = 0; i < 128; i++) {
 1410                   setPolyPressure(i, 0);
 1411               }
 1412               setChannelPressure(0);
 1413               setPitchBend(8192);
 1414               for (int i = 0; i < 128; i++) {
 1415                   if (!dontResetControls[i])
 1416                       controlChange(i, 0);
 1417               }
 1418   
 1419               controlChange(71, 64); // Filter Resonance
 1420               controlChange(72, 64); // Release Time
 1421               controlChange(73, 64); // Attack Time
 1422               controlChange(74, 64); // Brightness
 1423               controlChange(75, 64); // Decay Time
 1424               controlChange(76, 64); // Vibrato Rate
 1425               controlChange(77, 64); // Vibrato Depth
 1426               controlChange(78, 64); // Vibrato Delay
 1427   
 1428               controlChange(8, 64); // Balance
 1429               controlChange(11, 127); // Expression
 1430               controlChange(98, 127); // NRPN Null
 1431               controlChange(99, 127); // NRPN Null
 1432               controlChange(100, 127); // RPN = Null
 1433               controlChange(101, 127); // RPN = Null
 1434   
 1435               // see DLS 2.1 (Power-on Default Values)
 1436               if (allControls) {
 1437   
 1438                   keybasedcontroller_active = null;
 1439                   keybasedcontroller_value = null;
 1440   
 1441                   controlChange(7, 100); // Volume
 1442                   controlChange(10, 64); // Pan
 1443                   controlChange(91, 40); // Reverb
 1444   
 1445                   for (int controller : co_midi_rpn_rpn.keySet()) {
 1446                       // don't reset tuning settings
 1447                       if (controller != 3 && controller != 4)
 1448                           rpnChange(controller, 0);
 1449                   }
 1450                   for (int controller : co_midi_nrpn_nrpn.keySet())
 1451                       nrpnChange(controller, 0);
 1452                   rpnChange(0, 2 << 7);   // Bitch Bend sensitivity
 1453                   rpnChange(1, 64 << 7);  // Channel fine tunning
 1454                   rpnChange(2, 64 << 7);  // Channel Coarse Tuning
 1455                   rpnChange(5, 64);       // Modulation Depth, +/- 50 cent
 1456   
 1457                   tuning_bank = 0;
 1458                   tuning_program = 0;
 1459                   tuning = new SoftTuning();
 1460   
 1461               }
 1462   
 1463           }
 1464       }
 1465   
 1466       public void allNotesOff() {
 1467           if (current_mixer != null)
 1468               current_mixer.allNotesOff();
 1469           synchronized (control_mutex) {
 1470               for (int i = 0; i < voices.length; i++)
 1471                   if (voices[i].on && voices[i].channel == channel
 1472                           && voices[i].releaseTriggered == false) {
 1473                       voices[i].noteOff(0);
 1474                   }
 1475           }
 1476       }
 1477   
 1478       public void allSoundOff() {
 1479           if (current_mixer != null)
 1480               current_mixer.allSoundOff();
 1481           synchronized (control_mutex) {
 1482               for (int i = 0; i < voices.length; i++)
 1483                   if (voices[i].on && voices[i].channel == channel)
 1484                       voices[i].soundOff();
 1485           }
 1486       }
 1487   
 1488       public boolean localControl(boolean on) {
 1489           return false;
 1490       }
 1491   
 1492       public void setMono(boolean on) {
 1493           if (current_mixer != null)
 1494               current_mixer.setMono(on);
 1495           synchronized (control_mutex) {
 1496               allNotesOff();
 1497               mono = on;
 1498           }
 1499       }
 1500   
 1501       public boolean getMono() {
 1502           synchronized (control_mutex) {
 1503               return mono;
 1504           }
 1505       }
 1506   
 1507       public void setOmni(boolean on) {
 1508           if (current_mixer != null)
 1509               current_mixer.setOmni(on);
 1510           allNotesOff();
 1511       // Omni is not supported by GM2
 1512       }
 1513   
 1514       public boolean getOmni() {
 1515           return false;
 1516       }
 1517   
 1518       public void setMute(boolean mute) {
 1519           if (current_mixer != null)
 1520               current_mixer.setMute(mute);
 1521           synchronized (control_mutex) {
 1522               this.mute = mute;
 1523               for (int i = 0; i < voices.length; i++)
 1524                   if (voices[i].active && voices[i].channel == channel)
 1525                       voices[i].setMute(mute);
 1526           }
 1527       }
 1528   
 1529       public boolean getMute() {
 1530           synchronized (control_mutex) {
 1531               return mute;
 1532           }
 1533       }
 1534   
 1535       public void setSolo(boolean soloState) {
 1536           if (current_mixer != null)
 1537               current_mixer.setSolo(soloState);
 1538   
 1539           synchronized (control_mutex) {
 1540               this.solo = soloState;
 1541   
 1542               boolean soloinuse = false;
 1543               for (SoftChannel c : synthesizer.channels) {
 1544                   if (c.solo) {
 1545                       soloinuse = true;
 1546                       break;
 1547                   }
 1548               }
 1549   
 1550               if (!soloinuse) {
 1551                   for (SoftChannel c : synthesizer.channels)
 1552                       c.setSoloMute(false);
 1553                   return;
 1554               }
 1555   
 1556               for (SoftChannel c : synthesizer.channels)
 1557                   c.setSoloMute(!c.solo);
 1558   
 1559           }
 1560   
 1561       }
 1562   
 1563       private void setSoloMute(boolean mute) {
 1564           synchronized (control_mutex) {
 1565               if (solomute == mute)
 1566                   return;
 1567               this.solomute = mute;
 1568               for (int i = 0; i < voices.length; i++)
 1569                   if (voices[i].active && voices[i].channel == channel)
 1570                       voices[i].setSoloMute(solomute);
 1571           }
 1572       }
 1573   
 1574       public boolean getSolo() {
 1575           synchronized (control_mutex) {
 1576               return solo;
 1577           }
 1578       }
 1579   }

Save This Page
Home » openjdk-7 » com.sun.media » sound » [javadoc | source]