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); // 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
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 }
--- EOF ---