/*
 * 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
/** * 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); } }