/* BuildInstrument3.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 "BuildInstrument3.h"
#include "BuildInstrument2.h"
#include "BuildInstrument.h"
#include "CompilerScanner.h"
#include "LFOSpecifier.h"
#include "LFOListSpecifier.h"
#include "DelayEffectSpec.h"




/* <oscfilteroutlfolist>    ::= outputscalinglfo ( <lfo_definition> ) */
/*                              <oscfilteroutlfolist> */
/*                          ::= */
/* FOLLOW SET */
/* { ; } */
BuildInstrErrors						ParseOscFilterOutLFOList(struct LFOListSpecRec* LFOList,
															struct ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenSemicolon)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if ((GetTokenType(Token) != eTokenKeyword)
			|| (GetTokenKeywordTag(Token) != eKeywordOutputscalinglfo))
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOutputScalingLfoOrSemicolon;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseOscFilterOutLFOList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <oscbandwidthlfolist>    ::= bandwidthlfo ( <lfo_definition> ) <oscbandwidthlfolist> */
/*                          ::= */
BuildInstrErrors						ParseOscBandwidthLFOList(struct LFOListSpecRec* LFOList,
															struct ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedBandwidthLfoOrScalingOrChannel;
			}
		if (GetTokenKeywordTag(Token) != eKeywordBandwidthlfo)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseOscBandwidthLFOList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <oscfiltfreqlfolist>     ::= freqlfo ( <lfo_definition> ) <oscfiltfreqlfolist> */
/*                          ::= */
BuildInstrErrors						ParseOscFiltFreqLFOList(struct LFOListSpecRec* LFOList,
															struct ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFreqLfoOrScalingOrChannel;
			}
		if (GetTokenKeywordTag(Token) != eKeywordFreqlfo)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseOscFiltFreqLFOList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <oscfilterelem>          ::= filter <filtertype> [order <number>] freqenvelope ( */
/*                              <envelope_definition> ) <oscfiltfreqlfolist> */
/*                              [order <number>]<oscbandwidth> <oscgain> <scaling> <tapchannel> */
/*                              outputscalingenvelope ( <envelope_definition> ) */
/*                              <oscfilteroutlfolist> */
/* FOLLOW SET */
/* { ; } */
BuildInstrErrors						ParseOscFilterElem(struct FilterSpecRec* FilterSpec,
															struct ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		FilterTypes								FilterType;
		OneFilterRec*							OneFilter;
		long											Index;
		unsigned long							RequiredDefs;

		/* filter */
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if ((GetTokenType(Token) != eTokenKeyword)
			|| (GetTokenKeywordTag(Token) != eKeywordFilter))
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFilter;
			}
		/* <filtertype> */
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFilterType;
			}
		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedFilterType;
				case eKeywordNull:
					FilterType = eFilterNull;
					break;
				case eKeywordLowpass:
					FilterType = eFilterFirstOrderLowpass;
					break;
				case eKeywordHighpass:
					FilterType = eFilterFirstOrderHighpass;
					break;
				case eKeywordReson:
					FilterType = eFilterSecondOrderResonant;
					break;
				case eKeywordZero:
					FilterType = eFilterSecondOrderZero;
					break;
				case eKeywordButterworthlowpass:
					FilterType = eFilterButterworthLowpass;
					break;
				case eKeywordButterworthhighpass:
					FilterType = eFilterButterworthHighpass;
					break;
				case eKeywordButterworthbandpass:
					FilterType = eFilterButterworthBandpass;
					break;
				case eKeywordButterworthbandreject:
					FilterType = eFilterButterworthBandreject;
					break;
				case eKeywordParameq:
					FilterType = eFilterParametricEQ;
					break;
				case eKeywordResonantlowpass:
					FilterType = eFilterResonantLowpass;
					break;
			}
		Index = GetNumFiltersInSpec(FilterSpec);
		OneFilter = NewSingleFilterSpec(FilterType);
		if (OneFilter == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!AppendFilterToSpec(FilterSpec,OneFilter))
			{
				DisposeSingleFilterSpec(OneFilter);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (FilterType != eFilterNull)
			{
				if (FilterType == eFilterResonantLowpass)
					{
						double				Order;
						long					Order2;

						/* order <number> */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordOrder))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOrder;
							}
						/* get order number */
						Error = ParseNumber(Scanner,ErrorLine,&Order);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						Order2 = Order;
						if ((Order2 < 0) || (Order2 != Order) || ((Order2 % 2) != 0))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOrderMustBeNonNegativeEvenInteger;
							}
						/* remember value */
						SetFilterLowpassOrder(GetSingleFilterSpec(FilterSpec,Index),Order2);
					}
				/* freqenvelope OPAREN */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if ((GetTokenType(Token) != eTokenKeyword)
					|| (GetTokenKeywordTag(Token) != eKeywordFreqenvelope))
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedFreqEnvelope;
					}
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenOpenParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedOpenParen;
					}
				/* <envelope_definition> */
				RequiredDefs = 0;
				Error = ParseEnvelopeDefinition(GetFilterCutoffEnvelope(FilterSpec,Index),
					Scanner,ErrorLine,&RequiredDefs,0);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
				if (RequiredDefs != ENVELOPEDEFINITION_REQUIREDMASK)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrSomeRequiredEnvelopeParamsMissing;
					}
				/* CPAREN */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenCloseParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedCloseParen;
					}
				/* <oscfiltfreqlfolist> */
				Error = ParseOscFiltFreqLFOList(GetFilterCutoffLFO(FilterSpec,Index),
					Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
			}
		if ((FilterType == eFilterSecondOrderResonant)
			|| (FilterType == eFilterSecondOrderZero)
			|| (FilterType == eFilterButterworthBandpass)
			|| (FilterType == eFilterButterworthBandreject)
			|| (FilterType == eFilterParametricEQ)
			|| (FilterType == eFilterResonantLowpass))
			{
				if (FilterType == eFilterResonantLowpass)
					{
						double				Order;
						long					Order2;

						/* order <number> */
						Token = GetNextToken(Scanner);
						if (Token == NIL)
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOutOfMemory;
							}
						if ((GetTokenType(Token) != eTokenKeyword)
							|| (GetTokenKeywordTag(Token) != eKeywordOrder))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedOrder;
							}
						/* get order number */
						Error = ParseNumber(Scanner,ErrorLine,&Order);
						if (Error != eBuildInstrNoError)
							{
								return Error;
							}
						Order2 = Order;
						if ((Order2 < 0) || (Order2 != Order) || ((Order2 % 2) != 0))
							{
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrOrderMustBeNonNegativeEvenInteger;
							}
						/* remember value */
						SetFilterBandpassOrder(GetSingleFilterSpec(FilterSpec,Index),Order2);
					}
				/* bandwidthenvelope ( <envelope_definition> ) <oscbandwidthlfolist> */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if ((GetTokenType(Token) != eTokenKeyword)
					|| (GetTokenKeywordTag(Token) != eKeywordBandwidthenvelope))
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedBandwidthEnvelope;
					}
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenOpenParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedOpenParen;
					}
				/* <envelope_definition> */
				RequiredDefs = 0;
				Error = ParseEnvelopeDefinition(GetFilterBandwidthEnvelope(FilterSpec,Index),
					Scanner,ErrorLine,&RequiredDefs,0);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
				if (RequiredDefs != ENVELOPEDEFINITION_REQUIREDMASK)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrSomeRequiredEnvelopeParamsMissing;
					}
				/* CPAREN */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenCloseParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedCloseParen;
					}
				/* <oscbandwidthlfolist> */
				Error = ParseOscBandwidthLFOList(GetFilterBandwidthLFO(FilterSpec,Index),
					Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
			}
		if ((FilterType == eFilterParametricEQ)
			|| (FilterType == eFilterResonantLowpass))
			{
				/* gainenvelope ( <envelope_definition> ) <oscgainlfolist> */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if ((GetTokenType(Token) != eTokenKeyword)
					|| (GetTokenKeywordTag(Token) != eKeywordGainenvelope))
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedGainEnvelope;
					}
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenOpenParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedOpenParen;
					}
				/* <envelope_definition> */
				RequiredDefs = 0;
				Error = ParseEnvelopeDefinition(GetFilterGainEnvelope(FilterSpec,Index),
					Scanner,ErrorLine,&RequiredDefs,0);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
				if (RequiredDefs != ENVELOPEDEFINITION_REQUIREDMASK)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrSomeRequiredEnvelopeParamsMissing;
					}
				/* CPAREN */
				Token = GetNextToken(Scanner);
				if (Token == NIL)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrOutOfMemory;
					}
				if (GetTokenType(Token) != eTokenCloseParen)
					{
						*ErrorLine = GetCurrentLineNumber(Scanner);
						return eBuildInstrExpectedCloseParen;
					}
				/* <oscgainlfolist> */
				Error = ParseOscGainLFOList(GetFilterGainLFO(FilterSpec,Index),
					Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
				if (Error != eBuildInstrNoError)
					{
						return Error;
					}
			}
		/* <scaling> */
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if ((GetTokenType(Token) == eTokenKeyword)
			&& ((GetTokenKeywordTag(Token) == eKeywordDefaultscaling)
				|| (GetTokenKeywordTag(Token) == eKeywordUnitymidbandgain)
				|| (GetTokenKeywordTag(Token) == eKeywordUnitynoisegain)
				|| (GetTokenKeywordTag(Token) == eKeywordUnityzerohertzgain)))
			{
				switch (FilterType)
					{
						default:
							EXECUTE(PRERR(ForceAbort,"ParseFilter:  bad filter type"));
							break;
						case eFilterNull:
						case eFilterFirstOrderLowpass:
						case eFilterFirstOrderHighpass:
						case eFilterButterworthLowpass:
						case eFilterButterworthHighpass:
						case eFilterButterworthBandpass:
						case eFilterButterworthBandreject:
						case eFilterParametricEQ:
						case eFilterResonantLowpass:
							if (GetTokenKeywordTag(Token) != eKeywordDefaultscaling)
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedDefaultScaling;
								}
							break;
						case eFilterSecondOrderResonant:
							if (GetTokenKeywordTag(Token) == eKeywordDefaultscaling)
								{
								}
							else if (GetTokenKeywordTag(Token) == eKeywordUnitymidbandgain)
								{
									SetSingleFilterScalingMode(OneFilter,eFilterResonMidbandGain1);
								}
							else if (GetTokenKeywordTag(Token) == eKeywordUnitynoisegain)
								{
									SetSingleFilterScalingMode(OneFilter,eFilterResonNoiseGain1);
								}
							else
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedResonScaling;
								}
							break;
						case eFilterSecondOrderZero:
							if (GetTokenKeywordTag(Token) == eKeywordDefaultscaling)
								{
								}
							else if (GetTokenKeywordTag(Token) == eKeywordUnityzerohertzgain)
								{
									SetSingleFilterScalingMode(OneFilter,eFilterZeroGain1);
								}
							else
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedZeroScaling;
								}
							break;
					}
			}
		 else
			{
				UngetToken(Scanner,Token);
			}

		/* <tapchannel> */
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFilterChannel;
			}
		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedFilterChannel;
				case eKeywordLeft:
					SetSingleFilterChannel(OneFilter,eFilterLeft);
					break;
				case eKeywordRight:
					SetSingleFilterChannel(OneFilter,eFilterRight);
					break;
				case eKeywordMono:
					SetSingleFilterChannel(OneFilter,eFilterBoth);
					break;
			}
		/* outputscalingenvelope OPAREN */
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if ((GetTokenType(Token) != eTokenKeyword)
			|| (GetTokenKeywordTag(Token) != eKeywordOutputscalingenvelope))
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOutputScalingEnvelope;
			}
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}
		/* <envelope_definition> */
		RequiredDefs = 0;
		Error = ParseEnvelopeDefinition(GetFilterOutputEnvelope(FilterSpec,Index),
			Scanner,ErrorLine,&RequiredDefs,0);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (RequiredDefs != ENVELOPEDEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredEnvelopeParamsMissing;
			}
		/* CPAREN */
		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}
		/* <oscfilteroutlfolist> */
		Error = ParseOscFilterOutLFOList(GetFilterOutputLFO(FilterSpec,Index),
			Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}

		return eBuildInstrNoError;
	}




/* <oscfilterelems>         ::= <oscfilterelem> ; <oscfilterelems> */
/*                          ::= */
BuildInstrErrors						ParseOscFilterElems(struct FilterSpecRec* FilterSpec,
															struct ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenCloseParen)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		UngetToken(Scanner,Token);

		Error = ParseOscFilterElem(FilterSpec,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenSemicolon)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedSemicolon;
			}

		return ParseOscFilterElems(FilterSpec,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <nlindexlfolist>         ::= indexlfo ( <lfo_definition> ) <nlindexlfolist> */
/*                          ::= */
/* FOLLOW SET */
/* { ; } */
BuildInstrErrors						ParseNLIndexLFOList(struct LFOListSpecRec* LFOList,
															struct ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenSemicolon)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedIndexLfoOrSemicolon;
			}
		if (GetTokenKeywordTag(Token) != eKeywordIndexlfo)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedIndexLfoOrSemicolon;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseNLIndexLFOList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <nloutputscalinglfolist> ::= outputscalinglfo ( <lfo_definition> ) */
/*                              <nloutputscalinglfolist> */
/*                          ::= */
/* FOLLOW SET */
/* { indexenvelope } */
BuildInstrErrors						ParseNLOutputScalingLFOList(struct LFOListSpecRec* LFOList,
															struct ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOutputScalingLfoOrIndexEnvelope;
			}
		if (GetTokenKeywordTag(Token) == eKeywordIndexenvelope)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if (GetTokenKeywordTag(Token) != eKeywordOutputscalinglfo)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOutputScalingLfoOrIndexEnvelope;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseNLOutputScalingLFOList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <nlinputscalinglfolist>  ::= inputscalinglfo ( <lfo_definition> ) */
/*                              <nlinputscalinglfolist> */
/*                          ::= */
/* FOLLOW SET */
/* { outputscalingenvelope } */
BuildInstrErrors						ParseNLInputScalingLFOList(struct LFOListSpecRec* LFOList,
															struct ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedInputScalingLfoOrOutputScalingEnvelope;
			}
		if (GetTokenKeywordTag(Token) == eKeywordOutputscalingenvelope)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if (GetTokenKeywordTag(Token) != eKeywordInputscalinglfo)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedInputScalingLfoOrOutputScalingEnvelope;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseNLInputScalingLFOList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <oscdelaycutofflfolist>  ::= freqlfo ( <lfo_definition> ) <oscdelaycutofflfolist> */
/*                          ::= */
/* FOLLOW SET */
/* { ; } */
BuildInstrErrors						ParseOscDelayCutoffLfoList(LFOListSpecRec* LFOList,
															ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenSemicolon)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFreqLfoOrSemicolon;
			}
		if (GetTokenKeywordTag(Token) != eKeywordFreqlfo)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedFreqLfoOrSemicolon;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseOscDelayCutoffLfoList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <oscdelayscalelfolist>   ::= scalelfo ( <lfo_definition> ) <oscdelayscalelfolist> */
/*                          ::= */
/* FOLLOW SET */
/* { ; lowpass } */
BuildInstrErrors						ParseOscDelayScaleLfoList(LFOListSpecRec* LFOList,
															ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) == eTokenSemicolon)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedScaleLfoCutoffOrSemicolon;
			}
		if (GetTokenKeywordTag(Token) == eKeywordLowpass)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if (GetTokenKeywordTag(Token) != eKeywordScalelfo)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedScaleLfoCutoffOrSemicolon;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseOscDelayScaleLfoList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <oscdelaytargetlfolist>  ::= targetlfo ( <lfo_definition> ) <oscdelaytargetlfolist> */
/*                          ::= */
/* FOLLOW SET */
/* { scaleenvelope } */
BuildInstrErrors						ParseOscDelayTargetLfoList(LFOListSpecRec* LFOList,
															ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedTargetLfoOrScaleEnvelope;
			}
		if (GetTokenKeywordTag(Token) == eKeywordScaleenvelope)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if (GetTokenKeywordTag(Token) != eKeywordTargetlfo)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedTargetLfoOrScaleEnvelope;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseOscDelayTargetLfoList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <oscdelaysourcelfolist>  ::= sourcelfo ( <lfo_definition> ) <oscdelaysourcelfolist> */
/*                          ::= */
/* FOLLOW SET */
/* { to } */
BuildInstrErrors						ParseOscDelaySourceLfoList(LFOListSpecRec* LFOList,
															ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedSourceLfoOrTo;
			}
		if (GetTokenKeywordTag(Token) == eKeywordTo)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}
		if (GetTokenKeywordTag(Token) != eKeywordSourcelfo)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedSourceLfoOrTo;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseOscDelaySourceLfoList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}




/* <oscdelayelem>           ::= maxdelaytime <number> */
/*                          ::= tap <tapchannel> sourceenvelope ( */
/*                              <envelope_definition> ) <oscdelaysourcelfolist> */
/*                              to <tapchannel> targetenvelope ( */
/*                              <envelope_definition> ) <oscdelaytargetlfolist> */
/*                              scaleenvelope ( <envelope_definition> ) */
/*                              <oscdelayscalelfolist> */
/*                              [lowpass freqenvelope ( <envelope_definition> ) */
/*                              <freqlfolist>] */
/* FOLLOW SET */
/* { ; } */
BuildInstrErrors						ParseOscDelayElem(DelayEffectRec* DelayEffect,
															DelayTapRec* DelayTap, ScannerRec* Scanner,
															long *ErrorLine, unsigned long* OnceOnlyDefinitions,
															long Index, struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		double										Number;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedDelayLineElem;
			}

		switch (GetTokenKeywordTag(Token))
			{
				default:
					*ErrorLine = GetCurrentLineNumber(Scanner);
					return eBuildInstrExpectedDelayLineElem;

				case eKeywordMaxdelaytime:
					if ((*OnceOnlyDefinitions & DELAYEFFECT_ONCEONLY_MAXDELAYTIME) != 0)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrMultipleMaxDelayTime;
						}
					Error = ParseNumber(Scanner,ErrorLine,&Number);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					SetDelayMaxTime(DelayEffect,Number);
					*OnceOnlyDefinitions |= DELAYEFFECT_ONCEONLY_MAXDELAYTIME;
					break;

				case eKeywordTap:
					/* tap source <tapchannel> */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenKeyword)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedTapChannel;
						}
					switch (GetTokenKeywordTag(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedTapChannel;
							case eKeywordLeft:
								SetDelayTapSource(DelayTap,eTapLeftChannel);
								break;
							case eKeywordRight:
								SetDelayTapSource(DelayTap,eTapRightChannel);
								break;
							case eKeywordMono:
								SetDelayTapSource(DelayTap,eTapMonoChannel);
								break;
						}
					/* sourceenvelope OPAREN */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordSourceenvelope))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedSourceEnvelope;
						}
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenOpenParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOpenParen;
						}
					/* <envelope_definition> */
					Required = 0;
					Error = ParseEnvelopeDefinition(GetDelayTapSourceEnvelope(DelayEffect,Index),
						Scanner,ErrorLine,&Required,0);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					if (Required != ENVELOPEDEFINITION_REQUIREDMASK)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrSomeRequiredEnvelopeParamsMissing;
						}
					/* CPAREN */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenCloseParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCloseParen;
						}
					/* <oscdelaysourcelfolist> */
					Error = ParseOscDelaySourceLfoList(GetDelayTapSourceLFO(DelayEffect,Index),
						Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					/* to */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordTo))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedTo;
						}
					/* tap target <tapchannel> */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenKeyword)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedTapChannel;
						}
					switch (GetTokenKeywordTag(Token))
						{
							default:
								*ErrorLine = GetCurrentLineNumber(Scanner);
								return eBuildInstrExpectedTapChannel;
							case eKeywordLeft:
								SetDelayTapTarget(DelayTap,eTapLeftChannel);
								break;
							case eKeywordRight:
								SetDelayTapTarget(DelayTap,eTapRightChannel);
								break;
							case eKeywordMono:
								SetDelayTapTarget(DelayTap,eTapMonoChannel);
								break;
						}
					/* targetenvelope OPAREN */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordTargetenvelope))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedTargetEnvelope;
						}
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenOpenParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOpenParen;
						}
					/* <envelope_definition> */
					Required = 0;
					Error = ParseEnvelopeDefinition(GetDelayTapTargetEnvelope(DelayEffect,Index),
						Scanner,ErrorLine,&Required,0);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					if (Required != ENVELOPEDEFINITION_REQUIREDMASK)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrSomeRequiredEnvelopeParamsMissing;
						}
					/* CPAREN */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenCloseParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCloseParen;
						}
					/* <oscdelaytargetlfolist> */
					Error = ParseOscDelayTargetLfoList(GetDelayTapTargetLFO(DelayEffect,Index),
						Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					/* scaleenvelope OPAREN */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						|| (GetTokenKeywordTag(Token) != eKeywordScaleenvelope))
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedScaleEnvelope;
						}
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenOpenParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedOpenParen;
						}
					/* <envelope_definition> */
					Required = 0;
					Error = ParseEnvelopeDefinition(GetDelayTapScaleEnvelope(DelayEffect,Index),
						Scanner,ErrorLine,&Required,0);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					if (Required != ENVELOPEDEFINITION_REQUIREDMASK)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrSomeRequiredEnvelopeParamsMissing;
						}
					/* CPAREN */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if (GetTokenType(Token) != eTokenCloseParen)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrExpectedCloseParen;
						}
					/* <oscdelayscalelfolist> */
					Error = ParseOscDelayScaleLfoList(GetDelayTapTargetLFO(DelayEffect,Index),
						Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
					if (Error != eBuildInstrNoError)
						{
							return Error;
						}
					/* lowpass? */
					Token = GetNextToken(Scanner);
					if (Token == NIL)
						{
							*ErrorLine = GetCurrentLineNumber(Scanner);
							return eBuildInstrOutOfMemory;
						}
					if ((GetTokenType(Token) != eTokenKeyword)
						&& (GetTokenKeywordTag(Token) != eKeywordLowpass))
						{
							UngetToken(Scanner,Token);
						}
					 else
						{
							SetDelayTapFilterEnable(DelayTap,True);
							/* freqenvelope OPAREN */
							Token = GetNextToken(Scanner);
							if (Token == NIL)
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrOutOfMemory;
								}
							if ((GetTokenType(Token) != eTokenKeyword)
								|| (GetTokenKeywordTag(Token) != eKeywordFreqenvelope))
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedFreqEnvelope;
								}
							Token = GetNextToken(Scanner);
							if (Token == NIL)
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrOutOfMemory;
								}
							if (GetTokenType(Token) != eTokenOpenParen)
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedOpenParen;
								}
							/* <envelope_definition> */
							Required = 0;
							Error = ParseEnvelopeDefinition(GetDelayTapCutoffEnvelope(
								DelayEffect,Index),Scanner,ErrorLine,&Required,0);
							if (Error != eBuildInstrNoError)
								{
									return Error;
								}
							if (Required != ENVELOPEDEFINITION_REQUIREDMASK)
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrSomeRequiredEnvelopeParamsMissing;
								}
							/* CPAREN */
							Token = GetNextToken(Scanner);
							if (Token == NIL)
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrOutOfMemory;
								}
							if (GetTokenType(Token) != eTokenCloseParen)
								{
									*ErrorLine = GetCurrentLineNumber(Scanner);
									return eBuildInstrExpectedCloseParen;
								}
							/* <oscdelaycutofflfolist> */
							Error = ParseOscDelayCutoffLfoList(GetDelayTapCutoffLFO(DelayEffect,Index),
								Scanner,ErrorLine,WaveTableList,AlgoWaveTableList);
							if (Error != eBuildInstrNoError)
								{
									return Error;
								}
						}
				break;
			}

		return eBuildInstrNoError;
	}




/* <oscgainlfolist>         ::= gainlfo ( <lfo_definition> ) <oscgainlfolist> */
/*                          ::= */
BuildInstrErrors						ParseOscGainLFOList(struct LFOListSpecRec* LFOList,
															struct ScannerRec* Scanner, long *ErrorLine,
															struct WaveTableListRec* WaveTableList,
															struct AlgoWaveTableListRec* AlgoWaveTableList)
	{
		TokenRec*									Token;
		BuildInstrErrors					Error;
		LFOSpecRec*								LFOSpec;
		unsigned long							Required;

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenKeyword)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedGainLfoOrScalingOrChannel;
			}
		if (GetTokenKeywordTag(Token) != eKeywordGainlfo)
			{
				UngetToken(Scanner,Token);
				return eBuildInstrNoError;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenOpenParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedOpenParen;
			}

		LFOSpec = NewLFOSpecifier();
		if (LFOSpec == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (!LFOListSpecAppendNewEntry(LFOList,LFOSpec))
			{
				DisposeLFOSpecifier(LFOSpec);
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		Required = 0;
		Error = ParseLfoDefinition(LFOSpec,Scanner,ErrorLine,&Required,0,WaveTableList,
			AlgoWaveTableList);
		if (Error != eBuildInstrNoError)
			{
				return Error;
			}
		if (Required != LFODEFINITION_REQUIREDMASK)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrSomeRequiredLFOParamsMissing;
			}

		Token = GetNextToken(Scanner);
		if (Token == NIL)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrOutOfMemory;
			}
		if (GetTokenType(Token) != eTokenCloseParen)
			{
				*ErrorLine = GetCurrentLineNumber(Scanner);
				return eBuildInstrExpectedCloseParen;
			}

		return ParseOscGainLFOList(LFOList,Scanner,ErrorLine,WaveTableList,
			AlgoWaveTableList);
	}
