blob: 580882ba76587214e248278297d780677b08d1d0 [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.HashMap;
import java.util.List;
import java.util.Map;
import javax.sound.midi.Patch;
/**
* Soundfont instrument.
*
* @author Karl Helgason
*/
public final class SF2Instrument extends ModelInstrument {
String name = "";
int preset = 0;
int bank = 0;
long library = 0;
long genre = 0;
long morphology = 0;
SF2GlobalRegion globalregion = null;
List<SF2InstrumentRegion> regions
= new ArrayList<SF2InstrumentRegion>();
public SF2Instrument() {
super(null, null, null, null);
}
public SF2Instrument(SF2Soundbank soundbank) {
super(soundbank, null, null, null);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Patch getPatch() {
if (bank == 128)
return new ModelPatch(0, preset, true);
else
return new ModelPatch(bank << 7, preset, false);
}
public void setPatch(Patch patch) {
if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) {
bank = 128;
preset = patch.getProgram();
} else {
bank = patch.getBank() >> 7;
preset = patch.getProgram();
}
}
public Object getData() {
return null;
}
public long getGenre() {
return genre;
}
public void setGenre(long genre) {
this.genre = genre;
}
public long getLibrary() {
return library;
}
public void setLibrary(long library) {
this.library = library;
}
public long getMorphology() {
return morphology;
}
public void setMorphology(long morphology) {
this.morphology = morphology;
}
public List<SF2InstrumentRegion> getRegions() {
return regions;
}
public SF2GlobalRegion getGlobalRegion() {
return globalregion;
}
public void setGlobalZone(SF2GlobalRegion zone) {
globalregion = zone;
}
public String toString() {
if (bank == 128)
return "Drumkit: " + name + " preset #" + preset;
else
return "Instrument: " + name + " bank #" + bank
+ " preset #" + preset;
}
public ModelPerformer[] getPerformers() {
int performercount = 0;
for (SF2InstrumentRegion presetzone : regions)
performercount += presetzone.getLayer().getRegions().size();
ModelPerformer[] performers = new ModelPerformer[performercount];
int pi = 0;
SF2GlobalRegion presetglobal = globalregion;
for (SF2InstrumentRegion presetzone : regions) {
Map<Integer, Short> pgenerators = new HashMap<Integer, Short>();
pgenerators.putAll(presetzone.getGenerators());
if (presetglobal != null)
pgenerators.putAll(presetglobal.getGenerators());
SF2Layer layer = presetzone.getLayer();
SF2GlobalRegion layerglobal = layer.getGlobalRegion();
for (SF2LayerRegion layerzone : layer.getRegions()) {
ModelPerformer performer = new ModelPerformer();
if (layerzone.getSample() != null)
performer.setName(layerzone.getSample().getName());
else
performer.setName(layer.getName());
performers[pi++] = performer;
int keyfrom = 0;
int keyto = 127;
int velfrom = 0;
int velto = 127;
if (layerzone.contains(SF2Region.GENERATOR_EXCLUSIVECLASS)) {
performer.setExclusiveClass(layerzone.getInteger(
SF2Region.GENERATOR_EXCLUSIVECLASS));
}
if (layerzone.contains(SF2Region.GENERATOR_KEYRANGE)) {
byte[] bytes = layerzone.getBytes(
SF2Region.GENERATOR_KEYRANGE);
if (bytes[0] >= 0)
if (bytes[0] > keyfrom)
keyfrom = bytes[0];
if (bytes[1] >= 0)
if (bytes[1] < keyto)
keyto = bytes[1];
}
if (layerzone.contains(SF2Region.GENERATOR_VELRANGE)) {
byte[] bytes = layerzone.getBytes(
SF2Region.GENERATOR_VELRANGE);
if (bytes[0] >= 0)
if (bytes[0] > velfrom)
velfrom = bytes[0];
if (bytes[1] >= 0)
if (bytes[1] < velto)
velto = bytes[1];
}
if (presetzone.contains(SF2Region.GENERATOR_KEYRANGE)) {
byte[] bytes = presetzone.getBytes(
SF2Region.GENERATOR_KEYRANGE);
if (bytes[0] > keyfrom)
keyfrom = bytes[0];
if (bytes[1] < keyto)
keyto = bytes[1];
}
if (presetzone.contains(SF2Region.GENERATOR_VELRANGE)) {
byte[] bytes = presetzone.getBytes(
SF2Region.GENERATOR_VELRANGE);
if (bytes[0] > velfrom)
velfrom = bytes[0];
if (bytes[1] < velto)
velto = bytes[1];
}
performer.setKeyFrom(keyfrom);
performer.setKeyTo(keyto);
performer.setVelFrom(velfrom);
performer.setVelTo(velto);
int startAddrsOffset = layerzone.getShort(
SF2Region.GENERATOR_STARTADDRSOFFSET);
int endAddrsOffset = layerzone.getShort(
SF2Region.GENERATOR_ENDADDRSOFFSET);
int startloopAddrsOffset = layerzone.getShort(
SF2Region.GENERATOR_STARTLOOPADDRSOFFSET);
int endloopAddrsOffset = layerzone.getShort(
SF2Region.GENERATOR_ENDLOOPADDRSOFFSET);
startAddrsOffset += layerzone.getShort(
SF2Region.GENERATOR_STARTADDRSCOARSEOFFSET) * 32768;
endAddrsOffset += layerzone.getShort(
SF2Region.GENERATOR_ENDADDRSCOARSEOFFSET) * 32768;
startloopAddrsOffset += layerzone.getShort(
SF2Region.GENERATOR_STARTLOOPADDRSCOARSEOFFSET) * 32768;
endloopAddrsOffset += layerzone.getShort(
SF2Region.GENERATOR_ENDLOOPADDRSCOARSEOFFSET) * 32768;
startloopAddrsOffset -= startAddrsOffset;
endloopAddrsOffset -= startAddrsOffset;
SF2Sample sample = layerzone.getSample();
int rootkey = sample.originalPitch;
if (layerzone.getShort(SF2Region.GENERATOR_OVERRIDINGROOTKEY) != -1) {
rootkey = layerzone.getShort(
SF2Region.GENERATOR_OVERRIDINGROOTKEY);
}
float pitchcorrection = (-rootkey * 100) + sample.pitchCorrection;
ModelByteBuffer buff = sample.getDataBuffer();
ModelByteBuffer buff24 = sample.getData24Buffer();
if (startAddrsOffset != 0 || endAddrsOffset != 0) {
buff = buff.subbuffer(startAddrsOffset * 2,
buff.capacity() + endAddrsOffset * 2);
if (buff24 != null) {
buff24 = buff24.subbuffer(startAddrsOffset,
buff24.capacity() + endAddrsOffset);
}
/*
if (startAddrsOffset < 0)
startAddrsOffset = 0;
if (endAddrsOffset > (buff.capacity()/2-startAddrsOffset))
startAddrsOffset = (int)buff.capacity()/2-startAddrsOffset;
byte[] data = buff.array();
int off = (int)buff.arrayOffset() + startAddrsOffset*2;
int len = (int)buff.capacity() + endAddrsOffset*2;
if (off+len > data.length)
len = data.length - off;
buff = new ModelByteBuffer(data, off, len);
if(buff24 != null) {
data = buff.array();
off = (int)buff.arrayOffset() + startAddrsOffset;
len = (int)buff.capacity() + endAddrsOffset;
buff24 = new ModelByteBuffer(data, off, len);
}
*/
}
ModelByteBufferWavetable osc = new ModelByteBufferWavetable(
buff, sample.getFormat(), pitchcorrection);
if (buff24 != null)
osc.set8BitExtensionBuffer(buff24);
Map<Integer, Short> generators = new HashMap<Integer, Short>();
if (layerglobal != null)
generators.putAll(layerglobal.getGenerators());
generators.putAll(layerzone.getGenerators());
for (Map.Entry<Integer, Short> gen : pgenerators.entrySet()) {
short val;
if (!generators.containsKey(gen.getKey()))
val = layerzone.getShort(gen.getKey());
else
val = generators.get(gen.getKey());
val += gen.getValue();
generators.put(gen.getKey(), val);
}
// SampleMode:
// 0 indicates a sound reproduced with no loop
// 1 indicates a sound which loops continuously
// 2 is unused but should be interpreted as indicating no loop
// 3 indicates a sound which loops for the duration of key
// depression then proceeds to play the remainder of the sample.
int sampleMode = getGeneratorValue(generators,
SF2Region.GENERATOR_SAMPLEMODES);
if ((sampleMode == 1) || (sampleMode == 3)) {
if (sample.startLoop >= 0 && sample.endLoop > 0) {
osc.setLoopStart((int)(sample.startLoop
+ startloopAddrsOffset));
osc.setLoopLength((int)(sample.endLoop - sample.startLoop
+ endloopAddrsOffset - startloopAddrsOffset));
if (sampleMode == 1)
osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD);
if (sampleMode == 3)
osc.setLoopType(ModelWavetable.LOOP_TYPE_RELEASE);
}
}
performer.getOscillators().add(osc);
short volDelay = getGeneratorValue(generators,
SF2Region.GENERATOR_DELAYVOLENV);
short volAttack = getGeneratorValue(generators,
SF2Region.GENERATOR_ATTACKVOLENV);
short volHold = getGeneratorValue(generators,
SF2Region.GENERATOR_HOLDVOLENV);
short volDecay = getGeneratorValue(generators,
SF2Region.GENERATOR_DECAYVOLENV);
short volSustain = getGeneratorValue(generators,
SF2Region.GENERATOR_SUSTAINVOLENV);
short volRelease = getGeneratorValue(generators,
SF2Region.GENERATOR_RELEASEVOLENV);
if (volHold != -12000) {
short volKeyNumToHold = getGeneratorValue(generators,
SF2Region.GENERATOR_KEYNUMTOVOLENVHOLD);
volHold += 60 * volKeyNumToHold;
float fvalue = -volKeyNumToHold * 128;
ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
ModelIdentifier dest = ModelDestination.DESTINATION_EG1_HOLD;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(new ModelSource(src), fvalue,
new ModelDestination(dest)));
}
if (volDecay != -12000) {
short volKeyNumToDecay = getGeneratorValue(generators,
SF2Region.GENERATOR_KEYNUMTOVOLENVDECAY);
volDecay += 60 * volKeyNumToDecay;
float fvalue = -volKeyNumToDecay * 128;
ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
ModelIdentifier dest = ModelDestination.DESTINATION_EG1_DECAY;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(new ModelSource(src), fvalue,
new ModelDestination(dest)));
}
addTimecentValue(performer,
ModelDestination.DESTINATION_EG1_DELAY, volDelay);
addTimecentValue(performer,
ModelDestination.DESTINATION_EG1_ATTACK, volAttack);
addTimecentValue(performer,
ModelDestination.DESTINATION_EG1_HOLD, volHold);
addTimecentValue(performer,
ModelDestination.DESTINATION_EG1_DECAY, volDecay);
//float fvolsustain = (960-volSustain)*(1000.0f/960.0f);
volSustain = (short)(1000 - volSustain);
if (volSustain < 0)
volSustain = 0;
if (volSustain > 1000)
volSustain = 1000;
addValue(performer,
ModelDestination.DESTINATION_EG1_SUSTAIN, volSustain);
addTimecentValue(performer,
ModelDestination.DESTINATION_EG1_RELEASE, volRelease);
if (getGeneratorValue(generators,
SF2Region.GENERATOR_MODENVTOFILTERFC) != 0
|| getGeneratorValue(generators,
SF2Region.GENERATOR_MODENVTOPITCH) != 0) {
short modDelay = getGeneratorValue(generators,
SF2Region.GENERATOR_DELAYMODENV);
short modAttack = getGeneratorValue(generators,
SF2Region.GENERATOR_ATTACKMODENV);
short modHold = getGeneratorValue(generators,
SF2Region.GENERATOR_HOLDMODENV);
short modDecay = getGeneratorValue(generators,
SF2Region.GENERATOR_DECAYMODENV);
short modSustain = getGeneratorValue(generators,
SF2Region.GENERATOR_SUSTAINMODENV);
short modRelease = getGeneratorValue(generators,
SF2Region.GENERATOR_RELEASEMODENV);
if (modHold != -12000) {
short modKeyNumToHold = getGeneratorValue(generators,
SF2Region.GENERATOR_KEYNUMTOMODENVHOLD);
modHold += 60 * modKeyNumToHold;
float fvalue = -modKeyNumToHold * 128;
ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
ModelIdentifier dest = ModelDestination.DESTINATION_EG2_HOLD;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(new ModelSource(src),
fvalue, new ModelDestination(dest)));
}
if (modDecay != -12000) {
short modKeyNumToDecay = getGeneratorValue(generators,
SF2Region.GENERATOR_KEYNUMTOMODENVDECAY);
modDecay += 60 * modKeyNumToDecay;
float fvalue = -modKeyNumToDecay * 128;
ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
ModelIdentifier dest = ModelDestination.DESTINATION_EG2_DECAY;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(new ModelSource(src),
fvalue, new ModelDestination(dest)));
}
addTimecentValue(performer,
ModelDestination.DESTINATION_EG2_DELAY, modDelay);
addTimecentValue(performer,
ModelDestination.DESTINATION_EG2_ATTACK, modAttack);
addTimecentValue(performer,
ModelDestination.DESTINATION_EG2_HOLD, modHold);
addTimecentValue(performer,
ModelDestination.DESTINATION_EG2_DECAY, modDecay);
if (modSustain < 0)
modSustain = 0;
if (modSustain > 1000)
modSustain = 1000;
addValue(performer, ModelDestination.DESTINATION_EG2_SUSTAIN,
1000 - modSustain);
addTimecentValue(performer,
ModelDestination.DESTINATION_EG2_RELEASE, modRelease);
if (getGeneratorValue(generators,
SF2Region.GENERATOR_MODENVTOFILTERFC) != 0) {
double fvalue = getGeneratorValue(generators,
SF2Region.GENERATOR_MODENVTOFILTERFC);
ModelIdentifier src = ModelSource.SOURCE_EG2;
ModelIdentifier dest
= ModelDestination.DESTINATION_FILTER_FREQ;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(new ModelSource(src),
fvalue, new ModelDestination(dest)));
}
if (getGeneratorValue(generators,
SF2Region.GENERATOR_MODENVTOPITCH) != 0) {
double fvalue = getGeneratorValue(generators,
SF2Region.GENERATOR_MODENVTOPITCH);
ModelIdentifier src = ModelSource.SOURCE_EG2;
ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(new ModelSource(src),
fvalue, new ModelDestination(dest)));
}
}
if (getGeneratorValue(generators,
SF2Region.GENERATOR_MODLFOTOFILTERFC) != 0
|| getGeneratorValue(generators,
SF2Region.GENERATOR_MODLFOTOPITCH) != 0
|| getGeneratorValue(generators,
SF2Region.GENERATOR_MODLFOTOVOLUME) != 0) {
short lfo_freq = getGeneratorValue(generators,
SF2Region.GENERATOR_FREQMODLFO);
short lfo_delay = getGeneratorValue(generators,
SF2Region.GENERATOR_DELAYMODLFO);
addTimecentValue(performer,
ModelDestination.DESTINATION_LFO1_DELAY, lfo_delay);
addValue(performer,
ModelDestination.DESTINATION_LFO1_FREQ, lfo_freq);
}
short vib_freq = getGeneratorValue(generators,
SF2Region.GENERATOR_FREQVIBLFO);
short vib_delay = getGeneratorValue(generators,
SF2Region.GENERATOR_DELAYVIBLFO);
addTimecentValue(performer,
ModelDestination.DESTINATION_LFO2_DELAY, vib_delay);
addValue(performer,
ModelDestination.DESTINATION_LFO2_FREQ, vib_freq);
if (getGeneratorValue(generators,
SF2Region.GENERATOR_VIBLFOTOPITCH) != 0) {
double fvalue = getGeneratorValue(generators,
SF2Region.GENERATOR_VIBLFOTOPITCH);
ModelIdentifier src = ModelSource.SOURCE_LFO2;
ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(
new ModelSource(src,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR),
fvalue, new ModelDestination(dest)));
}
if (getGeneratorValue(generators,
SF2Region.GENERATOR_MODLFOTOFILTERFC) != 0) {
double fvalue = getGeneratorValue(generators,
SF2Region.GENERATOR_MODLFOTOFILTERFC);
ModelIdentifier src = ModelSource.SOURCE_LFO1;
ModelIdentifier dest = ModelDestination.DESTINATION_FILTER_FREQ;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(
new ModelSource(src,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR),
fvalue, new ModelDestination(dest)));
}
if (getGeneratorValue(generators,
SF2Region.GENERATOR_MODLFOTOPITCH) != 0) {
double fvalue = getGeneratorValue(generators,
SF2Region.GENERATOR_MODLFOTOPITCH);
ModelIdentifier src = ModelSource.SOURCE_LFO1;
ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(
new ModelSource(src,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR),
fvalue, new ModelDestination(dest)));
}
if (getGeneratorValue(generators,
SF2Region.GENERATOR_MODLFOTOVOLUME) != 0) {
double fvalue = getGeneratorValue(generators,
SF2Region.GENERATOR_MODLFOTOVOLUME);
ModelIdentifier src = ModelSource.SOURCE_LFO1;
ModelIdentifier dest = ModelDestination.DESTINATION_GAIN;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(
new ModelSource(src,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR),
fvalue, new ModelDestination(dest)));
}
if (layerzone.getShort(SF2Region.GENERATOR_KEYNUM) != -1) {
double val = layerzone.getShort(SF2Region.GENERATOR_KEYNUM)/128.0;
addValue(performer, ModelDestination.DESTINATION_KEYNUMBER, val);
}
if (layerzone.getShort(SF2Region.GENERATOR_VELOCITY) != -1) {
double val = layerzone.getShort(SF2Region.GENERATOR_VELOCITY)
/ 128.0;
addValue(performer, ModelDestination.DESTINATION_VELOCITY, val);
}
if (getGeneratorValue(generators,
SF2Region.GENERATOR_INITIALFILTERFC) < 13500) {
short filter_freq = getGeneratorValue(generators,
SF2Region.GENERATOR_INITIALFILTERFC);
short filter_q = getGeneratorValue(generators,
SF2Region.GENERATOR_INITIALFILTERQ);
addValue(performer,
ModelDestination.DESTINATION_FILTER_FREQ, filter_freq);
addValue(performer,
ModelDestination.DESTINATION_FILTER_Q, filter_q);
}
int tune = 100 * getGeneratorValue(generators,
SF2Region.GENERATOR_COARSETUNE);
tune += getGeneratorValue(generators,
SF2Region.GENERATOR_FINETUNE);
if (tune != 0) {
addValue(performer,
ModelDestination.DESTINATION_PITCH, (short) tune);
}
if (getGeneratorValue(generators, SF2Region.GENERATOR_PAN) != 0) {
short val = getGeneratorValue(generators,
SF2Region.GENERATOR_PAN);
addValue(performer, ModelDestination.DESTINATION_PAN, val);
}
if (getGeneratorValue(generators, SF2Region.GENERATOR_INITIALATTENUATION) != 0) {
short val = getGeneratorValue(generators,
SF2Region.GENERATOR_INITIALATTENUATION);
addValue(performer,
ModelDestination.DESTINATION_GAIN, -0.376287f * val);
}
if (getGeneratorValue(generators,
SF2Region.GENERATOR_CHORUSEFFECTSSEND) != 0) {
short val = getGeneratorValue(generators,
SF2Region.GENERATOR_CHORUSEFFECTSSEND);
addValue(performer, ModelDestination.DESTINATION_CHORUS, val);
}
if (getGeneratorValue(generators,
SF2Region.GENERATOR_REVERBEFFECTSSEND) != 0) {
short val = getGeneratorValue(generators,
SF2Region.GENERATOR_REVERBEFFECTSSEND);
addValue(performer, ModelDestination.DESTINATION_REVERB, val);
}
if (getGeneratorValue(generators,
SF2Region.GENERATOR_SCALETUNING) != 100) {
short fvalue = getGeneratorValue(generators,
SF2Region.GENERATOR_SCALETUNING);
if (fvalue == 0) {
ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(null, rootkey * 100,
new ModelDestination(dest)));
} else {
ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(null, rootkey * (100 - fvalue),
new ModelDestination(dest)));
}
ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER;
ModelIdentifier dest = ModelDestination.DESTINATION_PITCH;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(new ModelSource(src),
128 * fvalue, new ModelDestination(dest)));
}
performer.getConnectionBlocks().add(
new ModelConnectionBlock(
new ModelSource(ModelSource.SOURCE_NOTEON_VELOCITY,
new ModelTransform() {
public double transform(double value) {
if (value < 0.5)
return 1 - value * 2;
else
return 0;
}
}),
-2400,
new ModelDestination(
ModelDestination.DESTINATION_FILTER_FREQ)));
performer.getConnectionBlocks().add(
new ModelConnectionBlock(
new ModelSource(ModelSource.SOURCE_LFO2,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR,
ModelStandardTransform.TRANSFORM_LINEAR),
new ModelSource(new ModelIdentifier("midi_cc", "1", 0),
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_UNIPOLAR,
ModelStandardTransform.TRANSFORM_LINEAR),
50, new ModelDestination(
ModelDestination.DESTINATION_PITCH)));
if (layer.getGlobalRegion() != null) {
for (SF2Modulator modulator
: layer.getGlobalRegion().getModulators()) {
convertModulator(performer, modulator);
}
}
for (SF2Modulator modulator : layerzone.getModulators())
convertModulator(performer, modulator);
if (presetglobal != null) {
for (SF2Modulator modulator : presetglobal.getModulators())
convertModulator(performer, modulator);
}
for (SF2Modulator modulator : presetzone.getModulators())
convertModulator(performer, modulator);
}
}
return performers;
}
private void convertModulator(ModelPerformer performer,
SF2Modulator modulator) {
ModelSource src1 = convertSource(modulator.getSourceOperator());
ModelSource src2 = convertSource(modulator.getAmountSourceOperator());
if (src1 == null && modulator.getSourceOperator() != 0)
return;
if (src2 == null && modulator.getAmountSourceOperator() != 0)
return;
double amount = modulator.getAmount();
double[] amountcorrection = new double[1];
ModelSource[] extrasrc = new ModelSource[1];
amountcorrection[0] = 1;
ModelDestination dst = convertDestination(
modulator.getDestinationOperator(), amountcorrection, extrasrc);
amount *= amountcorrection[0];
if (dst == null)
return;
if (modulator.getTransportOperator() == SF2Modulator.TRANSFORM_ABSOLUTE) {
((ModelStandardTransform)dst.getTransform()).setTransform(
ModelStandardTransform.TRANSFORM_ABSOLUTE);
}
ModelConnectionBlock conn = new ModelConnectionBlock(src1, src2, amount, dst);
if (extrasrc[0] != null)
conn.addSource(extrasrc[0]);
performer.getConnectionBlocks().add(conn);
}
private static ModelSource convertSource(int src) {
if (src == 0)
return null;
ModelIdentifier id = null;
int idsrc = src & 0x7F;
if ((src & SF2Modulator.SOURCE_MIDI_CONTROL) != 0) {
id = new ModelIdentifier("midi_cc", Integer.toString(idsrc));
} else {
if (idsrc == SF2Modulator.SOURCE_NOTE_ON_VELOCITY)
id = ModelSource.SOURCE_NOTEON_VELOCITY;
if (idsrc == SF2Modulator.SOURCE_NOTE_ON_KEYNUMBER)
id = ModelSource.SOURCE_NOTEON_KEYNUMBER;
if (idsrc == SF2Modulator.SOURCE_POLY_PRESSURE)
id = ModelSource.SOURCE_MIDI_POLY_PRESSURE;
if (idsrc == SF2Modulator.SOURCE_CHANNEL_PRESSURE)
id = ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE;
if (idsrc == SF2Modulator.SOURCE_PITCH_WHEEL)
id = ModelSource.SOURCE_MIDI_PITCH;
if (idsrc == SF2Modulator.SOURCE_PITCH_SENSITIVITY)
id = new ModelIdentifier("midi_rpn", "0");
}
if (id == null)
return null;
ModelSource msrc = new ModelSource(id);
ModelStandardTransform transform
= (ModelStandardTransform) msrc.getTransform();
if ((SF2Modulator.SOURCE_DIRECTION_MAX_MIN & src) != 0)
transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN);
else
transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX);
if ((SF2Modulator.SOURCE_POLARITY_BIPOLAR & src) != 0)
transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR);
else
transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR);
if ((SF2Modulator.SOURCE_TYPE_CONCAVE & src) != 0)
transform.setTransform(ModelStandardTransform.TRANSFORM_CONCAVE);
if ((SF2Modulator.SOURCE_TYPE_CONVEX & src) != 0)
transform.setTransform(ModelStandardTransform.TRANSFORM_CONVEX);
if ((SF2Modulator.SOURCE_TYPE_SWITCH & src) != 0)
transform.setTransform(ModelStandardTransform.TRANSFORM_SWITCH);
return msrc;
}
static ModelDestination convertDestination(int dst,
double[] amountcorrection, ModelSource[] extrasrc) {
ModelIdentifier id = null;
switch (dst) {
case SF2Region.GENERATOR_INITIALFILTERFC:
id = ModelDestination.DESTINATION_FILTER_FREQ;
break;
case SF2Region.GENERATOR_INITIALFILTERQ:
id = ModelDestination.DESTINATION_FILTER_Q;
break;
case SF2Region.GENERATOR_CHORUSEFFECTSSEND:
id = ModelDestination.DESTINATION_CHORUS;
break;
case SF2Region.GENERATOR_REVERBEFFECTSSEND:
id = ModelDestination.DESTINATION_REVERB;
break;
case SF2Region.GENERATOR_PAN:
id = ModelDestination.DESTINATION_PAN;
break;
case SF2Region.GENERATOR_DELAYMODLFO:
id = ModelDestination.DESTINATION_LFO1_DELAY;
break;
case SF2Region.GENERATOR_FREQMODLFO:
id = ModelDestination.DESTINATION_LFO1_FREQ;
break;
case SF2Region.GENERATOR_DELAYVIBLFO:
id = ModelDestination.DESTINATION_LFO2_DELAY;
break;
case SF2Region.GENERATOR_FREQVIBLFO:
id = ModelDestination.DESTINATION_LFO2_FREQ;
break;
case SF2Region.GENERATOR_DELAYMODENV:
id = ModelDestination.DESTINATION_EG2_DELAY;
break;
case SF2Region.GENERATOR_ATTACKMODENV:
id = ModelDestination.DESTINATION_EG2_ATTACK;
break;
case SF2Region.GENERATOR_HOLDMODENV:
id = ModelDestination.DESTINATION_EG2_HOLD;
break;
case SF2Region.GENERATOR_DECAYMODENV:
id = ModelDestination.DESTINATION_EG2_DECAY;
break;
case SF2Region.GENERATOR_SUSTAINMODENV:
id = ModelDestination.DESTINATION_EG2_SUSTAIN;
amountcorrection[0] = -1;
break;
case SF2Region.GENERATOR_RELEASEMODENV:
id = ModelDestination.DESTINATION_EG2_RELEASE;
break;
case SF2Region.GENERATOR_DELAYVOLENV:
id = ModelDestination.DESTINATION_EG1_DELAY;
break;
case SF2Region.GENERATOR_ATTACKVOLENV:
id = ModelDestination.DESTINATION_EG1_ATTACK;
break;
case SF2Region.GENERATOR_HOLDVOLENV:
id = ModelDestination.DESTINATION_EG1_HOLD;
break;
case SF2Region.GENERATOR_DECAYVOLENV:
id = ModelDestination.DESTINATION_EG1_DECAY;
break;
case SF2Region.GENERATOR_SUSTAINVOLENV:
id = ModelDestination.DESTINATION_EG1_SUSTAIN;
amountcorrection[0] = -1;
break;
case SF2Region.GENERATOR_RELEASEVOLENV:
id = ModelDestination.DESTINATION_EG1_RELEASE;
break;
case SF2Region.GENERATOR_KEYNUM:
id = ModelDestination.DESTINATION_KEYNUMBER;
break;
case SF2Region.GENERATOR_VELOCITY:
id = ModelDestination.DESTINATION_VELOCITY;
break;
case SF2Region.GENERATOR_COARSETUNE:
amountcorrection[0] = 100;
id = ModelDestination.DESTINATION_PITCH;
break;
case SF2Region.GENERATOR_FINETUNE:
id = ModelDestination.DESTINATION_PITCH;
break;
case SF2Region.GENERATOR_INITIALATTENUATION:
id = ModelDestination.DESTINATION_GAIN;
amountcorrection[0] = -0.376287f;
break;
case SF2Region.GENERATOR_VIBLFOTOPITCH:
id = ModelDestination.DESTINATION_PITCH;
extrasrc[0] = new ModelSource(
ModelSource.SOURCE_LFO2,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR);
break;
case SF2Region.GENERATOR_MODLFOTOPITCH:
id = ModelDestination.DESTINATION_PITCH;
extrasrc[0] = new ModelSource(
ModelSource.SOURCE_LFO1,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR);
break;
case SF2Region.GENERATOR_MODLFOTOFILTERFC:
id = ModelDestination.DESTINATION_FILTER_FREQ;
extrasrc[0] = new ModelSource(
ModelSource.SOURCE_LFO1,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR);
break;
case SF2Region.GENERATOR_MODLFOTOVOLUME:
id = ModelDestination.DESTINATION_GAIN;
amountcorrection[0] = -0.376287f;
extrasrc[0] = new ModelSource(
ModelSource.SOURCE_LFO1,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR);
break;
case SF2Region.GENERATOR_MODENVTOPITCH:
id = ModelDestination.DESTINATION_PITCH;
extrasrc[0] = new ModelSource(
ModelSource.SOURCE_EG2,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR);
break;
case SF2Region.GENERATOR_MODENVTOFILTERFC:
id = ModelDestination.DESTINATION_FILTER_FREQ;
extrasrc[0] = new ModelSource(
ModelSource.SOURCE_EG2,
ModelStandardTransform.DIRECTION_MIN2MAX,
ModelStandardTransform.POLARITY_BIPOLAR);
break;
default:
break;
}
if (id != null)
return new ModelDestination(id);
return null;
}
private void addTimecentValue(ModelPerformer performer,
ModelIdentifier dest, short value) {
double fvalue;
if (value == -12000)
fvalue = Double.NEGATIVE_INFINITY;
else
fvalue = value;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(fvalue, new ModelDestination(dest)));
}
private void addValue(ModelPerformer performer,
ModelIdentifier dest, short value) {
double fvalue = value;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(fvalue, new ModelDestination(dest)));
}
private void addValue(ModelPerformer performer,
ModelIdentifier dest, double value) {
double fvalue = value;
performer.getConnectionBlocks().add(
new ModelConnectionBlock(fvalue, new ModelDestination(dest)));
}
private short getGeneratorValue(Map<Integer, Short> generators, int gen) {
if (generators.containsKey(gen))
return generators.get(gen);
return SF2Region.getDefaultValue(gen);
}
}