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 package com.sun.media.sound; 26 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 import java.util.Comparator; 30 import java.util.HashMap; 31 import java.util.List; 32 import java.util.Map; 33 34 /** 35 * This class decodes information from ModelPeformer for use in SoftVoice. 36 * It also adds default connections if they where missing in ModelPerformer. 37 * 38 * @author Karl Helgason 39 */ 40 public final class SoftPerformer { 41 42 static ModelConnectionBlock[] defaultconnections 43 = new ModelConnectionBlock[42]; 44 45 static { 46 int o = 0; 47 defaultconnections[o++] = new ModelConnectionBlock( 48 new ModelSource( 49 new ModelIdentifier("noteon", "on", 0), 50 ModelStandardTransform.DIRECTION_MIN2MAX, 51 ModelStandardTransform.POLARITY_UNIPOLAR, 52 ModelStandardTransform.TRANSFORM_LINEAR), 53 1, new ModelDestination(new ModelIdentifier("eg", "on", 0))); 54 55 defaultconnections[o++] = new ModelConnectionBlock( 56 new ModelSource( 57 new ModelIdentifier("noteon", "on", 0), 58 ModelStandardTransform.DIRECTION_MIN2MAX, 59 ModelStandardTransform.POLARITY_UNIPOLAR, 60 ModelStandardTransform.TRANSFORM_LINEAR), 61 1, new ModelDestination(new ModelIdentifier("eg", "on", 1))); 62 63 defaultconnections[o++] = new ModelConnectionBlock( 64 new ModelSource( 65 new ModelIdentifier("eg", "active", 0), 66 ModelStandardTransform.DIRECTION_MIN2MAX, 67 ModelStandardTransform.POLARITY_UNIPOLAR, 68 ModelStandardTransform.TRANSFORM_LINEAR), 69 1, new ModelDestination(new ModelIdentifier("mixer", "active", 0))); 70 71 defaultconnections[o++] = new ModelConnectionBlock( 72 new ModelSource( 73 new ModelIdentifier("eg", 0), 74 ModelStandardTransform.DIRECTION_MAX2MIN, 75 ModelStandardTransform.POLARITY_UNIPOLAR, 76 ModelStandardTransform.TRANSFORM_LINEAR), 77 -960, new ModelDestination(new ModelIdentifier("mixer", "gain"))); 78 79 defaultconnections[o++] = new ModelConnectionBlock( 80 new ModelSource( 81 new ModelIdentifier("noteon", "velocity"), 82 ModelStandardTransform.DIRECTION_MAX2MIN, 83 ModelStandardTransform.POLARITY_UNIPOLAR, 84 ModelStandardTransform.TRANSFORM_CONCAVE), 85 -960, new ModelDestination(new ModelIdentifier("mixer", "gain"))); 86 87 defaultconnections[o++] = new ModelConnectionBlock( 88 new ModelSource( 89 new ModelIdentifier("midi", "pitch"), 90 ModelStandardTransform.DIRECTION_MIN2MAX, 91 ModelStandardTransform.POLARITY_BIPOLAR, 92 ModelStandardTransform.TRANSFORM_LINEAR), 93 new ModelSource(new ModelIdentifier("midi_rpn", "0"), 94 new ModelTransform() { 95 public double transform(double value) { 96 int v = (int) (value * 16384.0); 97 int msb = v >> 7; 98 int lsb = v & 127; 99 return msb * 100 + lsb; 100 } 101 }), 102 new ModelDestination(new ModelIdentifier("osc", "pitch"))); 103 104 defaultconnections[o++] = new ModelConnectionBlock( 105 new ModelSource( 106 new ModelIdentifier("noteon", "keynumber"), 107 ModelStandardTransform.DIRECTION_MIN2MAX, 108 ModelStandardTransform.POLARITY_UNIPOLAR, 109 ModelStandardTransform.TRANSFORM_LINEAR), 110 12800, new ModelDestination(new ModelIdentifier("osc", "pitch"))); 111 112 defaultconnections[o++] = new ModelConnectionBlock( 113 new ModelSource( 114 new ModelIdentifier("midi_cc", "7"), 115 ModelStandardTransform.DIRECTION_MAX2MIN, 116 ModelStandardTransform.POLARITY_UNIPOLAR, 117 ModelStandardTransform.TRANSFORM_CONCAVE), 118 -960, new ModelDestination(new ModelIdentifier("mixer", "gain"))); 119 120 defaultconnections[o++] = new ModelConnectionBlock( 121 new ModelSource( 122 new ModelIdentifier("midi_cc", "8"), 123 ModelStandardTransform.DIRECTION_MIN2MAX, 124 ModelStandardTransform.POLARITY_UNIPOLAR, 125 ModelStandardTransform.TRANSFORM_LINEAR), 126 1000, new ModelDestination(new ModelIdentifier("mixer", "balance"))); 127 128 defaultconnections[o++] = new ModelConnectionBlock( 129 new ModelSource( 130 new ModelIdentifier("midi_cc", "10"), 131 ModelStandardTransform.DIRECTION_MIN2MAX, 132 ModelStandardTransform.POLARITY_UNIPOLAR, 133 ModelStandardTransform.TRANSFORM_LINEAR), 134 1000, new ModelDestination(new ModelIdentifier("mixer", "pan"))); 135 136 defaultconnections[o++] = new ModelConnectionBlock( 137 new ModelSource( 138 new ModelIdentifier("midi_cc", "11"), 139 ModelStandardTransform.DIRECTION_MAX2MIN, 140 ModelStandardTransform.POLARITY_UNIPOLAR, 141 ModelStandardTransform.TRANSFORM_CONCAVE), 142 -960, new ModelDestination(new ModelIdentifier("mixer", "gain"))); 143 144 defaultconnections[o++] = new ModelConnectionBlock( 145 new ModelSource( 146 new ModelIdentifier("midi_cc", "91"), 147 ModelStandardTransform.DIRECTION_MIN2MAX, 148 ModelStandardTransform.POLARITY_UNIPOLAR, 149 ModelStandardTransform.TRANSFORM_LINEAR), 150 1000, new ModelDestination(new ModelIdentifier("mixer", "reverb"))); 151 152 defaultconnections[o++] = new ModelConnectionBlock( 153 new ModelSource( 154 new ModelIdentifier("midi_cc", "93"), 155 ModelStandardTransform.DIRECTION_MIN2MAX, 156 ModelStandardTransform.POLARITY_UNIPOLAR, 157 ModelStandardTransform.TRANSFORM_LINEAR), 158 1000, new ModelDestination(new ModelIdentifier("mixer", "chorus"))); 159 160 defaultconnections[o++] = new ModelConnectionBlock( 161 new ModelSource( 162 new ModelIdentifier("midi_cc", "71"), 163 ModelStandardTransform.DIRECTION_MIN2MAX, 164 ModelStandardTransform.POLARITY_BIPOLAR, 165 ModelStandardTransform.TRANSFORM_LINEAR), 166 200, new ModelDestination(new ModelIdentifier("filter", "q"))); 167 defaultconnections[o++] = new ModelConnectionBlock( 168 new ModelSource( 169 new ModelIdentifier("midi_cc", "74"), 170 ModelStandardTransform.DIRECTION_MIN2MAX, 171 ModelStandardTransform.POLARITY_BIPOLAR, 172 ModelStandardTransform.TRANSFORM_LINEAR), 173 9600, new ModelDestination(new ModelIdentifier("filter", "freq"))); 174 175 defaultconnections[o++] = new ModelConnectionBlock( 176 new ModelSource( 177 new ModelIdentifier("midi_cc", "72"), 178 ModelStandardTransform.DIRECTION_MIN2MAX, 179 ModelStandardTransform.POLARITY_BIPOLAR, 180 ModelStandardTransform.TRANSFORM_LINEAR), 181 6000, new ModelDestination(new ModelIdentifier("eg", "release2"))); 182 183 defaultconnections[o++] = new ModelConnectionBlock( 184 new ModelSource( 185 new ModelIdentifier("midi_cc", "73"), 186 ModelStandardTransform.DIRECTION_MIN2MAX, 187 ModelStandardTransform.POLARITY_BIPOLAR, 188 ModelStandardTransform.TRANSFORM_LINEAR), 189 2000, new ModelDestination(new ModelIdentifier("eg", "attack2"))); 190 191 defaultconnections[o++] = new ModelConnectionBlock( 192 new ModelSource( 193 new ModelIdentifier("midi_cc", "75"), 194 ModelStandardTransform.DIRECTION_MIN2MAX, 195 ModelStandardTransform.POLARITY_BIPOLAR, 196 ModelStandardTransform.TRANSFORM_LINEAR), 197 6000, new ModelDestination(new ModelIdentifier("eg", "decay2"))); 198 199 defaultconnections[o++] = new ModelConnectionBlock( 200 new ModelSource( 201 new ModelIdentifier("midi_cc", "67"), 202 ModelStandardTransform.DIRECTION_MIN2MAX, 203 ModelStandardTransform.POLARITY_UNIPOLAR, 204 ModelStandardTransform.TRANSFORM_SWITCH), 205 -50, new ModelDestination(ModelDestination.DESTINATION_GAIN)); 206 207 defaultconnections[o++] = new ModelConnectionBlock( 208 new ModelSource( 209 new ModelIdentifier("midi_cc", "67"), 210 ModelStandardTransform.DIRECTION_MIN2MAX, 211 ModelStandardTransform.POLARITY_UNIPOLAR, 212 ModelStandardTransform.TRANSFORM_SWITCH), 213 -2400, new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ)); 214 215 defaultconnections[o++] = new ModelConnectionBlock( 216 new ModelSource( 217 new ModelIdentifier("midi_rpn", "1"), 218 ModelStandardTransform.DIRECTION_MIN2MAX, 219 ModelStandardTransform.POLARITY_BIPOLAR, 220 ModelStandardTransform.TRANSFORM_LINEAR), 221 100, new ModelDestination(new ModelIdentifier("osc", "pitch"))); 222 223 defaultconnections[o++] = new ModelConnectionBlock( 224 new ModelSource( 225 new ModelIdentifier("midi_rpn", "2"), 226 ModelStandardTransform.DIRECTION_MIN2MAX, 227 ModelStandardTransform.POLARITY_BIPOLAR, 228 ModelStandardTransform.TRANSFORM_LINEAR), 229 12800, new ModelDestination(new ModelIdentifier("osc", "pitch"))); 230 231 defaultconnections[o++] = new ModelConnectionBlock( 232 new ModelSource( 233 new ModelIdentifier("master", "fine_tuning"), 234 ModelStandardTransform.DIRECTION_MIN2MAX, 235 ModelStandardTransform.POLARITY_BIPOLAR, 236 ModelStandardTransform.TRANSFORM_LINEAR), 237 100, new ModelDestination(new ModelIdentifier("osc", "pitch"))); 238 239 defaultconnections[o++] = new ModelConnectionBlock( 240 new ModelSource( 241 new ModelIdentifier("master", "coarse_tuning"), 242 ModelStandardTransform.DIRECTION_MIN2MAX, 243 ModelStandardTransform.POLARITY_BIPOLAR, 244 ModelStandardTransform.TRANSFORM_LINEAR), 245 12800, new ModelDestination(new ModelIdentifier("osc", "pitch"))); 246 247 defaultconnections[o++] = new ModelConnectionBlock(13500, 248 new ModelDestination(new ModelIdentifier("filter", "freq", 0))); 249 250 defaultconnections[o++] = new ModelConnectionBlock( 251 Float.NEGATIVE_INFINITY, new ModelDestination( 252 new ModelIdentifier("eg", "delay", 0))); 253 defaultconnections[o++] = new ModelConnectionBlock( 254 Float.NEGATIVE_INFINITY, new ModelDestination( 255 new ModelIdentifier("eg", "attack", 0))); 256 defaultconnections[o++] = new ModelConnectionBlock( 257 Float.NEGATIVE_INFINITY, new ModelDestination( 258 new ModelIdentifier("eg", "hold", 0))); 259 defaultconnections[o++] = new ModelConnectionBlock( 260 Float.NEGATIVE_INFINITY, new ModelDestination( 261 new ModelIdentifier("eg", "decay", 0))); 262 defaultconnections[o++] = new ModelConnectionBlock(1000, 263 new ModelDestination(new ModelIdentifier("eg", "sustain", 0))); 264 defaultconnections[o++] = new ModelConnectionBlock( 265 Float.NEGATIVE_INFINITY, new ModelDestination( 266 new ModelIdentifier("eg", "release", 0))); 267 defaultconnections[o++] = new ModelConnectionBlock(1200.0 268 * Math.log(0.015) / Math.log(2), new ModelDestination( 269 new ModelIdentifier("eg", "shutdown", 0))); // 15 msec default 270 271 defaultconnections[o++] = new ModelConnectionBlock( 272 Float.NEGATIVE_INFINITY, new ModelDestination( 273 new ModelIdentifier("eg", "delay", 1))); 274 defaultconnections[o++] = new ModelConnectionBlock( 275 Float.NEGATIVE_INFINITY, new ModelDestination( 276 new ModelIdentifier("eg", "attack", 1))); 277 defaultconnections[o++] = new ModelConnectionBlock( 278 Float.NEGATIVE_INFINITY, new ModelDestination( 279 new ModelIdentifier("eg", "hold", 1))); 280 defaultconnections[o++] = new ModelConnectionBlock( 281 Float.NEGATIVE_INFINITY, new ModelDestination( 282 new ModelIdentifier("eg", "decay", 1))); 283 defaultconnections[o++] = new ModelConnectionBlock(1000, 284 new ModelDestination(new ModelIdentifier("eg", "sustain", 1))); 285 defaultconnections[o++] = new ModelConnectionBlock( 286 Float.NEGATIVE_INFINITY, new ModelDestination( 287 new ModelIdentifier("eg", "release", 1))); 288 289 defaultconnections[o++] = new ModelConnectionBlock(-8.51318, 290 new ModelDestination(new ModelIdentifier("lfo", "freq", 0))); 291 defaultconnections[o++] = new ModelConnectionBlock( 292 Float.NEGATIVE_INFINITY, new ModelDestination( 293 new ModelIdentifier("lfo", "delay", 0))); 294 defaultconnections[o++] = new ModelConnectionBlock(-8.51318, 295 new ModelDestination(new ModelIdentifier("lfo", "freq", 1))); 296 defaultconnections[o++] = new ModelConnectionBlock( 297 Float.NEGATIVE_INFINITY, new ModelDestination( 298 new ModelIdentifier("lfo", "delay", 1))); 299 300 } 301 public int keyFrom = 0; 302 public int keyTo = 127; 303 public int velFrom = 0; 304 public int velTo = 127; 305 public int exclusiveClass = 0; 306 public boolean selfNonExclusive = false; 307 public boolean forcedVelocity = false; 308 public boolean forcedKeynumber = false; 309 public ModelPerformer performer; 310 public ModelConnectionBlock[] connections; 311 public ModelOscillator[] oscillators; 312 public Map<Integer, int[]> midi_rpn_connections = new HashMap<Integer, int[]>(); 313 public Map<Integer, int[]> midi_nrpn_connections = new HashMap<Integer, int[]>(); 314 public int[][] midi_ctrl_connections; 315 public int[][] midi_connections; 316 public int[] ctrl_connections; 317 private List<Integer> ctrl_connections_list = new ArrayList<Integer>(); 318 319 private static class KeySortComparator implements Comparator<ModelSource> { 320 321 public int compare(ModelSource o1, ModelSource o2) { 322 return o1.getIdentifier().toString().compareTo( 323 o2.getIdentifier().toString()); 324 } 325 } 326 private static KeySortComparator keySortComparator = new KeySortComparator(); 327 328 private String extractKeys(ModelConnectionBlock conn) { 329 StringBuilder sb = new StringBuilder(); 330 if (conn.getSources() != null) { 331 sb.append("["); 332 ModelSource[] srcs = conn.getSources(); 333 ModelSource[] srcs2 = new ModelSource[srcs.length]; 334 for (int i = 0; i < srcs.length; i++) 335 srcs2[i] = srcs[i]; 336 Arrays.sort(srcs2, keySortComparator); 337 for (int i = 0; i < srcs.length; i++) { 338 sb.append(srcs[i].getIdentifier()); 339 sb.append(";"); 340 } 341 sb.append("]"); 342 } 343 sb.append(";"); 344 if (conn.getDestination() != null) { 345 sb.append(conn.getDestination().getIdentifier()); 346 } 347 sb.append(";"); 348 return sb.toString(); 349 } 350 351 private void processSource(ModelSource src, int ix) { 352 ModelIdentifier id = src.getIdentifier(); 353 String o = id.getObject(); 354 if (o.equals("midi_cc")) 355 processMidiControlSource(src, ix); 356 else if (o.equals("midi_rpn")) 357 processMidiRpnSource(src, ix); 358 else if (o.equals("midi_nrpn")) 359 processMidiNrpnSource(src, ix); 360 else if (o.equals("midi")) 361 processMidiSource(src, ix); 362 else if (o.equals("noteon")) 363 processNoteOnSource(src, ix); 364 else if (o.equals("osc")) 365 return; 366 else if (o.equals("mixer")) 367 return; 368 else 369 ctrl_connections_list.add(ix); 370 } 371 372 private void processMidiControlSource(ModelSource src, int ix) { 373 String v = src.getIdentifier().getVariable(); 374 if (v == null) 375 return; 376 int c = Integer.parseInt(v); 377 if (midi_ctrl_connections[c] == null) 378 midi_ctrl_connections[c] = new int[]{ix}; 379 else { 380 int[] olda = midi_ctrl_connections[c]; 381 int[] newa = new int[olda.length + 1]; 382 for (int i = 0; i < olda.length; i++) 383 newa[i] = olda[i]; 384 newa[newa.length - 1] = ix; 385 midi_ctrl_connections[c] = newa; 386 } 387 } 388 389 private void processNoteOnSource(ModelSource src, int ix) { 390 String v = src.getIdentifier().getVariable(); 391 int c = -1; 392 if (v.equals("on")) 393 c = 3; 394 if (v.equals("keynumber")) 395 c = 4; 396 if (c == -1) 397 return; 398 if (midi_connections[c] == null) 399 midi_connections[c] = new int[]{ix}; 400 else { 401 int[] olda = midi_connections[c]; 402 int[] newa = new int[olda.length + 1]; 403 for (int i = 0; i < olda.length; i++) 404 newa[i] = olda[i]; 405 newa[newa.length - 1] = ix; 406 midi_connections[c] = newa; 407 } 408 } 409 410 private void processMidiSource(ModelSource src, int ix) { 411 String v = src.getIdentifier().getVariable(); 412 int c = -1; 413 if (v.equals("pitch")) 414 c = 0; 415 if (v.equals("channel_pressure")) 416 c = 1; 417 if (v.equals("poly_pressure")) 418 c = 2; 419 if (c == -1) 420 return; 421 if (midi_connections[c] == null) 422 midi_connections[c] = new int[]{ix}; 423 else { 424 int[] olda = midi_connections[c]; 425 int[] newa = new int[olda.length + 1]; 426 for (int i = 0; i < olda.length; i++) 427 newa[i] = olda[i]; 428 newa[newa.length - 1] = ix; 429 midi_connections[c] = newa; 430 } 431 } 432 433 private void processMidiRpnSource(ModelSource src, int ix) { 434 String v = src.getIdentifier().getVariable(); 435 if (v == null) 436 return; 437 int c = Integer.parseInt(v); 438 if (midi_rpn_connections.get(c) == null) 439 midi_rpn_connections.put(c, new int[]{ix}); 440 else { 441 int[] olda = midi_rpn_connections.get(c); 442 int[] newa = new int[olda.length + 1]; 443 for (int i = 0; i < olda.length; i++) 444 newa[i] = olda[i]; 445 newa[newa.length - 1] = ix; 446 midi_rpn_connections.put(c, newa); 447 } 448 } 449 450 private void processMidiNrpnSource(ModelSource src, int ix) { 451 String v = src.getIdentifier().getVariable(); 452 if (v == null) 453 return; 454 int c = Integer.parseInt(v); 455 if (midi_nrpn_connections.get(c) == null) 456 midi_nrpn_connections.put(c, new int[]{ix}); 457 else { 458 int[] olda = midi_nrpn_connections.get(c); 459 int[] newa = new int[olda.length + 1]; 460 for (int i = 0; i < olda.length; i++) 461 newa[i] = olda[i]; 462 newa[newa.length - 1] = ix; 463 midi_nrpn_connections.put(c, newa); 464 } 465 } 466 467 public SoftPerformer(ModelPerformer performer) { 468 this.performer = performer; 469 470 keyFrom = performer.getKeyFrom(); 471 keyTo = performer.getKeyTo(); 472 velFrom = performer.getVelFrom(); 473 velTo = performer.getVelTo(); 474 exclusiveClass = performer.getExclusiveClass(); 475 selfNonExclusive = performer.isSelfNonExclusive(); 476 477 Map<String, ModelConnectionBlock> connmap = new HashMap<String, ModelConnectionBlock>(); 478 479 List<ModelConnectionBlock> performer_connections = new ArrayList<ModelConnectionBlock>(); 480 performer_connections.addAll(performer.getConnectionBlocks()); 481 482 if (performer.isDefaultConnectionsEnabled()) { 483 484 // Add modulation depth range (RPN 5) to the modulation wheel (cc#1) 485 486 boolean isModulationWheelConectionFound = false; 487 for (int j = 0; j < performer_connections.size(); j++) { 488 ModelConnectionBlock connection = performer_connections.get(j); 489 ModelSource[] sources = connection.getSources(); 490 ModelDestination dest = connection.getDestination(); 491 boolean isModulationWheelConection = false; 492 if (dest != null && sources != null && sources.length > 1) { 493 for (int i = 0; i < sources.length; i++) { 494 // check if connection block has the source "modulation 495 // wheel cc#1" 496 if (sources[i].getIdentifier().getObject().equals( 497 "midi_cc")) { 498 if (sources[i].getIdentifier().getVariable() 499 .equals("1")) { 500 isModulationWheelConection = true; 501 isModulationWheelConectionFound = true; 502 break; 503 } 504 } 505 } 506 } 507 if (isModulationWheelConection) { 508 509 ModelConnectionBlock newconnection = new ModelConnectionBlock(); 510 newconnection.setSources(connection.getSources()); 511 newconnection.setDestination(connection.getDestination()); 512 newconnection.addSource(new ModelSource( 513 new ModelIdentifier("midi_rpn", "5"))); 514 newconnection.setScale(connection.getScale() * 256.0); 515 performer_connections.set(j, newconnection); 516 } 517 } 518 519 if (!isModulationWheelConectionFound) { 520 ModelConnectionBlock conn = new ModelConnectionBlock( 521 new ModelSource(ModelSource.SOURCE_LFO1, 522 ModelStandardTransform.DIRECTION_MIN2MAX, 523 ModelStandardTransform.POLARITY_BIPOLAR, 524 ModelStandardTransform.TRANSFORM_LINEAR), 525 new ModelSource(new ModelIdentifier("midi_cc", "1", 0), 526 ModelStandardTransform.DIRECTION_MIN2MAX, 527 ModelStandardTransform.POLARITY_UNIPOLAR, 528 ModelStandardTransform.TRANSFORM_LINEAR), 529 50, 530 new ModelDestination(ModelDestination.DESTINATION_PITCH)); 531 conn.addSource(new ModelSource(new ModelIdentifier("midi_rpn", 532 "5"))); 533 conn.setScale(conn.getScale() * 256.0); 534 performer_connections.add(conn); 535 536 } 537 538 // Let Aftertouch to behave just like modulation wheel (cc#1) 539 boolean channel_pressure_set = false; 540 boolean poly_pressure = false; 541 ModelConnectionBlock mod_cc_1_connection = null; 542 int mod_cc_1_connection_src_ix = 0; 543 544 for (ModelConnectionBlock connection : performer_connections) { 545 ModelSource[] sources = connection.getSources(); 546 ModelDestination dest = connection.getDestination(); 547 // if(dest != null && sources != null) 548 if (dest != null && sources != null) { 549 for (int i = 0; i < sources.length; i++) { 550 ModelIdentifier srcid = sources[i].getIdentifier(); 551 // check if connection block has the source "modulation 552 // wheel cc#1" 553 if (srcid.getObject().equals("midi_cc")) { 554 if (srcid.getVariable().equals("1")) { 555 mod_cc_1_connection = connection; 556 mod_cc_1_connection_src_ix = i; 557 } 558 } 559 // check if channel or poly pressure are already 560 // connected 561 if (srcid.getObject().equals("midi")) { 562 if (srcid.getVariable().equals("channel_pressure")) 563 channel_pressure_set = true; 564 if (srcid.getVariable().equals("poly_pressure")) 565 poly_pressure = true; 566 } 567 } 568 } 569 570 } 571 572 if (mod_cc_1_connection != null) { 573 if (!channel_pressure_set) { 574 ModelConnectionBlock mc = new ModelConnectionBlock(); 575 mc.setDestination(mod_cc_1_connection.getDestination()); 576 mc.setScale(mod_cc_1_connection.getScale()); 577 ModelSource[] src_list = mod_cc_1_connection.getSources(); 578 ModelSource[] src_list_new = new ModelSource[src_list.length]; 579 for (int i = 0; i < src_list_new.length; i++) 580 src_list_new[i] = src_list[i]; 581 src_list_new[mod_cc_1_connection_src_ix] = new ModelSource( 582 new ModelIdentifier("midi", "channel_pressure")); 583 mc.setSources(src_list_new); 584 connmap.put(extractKeys(mc), mc); 585 } 586 if (!poly_pressure) { 587 ModelConnectionBlock mc = new ModelConnectionBlock(); 588 mc.setDestination(mod_cc_1_connection.getDestination()); 589 mc.setScale(mod_cc_1_connection.getScale()); 590 ModelSource[] src_list = mod_cc_1_connection.getSources(); 591 ModelSource[] src_list_new = new ModelSource[src_list.length]; 592 for (int i = 0; i < src_list_new.length; i++) 593 src_list_new[i] = src_list[i]; 594 src_list_new[mod_cc_1_connection_src_ix] = new ModelSource( 595 new ModelIdentifier("midi", "poly_pressure")); 596 mc.setSources(src_list_new); 597 connmap.put(extractKeys(mc), mc); 598 } 599 } 600 601 // Enable Vibration Sound Controllers : 76, 77, 78 602 ModelConnectionBlock found_vib_connection = null; 603 for (ModelConnectionBlock connection : performer_connections) { 604 ModelSource[] sources = connection.getSources(); 605 if (sources.length != 0 606 && sources[0].getIdentifier().getObject().equals("lfo")) { 607 if (connection.getDestination().getIdentifier().equals( 608 ModelDestination.DESTINATION_PITCH)) { 609 if (found_vib_connection == null) 610 found_vib_connection = connection; 611 else { 612 if (found_vib_connection.getSources().length > sources.length) 613 found_vib_connection = connection; 614 else if (found_vib_connection.getSources()[0] 615 .getIdentifier().getInstance() < 1) { 616 if (found_vib_connection.getSources()[0] 617 .getIdentifier().getInstance() > 618 sources[0].getIdentifier().getInstance()) { 619 found_vib_connection = connection; 620 } 621 } 622 } 623 624 } 625 } 626 } 627 628 int instance = 1; 629 630 if (found_vib_connection != null) { 631 instance = found_vib_connection.getSources()[0].getIdentifier() 632 .getInstance(); 633 } 634 ModelConnectionBlock connection; 635 636 connection = new ModelConnectionBlock( 637 new ModelSource(new ModelIdentifier("midi_cc", "78"), 638 ModelStandardTransform.DIRECTION_MIN2MAX, 639 ModelStandardTransform.POLARITY_BIPOLAR, 640 ModelStandardTransform.TRANSFORM_LINEAR), 641 2000, new ModelDestination( 642 new ModelIdentifier("lfo", "delay2", instance))); 643 connmap.put(extractKeys(connection), connection); 644 645 final double scale = found_vib_connection == null ? 0 646 : found_vib_connection.getScale(); 647 connection = new ModelConnectionBlock( 648 new ModelSource(new ModelIdentifier("lfo", instance)), 649 new ModelSource(new ModelIdentifier("midi_cc", "77"), 650 new ModelTransform() { 651 double s = scale; 652 public double transform(double value) { 653 value = value * 2 - 1; 654 value *= 600; 655 if (s == 0) { 656 return value; 657 } else if (s > 0) { 658 if (value < -s) 659 value = -s; 660 return value; 661 } else { 662 if (value < s) 663 value = -s; 664 return -value; 665 } 666 } 667 }), new ModelDestination(ModelDestination.DESTINATION_PITCH)); 668 connmap.put(extractKeys(connection), connection); 669 670 connection = new ModelConnectionBlock( 671 new ModelSource(new ModelIdentifier("midi_cc", "76"), 672 ModelStandardTransform.DIRECTION_MIN2MAX, 673 ModelStandardTransform.POLARITY_BIPOLAR, 674 ModelStandardTransform.TRANSFORM_LINEAR), 675 2400, new ModelDestination( 676 new ModelIdentifier("lfo", "freq", instance))); 677 connmap.put(extractKeys(connection), connection); 678 679 } 680 681 // Add default connection blocks 682 if (performer.isDefaultConnectionsEnabled()) 683 for (ModelConnectionBlock connection : defaultconnections) 684 connmap.put(extractKeys(connection), connection); 685 // Add connection blocks from modelperformer 686 for (ModelConnectionBlock connection : performer_connections) 687 connmap.put(extractKeys(connection), connection); 688 // seperate connection blocks : Init time, Midi Time, Midi/Control Time, 689 // Control Time 690 List<ModelConnectionBlock> connections = new ArrayList<ModelConnectionBlock>(); 691 692 midi_ctrl_connections = new int[128][]; 693 for (int i = 0; i < midi_ctrl_connections.length; i++) { 694 midi_ctrl_connections[i] = null; 695 } 696 midi_connections = new int[5][]; 697 for (int i = 0; i < midi_connections.length; i++) { 698 midi_connections[i] = null; 699 } 700 701 int ix = 0; 702 boolean mustBeOnTop = false; 703 704 for (ModelConnectionBlock connection : connmap.values()) { 705 if (connection.getDestination() != null) { 706 ModelDestination dest = connection.getDestination(); 707 ModelIdentifier id = dest.getIdentifier(); 708 if (id.getObject().equals("noteon")) { 709 mustBeOnTop = true; 710 if (id.getVariable().equals("keynumber")) 711 forcedKeynumber = true; 712 if (id.getVariable().equals("velocity")) 713 forcedVelocity = true; 714 } 715 } 716 if (mustBeOnTop) { 717 connections.add(0, connection); 718 mustBeOnTop = false; 719 } else 720 connections.add(connection); 721 } 722 723 for (ModelConnectionBlock connection : connections) { 724 if (connection.getSources() != null) { 725 ModelSource[] srcs = connection.getSources(); 726 for (int i = 0; i < srcs.length; i++) { 727 processSource(srcs[i], ix); 728 } 729 } 730 ix++; 731 } 732 733 this.connections = new ModelConnectionBlock[connections.size()]; 734 connections.toArray(this.connections); 735 736 this.ctrl_connections = new int[ctrl_connections_list.size()]; 737 738 for (int i = 0; i < this.ctrl_connections.length; i++) 739 this.ctrl_connections[i] = ctrl_connections_list.get(i); 740 741 oscillators = new ModelOscillator[performer.getOscillators().size()]; 742 performer.getOscillators().toArray(oscillators); 743 744 for (ModelConnectionBlock conn : connections) { 745 if (conn.getDestination() != null) { 746 if (isUnnecessaryTransform(conn.getDestination().getTransform())) { 747 conn.getDestination().setTransform(null); 748 } 749 } 750 if (conn.getSources() != null) { 751 for (ModelSource src : conn.getSources()) { 752 if (isUnnecessaryTransform(src.getTransform())) { 753 src.setTransform(null); 754 } 755 } 756 } 757 } 758 759 } 760 761 private static boolean isUnnecessaryTransform(ModelTransform transform) { 762 if (transform == null) 763 return false; 764 if (!(transform instanceof ModelStandardTransform)) 765 return false; 766 ModelStandardTransform stransform = (ModelStandardTransform)transform; 767 if (stransform.getDirection() != ModelStandardTransform.DIRECTION_MIN2MAX) 768 return false; 769 if (stransform.getPolarity() != ModelStandardTransform.POLARITY_UNIPOLAR) 770 return false; 771 if (stransform.getTransform() != ModelStandardTransform.TRANSFORM_LINEAR) 772 return false; 773 return false; 774 } 775 }