view overlays/openjdk/jdk/src/share/classes/com/sun/media/sound/SoftPerformer.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.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * This class decodes information from ModelPeformer for use in SoftVoice. It
 * also adds default connections if they where missing in ModelPerformer.
 * 
 * @version %I%, %E%
 * @author Karl Helgason
 */
public class SoftPerformer {

	static ModelConnectionBlock[] defaultconnections = new ModelConnectionBlock[42];
	static {

		int o = 0;
		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("noteon", "on", 0),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 1,
				new ModelDestination(new ModelIdentifier("eg", "on", 0)));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("noteon", "on", 0),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 1,
				new ModelDestination(new ModelIdentifier("eg", "on", 1)));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("eg", "active", 0),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 1,
				new ModelDestination(new ModelIdentifier("mixer", "active", 0)));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("eg", 0),
				ModelStandardTransform.DIRECTION_MAX2MIN,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), -960,
				new ModelDestination(new ModelIdentifier("mixer", "gain")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("noteon", "velocity"),
				ModelStandardTransform.DIRECTION_MAX2MIN,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_CONCAVE), -960,
				new ModelDestination(new ModelIdentifier("mixer", "gain")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi", "pitch"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), new ModelSource(
				new ModelIdentifier("midi_rpn", "0"), new ModelTransform() {
					public double transform(double value) {
						int v = (int) (value * 16384.0);
						int msb = v >> 7;
						int lsb = v & 127;
						return msb * 100 + lsb;
					}
				}), new ModelDestination(new ModelIdentifier("osc", "pitch")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("noteon", "keynumber"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 12800,
				new ModelDestination(new ModelIdentifier("osc", "pitch")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "7"),
				ModelStandardTransform.DIRECTION_MAX2MIN,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_CONCAVE), -960,
				new ModelDestination(new ModelIdentifier("mixer", "gain")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "8"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 1000,
				new ModelDestination(new ModelIdentifier("mixer", "balance")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "10"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 1000,
				new ModelDestination(new ModelIdentifier("mixer", "pan")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "11"),
				ModelStandardTransform.DIRECTION_MAX2MIN,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_CONCAVE), -960,
				new ModelDestination(new ModelIdentifier("mixer", "gain")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "91"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 1000,
				new ModelDestination(new ModelIdentifier("mixer", "reverb")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "93"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 1000,
				new ModelDestination(new ModelIdentifier("mixer", "chorus")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "71"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 200,
				new ModelDestination(new ModelIdentifier("filter", "q")));
		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "74"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 9600,
				new ModelDestination(new ModelIdentifier("filter", "freq")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "72"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 6000,
				new ModelDestination(new ModelIdentifier("eg", "release2")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "73"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 2000,
				new ModelDestination(new ModelIdentifier("eg", "attack2")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "75"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 6000,
				new ModelDestination(new ModelIdentifier("eg", "decay2")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "67"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_SWITCH), -50,
				new ModelDestination(ModelDestination.DESTINATION_GAIN));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_cc", "67"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_UNIPOLAR,
				ModelStandardTransform.TRANSFORM_SWITCH), -2400,
				new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_rpn", "1"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 100,
				new ModelDestination(new ModelIdentifier("osc", "pitch")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("midi_rpn", "2"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 12800,
				new ModelDestination(new ModelIdentifier("osc", "pitch")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("master", "fine_tuning"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 100,
				new ModelDestination(new ModelIdentifier("osc", "pitch")));

		defaultconnections[o++] = new ModelConnectionBlock(new ModelSource(
				new ModelIdentifier("master", "coarse_tuning"),
				ModelStandardTransform.DIRECTION_MIN2MAX,
				ModelStandardTransform.POLARITY_BIPOLAR,
				ModelStandardTransform.TRANSFORM_LINEAR), 12800,
				new ModelDestination(new ModelIdentifier("osc", "pitch")));

		defaultconnections[o++] = new ModelConnectionBlock(13500,
				new ModelDestination(new ModelIdentifier("filter", "freq", 0)));

		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "delay", 0)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "attack", 0)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "hold", 0)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "decay", 0)));
		defaultconnections[o++] = new ModelConnectionBlock(1000,
				new ModelDestination(new ModelIdentifier("eg", "sustain", 0)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "release", 0)));
		defaultconnections[o++] = new ModelConnectionBlock(1200.0
				* Math.log(0.015) / Math.log(2), new ModelDestination(
				new ModelIdentifier("eg", "shutdown", 0))); // 15 msec default

		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "delay", 1)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "attack", 1)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "hold", 1)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "decay", 1)));
		defaultconnections[o++] = new ModelConnectionBlock(1000,
				new ModelDestination(new ModelIdentifier("eg", "sustain", 1)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("eg", "release", 1)));

		defaultconnections[o++] = new ModelConnectionBlock(-8.51318,
				new ModelDestination(new ModelIdentifier("lfo", "freq", 0)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("lfo", "delay", 0)));
		defaultconnections[o++] = new ModelConnectionBlock(-8.51318,
				new ModelDestination(new ModelIdentifier("lfo", "freq", 1)));
		defaultconnections[o++] = new ModelConnectionBlock(
				Float.NEGATIVE_INFINITY, new ModelDestination(
						new ModelIdentifier("lfo", "delay", 1)));

	}

	public int keyFrom = 0;

	public int keyTo = 127;

	public int velFrom = 0;

	public int velTo = 127;

	public int exclusiveClass = 0;

	public boolean selfNonExclusive = false;

	public boolean forcedVelocity = false;

	public boolean forcedKeynumber = false;

	public ModelPerformer performer;

	public ModelConnectionBlock[] connections;

	public ModelOscillator[] oscillators;

	public Map<Integer, int[]> midi_rpn_connections = new HashMap<Integer, int[]>();

	public Map<Integer, int[]> midi_nrpn_connections = new HashMap<Integer, int[]>();

	public int[][] midi_ctrl_connections;

	public int[][] midi_connections;

	public int[] ctrl_connections;

	private List<Integer> ctrl_connections_list = new ArrayList<Integer>();

	private static class KeySortComparator implements Comparator<ModelSource> {
		public int compare(ModelSource o1, ModelSource o2) {
			return o1.getIdentifier().toString().compareTo(
					o2.getIdentifier().toString());
		}
	}

	private static KeySortComparator keySortComparator = new KeySortComparator();

	private String extractKeys(ModelConnectionBlock conn) {
		StringBuffer sb = new StringBuffer();
		if (conn.getSources() != null) {
			sb.append("[");
			ModelSource[] srcs = conn.getSources();
			ModelSource[] srcs2 = new ModelSource[srcs.length];
			for (int i = 0; i < srcs.length; i++)
				srcs2[i] = srcs[i];
			Arrays.sort(srcs2, keySortComparator);
			for (int i = 0; i < srcs.length; i++) {
				sb.append(srcs[i].getIdentifier());
				sb.append(";");
			}
			sb.append("]");
		}
		sb.append(";");
		if (conn.getDestination() != null) {
			sb.append(conn.getDestination().getIdentifier());
		}
		sb.append(";");
		return sb.toString();
	}

	private void processSource(ModelSource src, int ix) {
		ModelIdentifier id = src.getIdentifier();
		String o = id.getObject();
		if (o.equals("midi_cc"))
			processMidiControlSource(src, ix);
		else if (o.equals("midi_rpn"))
			processMidiRpnSource(src, ix);
		else if (o.equals("midi_nrpn"))
			processMidiNrpnSource(src, ix);
		else if (o.equals("midi"))
			processMidiSource(src, ix);
		else if (o.equals("noteon"))
			processNoteOnSource(src, ix);
		else if (o.equals("osc"))
			return;
		else if (o.equals("mixer"))
			return;
		else
			ctrl_connections_list.add(ix);
	}

	private void processMidiControlSource(ModelSource src, int ix) {
		String v = src.getIdentifier().getVariable();
		if (v == null)
			return;
		int c = Integer.parseInt(v);
		if (midi_ctrl_connections[c] == null)
			midi_ctrl_connections[c] = new int[] { ix };
		else {
			int[] olda = midi_ctrl_connections[c];
			int[] newa = new int[olda.length + 1];
			for (int i = 0; i < olda.length; i++)
				newa[i] = olda[i];
			newa[newa.length - 1] = ix;
			midi_ctrl_connections[c] = newa;
		}
	}

	private void processNoteOnSource(ModelSource src, int ix) {
		String v = src.getIdentifier().getVariable();
		int c = -1;
		if (v.equals("on"))
			c = 3;
		if (v.equals("keynumber"))
			c = 4;
		if (c == -1)
			return;
		if (midi_connections[c] == null)
			midi_connections[c] = new int[] { ix };
		else {
			int[] olda = midi_connections[c];
			int[] newa = new int[olda.length + 1];
			for (int i = 0; i < olda.length; i++)
				newa[i] = olda[i];
			newa[newa.length - 1] = ix;
			midi_connections[c] = newa;
		}
	}

	private void processMidiSource(ModelSource src, int ix) {
		String v = src.getIdentifier().getVariable();
		int c = -1;
		if (v.equals("pitch"))
			c = 0;
		if (v.equals("channel_pressure"))
			c = 1;
		if (v.equals("poly_pressure"))
			c = 2;
		if (c == -1)
			return;
		if (midi_connections[c] == null)
			midi_connections[c] = new int[] { ix };
		else {
			int[] olda = midi_connections[c];
			int[] newa = new int[olda.length + 1];
			for (int i = 0; i < olda.length; i++)
				newa[i] = olda[i];
			newa[newa.length - 1] = ix;
			midi_connections[c] = newa;
		}
	}

	private void processMidiRpnSource(ModelSource src, int ix) {
		String v = src.getIdentifier().getVariable();
		if (v == null)
			return;
		int c = Integer.parseInt(v);
		if (midi_rpn_connections.get(c) == null)
			midi_rpn_connections.put(c, new int[] { ix });
		else {
			int[] olda = midi_rpn_connections.get(c);
			int[] newa = new int[olda.length + 1];
			for (int i = 0; i < olda.length; i++)
				newa[i] = olda[i];
			newa[newa.length - 1] = ix;
			midi_rpn_connections.put(c, newa);
		}
	}

	private void processMidiNrpnSource(ModelSource src, int ix) {
		String v = src.getIdentifier().getVariable();
		if (v == null)
			return;
		int c = Integer.parseInt(v);
		if (midi_nrpn_connections.get(c) == null)
			midi_nrpn_connections.put(c, new int[] { ix });
		else {
			int[] olda = midi_nrpn_connections.get(c);
			int[] newa = new int[olda.length + 1];
			for (int i = 0; i < olda.length; i++)
				newa[i] = olda[i];
			newa[newa.length - 1] = ix;
			midi_nrpn_connections.put(c, newa);
		}
	}

	public SoftPerformer(ModelPerformer performer) {
		this.performer = performer;

		keyFrom = performer.getKeyFrom();
		keyTo = performer.getKeyTo();
		velFrom = performer.getVelFrom();
		velTo = performer.getVelTo();
		exclusiveClass = performer.getExclusiveClass();
		selfNonExclusive = performer.isSelfNonExclusive();

		Map<String, ModelConnectionBlock> connmap = new HashMap<String, ModelConnectionBlock>();

		List<ModelConnectionBlock> performer_connections = new ArrayList<ModelConnectionBlock>();
		performer_connections.addAll(performer.getConnectionBlocks());

		if (performer.isDefaultConnectionsEnabled()) {

			// Add modulation depth range (RPN 5) to the modulation wheel (cc#1)

			boolean isModulationWheelConectionFound = false;
			for (int j = 0; j < performer_connections.size(); j++) {
				ModelConnectionBlock connection = performer_connections.get(j);
				ModelSource[] sources = connection.getSources();
				ModelDestination dest = connection.getDestination();
				boolean isModulationWheelConection = false;
				if (dest != null && sources != null && sources.length > 1)
					for (int i = 0; i < sources.length; i++) {
						// check if connection block has the source "modulation
						// wheel cc#1"
						if (sources[i].getIdentifier().getObject().equals(
								"midi_cc"))
							if (sources[i].getIdentifier().getVariable()
									.equals("1")) {
								isModulationWheelConection = true;
								isModulationWheelConectionFound = true;
								break;
							}
					}
				if (isModulationWheelConection) {

					ModelConnectionBlock newconnection = new ModelConnectionBlock();
					newconnection.setSources(connection.getSources());
					newconnection.setDestination(connection.getDestination());
					newconnection.addSource(new ModelSource(
							new ModelIdentifier("midi_rpn", "5")));
					newconnection.setScale(connection.getScale() * 256.0);
					performer_connections.set(j, newconnection);
				}
			}

			if (!isModulationWheelConectionFound) {
				ModelConnectionBlock conn = new ModelConnectionBlock(
						new ModelSource(ModelSource.SOURCE_LFO1,
								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));				
				conn.addSource(new ModelSource(new ModelIdentifier("midi_rpn",
						"5")));
				conn.setScale(conn.getScale() * 256.0); 
				performer_connections.add(conn);

			}

			// Let Aftertouch to behave just like modulation wheel (cc#1)
			boolean channel_pressure_set = false;
			boolean poly_pressure = false;
			ModelConnectionBlock mod_cc_1_connection = null;
			int mod_cc_1_connection_src_ix = 0;

			for (ModelConnectionBlock connection : performer_connections) {
				ModelSource[] sources = connection.getSources();
				ModelDestination dest = connection.getDestination();
				// if(dest != null && sources != null)
				if (dest != null && sources != null)
					for (int i = 0; i < sources.length; i++) {
						ModelIdentifier srcid = sources[i].getIdentifier();
						// check if connection block has the source "modulation
						// wheel cc#1"
						if (srcid.getObject().equals("midi_cc"))
							if (srcid.getVariable().equals("1")) {
								mod_cc_1_connection = connection;
								mod_cc_1_connection_src_ix = i;
							}
						// check if channel or poly pressure are already
						// connected
						if (srcid.getObject().equals("midi")) {
							if (srcid.getVariable().equals("channel_pressure"))
								channel_pressure_set = true;
							if (srcid.getVariable().equals("poly_pressure"))
								poly_pressure = true;
						}
					}

			}

			if (mod_cc_1_connection != null) {
				if (!channel_pressure_set) {
					ModelConnectionBlock mc = new ModelConnectionBlock();
					mc.setDestination(mod_cc_1_connection.getDestination());
					mc.setScale(mod_cc_1_connection.getScale());
					ModelSource[] src_list = mod_cc_1_connection.getSources();
					ModelSource[] src_list_new = new ModelSource[src_list.length];
					for (int i = 0; i < src_list_new.length; i++)
						src_list_new[i] = src_list[i];
					src_list_new[mod_cc_1_connection_src_ix] = new ModelSource(
							new ModelIdentifier("midi", "channel_pressure"));
					mc.setSources(src_list_new);
					connmap.put(extractKeys(mc), mc);
				}
				if (!poly_pressure) {
					ModelConnectionBlock mc = new ModelConnectionBlock();
					mc.setDestination(mod_cc_1_connection.getDestination());
					mc.setScale(mod_cc_1_connection.getScale());
					ModelSource[] src_list = mod_cc_1_connection.getSources();
					ModelSource[] src_list_new = new ModelSource[src_list.length];
					for (int i = 0; i < src_list_new.length; i++)
						src_list_new[i] = src_list[i];
					src_list_new[mod_cc_1_connection_src_ix] = new ModelSource(
							new ModelIdentifier("midi", "poly_pressure"));
					mc.setSources(src_list_new);
					connmap.put(extractKeys(mc), mc);
				}
			}

			// Enable Vibration Sound Controllers : 76, 77, 78
			ModelConnectionBlock found_vib_connection = null;
			for (ModelConnectionBlock connection : performer_connections) {
				ModelSource[] sources = connection.getSources();
				if (sources.length != 0
						&& sources[0].getIdentifier().getObject().equals("lfo"))
					if (connection.getDestination().getIdentifier().equals(
							ModelDestination.DESTINATION_PITCH)) {
						if (found_vib_connection == null)
							found_vib_connection = connection;
						else {
							if (found_vib_connection.getSources().length > sources.length)
								found_vib_connection = connection;
							else if (found_vib_connection.getSources()[0]
									.getIdentifier().getInstance() < 1)
								if (found_vib_connection.getSources()[0]
										.getIdentifier().getInstance() > sources[0]
										.getIdentifier().getInstance())
									found_vib_connection = connection;
						}

					}
			}

			int instance = 1;

			if (found_vib_connection != null)
				instance = found_vib_connection.getSources()[0].getIdentifier()
						.getInstance();
			ModelConnectionBlock connection;

			connection = new ModelConnectionBlock(new ModelSource(
					new ModelIdentifier("midi_cc", "78"),
					ModelStandardTransform.DIRECTION_MIN2MAX,
					ModelStandardTransform.POLARITY_BIPOLAR,
					ModelStandardTransform.TRANSFORM_LINEAR), 2000,
					new ModelDestination(new ModelIdentifier("lfo", "delay2",
							instance)));
			connmap.put(extractKeys(connection), connection);

			final double scale = found_vib_connection == null ? 0
					: found_vib_connection.getScale();
			connection = new ModelConnectionBlock(new ModelSource(
					new ModelIdentifier("lfo", instance)), new ModelSource(
					new ModelIdentifier("midi_cc", "77"), new ModelTransform() {
						double s = scale;

						public double transform(double value) {
							value = value * 2 - 1;
							value *= 600;
							if (s == 0) {
								return value;
							} else if (s > 0) {
								if (value < -s)
									value = -s;
								return value;
							} else {
								if (value < s)
									value = -s;
								return -value;
							}
						}
					}),
					new ModelDestination(ModelDestination.DESTINATION_PITCH));
			connmap.put(extractKeys(connection), connection);

			connection = new ModelConnectionBlock(new ModelSource(
					new ModelIdentifier("midi_cc", "76"),
					ModelStandardTransform.DIRECTION_MIN2MAX,
					ModelStandardTransform.POLARITY_BIPOLAR,
					ModelStandardTransform.TRANSFORM_LINEAR), 2400,
					new ModelDestination(new ModelIdentifier("lfo", "freq",
							instance)));
			connmap.put(extractKeys(connection), connection);

		}

		// Add default connection blocks
		if (performer.isDefaultConnectionsEnabled())
			for (ModelConnectionBlock connection : defaultconnections)
				connmap.put(extractKeys(connection), connection);
		// Add connection blocks from modelperformer
		for (ModelConnectionBlock connection : performer_connections)
			connmap.put(extractKeys(connection), connection);
		// seperate connection blocks : Init time, Midi Time, Midi/Control Time,
		// Control Time
		List<ModelConnectionBlock> connections = new ArrayList<ModelConnectionBlock>();

		midi_ctrl_connections = new int[128][];
		for (int i = 0; i < midi_ctrl_connections.length; i++) {
			midi_ctrl_connections[i] = null;
		}
		midi_connections = new int[5][];
		for (int i = 0; i < midi_connections.length; i++) {
			midi_connections[i] = null;
		}

		int ix = 0;
		boolean mustBeOnTop = false;

		for (ModelConnectionBlock connection : connmap.values()) {
			if (connection.getDestination() != null) {
				ModelDestination dest = connection.getDestination();
				ModelIdentifier id = dest.getIdentifier();
				if (id.getObject().equals("noteon")) {
					mustBeOnTop = true;
					if (id.getVariable().equals("keynumber"))
						forcedKeynumber = true;
					if (id.getVariable().equals("velocity"))
						forcedVelocity = true;
				}
			}
			if (mustBeOnTop) {
				connections.add(0, connection);
				mustBeOnTop = false;
			} else
				connections.add(connection);
		}

		for (ModelConnectionBlock connection : connections) {
			if (connection.getSources() != null) {
				ModelSource[] srcs = connection.getSources();
				for (int i = 0; i < srcs.length; i++) {
					processSource(srcs[i], ix);
				}
			}
			ix++;
		}

		this.connections = new ModelConnectionBlock[connections.size()];
		connections.toArray(this.connections);

		this.ctrl_connections = new int[ctrl_connections_list.size()];

		for (int i = 0; i < this.ctrl_connections.length; i++)
			this.ctrl_connections[i] = ctrl_connections_list.get(i);

		oscillators = new ModelOscillator[performer.getOscillators().size()];
		performer.getOscillators().toArray(oscillators);
		
		for(ModelConnectionBlock conn : connections)
		{
			if(conn.getDestination() != null)
			{
				if(isUnnecessaryTransform(conn.getDestination().getTransform()))					
				{
					conn.getDestination().setTransform(null);
				}
			}	
			if(conn.getSources() != null)
			{
				for(ModelSource src : conn.getSources())
				{
					if(isUnnecessaryTransform(src.getTransform()))					
					{
						src.setTransform(null);
					}
				}
			}
		}

	}
	
	private static boolean isUnnecessaryTransform(ModelTransform transform)
	{
		if(transform == null) return false;
		if(!(transform instanceof ModelStandardTransform)) return false;
		ModelStandardTransform stransform = (ModelStandardTransform)transform;
		if(stransform.getDirection() != ModelStandardTransform.DIRECTION_MIN2MAX) return false; 
		if(stransform.getPolarity() != ModelStandardTransform.POLARITY_UNIPOLAR) return false;
		if(stransform.getTransform() != ModelStandardTransform.TRANSFORM_LINEAR) return false;
		return false;
	}

}