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
get(int instance, String name)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 
restrict7Bit(int value)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 
restrict14Bit(int value)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 
SoftChannel(SoftSynthesizer synth, int channel)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 
findFreeVoice(int x)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 
initVoice(SoftVoice voice, SoftPerformer p, int voiceID, int noteNumber, int velocity, int delay, ModelConnectionBlock[] connectionBlocks, ModelChannelMixer channelmixer, boolean releaseTriggered)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
noteOn(int noteNumber, int velocity)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      */
noteOn(int noteNumber, int velocity, int delay)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 
noteOn_internal(int noteNumber, int velocity, int delay)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
noteOff(int noteNumber, int velocity)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 
noteOff_internal(int noteNumber, int velocity)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
play(int performerIndex, ModelConnectionBlock[] connectionBlocks)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
noteOff(int noteNumber)669     public void noteOff(int noteNumber) {
670         if(noteNumber < 0 || noteNumber > 127) return;
671         noteOff_internal(noteNumber, 64);
672     }
673 
674     @Override
setPolyPressure(int noteNumber, int pressure)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
getPolyPressure(int noteNumber)694     public int getPolyPressure(int noteNumber) {
695         synchronized (control_mutex) {
696             return polypressure[noteNumber];
697         }
698     }
699 
700     @Override
setChannelPressure(int pressure)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
getChannelPressure()717     public int getChannelPressure() {
718         synchronized (control_mutex) {
719             return channelpressure;
720         }
721     }
722 
applyInstrumentCustomization()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 
createModelConnections(ModelIdentifier sid, int[] destination, int[] range)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 
mapPolyPressureToDestination(int[] destination, int[] range)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 
mapChannelPressureToDestination(int[] destination, int[] range)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 
mapControlToDestination(int control, int[] destination, int[] range)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 
controlChangePerNote(int noteNumber, int controller, int value)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 
getControlPerNote(int noteNumber, int controller)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
controlChange(int controller, int value)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
getController(int controller)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 
tuningChange(int program)1269     public void tuningChange(int program) {
1270         tuningChange(0, program);
1271     }
1272 
tuningChange(int bank, int program)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
programChange(int program)1280     public void programChange(int program) {
1281         programChange(bank, program);
1282     }
1283 
1284     @Override
programChange(int bank, int program)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
getProgram()1300     public int getProgram() {
1301         synchronized (control_mutex) {
1302             return program;
1303         }
1304     }
1305 
1306     @Override
setPitchBend(int bend)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
getPitchBend()1322     public int getPitchBend() {
1323         synchronized (control_mutex) {
1324             return pitchbend;
1325         }
1326     }
1327 
nrpnChange(int controller, int value)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 
rpnChange(int controller, int value)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
resetAllControllers()1424     public void resetAllControllers() {
1425         resetAllControllers(false);
1426     }
1427 
resetAllControllers(boolean allControls)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);   // Pitch 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
allNotesOff()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
allSoundOff()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
localControl(boolean on)1514     public boolean localControl(boolean on) {
1515         return false;
1516     }
1517 
1518     @Override
setMono(boolean on)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
getMono()1529     public boolean getMono() {
1530         synchronized (control_mutex) {
1531             return mono;
1532         }
1533     }
1534 
1535     @Override
setOmni(boolean on)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
getOmni()1544     public boolean getOmni() {
1545         return false;
1546     }
1547 
1548     @Override
setMute(boolean mute)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
getMute()1561     public boolean getMute() {
1562         synchronized (control_mutex) {
1563             return mute;
1564         }
1565     }
1566 
1567     @Override
setSolo(boolean soloState)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 
setSoloMute(boolean mute)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
getSolo()1608     public boolean getSolo() {
1609         synchronized (control_mutex) {
1610             return solo;
1611         }
1612     }
1613 }
1614