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