/* OscFilterArray.c */
/*****************************************************************************/
/*                                                                           */
/*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
/*    Copyright (C) 1994  Thomas R. Lawrence                                 */
/*                                                                           */
/*    This program is free software; you can redistribute it and/or modify   */
/*    it under the terms of the GNU General Public License as published by   */
/*    the Free Software Foundation; either version 2 of the License, or      */
/*    (at your option) any later version.                                    */
/*                                                                           */
/*    This program 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 for more details.                           */
/*                                                                           */
/*    You should have received a copy of the GNU General Public License      */
/*    along with this program; if not, write to the Free Software            */
/*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
/*                                                                           */
/*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
/*                                                                           */
/*****************************************************************************/

#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"

#include "OscFilterArray.h"
#include "Memory.h"
#include "FilterSpec.h"
#include "FilterFirstOrderLowpass.h"
#include "FilterFirstOrderHighpass.h"
#include "FilterSecondOrderReson.h"
#include "FilterSecondOrderZero.h"
#include "FilterButterworthLowpass.h"
#include "FilterButterworthHighpass.h"
#include "FilterButterworthBandpass.h"
#include "FilterButterworthBandreject.h"
#include "FilterNull.h"
#include "EnvelopeState.h"
#include "LFOGenerator.h"
#include "FilterParametricEqualizer.h"
#include "FilterResonantLowpass.h"


typedef struct OscFilterRec
	{
		struct OscFilterRec*		Next;
		union
			{
				FirstOrderLowpassRec*			FirstOrderLowpass;
				FirstOrderHighpassRec*		FirstOrderHighpass;
				SecondOrderResonRec*			SecondOrderReson;
				SecondOrderZeroRec*				SecondOrderZero;
				ButterworthLowpassRec*		ButterworthLowpass;
				ButterworthHighpassRec*		ButterworthHighpass;
				ButterworthBandpassRec*		ButterworthBandpass;
				ButterworthBandrejectRec*	ButterworthBandreject;
				ParametricEqualizerRec*		ParamEQ;
				FilterNullRec*						NullFilter;
				ResonantLowpassRec*				ResonantLowpass;
				void*											GenericRef;
			} Left;
		union
			{
				FirstOrderLowpassRec*			FirstOrderLowpass;
				FirstOrderHighpassRec*		FirstOrderHighpass;
				SecondOrderResonRec*			SecondOrderReson;
				SecondOrderZeroRec*				SecondOrderZero;
				ButterworthLowpassRec*		ButterworthLowpass;
				ButterworthHighpassRec*		ButterworthHighpass;
				ButterworthBandpassRec*		ButterworthBandpass;
				ButterworthBandrejectRec*	ButterworthBandreject;
				ParametricEqualizerRec*		ParamEQ;
				FilterNullRec*						NullFilter;
				ResonantLowpassRec*				ResonantLowpass;
				void*											GenericRef;
			} Right;
		float								(*ApplyFilter)(void* Ref, float Xin);
		float								CurrentMultiplier;
		FilterTypes					FilterType;
		FilterScalings			FilterScaling;
		EvalEnvelopeRec*		CutoffEnvelope;
		LFOGenRec*					CutoffLFO;
		EvalEnvelopeRec*		BandwidthEnvelope;
		LFOGenRec*					BandwidthLFO;
		EvalEnvelopeRec*		OutputMultiplierEnvelope;
		LFOGenRec*					OutputMultiplierLFO;
		EvalEnvelopeRec*		GainEnvelope;
		LFOGenRec*					GainLFO;
	} OscFilterRec;


struct OscFilterArrayRec
	{
		/* list of filters to process */
		OscFilterRec*				Filters;

		/* stuff */
		long								SamplingRate;
		MyBoolean						StereoFlag;
		float								EnvelopeTicksPerSecond;

		/* garbage link */
		OscFilterArrayRec*	Next;
	};


static OscFilterArrayRec*			OscFilterArrayFreeList = NIL;
static OscFilterRec*					OscFilterFreeList = NIL;


/* flush cached filter array records */
void								FlushCachedOscFilterArrayStuff(void)
	{
		while (OscFilterArrayFreeList != NIL)
			{
				OscFilterArrayRec*		Temp;

				Temp = OscFilterArrayFreeList;
				OscFilterArrayFreeList = OscFilterArrayFreeList->Next;
				ReleasePtr((char*)Temp);
			}
		while (OscFilterFreeList != NIL)
			{
				OscFilterRec*					Temp;

				Temp = OscFilterFreeList;
				OscFilterFreeList = OscFilterFreeList->Next;
				ReleasePtr((char*)Temp);
			}
	}


/* create a new parallel filter processor */
OscFilterArrayRec*	NewOscFilterArrayProcessor(struct FilterSpecRec* Template,
											float EnvelopeTicksPerSecond, long SamplingRate,
											struct MainWindowRec* MainWindow, AccentParam* Accents,
											float HurryUp, float InitialFrequency, float FreqForMultisampling,
											long* PreOriginTimeOut, MyBoolean StereoFlag)
	{
		OscFilterArrayRec*	Array;
		long								Scan;
		long								Limit;
		long								MaxPreOrigin;
		long								OnePreOrigin;

		CheckPtrExistence(Template);
		if (OscFilterArrayFreeList != NIL)
			{
				Array = OscFilterArrayFreeList;
				OscFilterArrayFreeList = OscFilterArrayFreeList->Next;
			}
		 else
			{
				Array = (OscFilterArrayRec*)AllocPtrCanFail(sizeof(OscFilterArrayRec),
					"OscFilterArrayRec");
				if (Array == NIL)
					{
					 FailurePoint1:
						return NIL;
					}
			}

		MaxPreOrigin = 0;

		Array->SamplingRate = SamplingRate;
		Array->StereoFlag = StereoFlag;
		Array->EnvelopeTicksPerSecond = EnvelopeTicksPerSecond;

		Array->Filters = NIL;
		Limit = GetNumFiltersInSpec(Template);
		for (Scan = 0; Scan < Limit; Scan += 1)
			{
				OscFilterRec*		Filter;
				MyBoolean				LeftChannel;
				MyBoolean				RightChannel;

				if (OscFilterFreeList != NIL)
					{
						Filter = OscFilterFreeList;
						OscFilterFreeList = OscFilterFreeList->Next;
					}
				 else
					{
						Filter = (OscFilterRec*)AllocPtrCanFail(sizeof(OscFilterRec),"OscFilterRec");
						if (Filter == NIL)
							{
							 FailurePoint2:
								while (Array->Filters != NIL)
									{
										Filter = Array->Filters;
										Array->Filters = Array->Filters->Next;
										switch (Filter->FilterType)
											{
												default:
													EXECUTE(PRERR(ForceAbort,"NewOscFilterArrayProcessor:  bad filter type"));
													break;
												case eFilterFirstOrderLowpass:
													if (Filter->Left.FirstOrderLowpass != NIL)
														{
															DisposeFirstOrderLowpass(Filter->Left.FirstOrderLowpass);
														}
													if (Filter->Right.FirstOrderLowpass != NIL)
														{
															DisposeFirstOrderLowpass(Filter->Right.FirstOrderLowpass);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													ERROR((Filter->BandwidthEnvelope != NIL)
														|| (Filter->BandwidthLFO != NIL),PRERR(AllowResume,
														"NewOscFilterArrayProcessor:  filter constructor problem"));
													break;
												case eFilterFirstOrderHighpass:
													if (Filter->Left.FirstOrderHighpass != NIL)
														{
															DisposeFirstOrderHighpass(Filter->Left.FirstOrderHighpass);
														}
													if (Filter->Right.FirstOrderHighpass != NIL)
														{
															DisposeFirstOrderHighpass(Filter->Right.FirstOrderHighpass);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													ERROR((Filter->BandwidthEnvelope != NIL)
														|| (Filter->BandwidthLFO != NIL),PRERR(AllowResume,
														"NewOscFilterArrayProcessor:  filter constructor problem"));
													break;
												case eFilterSecondOrderResonant:
													if (Filter->Left.SecondOrderReson != NIL)
														{
															DisposeSecondOrderReson(Filter->Left.SecondOrderReson);
														}
													if (Filter->Right.SecondOrderReson != NIL)
														{
															DisposeSecondOrderReson(Filter->Right.SecondOrderReson);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													DisposeEnvelopeStateRecord(Filter->BandwidthEnvelope);
													DisposeLFOGenerator(Filter->BandwidthLFO);
													break;
												case eFilterSecondOrderZero:
													if (Filter->Left.SecondOrderZero != NIL)
														{
															DisposeSecondOrderZero(Filter->Left.SecondOrderZero);
														}
													if (Filter->Right.SecondOrderZero != NIL)
														{
															DisposeSecondOrderZero(Filter->Right.SecondOrderZero);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													DisposeEnvelopeStateRecord(Filter->BandwidthEnvelope);
													DisposeLFOGenerator(Filter->BandwidthLFO);
													break;
												case eFilterButterworthLowpass:
													if (Filter->Left.ButterworthLowpass != NIL)
														{
															DisposeButterworthLowpass(Filter->Left.ButterworthLowpass);
														}
													if (Filter->Right.ButterworthLowpass != NIL)
														{
															DisposeButterworthLowpass(Filter->Right.ButterworthLowpass);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													ERROR((Filter->BandwidthEnvelope != NIL)
														|| (Filter->BandwidthLFO != NIL),PRERR(AllowResume,
														"NewOscFilterArrayProcessor:  filter constructor problem"));
													break;
												case eFilterButterworthHighpass:
													if (Filter->Left.ButterworthHighpass != NIL)
														{
															DisposeButterworthHighpass(Filter->Left.ButterworthHighpass);
														}
													if (Filter->Right.ButterworthHighpass != NIL)
														{
															DisposeButterworthHighpass(Filter->Right.ButterworthHighpass);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													ERROR((Filter->BandwidthEnvelope != NIL)
														|| (Filter->BandwidthLFO != NIL),PRERR(AllowResume,
														"NewOscFilterArrayProcessor:  filter constructor problem"));
													break;
												case eFilterButterworthBandpass:
													if (Filter->Left.ButterworthBandpass != NIL)
														{
															DisposeButterworthBandpass(Filter->Left.ButterworthBandpass);
														}
													if (Filter->Right.ButterworthBandpass != NIL)
														{
															DisposeButterworthBandpass(Filter->Right.ButterworthBandpass);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													DisposeEnvelopeStateRecord(Filter->BandwidthEnvelope);
													DisposeLFOGenerator(Filter->BandwidthLFO);
													break;
												case eFilterButterworthBandreject:
													if (Filter->Left.ButterworthBandreject != NIL)
														{
															DisposeButterworthBandreject(Filter->Left.ButterworthBandreject);
														}
													if (Filter->Right.ButterworthBandreject != NIL)
														{
															DisposeButterworthBandreject(Filter->Right.ButterworthBandreject);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													DisposeEnvelopeStateRecord(Filter->BandwidthEnvelope);
													DisposeLFOGenerator(Filter->BandwidthLFO);
													break;
												case eFilterNull:
													if (Filter->Left.NullFilter != NIL)
														{
															DisposeFilterNull(Filter->Left.NullFilter);
														}
													if (Filter->Right.NullFilter != NIL)
														{
															DisposeFilterNull(Filter->Right.NullFilter);
														}
													ERROR((Filter->CutoffEnvelope != NIL)
														|| (Filter->CutoffLFO != NIL)
														|| (Filter->BandwidthEnvelope != NIL)
														|| (Filter->BandwidthLFO != NIL),PRERR(AllowResume,
														"NewOscFilterArrayProcessor:  filter constructor problem"));
													break;
												case eFilterParametricEQ:
													if (Filter->Left.ParamEQ != NIL)
														{
															DisposeParametricEqualizer(Filter->Left.ParamEQ);
														}
													if (Filter->Right.ParamEQ != NIL)
														{
															DisposeParametricEqualizer(Filter->Right.ParamEQ);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													DisposeEnvelopeStateRecord(Filter->BandwidthEnvelope);
													DisposeLFOGenerator(Filter->BandwidthLFO);
													DisposeEnvelopeStateRecord(Filter->GainEnvelope);
													DisposeLFOGenerator(Filter->GainLFO);
													break;
												case eFilterResonantLowpass:
													if (Filter->Left.ResonantLowpass != NIL)
														{
															DisposeResonantLowpass(Filter->Left.ResonantLowpass);
														}
													if (Filter->Right.ResonantLowpass != NIL)
														{
															DisposeResonantLowpass(Filter->Right.ResonantLowpass);
														}
													DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
													DisposeLFOGenerator(Filter->CutoffLFO);
													DisposeEnvelopeStateRecord(Filter->BandwidthEnvelope);
													DisposeLFOGenerator(Filter->BandwidthLFO);
													DisposeEnvelopeStateRecord(Filter->GainEnvelope);
													DisposeLFOGenerator(Filter->GainLFO);
													break;
											}
										DisposeEnvelopeStateRecord(Filter->OutputMultiplierEnvelope);
										DisposeLFOGenerator(Filter->OutputMultiplierLFO);
										ReleasePtr((char*)Filter);
									}
								ReleasePtr((char*)Array);
								goto FailurePoint1;
							}
					}
				Filter->FilterType = GetFilterType(Template,Scan);
				Filter->FilterScaling = GetFilterScalingMode(Template,Scan);
				/* envelopes */
				Filter->OutputMultiplierEnvelope = NewEnvelopeStateRecord(
					GetFilterOutputEnvelope(Template,Scan),Accents,
					InitialFrequency,1,HurryUp,EnvelopeTicksPerSecond,&OnePreOrigin);
				if (Filter->OutputMultiplierEnvelope == NIL)
					{
					 FailurePoint2aa:
						Filter->Next = OscFilterFreeList;
						OscFilterFreeList = Filter;
						goto FailurePoint2;
					}
				if (OnePreOrigin > MaxPreOrigin)
					{
						MaxPreOrigin = OnePreOrigin;
					}
				Filter->OutputMultiplierLFO = NewLFOGenerator(GetFilterOutputLFO(Template,Scan),
					&OnePreOrigin,Accents,InitialFrequency,HurryUp,
					EnvelopeTicksPerSecond,1,1,FreqForMultisampling);
				if (Filter->OutputMultiplierLFO == NIL)
					{
					 FailurePoint2ab:
						DisposeEnvelopeStateRecord(Filter->OutputMultiplierEnvelope);
						goto FailurePoint2aa;
					}
				if (OnePreOrigin > MaxPreOrigin)
					{
						MaxPreOrigin = OnePreOrigin;
					}
				switch (Filter->FilterType)
					{
						default:
							EXECUTE(PRERR(ForceAbort,"NewOscFilterArrayProcessor:  bad filter type"));
							break;
						case eFilterNull:
							Filter->CutoffEnvelope = NIL;
							Filter->CutoffLFO = NIL;
							break;
						case eFilterFirstOrderLowpass:
						case eFilterFirstOrderHighpass:
						case eFilterSecondOrderResonant:
						case eFilterSecondOrderZero:
						case eFilterButterworthLowpass:
						case eFilterButterworthHighpass:
						case eFilterButterworthBandpass:
						case eFilterButterworthBandreject:
						case eFilterParametricEQ:
						case eFilterResonantLowpass:
							Filter->CutoffEnvelope = NewEnvelopeStateRecord(
								GetFilterCutoffEnvelope(Template,Scan),Accents,
								InitialFrequency,1,HurryUp,EnvelopeTicksPerSecond,&OnePreOrigin);
							if (Filter->CutoffEnvelope == NIL)
								{
								 FailurePoint2ac:
									DisposeLFOGenerator(Filter->OutputMultiplierLFO);
									goto FailurePoint2ab;
								}
							if (OnePreOrigin > MaxPreOrigin)
								{
									MaxPreOrigin = OnePreOrigin;
								}
							Filter->CutoffLFO = NewLFOGenerator(GetFilterCutoffLFO(Template,Scan),
								&OnePreOrigin,Accents,InitialFrequency,HurryUp,
								EnvelopeTicksPerSecond,1,1,FreqForMultisampling);
							if (Filter->CutoffLFO == NIL)
								{
								 FailurePoint2ad:
									if (Filter->CutoffEnvelope != NIL)
										{
											DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
										}
									goto FailurePoint2ac;
								}
							if (OnePreOrigin > MaxPreOrigin)
								{
									MaxPreOrigin = OnePreOrigin;
								}
							break;
					}
				switch (Filter->FilterType)
					{
						default:
							EXECUTE(PRERR(ForceAbort,"NewOscFilterArrayProcessor:  bad filter type"));
							break;
						case eFilterNull:
						case eFilterFirstOrderLowpass:
						case eFilterFirstOrderHighpass:
						case eFilterButterworthLowpass:
						case eFilterButterworthHighpass:
							Filter->BandwidthEnvelope = NIL;
							Filter->BandwidthLFO = NIL;
							break;
						case eFilterSecondOrderResonant:
						case eFilterSecondOrderZero:
						case eFilterButterworthBandpass:
						case eFilterButterworthBandreject:
						case eFilterParametricEQ:
						case eFilterResonantLowpass:
							Filter->BandwidthEnvelope = NewEnvelopeStateRecord(
								GetFilterBandwidthEnvelope(Template,Scan),Accents,
								InitialFrequency,1,HurryUp,EnvelopeTicksPerSecond,&OnePreOrigin);
							if (Filter->BandwidthEnvelope == NIL)
								{
								 FailurePoint2ae:
									if (Filter->CutoffLFO != NIL)
										{
											DisposeLFOGenerator(Filter->CutoffLFO);
										}
									goto FailurePoint2ad;
								}
							if (OnePreOrigin > MaxPreOrigin)
								{
									MaxPreOrigin = OnePreOrigin;
								}
							Filter->BandwidthLFO = NewLFOGenerator(GetFilterBandwidthLFO(Template,Scan),
								&OnePreOrigin,Accents,InitialFrequency,HurryUp,
								EnvelopeTicksPerSecond,1,1,FreqForMultisampling);
							if (Filter->BandwidthLFO == NIL)
								{
								 FailurePoint2af:
									if (Filter->BandwidthEnvelope != NIL)
										{
											DisposeEnvelopeStateRecord(Filter->BandwidthEnvelope);
										}
									goto FailurePoint2ae;
								}
							if (OnePreOrigin > MaxPreOrigin)
								{
									MaxPreOrigin = OnePreOrigin;
								}
							break;
					}
				switch (Filter->FilterType)
					{
						default:
							EXECUTE(PRERR(ForceAbort,"NewOscFilterArrayProcessor:  bad filter type"));
							break;
						case eFilterNull:
						case eFilterFirstOrderLowpass:
						case eFilterFirstOrderHighpass:
						case eFilterButterworthLowpass:
						case eFilterButterworthHighpass:
						case eFilterSecondOrderResonant:
						case eFilterSecondOrderZero:
						case eFilterButterworthBandpass:
						case eFilterButterworthBandreject:
							Filter->GainEnvelope = NIL;
							Filter->GainLFO = NIL;
							break;
						case eFilterParametricEQ:
						case eFilterResonantLowpass:
							Filter->GainEnvelope = NewEnvelopeStateRecord(
								GetFilterGainEnvelope(Template,Scan),Accents,
								InitialFrequency,1,HurryUp,EnvelopeTicksPerSecond,&OnePreOrigin);
							if (Filter->GainEnvelope == NIL)
								{
								 FailurePoint2ag:
									if (Filter->CutoffLFO != NIL)
										{
											DisposeLFOGenerator(Filter->CutoffLFO);
										}
									goto FailurePoint2af;
								}
							if (OnePreOrigin > MaxPreOrigin)
								{
									MaxPreOrigin = OnePreOrigin;
								}
							Filter->GainLFO = NewLFOGenerator(GetFilterGainLFO(Template,Scan),
								&OnePreOrigin,Accents,InitialFrequency,HurryUp,
								EnvelopeTicksPerSecond,1,1,FreqForMultisampling);
							if (Filter->GainLFO == NIL)
								{
								 FailurePoint2ah:
									if (Filter->GainEnvelope != NIL)
										{
											DisposeEnvelopeStateRecord(Filter->GainEnvelope);
										}
									goto FailurePoint2ag;
								}
							if (OnePreOrigin > MaxPreOrigin)
								{
									MaxPreOrigin = OnePreOrigin;
								}
							break;
					}
				/* figure out what channels are needed */
				Filter->Left.GenericRef = NIL;
				Filter->Right.GenericRef = NIL;
				switch (GetFilterChannel(Template,Scan))
					{
						default:
							EXECUTE(PRERR(ForceAbort,"NewOscFilterArrayProcessor:  bad channel type"));
							break;
						case eFilterLeft:
							LeftChannel = True;
							RightChannel = False;
							break;
						case eFilterRight:
							LeftChannel = False;
							RightChannel = True;
							break;
						case eFilterBoth:
							LeftChannel = True;
							RightChannel = True;
							break;
					}
				/* establish link */
				Filter->Next = Array->Filters;
				Array->Filters = Filter;
				/* set up filter processor */
				switch (Filter->FilterType)
					{
						default:
							EXECUTE(PRERR(ForceAbort,"NewOscFilterArrayProcessor:  bad filter type"));
							break;
						case eFilterFirstOrderLowpass:
							if (LeftChannel)
								{
									Filter->Left.FirstOrderLowpass = NewFirstOrderLowpass();
									if (Filter->Left.FirstOrderLowpass == NIL)
										{
										 FailurePoint2a:
											/* since link has been established already, we can */
											/* use the normal delete procedure. */
											goto FailurePoint2;
										}
								}
							if (RightChannel)
								{
									Filter->Right.FirstOrderLowpass = NewFirstOrderLowpass();
									if (Filter->Right.FirstOrderLowpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplyFirstOrderLowpass;
							break;
						case eFilterFirstOrderHighpass:
							if (LeftChannel)
								{
									Filter->Left.FirstOrderHighpass = NewFirstOrderHighpass();
									if (Filter->Left.FirstOrderHighpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.FirstOrderHighpass = NewFirstOrderHighpass();
									if (Filter->Right.FirstOrderHighpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplyFirstOrderHighpass;
							break;
						case eFilterSecondOrderResonant:
							if (LeftChannel)
								{
									Filter->Left.SecondOrderReson = NewSecondOrderReson();
									if (Filter->Left.SecondOrderReson == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.SecondOrderReson = NewSecondOrderReson();
									if (Filter->Right.SecondOrderReson == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplySecondOrderReson;
							break;
						case eFilterSecondOrderZero:
							if (LeftChannel)
								{
									Filter->Left.SecondOrderZero = NewSecondOrderZero();
									if (Filter->Left.SecondOrderZero == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.SecondOrderZero = NewSecondOrderZero();
									if (Filter->Right.SecondOrderZero == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplySecondOrderZero;
							break;
						case eFilterButterworthLowpass:
							if (LeftChannel)
								{
									Filter->Left.ButterworthLowpass = NewButterworthLowpass();
									if (Filter->Left.ButterworthLowpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.ButterworthLowpass = NewButterworthLowpass();
									if (Filter->Right.ButterworthLowpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplyButterworthLowpass;
							break;
						case eFilterButterworthHighpass:
							if (LeftChannel)
								{
									Filter->Left.ButterworthHighpass = NewButterworthHighpass();
									if (Filter->Left.ButterworthHighpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.ButterworthHighpass = NewButterworthHighpass();
									if (Filter->Right.ButterworthHighpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplyButterworthHighpass;
							break;
						case eFilterButterworthBandpass:
							if (LeftChannel)
								{
									Filter->Left.ButterworthBandpass = NewButterworthBandpass();
									if (Filter->Left.ButterworthBandpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.ButterworthBandpass = NewButterworthBandpass();
									if (Filter->Right.ButterworthBandpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplyButterworthBandpass;
							break;
						case eFilterButterworthBandreject:
							if (LeftChannel)
								{
									Filter->Left.ButterworthBandreject = NewButterworthBandreject();
									if (Filter->Left.ButterworthBandreject == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.ButterworthBandreject = NewButterworthBandreject();
									if (Filter->Right.ButterworthBandreject == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplyButterworthBandreject;
							break;
						case eFilterParametricEQ:
							if (LeftChannel)
								{
									Filter->Left.ParamEQ = NewParametricEqualizer();
									if (Filter->Left.ParamEQ == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.ParamEQ = NewParametricEqualizer();
									if (Filter->Right.ParamEQ == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplyParametricEqualizer;
							break;
						case eFilterResonantLowpass:
							if (LeftChannel)
								{
									Filter->Left.ResonantLowpass = NewResonantLowpass(
										GetFilterLowpassOrder(Template,Scan),
										GetFilterBandpassOrder(Template,Scan));
									if (Filter->Left.ResonantLowpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.ResonantLowpass = NewResonantLowpass(
										GetFilterLowpassOrder(Template,Scan),
										GetFilterBandpassOrder(Template,Scan));
									if (Filter->Right.ResonantLowpass == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplyResonantLowpass;
							break;
						case eFilterNull:
							if (LeftChannel)
								{
									Filter->Left.NullFilter = NewFilterNull();
									if (Filter->Left.NullFilter == NIL)
										{
											goto FailurePoint2a;
										}
								}
							if (RightChannel)
								{
									Filter->Right.NullFilter = NewFilterNull();
									if (Filter->Right.NullFilter == NIL)
										{
											goto FailurePoint2a;
										}
								}
							Filter->ApplyFilter = (float (*)(void*,float))&ApplyFilterNull;
							break;
					}
			}

		*PreOriginTimeOut = MaxPreOrigin;

		return Array;
	}


/* fix up the origin time so that envelopes start at the proper times */
void								FixUpOscFilterArrayProcessorOrigins(OscFilterArrayRec* Filters,
											long ActualPreOriginTime)
	{
		OscFilterRec*			Scan;

		CheckPtrExistence(Filters);
		Scan = Filters->Filters;
		while (Scan != NIL)
			{
				EnvelopeStateFixUpInitialDelay(Scan->OutputMultiplierEnvelope,ActualPreOriginTime);
				if (Scan->CutoffEnvelope != NIL)
					{
						EnvelopeStateFixUpInitialDelay(Scan->CutoffEnvelope,ActualPreOriginTime);
					}
				if (Scan->BandwidthEnvelope != NIL)
					{
						EnvelopeStateFixUpInitialDelay(Scan->BandwidthEnvelope,ActualPreOriginTime);
					}
				if (Scan->GainEnvelope != NIL)
					{
						EnvelopeStateFixUpInitialDelay(Scan->GainEnvelope,ActualPreOriginTime);
					}
				LFOGeneratorFixEnvelopeOrigins(Scan->OutputMultiplierLFO,ActualPreOriginTime);
				if (Scan->CutoffLFO != NIL)
					{
						LFOGeneratorFixEnvelopeOrigins(Scan->CutoffLFO,ActualPreOriginTime);
					}
				if (Scan->BandwidthLFO != NIL)
					{
						LFOGeneratorFixEnvelopeOrigins(Scan->BandwidthLFO,ActualPreOriginTime);
					}
				if (Scan->GainLFO != NIL)
					{
						LFOGeneratorFixEnvelopeOrigins(Scan->GainLFO,ActualPreOriginTime);
					}
				Scan = Scan->Next;
			}
	}


/* dispose of the filter processor */
void								DisposeOscFilterArrayProcessor(OscFilterArrayRec* Filters)
	{
		CheckPtrExistence(Filters);
		while (Filters->Filters != NIL)
			{
				OscFilterRec*		Filter;

				Filter = Filters->Filters;
				Filters->Filters = Filters->Filters->Next;
				CheckPtrExistence(Filter);
				DisposeEnvelopeStateRecord(Filter->OutputMultiplierEnvelope);
				if (Filter->CutoffEnvelope != NIL)
					{
						DisposeEnvelopeStateRecord(Filter->CutoffEnvelope);
					}
				if (Filter->BandwidthEnvelope != NIL)
					{
						DisposeEnvelopeStateRecord(Filter->BandwidthEnvelope);
					}
				if (Filter->GainEnvelope != NIL)
					{
						DisposeEnvelopeStateRecord(Filter->GainEnvelope);
					}
				DisposeLFOGenerator(Filter->OutputMultiplierLFO);
				if (Filter->CutoffLFO != NIL)
					{
						DisposeLFOGenerator(Filter->CutoffLFO);
					}
				if (Filter->BandwidthLFO != NIL)
					{
						DisposeLFOGenerator(Filter->BandwidthLFO);
					}
				if (Filter->GainLFO != NIL)
					{
						DisposeLFOGenerator(Filter->GainLFO);
					}
				switch (Filter->FilterType)
					{
						default:
							EXECUTE(PRERR(ForceAbort,"DisposeOscFilterArrayProcessor:  bad filter type"));
							break;
						case eFilterFirstOrderLowpass:
							if (Filter->Left.FirstOrderLowpass != NIL)
								{
									DisposeFirstOrderLowpass(Filter->Left.FirstOrderLowpass);
								}
							if (Filter->Right.FirstOrderLowpass != NIL)
								{
									DisposeFirstOrderLowpass(Filter->Right.FirstOrderLowpass);
								}
							break;
						case eFilterFirstOrderHighpass:
							if (Filter->Left.FirstOrderHighpass != NIL)
								{
									DisposeFirstOrderHighpass(Filter->Left.FirstOrderHighpass);
								}
							if (Filter->Right.FirstOrderHighpass != NIL)
								{
									DisposeFirstOrderHighpass(Filter->Right.FirstOrderHighpass);
								}
							break;
						case eFilterSecondOrderResonant:
							if (Filter->Left.SecondOrderReson != NIL)
								{
									DisposeSecondOrderReson(Filter->Left.SecondOrderReson);
								}
							if (Filter->Right.SecondOrderReson != NIL)
								{
									DisposeSecondOrderReson(Filter->Right.SecondOrderReson);
								}
							break;
						case eFilterSecondOrderZero:
							if (Filter->Left.SecondOrderZero != NIL)
								{
									DisposeSecondOrderZero(Filter->Left.SecondOrderZero);
								}
							if (Filter->Right.SecondOrderZero != NIL)
								{
									DisposeSecondOrderZero(Filter->Right.SecondOrderZero);
								}
							break;
						case eFilterButterworthLowpass:
							if (Filter->Left.ButterworthLowpass != NIL)
								{
									DisposeButterworthLowpass(Filter->Left.ButterworthLowpass);
								}
							if (Filter->Right.ButterworthLowpass != NIL)
								{
									DisposeButterworthLowpass(Filter->Right.ButterworthLowpass);
								}
							break;
						case eFilterButterworthHighpass:
							if (Filter->Left.ButterworthHighpass != NIL)
								{
									DisposeButterworthHighpass(Filter->Left.ButterworthHighpass);
								}
							if (Filter->Right.ButterworthHighpass != NIL)
								{
									DisposeButterworthHighpass(Filter->Right.ButterworthHighpass);
								}
							break;
						case eFilterButterworthBandpass:
							if (Filter->Left.ButterworthBandpass != NIL)
								{
									DisposeButterworthBandpass(Filter->Left.ButterworthBandpass);
								}
							if (Filter->Right.ButterworthBandpass != NIL)
								{
									DisposeButterworthBandpass(Filter->Right.ButterworthBandpass);
								}
							break;
						case eFilterButterworthBandreject:
							if (Filter->Left.ButterworthBandreject != NIL)
								{
									DisposeButterworthBandreject(Filter->Left.ButterworthBandreject);
								}
							if (Filter->Right.ButterworthBandreject != NIL)
								{
									DisposeButterworthBandreject(Filter->Right.ButterworthBandreject);
								}
							break;
						case eFilterNull:
							if (Filter->Left.NullFilter != NIL)
								{
									DisposeFilterNull(Filter->Left.NullFilter);
								}
							if (Filter->Right.NullFilter != NIL)
								{
									DisposeFilterNull(Filter->Right.NullFilter);
								}
							break;
						case eFilterParametricEQ:
							if (Filter->Left.ParamEQ != NIL)
								{
									DisposeParametricEqualizer(Filter->Left.ParamEQ);
								}
							if (Filter->Right.ParamEQ != NIL)
								{
									DisposeParametricEqualizer(Filter->Right.ParamEQ);
								}
							break;
						case eFilterResonantLowpass:
							if (Filter->Left.ResonantLowpass != NIL)
								{
									DisposeResonantLowpass(Filter->Left.ResonantLowpass);
								}
							if (Filter->Right.ResonantLowpass != NIL)
								{
									DisposeResonantLowpass(Filter->Right.ResonantLowpass);
								}
							break;
					}
				Filter->Next = OscFilterFreeList;
				OscFilterFreeList = Filter;
			}
		Filters->Next = OscFilterArrayFreeList;
		OscFilterArrayFreeList = Filters;
	}


/* update filter state with accent information */
void								OscFilterArrayProcessorUpdateEnvelopes(OscFilterArrayRec* Filters,
											float OscillatorFrequency)
	{
		OscFilterRec*			Scan;

		CheckPtrExistence(Filters);
		Scan = Filters->Filters;
		while (Scan != NIL)
			{
				float							Cutoff EXECUTE(= 1e38);
				float							Bandwidth EXECUTE(= 1e38);
				float							Gain EXECUTE(= 1e38);

				Scan->CurrentMultiplier = FastFixed2Float(LFOGenUpdateCycle(Scan->OutputMultiplierLFO,
					EnvelopeUpdate(Scan->OutputMultiplierEnvelope,OscillatorFrequency),
					OscillatorFrequency));
				if (Scan->CutoffEnvelope != NIL)
					{
						Cutoff = FastFixed2Float(LFOGenUpdateCycle(Scan->CutoffLFO,
							EnvelopeUpdate(Scan->CutoffEnvelope,OscillatorFrequency),
							OscillatorFrequency));
					}
				if (Scan->BandwidthEnvelope != NIL)
					{
						Bandwidth = FastFixed2Float(LFOGenUpdateCycle(Scan->BandwidthLFO,
							EnvelopeUpdate(Scan->BandwidthEnvelope,OscillatorFrequency),
							OscillatorFrequency));
					}
				if (Scan->GainEnvelope != NIL)
					{
						Gain = FastFixed2Float(LFOGenUpdateCycle(Scan->GainLFO,
							EnvelopeUpdate(Scan->GainEnvelope,OscillatorFrequency),
							OscillatorFrequency));
					}
				switch (Scan->FilterType)
					{
						default:
							EXECUTE(PRERR(ForceAbort,"OscFilterArrayProcessorUpdateEnvelopes:  bad filter type"));
							break;
						case eFilterFirstOrderLowpass:
							if (Scan->Left.FirstOrderLowpass != NIL)
								{
									SetFirstOrderLowpassCoefficients(Scan->Left.FirstOrderLowpass,
										Cutoff,Filters->SamplingRate);
								}
							if (Scan->Right.FirstOrderLowpass != NIL)
								{
									SetFirstOrderLowpassCoefficients(Scan->Right.FirstOrderLowpass,
										Cutoff,Filters->SamplingRate);
								}
							ERROR(Scan->FilterScaling != eFilterDefaultScaling,PRERR(ForceAbort,
								"OscFilterArrayProcessorUpdateEnvelopes:  bad scaling type"));
							break;
						case eFilterFirstOrderHighpass:
							if (Scan->Left.FirstOrderHighpass != NIL)
								{
									SetFirstOrderHighpassCoefficients(Scan->Left.FirstOrderHighpass,
										Cutoff,Filters->SamplingRate);
								}
							if (Scan->Right.FirstOrderHighpass != NIL)
								{
									SetFirstOrderHighpassCoefficients(Scan->Right.FirstOrderHighpass,
										Cutoff,Filters->SamplingRate);
								}
							ERROR(Scan->FilterScaling != eFilterDefaultScaling,PRERR(ForceAbort,
								"OscFilterArrayProcessorUpdateEnvelopes:  bad scaling type"));
							break;
						case eFilterSecondOrderResonant:
							if (Scan->Left.SecondOrderReson != NIL)
								{
									SetSecondOrderResonCoefficients(Scan->Left.SecondOrderReson,
										Cutoff,Bandwidth,Scan->FilterScaling,Filters->SamplingRate);
								}
							if (Scan->Right.SecondOrderReson != NIL)
								{
									SetSecondOrderResonCoefficients(Scan->Right.SecondOrderReson,
										Cutoff,Bandwidth,Scan->FilterScaling,Filters->SamplingRate);
								}
							break;
						case eFilterSecondOrderZero:
							if (Scan->Left.SecondOrderZero != NIL)
								{
									SetSecondOrderZeroCoefficients(Scan->Left.SecondOrderZero,
										Cutoff,Bandwidth,Scan->FilterScaling,Filters->SamplingRate);
								}
							if (Scan->Right.SecondOrderZero != NIL)
								{
									SetSecondOrderZeroCoefficients(Scan->Right.SecondOrderZero,
										Cutoff,Bandwidth,Scan->FilterScaling,Filters->SamplingRate);
								}
							break;
						case eFilterButterworthLowpass:
							if (Scan->Left.ButterworthLowpass != NIL)
								{
									SetButterworthLowpassCoefficients(Scan->Left.ButterworthLowpass,
										Cutoff,Filters->SamplingRate);
								}
							if (Scan->Right.ButterworthLowpass != NIL)
								{
									SetButterworthLowpassCoefficients(Scan->Right.ButterworthLowpass,
										Cutoff,Filters->SamplingRate);
								}
							ERROR(Scan->FilterScaling != eFilterDefaultScaling,PRERR(ForceAbort,
								"OscFilterArrayProcessorUpdateEnvelopes:  bad scaling type"));
							break;
						case eFilterButterworthHighpass:
							if (Scan->Left.ButterworthHighpass != NIL)
								{
									SetButterworthHighpassCoefficients(Scan->Left.ButterworthHighpass,
										Cutoff,Filters->SamplingRate);
								}
							if (Scan->Right.ButterworthHighpass != NIL)
								{
									SetButterworthHighpassCoefficients(Scan->Right.ButterworthHighpass,
										Cutoff,Filters->SamplingRate);
								}
							ERROR(Scan->FilterScaling != eFilterDefaultScaling,PRERR(ForceAbort,
								"OscFilterArrayProcessorUpdateEnvelopes:  bad scaling type"));
							break;
						case eFilterButterworthBandpass:
							if (Scan->Left.ButterworthBandpass != NIL)
								{
									SetButterworthBandpassCoefficients(Scan->Left.ButterworthBandpass,
										Cutoff,Bandwidth,Filters->SamplingRate);
								}
							if (Scan->Right.ButterworthBandpass != NIL)
								{
									SetButterworthBandpassCoefficients(Scan->Right.ButterworthBandpass,
										Cutoff,Bandwidth,Filters->SamplingRate);
								}
							ERROR(Scan->FilterScaling != eFilterDefaultScaling,PRERR(ForceAbort,
								"OscFilterArrayProcessorUpdateEnvelopes:  bad scaling type"));
							break;
						case eFilterButterworthBandreject:
							if (Scan->Left.ButterworthBandreject != NIL)
								{
									SetButterworthBandrejectCoefficients(Scan->Left.ButterworthBandreject,
										Cutoff,Bandwidth,Filters->SamplingRate);
								}
							if (Scan->Right.ButterworthBandreject != NIL)
								{
									SetButterworthBandrejectCoefficients(Scan->Right.ButterworthBandreject,
										Cutoff,Bandwidth,Filters->SamplingRate);
								}
							ERROR(Scan->FilterScaling != eFilterDefaultScaling,PRERR(ForceAbort,
								"OscFilterArrayProcessorUpdateEnvelopes:  bad scaling type"));
							break;
						case eFilterParametricEQ:
							if (Scan->Left.ParamEQ != NIL)
								{
									SetParametricEqualizerCoefficients(Scan->Left.ParamEQ,
										Cutoff,Bandwidth,Gain,Filters->SamplingRate);
								}
							if (Scan->Right.ParamEQ != NIL)
								{
									SetParametricEqualizerCoefficients(Scan->Right.ParamEQ,
										Cutoff,Bandwidth,Gain,Filters->SamplingRate);
								}
							ERROR(Scan->FilterScaling != eFilterDefaultScaling,PRERR(ForceAbort,
								"OscFilterArrayProcessorUpdateEnvelopes:  bad scaling type"));
							break;
						case eFilterResonantLowpass:
							if (Scan->Left.ResonantLowpass != NIL)
								{
									SetResonantLowpassCoefficients(Scan->Left.ResonantLowpass,
										Cutoff,Bandwidth,Gain,Filters->SamplingRate);
								}
							if (Scan->Right.ResonantLowpass != NIL)
								{
									SetResonantLowpassCoefficients(Scan->Right.ResonantLowpass,
										Cutoff,Bandwidth,Gain,Filters->SamplingRate);
								}
							ERROR(Scan->FilterScaling != eFilterDefaultScaling,PRERR(ForceAbort,
								"OscFilterArrayProcessorUpdateEnvelopes:  bad scaling type"));
							break;
						case eFilterNull:
							ERROR(Scan->FilterScaling != eFilterDefaultScaling,PRERR(ForceAbort,
								"OscFilterArrayProcessorUpdateEnvelopes:  bad scaling type"));
							break;
					}
				Scan = Scan->Next;
			}
	}


/* apply filter processing to some stuff */
void								ApplyOscFilterArray(largefixedsigned* Data, long NumFrames,
											OscFilterArrayRec* Filters)
	{
		long						Scan;

		CheckPtrExistence(Data);
		CheckPtrExistence(Filters);
		if (Filters->StereoFlag)
			{
				for (Scan = 0; Scan < NumFrames; Scan += 1)
					{
						float						LeftInput;
						float						LeftOutput;
						float						RightInput;
						float						RightOutput;
						OscFilterRec*		Filter;
		
						PRNGCHK(Data,&(Data[2 * Scan]),sizeof(Data[2 * Scan]));
						PRNGCHK(Data,&(Data[2 * Scan + 1]),sizeof(Data[2 * Scan + 1]));
						LeftInput = largefixed2single(Data[2 * Scan]);
						RightInput = largefixed2single(Data[2 * Scan + 1]);
						LeftOutput = 0;
						RightOutput = 0;
						Filter = Filters->Filters;
						while (Filter != NIL)
							{
								if (Filter->Left.GenericRef != NIL)
									{
										LeftOutput += Filter->CurrentMultiplier
											* (*Filter->ApplyFilter)(Filter->Left.GenericRef,LeftInput);
									}
								if (Filter->Right.GenericRef != NIL)
									{
										RightOutput += Filter->CurrentMultiplier
											* (*Filter->ApplyFilter)(Filter->Right.GenericRef,RightInput);
									}
								Filter = Filter->Next;
							}
						Data[2 * Scan] = double2largefixed(LeftOutput);
						Data[2 * Scan + 1] = double2largefixed(RightOutput);
					}
			}
		 else
			{
				for (Scan = 0; Scan < NumFrames; Scan += 1)
					{
						float						LeftInput;
						float						LeftOutput;
						float						RightInput;
						float						RightOutput;
						OscFilterRec*		Filter;
		
						PRNGCHK(Data,&(Data[Scan]),sizeof(Data[Scan]));
						LeftInput = largefixed2single(Data[Scan]);
						RightInput = largefixed2single(Data[Scan]);
						LeftOutput = 0;
						RightOutput = 0;
						Filter = Filters->Filters;
						while (Filter != NIL)
							{
								if (Filter->Left.GenericRef != NIL)
									{
										LeftOutput += Filter->CurrentMultiplier
											* (*Filter->ApplyFilter)(Filter->Left.GenericRef,LeftInput);
									}
								if (Filter->Right.GenericRef != NIL)
									{
										RightOutput += Filter->CurrentMultiplier
											* (*Filter->ApplyFilter)(Filter->Right.GenericRef,RightInput);
									}
								Filter = Filter->Next;
							}
						Data[Scan] = double2largefixed((LeftOutput + RightOutput) / 2);
					}
			}
	}


void								OscFilterArrayKeyUpSustain1(OscFilterArrayRec* Filters)
	{
		OscFilterRec*			Scan;

		CheckPtrExistence(Filters);
		Scan = Filters->Filters;
		while (Scan != NIL)
			{
				EnvelopeKeyUpSustain1(Scan->OutputMultiplierEnvelope);
				if (Scan->CutoffEnvelope != NIL)
					{
						EnvelopeKeyUpSustain1(Scan->CutoffEnvelope);
					}
				if (Scan->BandwidthEnvelope != NIL)
					{
						EnvelopeKeyUpSustain1(Scan->BandwidthEnvelope);
					}
				if (Scan->GainEnvelope != NIL)
					{
						EnvelopeKeyUpSustain1(Scan->GainEnvelope);
					}
				LFOGeneratorKeyUpSustain1(Scan->OutputMultiplierLFO);
				if (Scan->CutoffLFO != NIL)
					{
						LFOGeneratorKeyUpSustain1(Scan->CutoffLFO);
					}
				if (Scan->BandwidthLFO != NIL)
					{
						LFOGeneratorKeyUpSustain1(Scan->BandwidthLFO);
					}
				if (Scan->GainLFO != NIL)
					{
						LFOGeneratorKeyUpSustain1(Scan->GainLFO);
					}
				Scan = Scan->Next;
			}
	}


void								OscFilterArrayKeyUpSustain2(OscFilterArrayRec* Filters)
	{
		OscFilterRec*			Scan;

		CheckPtrExistence(Filters);
		Scan = Filters->Filters;
		while (Scan != NIL)
			{
				EnvelopeKeyUpSustain2(Scan->OutputMultiplierEnvelope);
				if (Scan->CutoffEnvelope != NIL)
					{
						EnvelopeKeyUpSustain2(Scan->CutoffEnvelope);
					}
				if (Scan->BandwidthEnvelope != NIL)
					{
						EnvelopeKeyUpSustain2(Scan->BandwidthEnvelope);
					}
				if (Scan->GainEnvelope != NIL)
					{
						EnvelopeKeyUpSustain2(Scan->GainEnvelope);
					}
				LFOGeneratorKeyUpSustain2(Scan->OutputMultiplierLFO);
				if (Scan->CutoffLFO != NIL)
					{
						LFOGeneratorKeyUpSustain2(Scan->CutoffLFO);
					}
				if (Scan->BandwidthLFO != NIL)
					{
						LFOGeneratorKeyUpSustain2(Scan->BandwidthLFO);
					}
				if (Scan->GainLFO != NIL)
					{
						LFOGeneratorKeyUpSustain2(Scan->GainLFO);
					}
				Scan = Scan->Next;
			}
	}


void								OscFilterArrayKeyUpSustain3(OscFilterArrayRec* Filters)
	{
		OscFilterRec*			Scan;

		CheckPtrExistence(Filters);
		Scan = Filters->Filters;
		while (Scan != NIL)
			{
				EnvelopeKeyUpSustain3(Scan->OutputMultiplierEnvelope);
				if (Scan->CutoffEnvelope != NIL)
					{
						EnvelopeKeyUpSustain3(Scan->CutoffEnvelope);
					}
				if (Scan->BandwidthEnvelope != NIL)
					{
						EnvelopeKeyUpSustain3(Scan->BandwidthEnvelope);
					}
				if (Scan->GainEnvelope != NIL)
					{
						EnvelopeKeyUpSustain3(Scan->GainEnvelope);
					}
				LFOGeneratorKeyUpSustain3(Scan->OutputMultiplierLFO);
				if (Scan->CutoffLFO != NIL)
					{
						LFOGeneratorKeyUpSustain3(Scan->CutoffLFO);
					}
				if (Scan->BandwidthLFO != NIL)
					{
						LFOGeneratorKeyUpSustain3(Scan->BandwidthLFO);
					}
				if (Scan->GainLFO != NIL)
					{
						LFOGeneratorKeyUpSustain3(Scan->GainLFO);
					}
				Scan = Scan->Next;
			}
	}


/* retrigger effect envelopes from the origin point */
void								OscFilterArrayRetriggerEnvelopes(OscFilterArrayRec* Filters,
											AccentParam* NewAccents, float NewHurryUp,
											float NewInitialFrequency, MyBoolean ActuallyRetrigger)
	{
		OscFilterRec*			Scan;

		CheckPtrExistence(Filters);
		Scan = Filters->Filters;
		while (Scan != NIL)
			{
				EnvelopeRetriggerFromOrigin(Scan->OutputMultiplierEnvelope,NewAccents,
					NewInitialFrequency,1,NewHurryUp,Filters->EnvelopeTicksPerSecond,
					ActuallyRetrigger);
				if (Scan->CutoffEnvelope != NIL)
					{
						EnvelopeRetriggerFromOrigin(Scan->CutoffEnvelope,NewAccents,
							NewInitialFrequency,1,NewHurryUp,Filters->EnvelopeTicksPerSecond,
							ActuallyRetrigger);
					}
				if (Scan->BandwidthEnvelope != NIL)
					{
						EnvelopeRetriggerFromOrigin(Scan->BandwidthEnvelope,NewAccents,
							NewInitialFrequency,1,NewHurryUp,
							Filters->EnvelopeTicksPerSecond,ActuallyRetrigger);
					}
				if (Scan->GainEnvelope != NIL)
					{
						EnvelopeRetriggerFromOrigin(Scan->GainEnvelope,NewAccents,
							NewInitialFrequency,1,NewHurryUp,
							Filters->EnvelopeTicksPerSecond,ActuallyRetrigger);
					}
				LFOGeneratorRetriggerFromOrigin(Scan->OutputMultiplierLFO,NewAccents,
					NewInitialFrequency,NewHurryUp,1,1,ActuallyRetrigger);
				if (Scan->CutoffLFO != NIL)
					{
						LFOGeneratorRetriggerFromOrigin(Scan->CutoffLFO,NewAccents,
							NewInitialFrequency,NewHurryUp,1,1,ActuallyRetrigger);
					}
				if (Scan->BandwidthLFO != NIL)
					{
						LFOGeneratorRetriggerFromOrigin(Scan->BandwidthLFO,NewAccents,
							NewInitialFrequency,NewHurryUp,1,1,ActuallyRetrigger);
					}
				if (Scan->GainLFO != NIL)
					{
						LFOGeneratorRetriggerFromOrigin(Scan->GainLFO,NewAccents,
							NewInitialFrequency,NewHurryUp,1,1,ActuallyRetrigger);
					}
				Scan = Scan->Next;
			}
	}
