< prev index next >

src/java.desktop/share/classes/com/sun/media/sound/SoftPerformer.java

Print this page




   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 


  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"),


 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         }


 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")) {


 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"))




   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.Comparator;
  31 import java.util.HashMap;
  32 import java.util.List;
  33 import java.util.Map;
  34 
  35 /**
  36  * This class decodes information from ModelPeformer for use in SoftVoice.
  37  * It also adds default connections if they where missing in ModelPerformer.
  38  *
  39  * @author Karl Helgason
  40  */
  41 public final class SoftPerformer {
  42 
  43     static ModelConnectionBlock[] defaultconnections
  44             = new ModelConnectionBlock[42];
  45 


  76                 ModelStandardTransform.POLARITY_UNIPOLAR,
  77                 ModelStandardTransform.TRANSFORM_LINEAR),
  78             -960, new ModelDestination(new ModelIdentifier("mixer", "gain")));
  79 
  80         defaultconnections[o++] = new ModelConnectionBlock(
  81             new ModelSource(
  82                 new ModelIdentifier("noteon", "velocity"),
  83                 ModelStandardTransform.DIRECTION_MAX2MIN,
  84                 ModelStandardTransform.POLARITY_UNIPOLAR,
  85                 ModelStandardTransform.TRANSFORM_CONCAVE),
  86             -960, new ModelDestination(new ModelIdentifier("mixer", "gain")));
  87 
  88         defaultconnections[o++] = new ModelConnectionBlock(
  89             new ModelSource(
  90                 new ModelIdentifier("midi", "pitch"),
  91                 ModelStandardTransform.DIRECTION_MIN2MAX,
  92                 ModelStandardTransform.POLARITY_BIPOLAR,
  93                 ModelStandardTransform.TRANSFORM_LINEAR),
  94             new ModelSource(new ModelIdentifier("midi_rpn", "0"),
  95                 new ModelTransform() {
  96                     @Override
  97                     public double transform(double value) {
  98                         int v = (int) (value * 16384.0);
  99                         int msb = v >> 7;
 100                         int lsb = v & 127;
 101                         return msb * 100 + lsb;
 102                     }
 103                 }),
 104             new ModelDestination(new ModelIdentifier("osc", "pitch")));
 105 
 106         defaultconnections[o++] = new ModelConnectionBlock(
 107             new ModelSource(
 108                 new ModelIdentifier("noteon", "keynumber"),
 109                 ModelStandardTransform.DIRECTION_MIN2MAX,
 110                 ModelStandardTransform.POLARITY_UNIPOLAR,
 111                 ModelStandardTransform.TRANSFORM_LINEAR),
 112             12800, new ModelDestination(new ModelIdentifier("osc", "pitch")));
 113 
 114         defaultconnections[o++] = new ModelConnectionBlock(
 115             new ModelSource(
 116                 new ModelIdentifier("midi_cc", "7"),


 294                 Float.NEGATIVE_INFINITY, new ModelDestination(
 295                 new ModelIdentifier("lfo", "delay", 0)));
 296         defaultconnections[o++] = new ModelConnectionBlock(-8.51318,
 297                 new ModelDestination(new ModelIdentifier("lfo", "freq", 1)));
 298         defaultconnections[o++] = new ModelConnectionBlock(
 299                 Float.NEGATIVE_INFINITY, new ModelDestination(
 300                 new ModelIdentifier("lfo", "delay", 1)));
 301 
 302     }
 303     public int keyFrom = 0;
 304     public int keyTo = 127;
 305     public int velFrom = 0;
 306     public int velTo = 127;
 307     public int exclusiveClass = 0;
 308     public boolean selfNonExclusive = false;
 309     public boolean forcedVelocity = false;
 310     public boolean forcedKeynumber = false;
 311     public ModelPerformer performer;
 312     public ModelConnectionBlock[] connections;
 313     public ModelOscillator[] oscillators;
 314     public Map<Integer, int[]> midi_rpn_connections = new HashMap<>();
 315     public Map<Integer, int[]> midi_nrpn_connections = new HashMap<>();
 316     public int[][] midi_ctrl_connections;
 317     public int[][] midi_connections;
 318     public int[] ctrl_connections;
 319     private final List<Integer> ctrl_connections_list = new ArrayList<>();
 320 
 321     private static class KeySortComparator implements Comparator<ModelSource> {
 322 
 323         @Override
 324         public int compare(ModelSource o1, ModelSource o2) {
 325             return o1.getIdentifier().toString().compareTo(
 326                     o2.getIdentifier().toString());
 327         }
 328     }
 329     private static final KeySortComparator keySortComparator = new KeySortComparator();
 330 
 331     private String extractKeys(ModelConnectionBlock conn) {
 332         StringBuilder sb = new StringBuilder();
 333         if (conn.getSources() != null) {
 334             sb.append("[");
 335             ModelSource[] srcs = conn.getSources();
 336             ModelSource[] srcs2 = new ModelSource[srcs.length];
 337             for (int i = 0; i < srcs.length; i++)
 338                 srcs2[i] = srcs[i];
 339             Arrays.sort(srcs2, keySortComparator);
 340             for (int i = 0; i < srcs.length; i++) {
 341                 sb.append(srcs[i].getIdentifier());
 342                 sb.append(";");
 343             }
 344             sb.append("]");
 345         }
 346         sb.append(";");
 347         if (conn.getDestination() != null) {
 348             sb.append(conn.getDestination().getIdentifier());
 349         }


 460         else {
 461             int[] olda = midi_nrpn_connections.get(c);
 462             int[] newa = new int[olda.length + 1];
 463             for (int i = 0; i < olda.length; i++)
 464                 newa[i] = olda[i];
 465             newa[newa.length - 1] = ix;
 466             midi_nrpn_connections.put(c, newa);
 467         }
 468     }
 469 
 470     public SoftPerformer(ModelPerformer performer) {
 471         this.performer = performer;
 472 
 473         keyFrom = performer.getKeyFrom();
 474         keyTo = performer.getKeyTo();
 475         velFrom = performer.getVelFrom();
 476         velTo = performer.getVelTo();
 477         exclusiveClass = performer.getExclusiveClass();
 478         selfNonExclusive = performer.isSelfNonExclusive();
 479 
 480         Map<String, ModelConnectionBlock> connmap = new HashMap<>();
 481 
 482         List<ModelConnectionBlock> performer_connections = new ArrayList<>();
 483         performer_connections.addAll(performer.getConnectionBlocks());
 484 
 485         if (performer.isDefaultConnectionsEnabled()) {
 486 
 487             // Add modulation depth range (RPN 5) to the modulation wheel (cc#1)
 488 
 489             boolean isModulationWheelConectionFound = false;
 490             for (int j = 0; j < performer_connections.size(); j++) {
 491                 ModelConnectionBlock connection = performer_connections.get(j);
 492                 ModelSource[] sources = connection.getSources();
 493                 ModelDestination dest = connection.getDestination();
 494                 boolean isModulationWheelConection = false;
 495                 if (dest != null && sources != null && sources.length > 1) {
 496                     for (int i = 0; i < sources.length; i++) {
 497                         // check if connection block has the source "modulation
 498                         // wheel cc#1"
 499                         if (sources[i].getIdentifier().getObject().equals(
 500                                 "midi_cc")) {
 501                             if (sources[i].getIdentifier().getVariable()
 502                                     .equals("1")) {


 635                         .getInstance();
 636             }
 637             ModelConnectionBlock connection;
 638 
 639             connection = new ModelConnectionBlock(
 640                 new ModelSource(new ModelIdentifier("midi_cc", "78"),
 641                     ModelStandardTransform.DIRECTION_MIN2MAX,
 642                     ModelStandardTransform.POLARITY_BIPOLAR,
 643                     ModelStandardTransform.TRANSFORM_LINEAR),
 644                 2000, new ModelDestination(
 645                     new ModelIdentifier("lfo", "delay2", instance)));
 646             connmap.put(extractKeys(connection), connection);
 647 
 648             final double scale = found_vib_connection == null ? 0
 649                     : found_vib_connection.getScale();
 650             connection = new ModelConnectionBlock(
 651                 new ModelSource(new ModelIdentifier("lfo", instance)),
 652                 new ModelSource(new ModelIdentifier("midi_cc", "77"),
 653                     new ModelTransform() {
 654                         double s = scale;
 655                         @Override
 656                         public double transform(double value) {
 657                             value = value * 2 - 1;
 658                             value *= 600;
 659                             if (s == 0) {
 660                                 return value;
 661                             } else if (s > 0) {
 662                                 if (value < -s)
 663                                     value = -s;
 664                                 return value;
 665                             } else {
 666                                 if (value < s)
 667                                     value = -s;
 668                                 return -value;
 669                             }
 670                         }
 671                     }), new ModelDestination(ModelDestination.DESTINATION_PITCH));
 672             connmap.put(extractKeys(connection), connection);
 673 
 674             connection = new ModelConnectionBlock(
 675                 new ModelSource(new ModelIdentifier("midi_cc", "76"),
 676                     ModelStandardTransform.DIRECTION_MIN2MAX,
 677                     ModelStandardTransform.POLARITY_BIPOLAR,
 678                     ModelStandardTransform.TRANSFORM_LINEAR),
 679                 2400, new ModelDestination(
 680                     new ModelIdentifier("lfo", "freq", instance)));
 681             connmap.put(extractKeys(connection), connection);
 682 
 683         }
 684 
 685         // Add default connection blocks
 686         if (performer.isDefaultConnectionsEnabled())
 687             for (ModelConnectionBlock connection : defaultconnections)
 688                 connmap.put(extractKeys(connection), connection);
 689         // Add connection blocks from modelperformer
 690         for (ModelConnectionBlock connection : performer_connections)
 691             connmap.put(extractKeys(connection), connection);
 692         // seperate connection blocks : Init time, Midi Time, Midi/Control Time,
 693         // Control Time
 694         List<ModelConnectionBlock> connections = new ArrayList<>();
 695 
 696         midi_ctrl_connections = new int[128][];
 697         for (int i = 0; i < midi_ctrl_connections.length; i++) {
 698             midi_ctrl_connections[i] = null;
 699         }
 700         midi_connections = new int[5][];
 701         for (int i = 0; i < midi_connections.length; i++) {
 702             midi_connections[i] = null;
 703         }
 704 
 705         int ix = 0;
 706         boolean mustBeOnTop = false;
 707 
 708         for (ModelConnectionBlock connection : connmap.values()) {
 709             if (connection.getDestination() != null) {
 710                 ModelDestination dest = connection.getDestination();
 711                 ModelIdentifier id = dest.getIdentifier();
 712                 if (id.getObject().equals("noteon")) {
 713                     mustBeOnTop = true;
 714                     if (id.getVariable().equals("keynumber"))


< prev index next >