/* * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.media.sound; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.sound.midi.Patch; /** * This class is used to store information to describe instrument. * It contains list of regions and modulators. * It is stored inside a "ins " List Chunk inside DLS files. * In the DLS documentation a modulator is called articulator. * * @author Karl Helgason */ public final class DLSInstrument extends ModelInstrument { int preset = 0; int bank = 0; boolean druminstrument = false; byte[] guid = null; DLSInfo info = new DLSInfo(); List<DLSRegion> regions = new ArrayList<DLSRegion>(); List<DLSModulator> modulators = new ArrayList<DLSModulator>(); public DLSInstrument() { super(null, null, null, null); } public DLSInstrument(DLSSoundbank soundbank) { super(soundbank, null, null, null); } public DLSInfo getInfo() { return info; } public String getName() { return info.name; } public void setName(String name) { info.name = name; } public ModelPatch getPatch() { return new ModelPatch(bank, preset, druminstrument); } public void setPatch(Patch patch) { if (patch instanceof ModelPatch && ((ModelPatch)patch).isPercussion()) { druminstrument = true; bank = patch.getBank(); preset = patch.getProgram(); } else { druminstrument = false; bank = patch.getBank(); preset = patch.getProgram(); } } public Object getData() { return null; } public List<DLSRegion> getRegions() { return regions; } public List<DLSModulator> getModulators() { return modulators; } public String toString() { if (druminstrument) return "Drumkit: " + info.name + " bank #" + bank + " preset #" + preset; else return "Instrument: " + info.name + " bank #" + bank + " preset #" + preset; } private ModelIdentifier convertToModelDest(int dest) { if (dest == DLSModulator.CONN_DST_NONE) return null; if (dest == DLSModulator.CONN_DST_GAIN) return ModelDestination.DESTINATION_GAIN; if (dest == DLSModulator.CONN_DST_PITCH) return ModelDestination.DESTINATION_PITCH; if (dest == DLSModulator.CONN_DST_PAN) return ModelDestination.DESTINATION_PAN; if (dest == DLSModulator.CONN_DST_LFO_FREQUENCY) return ModelDestination.DESTINATION_LFO1_FREQ; if (dest == DLSModulator.CONN_DST_LFO_STARTDELAY) return ModelDestination.DESTINATION_LFO1_DELAY; if (dest == DLSModulator.CONN_DST_EG1_ATTACKTIME) return ModelDestination.DESTINATION_EG1_ATTACK; if (dest == DLSModulator.CONN_DST_EG1_DECAYTIME) return ModelDestination.DESTINATION_EG1_DECAY; if (dest == DLSModulator.CONN_DST_EG1_RELEASETIME) return ModelDestination.DESTINATION_EG1_RELEASE; if (dest == DLSModulator.CONN_DST_EG1_SUSTAINLEVEL) return ModelDestination.DESTINATION_EG1_SUSTAIN; if (dest == DLSModulator.CONN_DST_EG2_ATTACKTIME) return ModelDestination.DESTINATION_EG2_ATTACK; if (dest == DLSModulator.CONN_DST_EG2_DECAYTIME) return ModelDestination.DESTINATION_EG2_DECAY; if (dest == DLSModulator.CONN_DST_EG2_RELEASETIME) return ModelDestination.DESTINATION_EG2_RELEASE; if (dest == DLSModulator.CONN_DST_EG2_SUSTAINLEVEL) return ModelDestination.DESTINATION_EG2_SUSTAIN; // DLS2 Destinations if (dest == DLSModulator.CONN_DST_KEYNUMBER) return ModelDestination.DESTINATION_KEYNUMBER; if (dest == DLSModulator.CONN_DST_CHORUS) return ModelDestination.DESTINATION_CHORUS; if (dest == DLSModulator.CONN_DST_REVERB) return ModelDestination.DESTINATION_REVERB; if (dest == DLSModulator.CONN_DST_VIB_FREQUENCY) return ModelDestination.DESTINATION_LFO2_FREQ; if (dest == DLSModulator.CONN_DST_VIB_STARTDELAY) return ModelDestination.DESTINATION_LFO2_DELAY; if (dest == DLSModulator.CONN_DST_EG1_DELAYTIME) return ModelDestination.DESTINATION_EG1_DELAY; if (dest == DLSModulator.CONN_DST_EG1_HOLDTIME) return ModelDestination.DESTINATION_EG1_HOLD; if (dest == DLSModulator.CONN_DST_EG1_SHUTDOWNTIME) return ModelDestination.DESTINATION_EG1_SHUTDOWN; if (dest == DLSModulator.CONN_DST_EG2_DELAYTIME) return ModelDestination.DESTINATION_EG2_DELAY; if (dest == DLSModulator.CONN_DST_EG2_HOLDTIME) return ModelDestination.DESTINATION_EG2_HOLD; if (dest == DLSModulator.CONN_DST_FILTER_CUTOFF) return ModelDestination.DESTINATION_FILTER_FREQ; if (dest == DLSModulator.CONN_DST_FILTER_Q) return ModelDestination.DESTINATION_FILTER_Q; return null; } private ModelIdentifier convertToModelSrc(int src) { if (src == DLSModulator.CONN_SRC_NONE) return null; if (src == DLSModulator.CONN_SRC_LFO) return ModelSource.SOURCE_LFO1; if (src == DLSModulator.CONN_SRC_KEYONVELOCITY) return ModelSource.SOURCE_NOTEON_VELOCITY; if (src == DLSModulator.CONN_SRC_KEYNUMBER) return ModelSource.SOURCE_NOTEON_KEYNUMBER; if (src == DLSModulator.CONN_SRC_EG1) return ModelSource.SOURCE_EG1; if (src == DLSModulator.CONN_SRC_EG2) return ModelSource.SOURCE_EG2; if (src == DLSModulator.CONN_SRC_PITCHWHEEL) return ModelSource.SOURCE_MIDI_PITCH; if (src == DLSModulator.CONN_SRC_CC1) return new ModelIdentifier("midi_cc", "1", 0); if (src == DLSModulator.CONN_SRC_CC7) return new ModelIdentifier("midi_cc", "7", 0); if (src == DLSModulator.CONN_SRC_CC10) return new ModelIdentifier("midi_cc", "10", 0); if (src == DLSModulator.CONN_SRC_CC11) return new ModelIdentifier("midi_cc", "11", 0); if (src == DLSModulator.CONN_SRC_RPN0) return new ModelIdentifier("midi_rpn", "0", 0); if (src == DLSModulator.CONN_SRC_RPN1) return new ModelIdentifier("midi_rpn", "1", 0); if (src == DLSModulator.CONN_SRC_POLYPRESSURE) return ModelSource.SOURCE_MIDI_POLY_PRESSURE; if (src == DLSModulator.CONN_SRC_CHANNELPRESSURE) return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; if (src == DLSModulator.CONN_SRC_VIBRATO) return ModelSource.SOURCE_LFO2; if (src == DLSModulator.CONN_SRC_MONOPRESSURE) return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; if (src == DLSModulator.CONN_SRC_CC91) return new ModelIdentifier("midi_cc", "91", 0); if (src == DLSModulator.CONN_SRC_CC93) return new ModelIdentifier("midi_cc", "93", 0); return null; } private ModelConnectionBlock convertToModel(DLSModulator mod) { ModelIdentifier source = convertToModelSrc(mod.getSource()); ModelIdentifier control = convertToModelSrc(mod.getControl()); ModelIdentifier destination_id = convertToModelDest(mod.getDestination()); int scale = mod.getScale(); double f_scale; if (scale == Integer.MIN_VALUE) f_scale = Double.NEGATIVE_INFINITY; else f_scale = scale / 65536.0; if (destination_id != null) { ModelSource src = null; ModelSource ctrl = null; ModelConnectionBlock block = new ModelConnectionBlock(); if (control != null) { ModelSource s = new ModelSource(); if (control == ModelSource.SOURCE_MIDI_PITCH) { ((ModelStandardTransform)s.getTransform()).setPolarity( ModelStandardTransform.POLARITY_BIPOLAR); } else if (control == ModelSource.SOURCE_LFO1 || control == ModelSource.SOURCE_LFO2) { ((ModelStandardTransform)s.getTransform()).setPolarity( ModelStandardTransform.POLARITY_BIPOLAR); } s.setIdentifier(control); block.addSource(s); ctrl = s; } if (source != null) { ModelSource s = new ModelSource(); if (source == ModelSource.SOURCE_MIDI_PITCH) { ((ModelStandardTransform)s.getTransform()).setPolarity( ModelStandardTransform.POLARITY_BIPOLAR); } else if (source == ModelSource.SOURCE_LFO1 || source == ModelSource.SOURCE_LFO2) { ((ModelStandardTransform)s.getTransform()).setPolarity( ModelStandardTransform.POLARITY_BIPOLAR); } s.setIdentifier(source); block.addSource(s); src = s; } ModelDestination destination = new ModelDestination(); destination.setIdentifier(destination_id); block.setDestination(destination); if (mod.getVersion() == 1) { //if (mod.getTransform() == DLSModulator.CONN_TRN_CONCAVE) { // ((ModelStandardTransform)destination.getTransform()) // .setTransform( // ModelStandardTransform.TRANSFORM_CONCAVE); //} if (mod.getTransform() == DLSModulator.CONN_TRN_CONCAVE) { if (src != null) { ((ModelStandardTransform)src.getTransform()) .setTransform( ModelStandardTransform.TRANSFORM_CONCAVE); ((ModelStandardTransform)src.getTransform()) .setDirection( ModelStandardTransform.DIRECTION_MAX2MIN); } if (ctrl != null) { ((ModelStandardTransform)ctrl.getTransform()) .setTransform( ModelStandardTransform.TRANSFORM_CONCAVE); ((ModelStandardTransform)ctrl.getTransform()) .setDirection( ModelStandardTransform.DIRECTION_MAX2MIN); } } } else if (mod.getVersion() == 2) { int transform = mod.getTransform(); int src_transform_invert = (transform >> 15) & 1; int src_transform_bipolar = (transform >> 14) & 1; int src_transform = (transform >> 10) & 8; int ctr_transform_invert = (transform >> 9) & 1; int ctr_transform_bipolar = (transform >> 8) & 1; int ctr_transform = (transform >> 4) & 8; if (src != null) { int trans = ModelStandardTransform.TRANSFORM_LINEAR; if (src_transform == DLSModulator.CONN_TRN_SWITCH) trans = ModelStandardTransform.TRANSFORM_SWITCH; if (src_transform == DLSModulator.CONN_TRN_CONCAVE) trans = ModelStandardTransform.TRANSFORM_CONCAVE; if (src_transform == DLSModulator.CONN_TRN_CONVEX) trans = ModelStandardTransform.TRANSFORM_CONVEX; ((ModelStandardTransform)src.getTransform()) .setTransform(trans); ((ModelStandardTransform)src.getTransform()) .setPolarity(src_transform_bipolar == 1); ((ModelStandardTransform)src.getTransform()) .setDirection(src_transform_invert == 1); } if (ctrl != null) { int trans = ModelStandardTransform.TRANSFORM_LINEAR; if (ctr_transform == DLSModulator.CONN_TRN_SWITCH) trans = ModelStandardTransform.TRANSFORM_SWITCH; if (ctr_transform == DLSModulator.CONN_TRN_CONCAVE) trans = ModelStandardTransform.TRANSFORM_CONCAVE; if (ctr_transform == DLSModulator.CONN_TRN_CONVEX) trans = ModelStandardTransform.TRANSFORM_CONVEX; ((ModelStandardTransform)ctrl.getTransform()) .setTransform(trans); ((ModelStandardTransform)ctrl.getTransform()) .setPolarity(ctr_transform_bipolar == 1); ((ModelStandardTransform)ctrl.getTransform()) .setDirection(ctr_transform_invert == 1); } /* No output transforms are defined the DLS Level 2 int out_transform = transform % 8; int trans = ModelStandardTransform.TRANSFORM_LINEAR; if (out_transform == DLSModulator.CONN_TRN_SWITCH) trans = ModelStandardTransform.TRANSFORM_SWITCH; if (out_transform == DLSModulator.CONN_TRN_CONCAVE) trans = ModelStandardTransform.TRANSFORM_CONCAVE; if (out_transform == DLSModulator.CONN_TRN_CONVEX) trans = ModelStandardTransform.TRANSFORM_CONVEX; if (ctrl != null) { ((ModelStandardTransform)destination.getTransform()) .setTransform(trans); } */ } block.setScale(f_scale); return block; } return null; } public ModelPerformer[] getPerformers() { List<ModelPerformer> performers = new ArrayList<ModelPerformer>(); Map<String, DLSModulator> modmap = new HashMap<String, DLSModulator>(); for (DLSModulator mod: getModulators()) { modmap.put(mod.getSource() + "x" + mod.getControl() + "=" + mod.getDestination(), mod); } Map<String, DLSModulator> insmodmap = new HashMap<String, DLSModulator>(); for (DLSRegion zone: regions) { ModelPerformer performer = new ModelPerformer(); performer.setName(zone.getSample().getName()); performer.setSelfNonExclusive((zone.getFusoptions() & DLSRegion.OPTION_SELFNONEXCLUSIVE) != 0); performer.setExclusiveClass(zone.getExclusiveClass()); performer.setKeyFrom(zone.getKeyfrom()); performer.setKeyTo(zone.getKeyto()); performer.setVelFrom(zone.getVelfrom()); performer.setVelTo(zone.getVelto()); insmodmap.clear(); insmodmap.putAll(modmap); for (DLSModulator mod: zone.getModulators()) { insmodmap.put(mod.getSource() + "x" + mod.getControl() + "=" + mod.getDestination(), mod); } List<ModelConnectionBlock> blocks = performer.getConnectionBlocks(); for (DLSModulator mod: insmodmap.values()) { ModelConnectionBlock p = convertToModel(mod); if (p != null) blocks.add(p); } DLSSample sample = zone.getSample(); DLSSampleOptions sampleopt = zone.getSampleoptions(); if (sampleopt == null) sampleopt = sample.getSampleoptions(); ModelByteBuffer buff = sample.getDataBuffer(); float pitchcorrection = (-sampleopt.unitynote * 100) + sampleopt.finetune; ModelByteBufferWavetable osc = new ModelByteBufferWavetable(buff, sample.getFormat(), pitchcorrection); osc.setAttenuation(osc.getAttenuation() / 65536f); if (sampleopt.getLoops().size() != 0) { DLSSampleLoop loop = sampleopt.getLoops().get(0); osc.setLoopStart((int)loop.getStart()); osc.setLoopLength((int)loop.getLength()); if (loop.getType() == DLSSampleLoop.LOOP_TYPE_FORWARD) osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); if (loop.getType() == DLSSampleLoop.LOOP_TYPE_RELEASE) osc.setLoopType(ModelWavetable.LOOP_TYPE_RELEASE); else osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); } performer.getConnectionBlocks().add( new ModelConnectionBlock(SoftFilter.FILTERTYPE_LP12, new ModelDestination( new ModelIdentifier("filter", "type", 1)))); performer.getOscillators().add(osc); performers.add(performer); } return performers.toArray(new ModelPerformer[performers.size()]); } public byte[] getGuid() { return guid == null ? null : Arrays.copyOf(guid, guid.length); } public void setGuid(byte[] guid) { this.guid = guid == null ? null : Arrays.copyOf(guid, guid.length); } }