1 /* 2 * Copyright (c) 2010, 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.Arrays; 29 30 /** 31 * A standard indexed director who chooses performers 32 * by there keyfrom,keyto,velfrom,velto properties. 33 * 34 * @author Karl Helgason 35 */ 36 public final class ModelStandardIndexedDirector implements ModelDirector { 37 38 private final ModelPerformer[] performers; 39 private final ModelDirectedPlayer player; 40 private boolean noteOnUsed = false; 41 private boolean noteOffUsed = false; 42 43 // Variables needed for index 44 private byte[][] trantables; 45 private int[] counters; 46 private int[][] mat; 47 ModelStandardIndexedDirector(final ModelPerformer[] performers, final ModelDirectedPlayer player)48 public ModelStandardIndexedDirector(final ModelPerformer[] performers, 49 final ModelDirectedPlayer player) { 50 this.performers = Arrays.copyOf(performers, performers.length); 51 this.player = player; 52 for (final ModelPerformer p : this.performers) { 53 if (p.isReleaseTriggered()) { 54 noteOffUsed = true; 55 } else { 56 noteOnUsed = true; 57 } 58 } 59 buildindex(); 60 } 61 lookupIndex(int x, int y)62 private int[] lookupIndex(int x, int y) { 63 if ((x >= 0) && (x < 128) && (y >= 0) && (y < 128)) { 64 int xt = trantables[0][x]; 65 int yt = trantables[1][y]; 66 if (xt != -1 && yt != -1) { 67 return mat[xt + yt * counters[0]]; 68 } 69 } 70 return null; 71 } 72 restrict(int value)73 private int restrict(int value) { 74 if(value < 0) return 0; 75 if(value > 127) return 127; 76 return value; 77 } 78 buildindex()79 private void buildindex() { 80 trantables = new byte[2][129]; 81 counters = new int[trantables.length]; 82 for (ModelPerformer performer : performers) { 83 int keyFrom = performer.getKeyFrom(); 84 int keyTo = performer.getKeyTo(); 85 int velFrom = performer.getVelFrom(); 86 int velTo = performer.getVelTo(); 87 if (keyFrom > keyTo) continue; 88 if (velFrom > velTo) continue; 89 keyFrom = restrict(keyFrom); 90 keyTo = restrict(keyTo); 91 velFrom = restrict(velFrom); 92 velTo = restrict(velTo); 93 trantables[0][keyFrom] = 1; 94 trantables[0][keyTo + 1] = 1; 95 trantables[1][velFrom] = 1; 96 trantables[1][velTo + 1] = 1; 97 } 98 for (int d = 0; d < trantables.length; d++) { 99 byte[] trantable = trantables[d]; 100 int transize = trantable.length; 101 for (int i = transize - 1; i >= 0; i--) { 102 if (trantable[i] == 1) { 103 trantable[i] = -1; 104 break; 105 } 106 trantable[i] = -1; 107 } 108 int counter = -1; 109 for (int i = 0; i < transize; i++) { 110 if (trantable[i] != 0) { 111 counter++; 112 if (trantable[i] == -1) 113 break; 114 } 115 trantable[i] = (byte) counter; 116 } 117 counters[d] = counter; 118 } 119 mat = new int[counters[0] * counters[1]][]; 120 int ix = 0; 121 for (ModelPerformer performer : performers) { 122 int keyFrom = performer.getKeyFrom(); 123 int keyTo = performer.getKeyTo(); 124 int velFrom = performer.getVelFrom(); 125 int velTo = performer.getVelTo(); 126 if (keyFrom > keyTo) continue; 127 if (velFrom > velTo) continue; 128 keyFrom = restrict(keyFrom); 129 keyTo = restrict(keyTo); 130 velFrom = restrict(velFrom); 131 velTo = restrict(velTo); 132 int x_from = trantables[0][keyFrom]; 133 int x_to = trantables[0][keyTo + 1]; 134 int y_from = trantables[1][velFrom]; 135 int y_to = trantables[1][velTo + 1]; 136 if (x_to == -1) 137 x_to = counters[0]; 138 if (y_to == -1) 139 y_to = counters[1]; 140 for (int y = y_from; y < y_to; y++) { 141 int i = x_from + y * counters[0]; 142 for (int x = x_from; x < x_to; x++) { 143 int[] mprev = mat[i]; 144 if (mprev == null) { 145 mat[i] = new int[] { ix }; 146 } else { 147 int[] mnew = new int[mprev.length + 1]; 148 mnew[mnew.length - 1] = ix; 149 for (int k = 0; k < mprev.length; k++) 150 mnew[k] = mprev[k]; 151 mat[i] = mnew; 152 } 153 i++; 154 } 155 } 156 ix++; 157 } 158 } 159 160 @Override close()161 public void close() { 162 } 163 164 @Override noteOff(int noteNumber, int velocity)165 public void noteOff(int noteNumber, int velocity) { 166 if (!noteOffUsed) 167 return; 168 int[] plist = lookupIndex(noteNumber, velocity); 169 if(plist == null) return; 170 for (int i : plist) { 171 ModelPerformer p = performers[i]; 172 if (p.isReleaseTriggered()) { 173 player.play(i, null); 174 } 175 } 176 } 177 178 @Override noteOn(int noteNumber, int velocity)179 public void noteOn(int noteNumber, int velocity) { 180 if (!noteOnUsed) 181 return; 182 int[] plist = lookupIndex(noteNumber, velocity); 183 if(plist == null) return; 184 for (int i : plist) { 185 ModelPerformer p = performers[i]; 186 if (!p.isReleaseTriggered()) { 187 player.play(i, null); 188 } 189 } 190 } 191 } 192