912 lines
41 KiB
Java
912 lines
41 KiB
Java
/*
|
|
* 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);
|
|
}
|
|
}
|