gt:                 ModelTransform mt = new ModelTransform() {
context: /*
   * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Sun designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Sun in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  package com.sun.media.sound;
  
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import javax.sound.midi.MidiChannel;
  import javax.sound.midi.Patch;
  
  
  
  /**
   * Software Synthesizer MIDI channel class.
   *
   * @author Karl Helgason
   */
  public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
  
      private static boolean[] dontResetControls = new boolean[128];
      static {
          for (int i = 0; i < dontResetControls.length; i++)
              dontResetControls[i] = false;
  
          dontResetControls[0] = true;   // Bank Select (MSB)
          dontResetControls[32] = true;  // Bank Select (LSB)
          dontResetControls[7] = true;   // Channel Volume (MSB)
          dontResetControls[8] = true;   // Balance (MSB)
          dontResetControls[10] = true;  // Pan (MSB)
          dontResetControls[11] = true;  // Expression (MSB)
          dontResetControls[91] = true;  // Effects 1 Depth (default: Reverb Send)
          dontResetControls[92] = true;  // Effects 2 Depth (default: Tremolo Depth)
          dontResetControls[93] = true;  // Effects 3 Depth (default: Chorus Send)
          dontResetControls[94] = true;  // Effects 4 Depth (default: Celeste [Detune] Depth)
          dontResetControls[95] = true;  // Effects 5 Depth (default: Phaser Depth)
          dontResetControls[70] = true;  // Sound Controller 1 (default: Sound Variation)
          dontResetControls[71] = true;  // Sound Controller 2 (default: Timbre / Harmonic Quality)
          dontResetControls[72] = true;  // Sound Controller 3 (default: Release Time)
          dontResetControls[73] = true;  // Sound Controller 4 (default: Attack Time)
          dontResetControls[74] = true;  // Sound Controller 5 (default: Brightness)
          dontResetControls[75] = true;  // Sound Controller 6 (GM2 default: Decay Time)
          dontResetControls[76] = true;  // Sound Controller 7 (GM2 default: Vibrato Rate)
          dontResetControls[77] = true;  // Sound Controller 8 (GM2 default: Vibrato Depth)
          dontResetControls[78] = true;  // Sound Controller 9 (GM2 default: Vibrato Delay)
          dontResetControls[79] = true;  // Sound Controller 10 (GM2 default: Undefined)
          dontResetControls[120] = true; // All Sound Off
          dontResetControls[121] = true; // Reset All Controllers
          dontResetControls[122] = true; // Local Control On/Off
          dontResetControls[123] = true; // All Notes Off
          dontResetControls[124] = true; // Omni Mode Off
          dontResetControls[125] = true; // Omni Mode On
          dontResetControls[126] = true; // Poly Mode Off
          dontResetControls[127] = true; // Poly Mode On
  
          dontResetControls[6] = true;   // Data Entry (MSB)
          dontResetControls[38] = true;  // Data Entry (LSB)
          dontResetControls[96] = true;  // Data Increment
          dontResetControls[97] = true;  // Data Decrement
          dontResetControls[98] = true;  // Non-Registered Parameter Number (LSB)
          dontResetControls[99] = true;  // Non-Registered Parameter Number(MSB)
          dontResetControls[100] = true; // RPN = Null
          dontResetControls[101] = true; // RPN = Null
  
      }
  
      private static final int RPN_NULL_VALUE = (127 << 7) + 127;
      private int rpn_control = RPN_NULL_VALUE;
      private int nrpn_control = RPN_NULL_VALUE;
      protected double portamento_time = 1; // keyschanges per control buffer time
      protected int[] portamento_lastnote = new int[128];
      protected int portamento_lastnote_ix = 0;
      private int portamento_control_note = -1;
      private boolean portamento = false;
      private boolean mono = false;
      private boolean mute = false;
      private boolean solo = false;
      private boolean solomute = false;
      private Object control_mutex;
      private int channel;
      private SoftVoice[] voices;
      private int bank;
      private int program;
      private SoftSynthesizer synthesizer;
      private SoftMainMixer mainmixer;
      private int[] polypressure = new int[128];
      private int channelpressure = 0;
      private int[] controller = new int[128];
      private int pitchbend;
      private double[] co_midi_pitch = new double[1];
      private double[] co_midi_channel_pressure = new double[1];
      protected SoftTuning tuning = new SoftTuning();
      protected int tuning_bank = 0;
      protected int tuning_program = 0;
      protected SoftInstrument current_instrument = null;
      protected ModelChannelMixer current_mixer = null;
      private ModelDirector current_director = null;
  
      // Controller Destination Settings
      protected int cds_control_number = -1;
      protected ModelConnectionBlock[] cds_control_connections = null;
      protected ModelConnectionBlock[] cds_channelpressure_connections = null;
      protected ModelConnectionBlock[] cds_polypressure_connections = null;
      protected boolean sustain = false;
      protected boolean[][] keybasedcontroller_active = null;
      protected double[][] keybasedcontroller_value = null;
  
      private class MidiControlObject implements SoftControl {
          double[] pitch = co_midi_pitch;
          double[] channel_pressure = co_midi_channel_pressure;
          double[] poly_pressure = new double[1];
  
          public double[] get(int instance, String name) {
              if (name == null)
                  return null;
              if (name.equals("pitch"))
                  return pitch;
              if (name.equals("channel_pressure"))
                  return channel_pressure;
              if (name.equals("poly_pressure"))
                  return poly_pressure;
              return null;
          }
      }
  
      private SoftControl[] co_midi = new SoftControl[128];
      {
          for (int i = 0; i < co_midi.length; i++) {
              co_midi[i] = new MidiControlObject();
          }
      }
  
      private double[][] co_midi_cc_cc = new double[128][1];
      private SoftControl co_midi_cc = new SoftControl() {
          double[][] cc = co_midi_cc_cc;
          public double[] get(int instance, String name) {
              if (name == null)
                  return null;
              return cc[Integer.parseInt(name)];
          }
      };
      Map<Integer, int[]> co_midi_rpn_rpn_i = new HashMap<Integer, int[]>();
      Map<Integer, double[]> co_midi_rpn_rpn = new HashMap<Integer, double[]>();
      private SoftControl co_midi_rpn = new SoftControl() {
          Map<Integer, double[]> rpn = co_midi_rpn_rpn;
          public double[] get(int instance, String name) {
              if (name == null)
                  return null;
              int iname = Integer.parseInt(name);
              double[] v = rpn.get(iname);
              if (v == null) {
                  v = new double[1];
                  rpn.put(iname, v);
              }
              return v;
          }
      };
      Map<Integer, int[]> co_midi_nrpn_nrpn_i = new HashMap<Integer, int[]>();
      Map<Integer, double[]> co_midi_nrpn_nrpn = new HashMap<Integer, double[]>();
      private SoftControl co_midi_nrpn = new SoftControl() {
          Map<Integer, double[]> nrpn = co_midi_nrpn_nrpn;
          public double[] get(int instance, String name) {
              if (name == null)
                  return null;
              int iname = Integer.parseInt(name);
              double[] v = nrpn.get(iname);
              if (v == null) {
                  v = new double[1];
                  nrpn.put(iname, v);
              }
              return v;
          }
      };
      
      private static int restrict7Bit(int value)
      {
          if(value < 0) return 0;
          if(value > 127) return 127;
          return value;
      }
      
      private static int restrict14Bit(int value)
      {
          if(value < 0) return 0;
          if(value > 16256) return 16256;
          return value;
      }
  
      public SoftChannel(SoftSynthesizer synth, int channel) {
          this.channel = channel;
          this.voices = synth.getVoices();
          this.synthesizer = synth;
          this.mainmixer = synth.getMainMixer();
          control_mutex = synth.control_mutex;
          resetAllControllers(true);
      }
  
      private int findFreeVoice(int x) {
          for (int i = x; i < voices.length; i++)
              if (!voices[i].active)
                  return i;
  
          // No free voice was found, we must steal one
  
          int vmode = synthesizer.getVoiceAllocationMode();
          if (vmode == 1) {
              // DLS Static Voice Allocation
  
              //  * priority ( 10, 1-9, 11-16)
              // Search for channel to steal from
              int steal_channel = channel;
              for (int j = 0; j < voices.length; j++) {
                  if (voices[j].stealer_channel == null) {
                      if (steal_channel == 9) {
                          steal_channel = voices[j].channel;
                      } else {
                          if (voices[j].channel != 9) {
                              if (voices[j].channel > steal_channel)
                                  steal_channel = voices[j].channel;
                          }
                      }
                  }
              }
  
              int voiceNo = -1;
  
              SoftVoice v = null;
              // Search for oldest voice in off state on steal_channel
              for (int j = 0; j < voices.length; j++) {
                  if (voices[j].channel == steal_channel) {
                      if (voices[j].stealer_channel == null && !voices[j].on) {
                          if (v == null) {
                              v = voices[j];
                              voiceNo = j;
                          }
                          if (voices[j].voiceID < v.voiceID) {
                              v = voices[j];
                              voiceNo = j;
                          }
                      }
                  }
              }
              // Search for oldest voice in on state on steal_channel
              if (voiceNo == -1) {
                  for (int j = 0; j < voices.length; j++) {
                      if (voices[j].channel == steal_channel) {
                          if (voices[j].stealer_channel == null) {
                              if (v == null) {
                                  v = voices[j];
                                  voiceNo = j;
                              }
                              if (voices[j].voiceID < v.voiceID) {
                                  v = voices[j];
                                  voiceNo = j;
                              }
                          }
                      }
                  }
              }
  
              return voiceNo;
  
          } else {
              // Default Voice Allocation
              //  * Find voice that is on
              //  	and Find voice which has lowest voiceID ( oldest voice)
              //  * Or find voice that is off
              //  	and Find voice which has lowest voiceID ( oldest voice)
  
              int voiceNo = -1;
  
              SoftVoice v = null;
              // Search for oldest voice in off state
              for (int j = 0; j < voices.length; j++) {
                  if (voices[j].stealer_channel == null && !voices[j].on) {
                      if (v == null) {
                          v = voices[j];
                          voiceNo = j;
                      }
                      if (voices[j].voiceID < v.voiceID) {
                          v = voices[j];
                          voiceNo = j;
                      }
                  }
              }
              // Search for oldest voice in on state
              if (voiceNo == -1) {
  
                  for (int j = 0; j < voices.length; j++) {
                      if (voices[j].stealer_channel == null) {
                          if (v == null) {
                              v = voices[j];
                              voiceNo = j;
                          }
                          if (voices[j].voiceID < v.voiceID) {
                              v = voices[j];
                              voiceNo = j;
                          }
                      }
                  }
              }
  
              return voiceNo;
          }
  
      }
  
      protected void initVoice(SoftVoice voice, SoftPerformer p, int voiceID,
              int noteNumber, int velocity, ModelConnectionBlock[] connectionBlocks,
              ModelChannelMixer channelmixer, boolean releaseTriggered) {
          if (voice.active) {
              // Voice is active , we must steal the voice
              voice.stealer_channel = this;
              voice.stealer_performer = p;
              voice.stealer_voiceID = voiceID;
              voice.stealer_noteNumber = noteNumber;
              voice.stealer_velocity = velocity;
              voice.stealer_extendedConnectionBlocks = connectionBlocks;
              voice.stealer_channelmixer = channelmixer;
              voice.stealer_releaseTriggered = releaseTriggered;
              for (int i = 0; i < voices.length; i++)
                  if (voices[i].active && voices[i].voiceID == voice.voiceID)
                      voices[i].soundOff();
              return;
          }
  
          voice.extendedConnectionBlocks = connectionBlocks;
          voice.channelmixer = channelmixer;
          voice.releaseTriggered = releaseTriggered;
          voice.voiceID = voiceID;
          voice.tuning = tuning;
          voice.exclusiveClass = p.exclusiveClass;
          voice.softchannel = this;
          voice.channel = channel;
          voice.bank = bank;
          voice.program = program;
          voice.instrument = current_instrument;
          voice.performer = p;
          voice.objects.clear();
          voice.objects.put("midi", co_midi[noteNumber]);
          voice.objects.put("midi_cc", co_midi_cc);
          voice.objects.put("midi_rpn", co_midi_rpn);
          voice.objects.put("midi_nrpn", co_midi_nrpn);
          voice.noteOn(noteNumber, velocity);
          voice.setMute(mute);
          voice.setSoloMute(solomute);
          if (releaseTriggered)
              return;
          if (portamento_control_note != -1) {
              voice.co_noteon_keynumber[0]
                      = (tuning.getTuning(portamento_control_note) / 100.0)
                      * (1f / 128f);
              voice.portamento = true;
              portamento_control_note = -1;
          } else if (portamento) {
              if (mono) {
                  if (portamento_lastnote[0] != -1) {
                      voice.co_noteon_keynumber[0]
                              = (tuning.getTuning(portamento_lastnote[0]) / 100.0)
                              * (1f / 128f);
                      voice.portamento = true;
                      portamento_control_note = -1;
                  }
                  portamento_lastnote[0] = noteNumber;
              } else {
                  if (portamento_lastnote_ix != 0) {
                      portamento_lastnote_ix--;
                      voice.co_noteon_keynumber[0]
                              = (tuning.getTuning(
                                      portamento_lastnote[portamento_lastnote_ix])
                                  / 100.0)
                              * (1f / 128f);
                      voice.portamento = true;
                  }
              }
          }
      }
  
      public void noteOn(int noteNumber, int velocity) {
          noteNumber = restrict7Bit(noteNumber);
          velocity = restrict7Bit(velocity);        
          noteOn_internal(noteNumber, velocity);
          if (current_mixer != null)
              current_mixer.noteOn(noteNumber, velocity);
      }
  
      private void noteOn_internal(int noteNumber, int velocity) {
  
          if (velocity == 0) {
              noteOff_internal(noteNumber, 64);
              return;
          }
  
          synchronized (control_mutex) {
              if (sustain) {
                  sustain = false;
                  for (int i = 0; i < voices.length; i++) {
                      if ((voices[i].sustain || voices[i].on)
                              && voices[i].channel == channel && voices[i].active
                              && voices[i].note == noteNumber) {
                          voices[i].sustain = false;
                          voices[i].on = true;
                          voices[i].noteOff(0);
                      }
                  }
                  sustain = true;
              }
  
              mainmixer.activity();
  
              if (mono) {
                  if (portamento) {
                      boolean n_found = false;
                      for (int i = 0; i < voices.length; i++) {
                          if (voices[i].on && voices[i].channel == channel
                                  && voices[i].active
                                  && voices[i].releaseTriggered == false) {
                              voices[i].portamento = true;
                              voices[i].setNote(noteNumber);
                              n_found = true;
                          }
                      }
                      if (n_found) {
                          portamento_lastnote[0] = noteNumber;
                          return;
                      }
                  }
  
                  if (portamento_control_note != -1) {
                      boolean n_found = false;
                      for (int i = 0; i < voices.length; i++) {
                          if (voices[i].on && voices[i].channel == channel
                                  && voices[i].active
                                  && voices[i].note == portamento_control_note
                                  && voices[i].releaseTriggered == false) {
                              voices[i].portamento = true;
                              voices[i].setNote(noteNumber);
                              n_found = true;
                          }
                      }
                      portamento_control_note = -1;
                      if (n_found)
                          return;
                  }
              }
  
              if (mono)
                  allNotesOff();
  
              if (current_instrument == null) {
                  current_instrument
                          = synthesizer.findInstrument(program, bank, channel);
                  if (current_instrument == null)
                      return;
                  if (current_mixer != null)
                      mainmixer.stopMixer(current_mixer);
                  current_mixer = current_instrument.getSourceInstrument()
                          .getChannelMixer(this, synthesizer.getFormat());
                  if (current_mixer != null)
                      mainmixer.registerMixer(current_mixer);
                  current_director = current_instrument.getDirector(this, this);
                  applyInstrumentCustomization();
              }
              prevVoiceID = synthesizer.voiceIDCounter++;
              firstVoice = true;
              voiceNo = 0;
  
              int tunedKey = (int)(Math.round(tuning.getTuning()[noteNumber]/100.0));
              play_noteNumber = noteNumber;
              play_velocity = velocity;
              play_releasetriggered = false;
              lastVelocity[noteNumber] = velocity;
              current_director.noteOn(tunedKey, velocity);
  
              /*
              SoftPerformer[] performers = current_instrument.getPerformers();
              for (int i = 0; i < performers.length; i++) {
                  SoftPerformer p = performers[i];
                  if (p.keyFrom <= tunedKey && p.keyTo >= tunedKey) {
                      if (p.velFrom <= velocity && p.velTo >= velocity) {
                          if (firstVoice) {
                              firstVoice = false;
                              if (p.exclusiveClass != 0) {
                                  int x = p.exclusiveClass;
                                  for (int j = 0; j < voices.length; j++) {
                                      if (voices[j].active
                                              && voices[j].channel == channel
                                              && voices[j].exclusiveClass == x) {
                                          if (!(p.selfNonExclusive
                                                  && voices[j].note == noteNumber))
                                              voices[j].shutdown();
                                      }
                                  }
                              }
                          }
                          voiceNo = findFreeVoice(voiceNo);
                          if (voiceNo == -1)
                              return;
                          initVoice(voices[voiceNo], p, prevVoiceID, noteNumber,
                                  velocity);
                      }
                  }
              }
              */
          }
      }
  
      public void noteOff(int noteNumber, int velocity) {
          noteNumber = restrict7Bit(noteNumber);
          velocity = restrict7Bit(velocity);        
          noteOff_internal(noteNumber, velocity);
  
          if (current_mixer != null)
              current_mixer.noteOff(noteNumber, velocity);
      }
  
      private void noteOff_internal(int noteNumber, int velocity) {
          synchronized (control_mutex) {
  
              if (!mono) {
                  if (portamento) {
                      if (portamento_lastnote_ix != 127) {
                          portamento_lastnote[portamento_lastnote_ix] = noteNumber;
                          portamento_lastnote_ix++;
                      }
                  }
              }
  
              mainmixer.activity();
              for (int i = 0; i < voices.length; i++) {
                  if (voices[i].on && voices[i].channel == channel
                          && voices[i].note == noteNumber
                          && voices[i].releaseTriggered == false) {
                      voices[i].noteOff(velocity);
                  }
              }
  
              // Try play back note-off triggered voices,
  
              if (current_instrument == null) {
                  current_instrument
                          = synthesizer.findInstrument(program, bank, channel);
                  if (current_instrument == null)
                      return;
                  if (current_mixer != null)
                      mainmixer.stopMixer(current_mixer);
                  current_mixer = current_instrument.getSourceInstrument()
                          .getChannelMixer(this, synthesizer.getFormat());
                  if (current_mixer != null)
                      mainmixer.registerMixer(current_mixer);
                  current_director = current_instrument.getDirector(this, this);
                  applyInstrumentCustomization();
  
              }
              prevVoiceID = synthesizer.voiceIDCounter++;
              firstVoice = true;
              voiceNo = 0;
  
              int tunedKey = (int)(Math.round(tuning.getTuning()[noteNumber]/100.0));
              play_noteNumber = noteNumber;
              play_velocity = lastVelocity[noteNumber];
              play_releasetriggered = true;
              current_director.noteOff(tunedKey, velocity);
  
          }
      }
      private int[] lastVelocity = new int[128];
      private int prevVoiceID;
      private boolean firstVoice = true;
      private int voiceNo = 0;
      private int play_noteNumber = 0;
      private int play_velocity = 0;
      private boolean play_releasetriggered = false;
  
      public void play(int performerIndex, ModelConnectionBlock[] connectionBlocks) {
  
          int noteNumber = play_noteNumber;
          int velocity = play_velocity;
          boolean releasetriggered = play_releasetriggered;
  
          SoftPerformer p = current_instrument.getPerformers()[performerIndex];
  
          if (firstVoice) {
              firstVoice = false;
              if (p.exclusiveClass != 0) {
                  int x = p.exclusiveClass;
                  for (int j = 0; j < voices.length; j++) {
                      if (voices[j].active && voices[j].channel == channel
                              && voices[j].exclusiveClass == x) {
                          if (!(p.selfNonExclusive && voices[j].note == noteNumber))
                              voices[j].shutdown();
                      }
                  }
              }
          }
  
          voiceNo = findFreeVoice(Math.max(voiceNo, 0));
  
          if (voiceNo == -1)
              return;
  
          initVoice(voices[voiceNo], p, prevVoiceID, noteNumber, velocity,
                  connectionBlocks, current_mixer, releasetriggered);
      }
  
      public void noteOff(int noteNumber) {
          if(noteNumber < 0 || noteNumber > 127) return;
          noteOff_internal(noteNumber, 64);
      }
  
      public void setPolyPressure(int noteNumber, int pressure) {
          noteNumber = restrict7Bit(noteNumber);
          pressure = restrict7Bit(pressure);        
  
          if (current_mixer != null)
              current_mixer.setPolyPressure(noteNumber, pressure);
  
          synchronized (control_mutex) {
              mainmixer.activity();
              co_midi[noteNumber].get(0, "poly_pressure")[0] = pressure*(1.0/128.0);
              polypressure[noteNumber] = pressure;
              for (int i = 0; i < voices.length; i++) {
                  if (voices[i].active && voices[i].note == noteNumber)
                      voices[i].setPolyPressure(pressure);
              }
          }
      }
  
      public int getPolyPressure(int noteNumber) {
          synchronized (control_mutex) {
              return polypressure[noteNumber];
          }
      }
  
      public void setChannelPressure(int pressure) {        
          pressure = restrict7Bit(pressure);                
          if (current_mixer != null)
              current_mixer.setChannelPressure(pressure);
          synchronized (control_mutex) {
              mainmixer.activity();
              co_midi_channel_pressure[0] = pressure * (1.0 / 128.0);
              channelpressure = pressure;
              for (int i = 0; i < voices.length; i++) {
                  if (voices[i].active)
                      voices[i].setChannelPressure(pressure);
              }
          }
      }
  
      public int getChannelPressure() {
          synchronized (control_mutex) {
              return channelpressure;
          }
      }
  
      protected void applyInstrumentCustomization() {
          if (cds_control_connections == null
                  && cds_channelpressure_connections == null
                  && cds_polypressure_connections == null) {
              return;
          }
  
          ModelInstrument src_instrument = current_instrument.getSourceInstrument();
          ModelPerformer[] performers = src_instrument.getPerformers();
          ModelPerformer[] new_performers = new ModelPerformer[performers.length];
          for (int i = 0; i < new_performers.length; i++) {
              ModelPerformer performer = performers[i];
              ModelPerformer new_performer = new ModelPerformer();
              new_performer.setName(performer.getName());
              new_performer.setExclusiveClass(performer.getExclusiveClass());
              new_performer.setKeyFrom(performer.getKeyFrom());
              new_performer.setKeyTo(performer.getKeyTo());
              new_performer.setVelFrom(performer.getVelFrom());
              new_performer.setVelTo(performer.getVelTo());
              new_performer.getOscillators().addAll(performer.getOscillators());
              new_performer.getConnectionBlocks().addAll(
                      performer.getConnectionBlocks());
              new_performers[i] = new_performer;
  
              List<ModelConnectionBlock> connblocks =
                      new_performer.getConnectionBlocks();
  
              if (cds_control_connections != null) {
                  String cc = Integer.toString(cds_control_number);
                  Iterator<ModelConnectionBlock> iter = connblocks.iterator();
                  while (iter.hasNext()) {
                      ModelConnectionBlock conn = iter.next();
                      ModelSource[] sources = conn.getSources();
                      boolean removeok = false;
                      if (sources != null) {
                          for (int j = 0; j < sources.length; j++) {
                              ModelSource src = sources[j];
                              if ("midi_cc".equals(src.getIdentifier().getObject())
                                      && cc.equals(src.getIdentifier().getVariable())) {
                                  removeok = true;
                              }
                          }
                      }
                      if (removeok)
                          iter.remove();
                  }
                  for (int j = 0; j < cds_control_connections.length; j++)
                      connblocks.add(cds_control_connections[j]);
              }
  
              if (cds_polypressure_connections != null) {
                  Iterator<ModelConnectionBlock> iter = connblocks.iterator();
                  while (iter.hasNext()) {
                      ModelConnectionBlock conn = iter.next();
                      ModelSource[] sources = conn.getSources();
                      boolean removeok = false;
                      if (sources != null) {
                          for (int j = 0; j < sources.length; j++) {
                              ModelSource src = sources[j];
                              if ("midi".equals(src.getIdentifier().getObject())
                                      && "poly_pressure".equals(
                                          src.getIdentifier().getVariable())) {
                                  removeok = true;
                              }
                          }
                      }
                      if (removeok)
                          iter.remove();
                  }
                  for (int j = 0; j < cds_polypressure_connections.length; j++)
                      connblocks.add(cds_polypressure_connections[j]);
              }
  
  
              if (cds_channelpressure_connections != null) {
                  Iterator<ModelConnectionBlock> iter = connblocks.iterator();
                  while (iter.hasNext()) {
                      ModelConnectionBlock conn = iter.next();
                      ModelSource[] sources = conn.getSources();
                      boolean removeok = false;
                      if (sources != null) {
                          for (int j = 0; j < sources.length; j++) {
                              ModelIdentifier srcid = sources[j].getIdentifier();
                              if ("midi".equals(srcid.getObject()) &&
                                      "channel_pressure".equals(srcid.getVariable())) {
                                  removeok = true;
                              }
                          }
                      }
                      if (removeok)
                          iter.remove();
                  }
                  for (int j = 0; j < cds_channelpressure_connections.length; j++)
                      connblocks.add(cds_channelpressure_connections[j]);
              }
  
          }
  
          current_instrument = new SoftInstrument(src_instrument, new_performers);
  
      }
  
      private ModelConnectionBlock[] createModelConnections(ModelIdentifier sid,
              int[] destination, int[] range) {
  
          /*
          controlled parameter (pp)|range (rr)| Description             |Default
          -------------------------|----------|-------------------------|-------
          00 Pitch Control         | 28H..58H | -24..+24 semitones      | 40H
          01 Filter Cutoff Control | 00H..7FH | -9600..+9450 cents      | 40H
          02 Amplitude Control     | 00H..7FH | 0..(127/64)*100 percent | 40H
          03 LFO Pitch Depth       | 00H..7FH | 0..600 cents            |  0
          04 LFO Filter Depth      | 00H..7FH | 0..2400 cents           |  0
          05 LFO Amplitude Depth   | 00H..7FH | 0..100 percent          |  0
          */
  
          List<ModelConnectionBlock> conns = new ArrayList<ModelConnectionBlock>();
  
          for (int i = 0; i < destination.length; i++) {
              int d = destination[i];
              int r = range[i];
              if (d == 0) {
                  double scale = (r - 64) * 100;
                  ModelConnectionBlock conn = new ModelConnectionBlock(
                          new ModelSource(sid,
                              ModelStandardTransform.DIRECTION_MIN2MAX,
                              ModelStandardTransform.POLARITY_UNIPOLAR,
                              ModelStandardTransform.TRANSFORM_LINEAR),
                          scale,
                          new ModelDestination(
                              new ModelIdentifier("osc", "pitch")));
                  conns.add(conn);
  
              }
              if (d == 1) {
                  double scale = (r / 64.0 - 1.0) * 9600.0;
                  ModelConnectionBlock conn;
                  if (scale > 0) {
                      conn = new ModelConnectionBlock(
                              new ModelSource(sid,
                                  ModelStandardTransform.DIRECTION_MAX2MIN,
                                  ModelStandardTransform.POLARITY_UNIPOLAR,
                                  ModelStandardTransform.TRANSFORM_LINEAR),
                              -scale,
                              new ModelDestination(
                                  ModelDestination.DESTINATION_FILTER_FREQ));
                  } else {
                      conn = new ModelConnectionBlock(
                              new ModelSource(sid,
                                  ModelStandardTransform.DIRECTION_MIN2MAX,
                                  ModelStandardTransform.POLARITY_UNIPOLAR,
                                  ModelStandardTransform.TRANSFORM_LINEAR),
                              scale,
                              new ModelDestination(
                                  ModelDestination.DESTINATION_FILTER_FREQ));
                  }
                  conns.add(conn);
              }
              if (d == 2) {
                  final double scale = (r / 64.0);
                  ModelTransform mt = new ModelTransform() {
                      double s = scale;
                      public double transform(double value) {
                          if (s < 1)
                              value = s + (value * (1.0 - s));
                          else if (s > 1)
                              value = 1 + (value * (s - 1.0));
                          else
                              return 0;
                          return -((5.0 / 12.0) / Math.log(10)) * Math.log(value);
                      }
                  };
  
                  ModelConnectionBlock conn = new ModelConnectionBlock(
                          new ModelSource(sid, mt), -960,
                          new ModelDestination(ModelDestination.DESTINATION_GAIN));
                  conns.add(conn);
  
              }
              if (d == 3) {
                  double scale = (r / 64.0 - 1.0) * 9600.0;
                  ModelConnectionBlock conn = new ModelConnectionBlock(
                          new ModelSource(ModelSource.SOURCE_LFO1,
                              ModelStandardTransform.DIRECTION_MIN2MAX,
                              ModelStandardTransform.POLARITY_BIPOLAR,
                              ModelStandardTransform.TRANSFORM_LINEAR),
                          new ModelSource(sid,
                              ModelStandardTransform.DIRECTION_MIN2MAX,
                              ModelStandardTransform.POLARITY_UNIPOLAR,
                              ModelStandardTransform.TRANSFORM_LINEAR),
                          scale,
                          new ModelDestination(
                              ModelDestination.DESTINATION_PITCH));
                  conns.add(conn);
              }
              if (d == 4) {
                  double scale = (r / 128.0) * 2400.0;
                  ModelConnectionBlock conn = new ModelConnectionBlock(
                          new ModelSource(ModelSource.SOURCE_LFO1,
                              ModelStandardTransform.DIRECTION_MIN2MAX,
                              ModelStandardTransform.POLARITY_BIPOLAR,
                              ModelStandardTransform.TRANSFORM_LINEAR),
                          new ModelSource(sid,
                              ModelStandardTransform.DIRECTION_MIN2MAX,
                              ModelStandardTransform.POLARITY_UNIPOLAR,
                              ModelStandardTransform.TRANSFORM_LINEAR),
                          scale,
                          new ModelDestination(
                              ModelDestination.DESTINATION_FILTER_FREQ));
                  conns.add(conn);
              }
              if (d == 5) {
                  final double scale = (r / 127.0);
  
  