view overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/DLSInstrument.java @ 843:bcba163568ac

Integrate Gervill. 2008-04-30 Mark Wielaard <mark@klomp.org> * Makefile.am (ICEDTEA_PATCHES): Add patches/icedtea-gervill.patch. * Makefile.in: Regenerated. * patches/icedtea-gervill.patch: New patch. * overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/*: New Gervill files.
author Mark Wielaard <mark@klomp.org>
date Wed, 30 Apr 2008 22:09:08 +0200
parents
children
line wrap: on
line source

/*
  * Copyright 2007 Sun Microsystems, Inc.  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.  Sun designates this
  * particular file as subject to the "Classpath" exception as provided
  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  * CA 95054 USA or visit www.sun.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;

/**
 * This class is used to store information 
 * to describe instrument. I 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.
 *
 * @version %I%, %E%
 * @author Karl Helgason
 */ 
public class DLSInstrument extends ModelInstrument {
	
	protected int preset = 0;
	protected int bank = 0;
	
	protected boolean druminstrument = false;	
	protected byte[] guid = null;
	
	protected DLSInfo info = new DLSInfo();
	
	protected List<DLSRegion> regions = new ArrayList<DLSRegion>();
	protected 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;
	}

	public void setGuid(byte[] guid) {
		this.guid = guid;
	}

}