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

import javax.sound.midi.VoiceStatus;

/**
 * 
 * Software synthesizer voice class.
 * 
 * @version %I%, %E%
 * @author Karl Helgason
 */
public class SoftVoice extends VoiceStatus {

	public int exclusiveClass = 0;
	
	public boolean releaseTriggered = false;

	private int noteOn_noteNumber = 0;

	private int noteOn_velocity = 0;

	private int noteOff_velocity = 0;
	
	protected ModelChannelMixer channelmixer = null;

	protected double tunedKey = 0;

	protected SoftTuning tuning = null;

	protected SoftChannel stealer_channel = null;
	
	protected ModelConnectionBlock[] stealer_extendedConnectionBlocks = null;

	protected SoftPerformer stealer_performer = null;
	
	protected ModelChannelMixer stealer_channelmixer = null;

	protected int stealer_voiceID = -1;

	protected int stealer_noteNumber = 0;

	protected int stealer_velocity = 0;
	
	protected boolean stealer_releaseTriggered = false;

	protected int voiceID = -1;

	protected boolean sustain = false;

	protected boolean sostenuto = false;

	protected boolean portamento = false;

	private SoftFilter filter_left;

	private SoftFilter filter_right;

	private SoftProcess eg = new SoftEnvelopeGenerator();

	private SoftProcess lfo = new SoftLowFrequencyOscillator();

	protected Map<String, SoftControl> objects = new HashMap<String, SoftControl>();

	protected SoftSynthesizer synthesizer;

	protected SoftInstrument instrument;

	protected SoftPerformer performer;

	protected SoftChannel softchannel = null;

	protected boolean on = false;

	private boolean audiostarted = false;

	private boolean started = false;

	private boolean stopping = false;

	private float osc_attenuation = 0.0f;

	private ModelOscillatorStream osc_stream;;

	private int osc_stream_nrofchannels;

	private float[][] osc_buff = new float[2][];

	private boolean osc_stream_off_transmitted = false;

	private boolean out_mixer_end = false;

	private float out_mixer_left = 0;

	private float out_mixer_right = 0;

	private float out_mixer_effect1 = 0;

	private float out_mixer_effect2 = 0;

	private float last_out_mixer_left = 0;

	private float last_out_mixer_right = 0;

	private float last_out_mixer_effect1 = 0;

	private float last_out_mixer_effect2 = 0;
	
	protected ModelConnectionBlock[] extendedConnectionBlocks = null;

	private ModelConnectionBlock[] connections;

	private double[] connections_last = new double[50]; // Last value added to
														// destination

	private double[][][] connections_src = new double[50][3][]; // Pointer to
																// source value

	private int[][] connections_src_kc = new int[50][3]; // Key-based
															// override (if any)

	private double[][] connections_dst = new double[50][]; // Pointer to
															// destination value

	private boolean soundoff = false;

	private float lastMuteValue = 0;

	private float lastSoloMuteValue = 0;

	protected double[] co_noteon_keynumber = new double[1];

	protected double[] co_noteon_velocity = new double[1];

	protected double[] co_noteon_on = new double[1];

	private SoftControl co_noteon = new SoftControl() {
		double[] keynumber = co_noteon_keynumber;

		double[] velocity = co_noteon_velocity;

		double[] on = co_noteon_on;

		public double[] get(int instance, String name) {
			if (name == null)
				return null;
			if (name.equals("keynumber"))
				return keynumber;
			if (name.equals("velocity"))
				return velocity;
			if (name.equals("on"))
				return on;
			return null;
		}
	};

	private double[] co_mixer_active = new double[1];

	private double[] co_mixer_gain = new double[1];

	private double[] co_mixer_pan = new double[1];

	private double[] co_mixer_balance = new double[1];

	private double[] co_mixer_reverb = new double[1];

	private double[] co_mixer_chorus = new double[1];

	private SoftControl co_mixer = new SoftControl() {
		double[] active = co_mixer_active;

		double[] gain = co_mixer_gain;

		double[] pan = co_mixer_pan;

		double[] balance = co_mixer_balance;

		double[] reverb = co_mixer_reverb;

		double[] chorus = co_mixer_chorus;

		public double[] get(int instance, String name) {
			if (name == null)
				return null;
			if (name.equals("active"))
				return active;
			if (name.equals("gain"))
				return gain;
			if (name.equals("pan"))
				return pan;
			if (name.equals("balance"))
				return balance;
			if (name.equals("reverb"))
				return reverb;
			if (name.equals("chorus"))
				return chorus;
			return null;
		}
	};

	private double[] co_osc_pitch = new double[1];

	private SoftControl co_osc = new SoftControl() {
		double[] pitch = co_osc_pitch;

		public double[] get(int instance, String name) {
			if (name == null)
				return null;
			if (name.equals("pitch"))
				return pitch;
			return null;
		}
	};

	private double[] co_filter_freq = new double[1];

	private double[] co_filter_type = new double[1];

	private double[] co_filter_q = new double[1];

	private SoftControl co_filter = new SoftControl() {
		double[] freq = co_filter_freq;

		double[] ftype = co_filter_type;

		double[] q = co_filter_q;

		public double[] get(int instance, String name) {
			if (name == null)
				return null;
			if (name.equals("freq"))
				return freq;
			if (name.equals("type"))
				return ftype;
			if (name.equals("q"))
				return q;
			return null;
		}
	};

	protected SoftResamplerStreamer resampler;

	private int nrofchannels;

	public SoftVoice(SoftSynthesizer synth) {
		synthesizer = synth;
		filter_left = new SoftFilter(synth.getFormat().getSampleRate());
		filter_right = new SoftFilter(synth.getFormat().getSampleRate());
		nrofchannels = synth.getFormat().getChannels();
	}

	private int getValueKC(ModelIdentifier id) {
		if (id.getObject().equals("midi_cc")) {
			int ic = Integer.parseInt(id.getVariable());
			if (ic != 0 && ic != 32)
				if (ic < 120) {
					return ic;
				}
		} else if (id.getObject().equals("midi_rpn")) {
			if (id.getVariable().equals("1"))
				return 120; // Fine tuning
			if (id.getVariable().equals("2"))
				return 121; // Coarse tuning
		}
		return -1;
	}

	private double[] getValue(ModelIdentifier id) {
		SoftControl o = objects.get(id.getObject());
		if (o == null)
			return null;
		return o.get(id.getInstance(), id.getVariable());
	}

	private double transformValue(double value, ModelSource src) {
		if (src.getTransform() != null)
			return src.getTransform().transform(value);
		else
			return value;
	}

	private double transformValue(double value, ModelDestination dst) {
		if (dst.getTransform() != null)
			return dst.getTransform().transform(value);
		else
			return value;
	}

	private double processKeyBasedController(double value, int keycontrol) {
		if (keycontrol == -1)
			return value;
		if (softchannel.keybasedcontroller_active != null)
			if (softchannel.keybasedcontroller_active[note] != null)
				if (softchannel.keybasedcontroller_active[note][keycontrol]) {
					double key_controlvalue = softchannel.keybasedcontroller_value[note][keycontrol];
					if (keycontrol == 10 || keycontrol == 91
							|| keycontrol == 93)
						return key_controlvalue;
					value += key_controlvalue * 2.0 - 1.0;
					if (value > 1)
						value = 1;
					else if (value < 0)
						value = 0;
				}
		return value;
	}

	private void processConnection(int ix) {
		ModelConnectionBlock conn = connections[ix];
		double[][] src = connections_src[ix];		
		double[] dst = connections_dst[ix];
		if (dst == null || Double.isInfinite(dst[0]))
			return;

		double value = conn.getScale();
		if(softchannel.keybasedcontroller_active == null)
		{
			ModelSource[] srcs = conn.getSources();
			for (int i = 0; i < srcs.length; i++) {
				value *= transformValue(src[i][0], srcs[i]);
				if(value == 0) break;
			}
		}
		else
		{
			ModelSource[] srcs = conn.getSources();
			int[] src_kc = connections_src_kc[ix];
			for (int i = 0; i < srcs.length; i++) {
				value *= transformValue(processKeyBasedController(src[i][0],
					src_kc[i]), srcs[i]);
				if(value == 0) break;
			}
		}

		value = transformValue(value, conn.getDestination());
		dst[0] = dst[0] - connections_last[ix] + value;
		connections_last[ix] = value;
		// co_mixer_gain[0] = 0;

		
	}

	protected void updateTuning(SoftTuning newtuning) {
		tunedKey = tuning.getTuning(note) / 100.0;
		if (!portamento) {
			co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
			;
			int[] c = performer.midi_connections[4];
			if (c == null)
				return;
			for (int i = 0; i < c.length; i++)
				processConnection(c[i]);
		}
	}

	protected void setNote(int noteNumber) {
		note = noteNumber;
		tunedKey = tuning.getTuning(noteNumber) / 100.0;
	}
	
	protected void noteOn(int noteNumber, int velocity) {
		
		sustain = false;
		sostenuto = false;
		portamento = false;

		soundoff = false;
		on = true;
		active = true;
		started = true;
		// volume = velocity;

		noteOn_noteNumber = noteNumber;
		noteOn_velocity = velocity;

		lastMuteValue = 0;
		lastSoloMuteValue = 0;

		setNote(noteNumber);

		if (performer.forcedKeynumber)
			co_noteon_keynumber[0] = 0;
		else
			co_noteon_keynumber[0] = tunedKey * (1f / 128f);
		if (performer.forcedVelocity)
			co_noteon_velocity[0] = 0;
		else
			co_noteon_velocity[0] = velocity * (1f / 128f);
		co_mixer_active[0] = 0;
		co_mixer_gain[0] = 0;
		co_mixer_pan[0] = 0;
		co_mixer_balance[0] = 0;
		co_mixer_reverb[0] = 0;
		co_mixer_chorus[0] = 0;
		co_osc_pitch[0] = 0;
		co_filter_freq[0] = 0;
		co_filter_q[0] = 0;
		co_filter_type[0] = 0;
		co_noteon_on[0] = 1;

		eg.reset();
		lfo.reset();
		filter_left.reset();
		filter_right.reset();

		objects.put("master", synthesizer.getMainMixer().co_master);
		objects.put("eg", eg);
		objects.put("lfo", lfo);
		objects.put("noteon", co_noteon);
		objects.put("osc", co_osc);
		objects.put("mixer", co_mixer);
		objects.put("filter", co_filter);

		connections = performer.connections;

		if (connections_last == null
				|| connections_last.length < connections.length)
			connections_last = new double[connections.length];
		if (connections_src == null
				|| connections_src.length < connections.length) {
			connections_src = new double[connections.length][][];
			connections_src_kc = new int[connections.length][];
		}
		if (connections_dst == null
				|| connections_dst.length < connections.length)
			connections_dst = new double[connections.length][];
		for (int i = 0; i < connections.length; i++) {
			ModelConnectionBlock conn = connections[i];
			connections_last[i] = 0;
			if (conn.getSources() != null) {
				ModelSource[] srcs = conn.getSources();
				if (connections_src[i] == null
						|| connections_src[i].length < srcs.length) {
					connections_src[i] = new double[srcs.length][];
					connections_src_kc[i] = new int[srcs.length];
				}
				double[][] src = connections_src[i];
				int[] src_kc = connections_src_kc[i];
				connections_src[i] = src;
				for (int j = 0; j < srcs.length; j++) {
					src_kc[j] = getValueKC(srcs[j].getIdentifier());
					src[j] = getValue(srcs[j].getIdentifier());
				}
			}

			if (conn.getDestination() != null)
				connections_dst[i] = getValue(conn.getDestination()
						.getIdentifier());
			else
				connections_dst[i] = null;
		}

		for (int i = 0; i < connections.length; i++)
			processConnection(i);
		
		
		if(extendedConnectionBlocks != null)
		{
			for (ModelConnectionBlock connection : extendedConnectionBlocks) {
				
				double value = 0;
				
				if(softchannel.keybasedcontroller_active == null)
				{					
					for(ModelSource src : connection.getSources())
					{
						double x = getValue(src.getIdentifier())[0];
						ModelTransform t = src.getTransform();
						if(t == null)
							value += x;
						else
							value += t.transform(x);
					}
				}
				else
				{
					for(ModelSource src : connection.getSources())
					{
						double x = getValue(src.getIdentifier())[0];
						x = processKeyBasedController(x, getValueKC(src.getIdentifier()));
						ModelTransform t = src.getTransform();
						if(t == null)
							value += x;
						else
							value += t.transform(x);
					}					
				}

				ModelDestination dest = connection.getDestination();
				ModelTransform t = dest.getTransform();
				if(t != null)
					value = t.transform(value);
				getValue(dest.getIdentifier())[0] += value;
				
			}
		} 

		eg.init(synthesizer);
		lfo.init(synthesizer);

	}

	protected void setPolyPressure(int pressure) {
		int[] c = performer.midi_connections[2];
		if (c == null)
			return;
		for (int i = 0; i < c.length; i++)
			processConnection(c[i]);
	}

	protected void setChannelPressure(int pressure) {
		int[] c = performer.midi_connections[1];
		if (c == null)
			return;
		for (int i = 0; i < c.length; i++)
			processConnection(c[i]);
	}

	protected void controlChange(int controller, int value) {
		int[] c = performer.midi_ctrl_connections[controller];
		if (c == null)
			return;
		for (int i = 0; i < c.length; i++)
			processConnection(c[i]);
	}

	protected void nrpnChange(int controller, int value) {
		int[] c = performer.midi_nrpn_connections.get(controller);
		if (c == null)
			return;
		for (int i = 0; i < c.length; i++)
			processConnection(c[i]);

	}

	protected void rpnChange(int controller, int value) {
		int[] c = performer.midi_rpn_connections.get(controller);
		if (c == null)
			return;
		for (int i = 0; i < c.length; i++)
			processConnection(c[i]);
	}

	protected void setPitchBend(int bend) {
		int[] c = performer.midi_connections[0];
		if (c == null)
			return;
		for (int i = 0; i < c.length; i++)
			processConnection(c[i]);

	}

	protected void setMute(boolean mute) {
		co_mixer_gain[0] -= lastMuteValue;
		lastMuteValue = mute ? -960 : 0;
		co_mixer_gain[0] += lastMuteValue;
	}

	protected void setSoloMute(boolean mute) {
		co_mixer_gain[0] -= lastSoloMuteValue;
		lastSoloMuteValue = mute ? -960 : 0;
		co_mixer_gain[0] += lastSoloMuteValue;
	}

	protected void shutdown() {
		if (co_noteon_on[0] < -0.5)
			return;
		on = false;

		co_noteon_on[0] = -1;

		int[] c = performer.midi_connections[3];
		if (c == null)
			return;
		for (int i = 0; i < c.length; i++)
			processConnection(c[i]);

	}

	protected void soundOff() {
		on = false;
		soundoff = true;
	}

	protected void noteOff(int velocity) {
		if (!on)
			return;
		on = false;

		noteOff_velocity = velocity;

		if (softchannel.sustain) {
			sustain = true;
			return;
		}
		if (sostenuto)
			return;

		co_noteon_on[0] = 0;

		int[] c = performer.midi_connections[3];
		if (c == null)
			return;
		for (int i = 0; i < c.length; i++)
			processConnection(c[i]);

	}

	protected void redamp() {
		if (co_noteon_on[0] > 0.5)
			return;
		if (co_noteon_on[0] < -0.5)
			return; // don't redamp notes in shutdown stage

		sustain = true;
		co_noteon_on[0] = 1;

		int[] c = performer.midi_connections[3];
		if (c == null)
			return;
		for (int i = 0; i < c.length; i++)
			processConnection(c[i]);

	}

	protected void processControlLogic() {
		
		
		
		if (stopping) {
			active = false;
			stopping = false;
			audiostarted = false;
			if (osc_stream != null)
				try {
					osc_stream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			if (stealer_channel != null) {
				stealer_channel.initVoice(this, stealer_performer,
				stealer_voiceID, stealer_noteNumber, stealer_velocity, stealer_extendedConnectionBlocks, stealer_channelmixer, stealer_releaseTriggered);
				stealer_releaseTriggered = false;
				stealer_channel = null;
				stealer_performer = null;				
				stealer_voiceID = -1;
				stealer_noteNumber = 0;
				stealer_velocity = 0;
				stealer_extendedConnectionBlocks = null;
				stealer_channelmixer = null;
			}
		}
		if (started) {
			audiostarted = true;
			
			ModelOscillator osc = performer.oscillators[0];

			osc_stream_off_transmitted = false;
			if (osc instanceof ModelWavetable) {
				try {
					resampler.open((ModelWavetable) osc, synthesizer
							.getFormat().getSampleRate());
					osc_stream = resampler;
				} catch (IOException e) {
					e.printStackTrace();
				}
			} else {
				osc_stream = osc.open(synthesizer.getFormat().getSampleRate());
			}
			osc_attenuation = osc.getAttenuation();
			osc_stream_nrofchannels = osc.getChannels();
			if (osc_buff == null || osc_buff.length < osc_stream_nrofchannels)
				osc_buff = new float[osc_stream_nrofchannels][];

			if (osc_stream != null)
				osc_stream.noteOn(softchannel, this, noteOn_noteNumber,
						noteOn_velocity);
						

		}
		if (audiostarted) {
			
			if (portamento) {

				double note_delta = tunedKey - (co_noteon_keynumber[0] * 128);
				double note_delta_a = Math.abs(note_delta);
				if (note_delta_a < 0.0000000001) {
					co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
					;
					portamento = false;

				} else {
					if (note_delta_a > softchannel.portamento_time)
						note_delta = Math.signum(note_delta)
								* softchannel.portamento_time;
					co_noteon_keynumber[0] += note_delta * (1.0 / 128.0);
				}

				int[] c = performer.midi_connections[4];
				if (c == null)
					return;
				for (int i = 0; i < c.length; i++)
					processConnection(c[i]);

			}

			eg.processControlLogic();			
			lfo.processControlLogic();
			
			for (int i = 0; i < performer.ctrl_connections.length; i++)
				processConnection(performer.ctrl_connections[i]);

			osc_stream.setPitch((float) co_osc_pitch[0]);

			int filter_type = (int) co_filter_type[0];
			double filter_freq;
			
			if(co_filter_freq[0] == 13500.0)
				filter_freq = 19912.126958213175;
			else
				filter_freq = 440.0 * Math.exp(
						((co_filter_freq[0]) - 6900.0) * (Math.log(2.0)/ 1200.0));
			/*
				filter_freq = 440.0 * Math.pow(2.0,
					((co_filter_freq[0]) - 6900.0) / 1200.0);*/
			/*
			 * double velocity = co_noteon_velocity[0]; if(velocity < 0.5)
			 * filter_freq *= ((velocity * 2)*0.75 + 0.25);
			 */
			
			double q = co_filter_q[0] / 10.0;
			filter_left.setFilterType(filter_type);
			filter_left.setFrequency(filter_freq);
			filter_left.setResonance(q);
			filter_right.setFilterType(filter_type);
			filter_right.setFrequency(filter_freq);
			filter_right.setResonance(q);
			/*
			float gain = (float) Math.pow(10,					
					(-osc_attenuation + co_mixer_gain[0]) / 200.0);
			*/
			float gain = (float) Math.exp((					
					(-osc_attenuation + co_mixer_gain[0]) * ( Math.log(10)/ 200.0))); 
			
			if (co_mixer_gain[0] <= -960)
				gain = 0;

			if (soundoff) {
				stopping = true;
				gain = 0;
				/*
				 * if(co_mixer_gain[0] > -960) co_mixer_gain[0] -= 960;
				 */
			}

			volume = (int) (Math.sqrt(gain) * 128);

			// gain *= 0.2;

			double pan = co_mixer_pan[0] * (1.0 / 1000.0);
			// System.out.println("pan = " + pan);
			if (pan < 0)
				pan = 0;
			else if (pan > 1)
				pan = 1;

			if(pan == 0.5)
			{
				out_mixer_left = gain * 0.7071067811865476f;
				out_mixer_right = out_mixer_left;				
			}
			else
			{
				out_mixer_left = gain * (float) Math.cos(pan * Math.PI * 0.5);
				out_mixer_right = gain * (float) Math.sin(pan * Math.PI * 0.5);
			}

			double balance = co_mixer_balance[0] * (1.0 / 1000.0);
			if(balance != 0.5)
			{
				if (balance > 0.5)
					out_mixer_left *= (1 - balance) * 2;
				else			
					out_mixer_right *= balance * 2;
			}

			if(synthesizer.reverb_on)
			{
				out_mixer_effect1 = (float) (co_mixer_reverb[0] * (1.0 / 1000.0));
				out_mixer_effect1 *= gain;
			}
			else
				out_mixer_effect1 = 0;			
			if(synthesizer.chorus_on)
			{
				out_mixer_effect2 = (float) (co_mixer_chorus[0] * (1.0 / 1000.0));
				out_mixer_effect2 *= gain;
			}
			else
				out_mixer_effect2 = 0;
			out_mixer_end = co_mixer_active[0] < 0.5;

			if (!on)
				if (!osc_stream_off_transmitted) {
					osc_stream_off_transmitted = true;
					if (osc_stream != null)
						osc_stream.noteOff(noteOff_velocity);
				}
			
		}
		if (started) {
			last_out_mixer_left = out_mixer_left;
			last_out_mixer_right = out_mixer_right;
			last_out_mixer_effect1 = out_mixer_effect1;
			last_out_mixer_effect2 = out_mixer_effect2;
			started = false;
		}
				
	}

	protected void mixAudioStream(SoftAudioBuffer in, SoftAudioBuffer out,
			float amp_from, float amp_to) {
		int bufferlen = in.getSize();
		if (amp_from < 0.000000001 && amp_to < 0.000000001)
			return;
		if (amp_from == amp_to) {
			float[] fout = out.array();
			float[] fin = in.array();
			for (int i = 0; i < bufferlen; i++)
				fout[i] += fin[i] * amp_to;
		} else {
			float amp = amp_from;
			float amp_delta = (amp_to - amp_from) / bufferlen;
			float[] fout = out.array();
			float[] fin = in.array();
			for (int i = 0; i < bufferlen; i++) {
				amp += amp_delta;
				fout[i] += fin[i] * amp;
			}
		}

	}
	
	protected void processAudioLogic(SoftAudioBuffer[] buffer) {
		if (!audiostarted)
			return;
		
		int bufferlen = buffer[0].getSize();
 
		try {
			osc_buff[0] = buffer[SoftMainMixer.CHANNEL_LEFT_DRY].array();
			if(nrofchannels != 1)
				osc_buff[1] = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY].array();
			int ret = osc_stream.read(osc_buff, 0, bufferlen);
			if (ret == -1) {
				stopping = true;
				return;
			}
			if (ret != bufferlen) {				
				Arrays.fill(osc_buff[0], ret, bufferlen, 0f);
				if(nrofchannels != 1)
					Arrays.fill(osc_buff[1], ret, bufferlen, 0f);
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
		
		SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT];
		SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT];
		SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1];
		SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2];
		SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY];
		SoftAudioBuffer rightdry = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY];

		if (osc_stream_nrofchannels == 1)
			rightdry = null;

		if (!Double.isInfinite(co_filter_freq[0])) {
			filter_left.processAudio(leftdry);
			if (rightdry != null)
				filter_right.processAudio(rightdry);
		}

		if (nrofchannels == 1) {
			out_mixer_left = (out_mixer_left + out_mixer_right) / 2;
			mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
			if (rightdry != null)
				mixAudioStream(rightdry, left, last_out_mixer_left,
						out_mixer_left);
		} else {
			mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left);
			if (rightdry != null)
				mixAudioStream(rightdry, right, last_out_mixer_right,
						out_mixer_right);
			else
				mixAudioStream(leftdry, right, last_out_mixer_right,
						out_mixer_right);
		}

		if (rightdry == null) {			
			mixAudioStream(leftdry, eff1, last_out_mixer_effect1,
					out_mixer_effect1);
			mixAudioStream(leftdry, eff2, last_out_mixer_effect2,
					out_mixer_effect2);
		} else {
			mixAudioStream(leftdry, eff1, last_out_mixer_effect1 * 0.5f,
					out_mixer_effect1 * 0.5f);
			mixAudioStream(leftdry, eff2, last_out_mixer_effect2 * 0.5f,
					out_mixer_effect2 * 0.5f);
			mixAudioStream(rightdry, eff1, last_out_mixer_effect1 * 0.5f,
					out_mixer_effect1 * 0.5f);
			mixAudioStream(rightdry, eff2, last_out_mixer_effect2 * 0.5f,
					out_mixer_effect2 * 0.5f);
		}

		last_out_mixer_left = out_mixer_left;
		last_out_mixer_right = out_mixer_right;
		last_out_mixer_effect1 = out_mixer_effect1;
		last_out_mixer_effect2 = out_mixer_effect2;

		if (out_mixer_end) {
			stopping = true;
		}
		

	}

}