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