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.HashMap; 30 import java.util.List; 31 import java.util.Map; 32 33 import javax.sound.midi.Patch; 34 35 /** 36 * This class is used to store information to describe instrument. 37 * It contains list of regions and modulators. 38 * It is stored inside a "ins " List Chunk inside DLS files. 39 * In the DLS documentation a modulator is called articulator. 40 * 41 * @author Karl Helgason 42 */ 43 public final class DLSInstrument extends ModelInstrument { 44 45 int preset = 0; 46 int bank = 0; 47 boolean druminstrument = false; 48 byte[] guid = null; 49 DLSInfo info = new DLSInfo(); 50 List<DLSRegion> regions = new ArrayList<DLSRegion>(); 51 List<DLSModulator> modulators = new ArrayList<DLSModulator>(); 52 53 public DLSInstrument() { 54 super(null, null, null, null); 55 } 56 57 public DLSInstrument(DLSSoundbank soundbank) { 58 super(soundbank, null, null, null); 59 } 60 61 public DLSInfo getInfo() { 62 return info; 63 } 64 65 public String getName() { 66 return info.name; 67 } 68 69 public void setName(String name) { 70 info.name = name; 71 } 72 73 public ModelPatch getPatch() { 74 return new ModelPatch(bank, preset, druminstrument); 75 } 76 77 public void setPatch(Patch patch) { 78 if (patch instanceof ModelPatch && ((ModelPatch)patch).isPercussion()) { 79 druminstrument = true; 80 bank = patch.getBank(); 81 preset = patch.getProgram(); 82 } else { 83 druminstrument = false; 84 bank = patch.getBank(); 85 preset = patch.getProgram(); 86 } 87 } 88 89 public Object getData() { 90 return null; 91 } 92 93 public List<DLSRegion> getRegions() { 94 return regions; 95 } 96 97 public List<DLSModulator> getModulators() { 98 return modulators; 99 } 100 101 public String toString() { 102 if (druminstrument) 103 return "Drumkit: " + info.name 104 + " bank #" + bank + " preset #" + preset; 105 else 106 return "Instrument: " + info.name 107 + " bank #" + bank + " preset #" + preset; 108 } 109 110 private ModelIdentifier convertToModelDest(int dest) { 111 if (dest == DLSModulator.CONN_DST_NONE) 112 return null; 113 if (dest == DLSModulator.CONN_DST_GAIN) 114 return ModelDestination.DESTINATION_GAIN; 115 if (dest == DLSModulator.CONN_DST_PITCH) 116 return ModelDestination.DESTINATION_PITCH; 117 if (dest == DLSModulator.CONN_DST_PAN) 118 return ModelDestination.DESTINATION_PAN; 119 120 if (dest == DLSModulator.CONN_DST_LFO_FREQUENCY) 121 return ModelDestination.DESTINATION_LFO1_FREQ; 122 if (dest == DLSModulator.CONN_DST_LFO_STARTDELAY) 123 return ModelDestination.DESTINATION_LFO1_DELAY; 124 125 if (dest == DLSModulator.CONN_DST_EG1_ATTACKTIME) 126 return ModelDestination.DESTINATION_EG1_ATTACK; 127 if (dest == DLSModulator.CONN_DST_EG1_DECAYTIME) 128 return ModelDestination.DESTINATION_EG1_DECAY; 129 if (dest == DLSModulator.CONN_DST_EG1_RELEASETIME) 130 return ModelDestination.DESTINATION_EG1_RELEASE; 131 if (dest == DLSModulator.CONN_DST_EG1_SUSTAINLEVEL) 132 return ModelDestination.DESTINATION_EG1_SUSTAIN; 133 134 if (dest == DLSModulator.CONN_DST_EG2_ATTACKTIME) 135 return ModelDestination.DESTINATION_EG2_ATTACK; 136 if (dest == DLSModulator.CONN_DST_EG2_DECAYTIME) 137 return ModelDestination.DESTINATION_EG2_DECAY; 138 if (dest == DLSModulator.CONN_DST_EG2_RELEASETIME) 139 return ModelDestination.DESTINATION_EG2_RELEASE; 140 if (dest == DLSModulator.CONN_DST_EG2_SUSTAINLEVEL) 141 return ModelDestination.DESTINATION_EG2_SUSTAIN; 142 143 // DLS2 Destinations 144 if (dest == DLSModulator.CONN_DST_KEYNUMBER) 145 return ModelDestination.DESTINATION_KEYNUMBER; 146 147 if (dest == DLSModulator.CONN_DST_CHORUS) 148 return ModelDestination.DESTINATION_CHORUS; 149 if (dest == DLSModulator.CONN_DST_REVERB) 150 return ModelDestination.DESTINATION_REVERB; 151 152 if (dest == DLSModulator.CONN_DST_VIB_FREQUENCY) 153 return ModelDestination.DESTINATION_LFO2_FREQ; 154 if (dest == DLSModulator.CONN_DST_VIB_STARTDELAY) 155 return ModelDestination.DESTINATION_LFO2_DELAY; 156 157 if (dest == DLSModulator.CONN_DST_EG1_DELAYTIME) 158 return ModelDestination.DESTINATION_EG1_DELAY; 159 if (dest == DLSModulator.CONN_DST_EG1_HOLDTIME) 160 return ModelDestination.DESTINATION_EG1_HOLD; 161 if (dest == DLSModulator.CONN_DST_EG1_SHUTDOWNTIME) 162 return ModelDestination.DESTINATION_EG1_SHUTDOWN; 163 164 if (dest == DLSModulator.CONN_DST_EG2_DELAYTIME) 165 return ModelDestination.DESTINATION_EG2_DELAY; 166 if (dest == DLSModulator.CONN_DST_EG2_HOLDTIME) 167 return ModelDestination.DESTINATION_EG2_HOLD; 168 169 if (dest == DLSModulator.CONN_DST_FILTER_CUTOFF) 170 return ModelDestination.DESTINATION_FILTER_FREQ; 171 if (dest == DLSModulator.CONN_DST_FILTER_Q) 172 return ModelDestination.DESTINATION_FILTER_Q; 173 174 return null; 175 } 176 177 private ModelIdentifier convertToModelSrc(int src) { 178 if (src == DLSModulator.CONN_SRC_NONE) 179 return null; 180 181 if (src == DLSModulator.CONN_SRC_LFO) 182 return ModelSource.SOURCE_LFO1; 183 if (src == DLSModulator.CONN_SRC_KEYONVELOCITY) 184 return ModelSource.SOURCE_NOTEON_VELOCITY; 185 if (src == DLSModulator.CONN_SRC_KEYNUMBER) 186 return ModelSource.SOURCE_NOTEON_KEYNUMBER; 187 if (src == DLSModulator.CONN_SRC_EG1) 188 return ModelSource.SOURCE_EG1; 189 if (src == DLSModulator.CONN_SRC_EG2) 190 return ModelSource.SOURCE_EG2; 191 if (src == DLSModulator.CONN_SRC_PITCHWHEEL) 192 return ModelSource.SOURCE_MIDI_PITCH; 193 if (src == DLSModulator.CONN_SRC_CC1) 194 return new ModelIdentifier("midi_cc", "1", 0); 195 if (src == DLSModulator.CONN_SRC_CC7) 196 return new ModelIdentifier("midi_cc", "7", 0); 197 if (src == DLSModulator.CONN_SRC_CC10) 198 return new ModelIdentifier("midi_cc", "10", 0); 199 if (src == DLSModulator.CONN_SRC_CC11) 200 return new ModelIdentifier("midi_cc", "11", 0); 201 if (src == DLSModulator.CONN_SRC_RPN0) 202 return new ModelIdentifier("midi_rpn", "0", 0); 203 if (src == DLSModulator.CONN_SRC_RPN1) 204 return new ModelIdentifier("midi_rpn", "1", 0); 205 206 if (src == DLSModulator.CONN_SRC_POLYPRESSURE) 207 return ModelSource.SOURCE_MIDI_POLY_PRESSURE; 208 if (src == DLSModulator.CONN_SRC_CHANNELPRESSURE) 209 return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; 210 if (src == DLSModulator.CONN_SRC_VIBRATO) 211 return ModelSource.SOURCE_LFO2; 212 if (src == DLSModulator.CONN_SRC_MONOPRESSURE) 213 return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; 214 215 if (src == DLSModulator.CONN_SRC_CC91) 216 return new ModelIdentifier("midi_cc", "91", 0); 217 if (src == DLSModulator.CONN_SRC_CC93) 218 return new ModelIdentifier("midi_cc", "93", 0); 219 220 return null; 221 } 222 223 private ModelConnectionBlock convertToModel(DLSModulator mod) { 224 ModelIdentifier source = convertToModelSrc(mod.getSource()); 225 ModelIdentifier control = convertToModelSrc(mod.getControl()); 226 ModelIdentifier destination_id = 227 convertToModelDest(mod.getDestination()); 228 229 int scale = mod.getScale(); 230 double f_scale; 231 if (scale == Integer.MIN_VALUE) 232 f_scale = Double.NEGATIVE_INFINITY; 233 else 234 f_scale = scale / 65536.0; 235 236 if (destination_id != null) { 237 ModelSource src = null; 238 ModelSource ctrl = null; 239 ModelConnectionBlock block = new ModelConnectionBlock(); 240 if (control != null) { 241 ModelSource s = new ModelSource(); 242 if (control == ModelSource.SOURCE_MIDI_PITCH) { 243 ((ModelStandardTransform)s.getTransform()).setPolarity( 244 ModelStandardTransform.POLARITY_BIPOLAR); 245 } else if (control == ModelSource.SOURCE_LFO1 246 || control == ModelSource.SOURCE_LFO2) { 247 ((ModelStandardTransform)s.getTransform()).setPolarity( 248 ModelStandardTransform.POLARITY_BIPOLAR); 249 } 250 s.setIdentifier(control); 251 block.addSource(s); 252 ctrl = s; 253 } 254 if (source != null) { 255 ModelSource s = new ModelSource(); 256 if (source == ModelSource.SOURCE_MIDI_PITCH) { 257 ((ModelStandardTransform)s.getTransform()).setPolarity( 258 ModelStandardTransform.POLARITY_BIPOLAR); 259 } else if (source == ModelSource.SOURCE_LFO1 260 || source == ModelSource.SOURCE_LFO2) { 261 ((ModelStandardTransform)s.getTransform()).setPolarity( 262 ModelStandardTransform.POLARITY_BIPOLAR); 263 } 264 s.setIdentifier(source); 265 block.addSource(s); 266 src = s; 267 } 268 ModelDestination destination = new ModelDestination(); 269 destination.setIdentifier(destination_id); 270 block.setDestination(destination); 271 272 if (mod.getVersion() == 1) { 273 //if (mod.getTransform() == DLSModulator.CONN_TRN_CONCAVE) { 274 // ((ModelStandardTransform)destination.getTransform()) 275 // .setTransform( 276 // ModelStandardTransform.TRANSFORM_CONCAVE); 277 //} 278 if (mod.getTransform() == DLSModulator.CONN_TRN_CONCAVE) { 279 if (src != null) { 280 ((ModelStandardTransform)src.getTransform()) 281 .setTransform( 282 ModelStandardTransform.TRANSFORM_CONCAVE); 283 ((ModelStandardTransform)src.getTransform()) 284 .setDirection( 285 ModelStandardTransform.DIRECTION_MAX2MIN); 286 } 287 if (ctrl != null) { 288 ((ModelStandardTransform)ctrl.getTransform()) 289 .setTransform( 290 ModelStandardTransform.TRANSFORM_CONCAVE); 291 ((ModelStandardTransform)ctrl.getTransform()) 292 .setDirection( 293 ModelStandardTransform.DIRECTION_MAX2MIN); 294 } 295 } 296 297 } else if (mod.getVersion() == 2) { 298 int transform = mod.getTransform(); 299 int src_transform_invert = (transform >> 15) & 1; 300 int src_transform_bipolar = (transform >> 14) & 1; 301 int src_transform = (transform >> 10) & 8; 302 int ctr_transform_invert = (transform >> 9) & 1; 303 int ctr_transform_bipolar = (transform >> 8) & 1; 304 int ctr_transform = (transform >> 4) & 8; 305 306 307 if (src != null) { 308 int trans = ModelStandardTransform.TRANSFORM_LINEAR; 309 if (src_transform == DLSModulator.CONN_TRN_SWITCH) 310 trans = ModelStandardTransform.TRANSFORM_SWITCH; 311 if (src_transform == DLSModulator.CONN_TRN_CONCAVE) 312 trans = ModelStandardTransform.TRANSFORM_CONCAVE; 313 if (src_transform == DLSModulator.CONN_TRN_CONVEX) 314 trans = ModelStandardTransform.TRANSFORM_CONVEX; 315 ((ModelStandardTransform)src.getTransform()) 316 .setTransform(trans); 317 ((ModelStandardTransform)src.getTransform()) 318 .setPolarity(src_transform_bipolar == 1); 319 ((ModelStandardTransform)src.getTransform()) 320 .setDirection(src_transform_invert == 1); 321 322 } 323 324 if (ctrl != null) { 325 int trans = ModelStandardTransform.TRANSFORM_LINEAR; 326 if (ctr_transform == DLSModulator.CONN_TRN_SWITCH) 327 trans = ModelStandardTransform.TRANSFORM_SWITCH; 328 if (ctr_transform == DLSModulator.CONN_TRN_CONCAVE) 329 trans = ModelStandardTransform.TRANSFORM_CONCAVE; 330 if (ctr_transform == DLSModulator.CONN_TRN_CONVEX) 331 trans = ModelStandardTransform.TRANSFORM_CONVEX; 332 ((ModelStandardTransform)ctrl.getTransform()) 333 .setTransform(trans); 334 ((ModelStandardTransform)ctrl.getTransform()) 335 .setPolarity(ctr_transform_bipolar == 1); 336 ((ModelStandardTransform)ctrl.getTransform()) 337 .setDirection(ctr_transform_invert == 1); 338 } 339 340 /* No output transforms are defined the DLS Level 2 341 int out_transform = transform % 8; 342 int trans = ModelStandardTransform.TRANSFORM_LINEAR; 343 if (out_transform == DLSModulator.CONN_TRN_SWITCH) 344 trans = ModelStandardTransform.TRANSFORM_SWITCH; 345 if (out_transform == DLSModulator.CONN_TRN_CONCAVE) 346 trans = ModelStandardTransform.TRANSFORM_CONCAVE; 347 if (out_transform == DLSModulator.CONN_TRN_CONVEX) 348 trans = ModelStandardTransform.TRANSFORM_CONVEX; 349 if (ctrl != null) { 350 ((ModelStandardTransform)destination.getTransform()) 351 .setTransform(trans); 352 } 353 */ 354 355 } 356 357 block.setScale(f_scale); 358 359 return block; 360 } 361 362 return null; 363 } 364 365 public ModelPerformer[] getPerformers() { 366 List<ModelPerformer> performers = new ArrayList<ModelPerformer>(); 367 368 Map<String, DLSModulator> modmap = new HashMap<String, DLSModulator>(); 369 for (DLSModulator mod: getModulators()) { 370 modmap.put(mod.getSource() + "x" + mod.getControl() + "=" + 371 mod.getDestination(), mod); 372 } 373 374 Map<String, DLSModulator> insmodmap = 375 new HashMap<String, DLSModulator>(); 376 377 for (DLSRegion zone: regions) { 378 ModelPerformer performer = new ModelPerformer(); 379 performer.setName(zone.getSample().getName()); 380 performer.setSelfNonExclusive((zone.getFusoptions() & 381 DLSRegion.OPTION_SELFNONEXCLUSIVE) != 0); 382 performer.setExclusiveClass(zone.getExclusiveClass()); 383 performer.setKeyFrom(zone.getKeyfrom()); 384 performer.setKeyTo(zone.getKeyto()); 385 performer.setVelFrom(zone.getVelfrom()); 386 performer.setVelTo(zone.getVelto()); 387 388 insmodmap.clear(); 389 insmodmap.putAll(modmap); 390 for (DLSModulator mod: zone.getModulators()) { 391 insmodmap.put(mod.getSource() + "x" + mod.getControl() + "=" + 392 mod.getDestination(), mod); 393 } 394 395 List<ModelConnectionBlock> blocks = performer.getConnectionBlocks(); 396 for (DLSModulator mod: insmodmap.values()) { 397 ModelConnectionBlock p = convertToModel(mod); 398 if (p != null) 399 blocks.add(p); 400 } 401 402 403 DLSSample sample = zone.getSample(); 404 DLSSampleOptions sampleopt = zone.getSampleoptions(); 405 if (sampleopt == null) 406 sampleopt = sample.getSampleoptions(); 407 408 ModelByteBuffer buff = sample.getDataBuffer(); 409 410 float pitchcorrection = (-sampleopt.unitynote * 100) + 411 sampleopt.finetune; 412 413 ModelByteBufferWavetable osc = new ModelByteBufferWavetable(buff, 414 sample.getFormat(), pitchcorrection); 415 osc.setAttenuation(osc.getAttenuation() / 65536f); 416 if (sampleopt.getLoops().size() != 0) { 417 DLSSampleLoop loop = sampleopt.getLoops().get(0); 418 osc.setLoopStart((int)loop.getStart()); 419 osc.setLoopLength((int)loop.getLength()); 420 if (loop.getType() == DLSSampleLoop.LOOP_TYPE_FORWARD) 421 osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); 422 if (loop.getType() == DLSSampleLoop.LOOP_TYPE_RELEASE) 423 osc.setLoopType(ModelWavetable.LOOP_TYPE_RELEASE); 424 else 425 osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); 426 } 427 428 performer.getConnectionBlocks().add( 429 new ModelConnectionBlock(SoftFilter.FILTERTYPE_LP12, 430 new ModelDestination( 431 new ModelIdentifier("filter", "type", 1)))); 432 433 performer.getOscillators().add(osc); 434 435 performers.add(performer); 436 437 } 438 439 return performers.toArray(new ModelPerformer[performers.size()]); 440 } 441 442 public byte[] getGuid() { 443 return guid == null ? null : Arrays.copyOf(guid, guid.length); 444 } 445 446 public void setGuid(byte[] guid) { 447 this.guid = guid == null ? null : Arrays.copyOf(guid, guid.length); 448 } 449 }