blob: c7e6188a25c4b37ae5355a74459b0c315d98ed1f [file] [log] [blame]
/*
* 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);
}
}