/* create a new track user effect processor */ public static SynthErrorCodes NewTrackUserEffectProc( UserEffectSpecRec Template, SynthParamRec SynthParams, out UserEffectProcRec effectOut) { effectOut = null; /* allocate structure */ UserEffectProcRec Proc = new UserEffectProcRec(); SynthErrorCodes error = UserEffectSharedInit(Proc, Template, SynthParams); if (error != SynthErrorCodes.eSynthDone) { return(error); } Proc.params_Track = new UserEffectParamRec_Track[Proc.paramCount]; /* initialize argument evaluators */ for (int i = 0; i < Proc.paramCount; i += 1) { GetUserEffectSpecParamAgg( Template, i, out Proc.params_Track[i].Eval); } effectOut = Proc; return(SynthErrorCodes.eSynthDone); }
/* shared initialization */ private static SynthErrorCodes UserEffectSharedInit( UserEffectProcRec Proc, UserEffectSpecRec Template, SynthParamRec SynthParams) { Proc.disableOversampling = GetUserEffectSpecNoOversampling(Template); double sr = SynthParams.dSamplingRate; if (!((SynthParams.iOversampling == 1) || !Proc.disableOversampling)) { sr /= SynthParams.iOversampling; } /* init func */ { string FuncName = GetUserEffectSpecInitFuncName(Template); if (FuncName != null) { FuncCodeRec FuncCode = SynthParams.CodeCenter.ObtainFunctionHandle(FuncName); if (FuncCode == null) { // Function missing; should have been found by CheckUnreferencedThings Debug.Assert(false); throw new ArgumentException(); } DataTypes[] argsTypes; DataTypes returnType; UserEffectGetInitSignature(Template, out argsTypes, out returnType); FunctionSignature expectedSignature = new FunctionSignature(argsTypes, returnType); FunctionSignature actualSignature = new FunctionSignature( FuncCode.GetFunctionParameterTypeList(), FuncCode.GetFunctionReturnType()); if (!FunctionSignature.Equals(expectedSignature, actualSignature)) { // Function type mismatch; should have been found by CheckUnreferencedThings Debug.Assert(false); throw new ArgumentException(); } Proc.InitFunc = FuncCode.GetFunctionPcode(); } } /* data func */ { DataTypes[] argsTypes; DataTypes returnType; UserEffectGetDataSignature(Template, out argsTypes, out returnType); FunctionSignature expectedSignature = new FunctionSignature(argsTypes, returnType); foreach (string FuncName in GetUserEffectSpecProcessDataFuncNames(Template)) { FuncCodeRec FuncCode = SynthParams.CodeCenter.ObtainFunctionHandle(FuncName); if (FuncCode == null) { // Function missing; should have been found by CheckUnreferencedThings Debug.Assert(false); throw new ArgumentException(); } FunctionSignature actualSignature = new FunctionSignature( FuncCode.GetFunctionParameterTypeList(), FuncCode.GetFunctionReturnType()); if (FunctionSignature.Equals(expectedSignature, actualSignature)) { Proc.DataFunc = FuncCode.GetFunctionPcode(); break; } } if (Proc.DataFunc == null) { // None matched -- should have been found by CheckUnreferencedThings Debug.Assert(false); throw new ArgumentException(); } } Proc.paramCount = GetUserEffectSpecParamCount(Template); Proc.paramResults = new double[Proc.paramCount]; Proc.paramResultsPrevious = new double[Proc.paramCount]; // create state objects DataTypes[] stateTypes = UserEffectGetWorkspaceTypes(Template); Proc.userState = new ArrayHandle[stateTypes.Length]; for (int i = 0; i < Proc.userState.Length; i++) { switch (stateTypes[i]) { default: Debug.Assert(false); throw new ArgumentException(); case DataTypes.eArrayOfInteger: Proc.userState[i] = new ArrayHandleInt32(new int[0]); break; case DataTypes.eArrayOfFloat: Proc.userState[i] = new ArrayHandleFloat(new float[0]); break; case DataTypes.eArrayOfDouble: Proc.userState[i] = new ArrayHandleDouble(new double[0]); break; } } Proc.smoothingBuffers = new SmoothingEntry[Template.Items.Length]; for (int i = 0; i < Template.Items.Length; i++) { if (Template.Items[i].Smoothed) { float[] vector = new float[SynthParams.nAllocatedPointsOneChannel]; Proc.smoothingBuffers[i].vector = vector; Proc.smoothingBuffers[i].arrayHandle = new ArrayHandleFloat(vector); } } /* initialize user state */ if (Proc.InitFunc != null) { int argCount = 1 /*retval*/ + 1 /*t*/ + 1 /*bpm*/ + 1 /*samplingRate*/ + 1 /*maxSampleCount*/ + Proc.userState.Length /*user state arrays*/ + 1 /*retaddr*/; SynthParams.FormulaEvalContext.EmptyParamStackEnsureCapacity(argCount); StackElement[] StackBase; int StackNumElements; SynthParams.FormulaEvalContext.GetRawStack(out StackBase, out StackNumElements); StackBase[StackNumElements++].Data.Double = SynthParams.dElapsedTimeInSeconds; /* t */ StackBase[StackNumElements++].Data.Double = SynthParams.dCurrentBeatsPerMinute; /* bpm */ StackBase[StackNumElements++].Data.Double = sr; /* samplingRate */ StackBase[StackNumElements++].Data.Integer = SynthParams.nAllocatedPointsOneChannel; /* maxSampleCount */ for (int i = 0; i < Proc.userState.Length; i++) { StackBase[StackNumElements++].reference.arrayHandleGeneric = Proc.userState[i]; // user state } StackNumElements++; /* return address placeholder */ SynthParams.FormulaEvalContext.UpdateRawStack(StackBase, StackNumElements); EvalErrInfoRec ErrorInfo; EvalErrors Error = PcodeSystem.EvaluatePcode( SynthParams.FormulaEvalContext, Proc.InitFunc, SynthParams.CodeCenter, out ErrorInfo, PcodeExternsNull.Default, ref SynthParams.pcodeThreadContext); if (Error != EvalErrors.eEvalNoError) { SynthParams.ErrorInfo.ErrorEx = SynthErrorSubCodes.eSynthErrorExUserEffectFunctionEvalError; SynthParams.ErrorInfo.UserEvalErrorCode = Error; SynthParams.ErrorInfo.UserEvalErrorInfo = ErrorInfo; return(SynthErrorCodes.eSynthErrorEx); } Debug.Assert(SynthParams.FormulaEvalContext.GetStackNumElements() == 1); // return value SynthParams.FormulaEvalContext.Clear(); } // initialize sample data in/out staging areas Proc.leftWorkspace = new float[SynthParams.nAllocatedPointsOneChannel]; Proc.leftWorkspaceHandle = new ArrayHandleFloat(null); Proc.rightWorkspace = new float[SynthParams.nAllocatedPointsOneChannel]; Proc.rightWorkspaceHandle = new ArrayHandleFloat(null); return(SynthErrorCodes.eSynthDone); }
/* create a new oscillator user effect processor */ public static SynthErrorCodes NewOscUserEffectProc( UserEffectSpecRec Template, ref AccentRec Accents, double HurryUp, double InitialFrequency, double FreqForMultisampling, out int PreOriginTimeOut, PlayTrackInfoRec TrackInfo, SynthParamRec SynthParams, out UserEffectProcRec effectOut) { effectOut = null; PreOriginTimeOut = 0; /* allocate structure */ UserEffectProcRec Proc = new UserEffectProcRec(); SynthErrorCodes error = UserEffectSharedInit(Proc, Template, SynthParams); if (error != SynthErrorCodes.eSynthDone) { return(error); } Proc.params_Osc = new UserEffectParamRec_Osc[Proc.paramCount]; /* initialize argument evaluators */ int MaxPreOrigin = 0; for (int i = 0; i < Proc.paramCount; i += 1) { int OnePreOrigin; Proc.params_Osc[i].Envelope = NewEnvelopeStateRecord( GetUserEffectSpecParamEnvelope(Template, i), ref Accents, InitialFrequency, 1, HurryUp, out OnePreOrigin, _PlayTrackParamGetter, TrackInfo, SynthParams); if (OnePreOrigin > MaxPreOrigin) { MaxPreOrigin = OnePreOrigin; } Proc.params_Osc[i].LFO = NewLFOGenerator( GetUserEffectSpecParamLFO(Template, i), out OnePreOrigin, ref Accents, InitialFrequency, HurryUp, 1, 1, FreqForMultisampling, _PlayTrackParamGetter, TrackInfo, SynthParams); if (OnePreOrigin > MaxPreOrigin) { MaxPreOrigin = OnePreOrigin; } } PreOriginTimeOut = MaxPreOrigin; for (int i = 0; i < Template.Items.Length; i++) { if (Template.Items[i].Smoothed) { if (IsLFOSampleAndHold(Proc.params_Osc[i].LFO)) { // degrade sample & hold, since smoothing is probably not what was intended Proc.smoothingBuffers[i].degraded = true; } } } effectOut = Proc; return(SynthErrorCodes.eSynthDone); }
/* create a new oscillator effect generator */ public static SynthErrorCodes NewOscEffectGenerator( EffectSpecListRec SpecList, ref AccentRec Accents, double HurryUp, double InitialFrequency, double FreqForMultisampling, out int PreOriginTimeOut, PlayTrackInfoRec TrackInfo, SynthParamRec SynthParams, out OscEffectGenRec GeneratorOut) { int OnePreOrigin; GeneratorOut = null; PreOriginTimeOut = 0; OscEffectGenRec Generator = New(ref SynthParams.freelists.OscEffectGenRecFreeList); int count = Generator.count = GetEffectSpecListEnabledLength(SpecList); IOscillatorEffect[] List = Generator.List = New(ref SynthParams.freelists.IOscillatorEffectFreeList, count); // zeroed if (unchecked ((uint)count > (uint)List.Length)) { Debug.Assert(false); throw new IndexOutOfRangeException(); } int MaxPreOrigin = 0; /* build list of thingers */ int j = 0; for (int i = 0; j < count; i++) { /* see if effect is enabled */ if (!IsEffectFromEffectSpecListEnabled(SpecList, i)) { continue; } /* fill in fields */ EffectTypes Type = GetEffectSpecListElementType(SpecList, i); switch (Type) { default: Debug.Assert(false); throw new ArgumentException(); case EffectTypes.eDelayEffect: List[j] = DelayUnifiedRec.NewOscUnifiedDelayLineProcessor( GetDelayEffectFromEffectSpecList(SpecList, i), ref Accents, HurryUp, InitialFrequency, FreqForMultisampling, out OnePreOrigin, TrackInfo, SynthParams); if (OnePreOrigin > MaxPreOrigin) { MaxPreOrigin = OnePreOrigin; } break; case EffectTypes.eNLProcEffect: List[j] = NLProcUnifiedRec.NewOscNLProcProcessor( GetNLProcEffectFromEffectSpecList(SpecList, i), ref Accents, HurryUp, InitialFrequency, FreqForMultisampling, out OnePreOrigin, TrackInfo, SynthParams); if (OnePreOrigin > MaxPreOrigin) { MaxPreOrigin = OnePreOrigin; } break; case EffectTypes.eFilterEffect: List[j] = FilterArrayRec.NewOscFilterArrayProcessor( GetFilterEffectFromEffectSpecList(SpecList, i), ref Accents, HurryUp, InitialFrequency, FreqForMultisampling, out OnePreOrigin, TrackInfo, SynthParams); if (OnePreOrigin > MaxPreOrigin) { MaxPreOrigin = OnePreOrigin; } break; case EffectTypes.eAnalyzerEffect: List[j] = AnalyzerRec.NewAnalyzer( GetAnalyzerEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eHistogramEffect: List[j] = HistogramRec.NewHistogram( GetHistogramEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eResamplerEffect: List[j] = ResamplerRec.NewResampler( GetResamplerEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eCompressorEffect: List[j] = CompressorRec.NewOscCompressor( GetCompressorEffectFromEffectSpecList(SpecList, i), ref Accents, HurryUp, InitialFrequency, FreqForMultisampling, out OnePreOrigin, TrackInfo, SynthParams); if (OnePreOrigin > MaxPreOrigin) { MaxPreOrigin = OnePreOrigin; } break; case EffectTypes.eVocoderEffect: List[j] = VocoderRec.NewOscVocoder( GetVocoderEffectFromEffectSpecList(SpecList, i), ref Accents, HurryUp, InitialFrequency, FreqForMultisampling, out OnePreOrigin, TrackInfo, SynthParams); if (OnePreOrigin > MaxPreOrigin) { MaxPreOrigin = OnePreOrigin; } break; case EffectTypes.eIdealLowpassEffect: List[j] = IdealLPRec.NewIdealLP( GetIdealLPEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eUserEffect: { UserEffectProcRec userEffect; SynthErrorCodes error = UserEffectProcRec.NewOscUserEffectProc( GetUserEffectFromEffectSpecList(SpecList, i), ref Accents, HurryUp, InitialFrequency, FreqForMultisampling, out OnePreOrigin, TrackInfo, SynthParams, out userEffect); if (error != SynthErrorCodes.eSynthDone) { return(error); } List[j] = userEffect; if (OnePreOrigin > MaxPreOrigin) { MaxPreOrigin = OnePreOrigin; } } break; case EffectTypes.ePluggableEffect: { PluggableSpec Spec = GetPluggableEffectFromEffectSpecList(SpecList, i); Debug.Assert(Spec is PluggableOscSpec); PluggableOscEffectTemplate template = new PluggableOscEffectTemplate( (PluggableOscSpec)Spec, SynthParams); IOscillatorEffect effect; SynthErrorCodes error = template.Create( ref Accents, HurryUp, InitialFrequency, FreqForMultisampling, out OnePreOrigin, TrackInfo, SynthParams, out effect); if (error != SynthErrorCodes.eSynthDone) { return(error); } List[j] = effect; if (OnePreOrigin > MaxPreOrigin) { MaxPreOrigin = OnePreOrigin; } } break; } j++; } Debug.Assert(j == count); PreOriginTimeOut = MaxPreOrigin; GeneratorOut = Generator; return(SynthErrorCodes.eSynthDone); }
/* create a new track effect generator */ public static SynthErrorCodes NewTrackEffectGenerator( EffectSpecListRec SpecList, SynthParamRec SynthParams, out TrackEffectGenRec GeneratorOut) { GeneratorOut = null; TrackEffectGenRec Generator = new TrackEffectGenRec(); Generator.Enable = true; Generator.AutoQuiescence = EffectSpecListIsAutoQuiescenceEnabled(SpecList); if (Generator.AutoQuiescence) { Generator.Enable = false; /* start with it off in this case */ Generator.GateLevel = (float)(Math.Pow( 2, EffectSpecListGetAutoQuiescenceDecibels(SpecList) * (1 / -6.0205999132796239)) / SynthParams.fOverallVolumeScaling); Generator.WindowDuration = (int)(SynthParams.dEnvelopeRate * EffectSpecListGetAutoQuiescenceWindowDuration(SpecList)); Generator.CurrentWindowDuration = 0; } /* this is the current envelope update index for removing things from the */ /* scanning gap list (i.e. the back edge of the scanning gap) */ /* by setting this negative, we cause the scanning gap to open. */ Generator.ExecutionIndex = -SynthParams.iScanningGapWidthInEnvelopeTicks; /* initialize accent trackers */ InitAccentTracker(ref Generator.Accents0); InitAccentTracker(ref Generator.Accents1); InitAccentTracker(ref Generator.Accents2); InitAccentTracker(ref Generator.Accents3); InitAccentTracker(ref Generator.Accents4); InitAccentTracker(ref Generator.Accents5); InitAccentTracker(ref Generator.Accents6); InitAccentTracker(ref Generator.Accents7); /* build list of thingers */ OneEffectRec Appender = null; int l = GetEffectSpecListLength(SpecList); for (int i = 0; i < l; i += 1) { /* see if effect is enabled */ if (IsEffectFromEffectSpecListEnabled(SpecList, i)) { OneEffectRec Effect = new OneEffectRec(); /* link */ Effect.Next = null; if (Appender == null) { Generator.List = Effect; } else { Appender.Next = Effect; } Appender = Effect; /* fill in fields */ EffectTypes Type = GetEffectSpecListElementType(SpecList, i); switch (Type) { default: Debug.Assert(false); throw new ArgumentException(); case EffectTypes.eDelayEffect: Effect.u = DelayUnifiedRec.NewTrackDelayLineProcessor( GetDelayEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eNLProcEffect: Effect.u = NLProcUnifiedRec.NewTrackNLProcProcessor( GetNLProcEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eFilterEffect: Effect.u = FilterArrayRec.NewTrackFilterArrayProcessor( GetFilterEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eAnalyzerEffect: Effect.u = AnalyzerRec.NewAnalyzer( GetAnalyzerEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eHistogramEffect: Effect.u = HistogramRec.NewHistogram( GetHistogramEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eResamplerEffect: Effect.u = ResamplerRec.NewResampler( GetResamplerEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eCompressorEffect: Effect.u = CompressorRec.NewTrackCompressor( GetCompressorEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eVocoderEffect: Effect.u = VocoderRec.NewTrackVocoder( GetVocoderEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eIdealLowpassEffect: Effect.u = IdealLPRec.NewIdealLP( GetIdealLPEffectFromEffectSpecList(SpecList, i), SynthParams); break; case EffectTypes.eConvolverEffect: { ConvolverRec ConvolverEffect; SynthErrorCodes Result = ConvolverRec.NewConvolver( GetConvolverEffectFromEffectSpecList(SpecList, i), SynthParams, out ConvolverEffect); if (Result != SynthErrorCodes.eSynthDone) { return(Result); } Effect.u = ConvolverEffect; } break; case EffectTypes.eUserEffect: { UserEffectProcRec userEffect; SynthErrorCodes error = UserEffectProcRec.NewTrackUserEffectProc( GetUserEffectFromEffectSpecList(SpecList, i), SynthParams, out userEffect); if (error != SynthErrorCodes.eSynthDone) { return(error); } Effect.u = userEffect; } break; case EffectTypes.ePluggableEffect: { PluggableSpec Spec = GetPluggableEffectFromEffectSpecList(SpecList, i); Debug.Assert(Spec is PluggableTrackSpec); PluggableTrackEffectTemplate Template = new PluggableTrackEffectTemplate( (PluggableTrackSpec)Spec, SynthParams); ITrackEffect effect; SynthErrorCodes error = Template.Create( SynthParams, out effect); if (error != SynthErrorCodes.eSynthDone) { return(error); } Effect.u = effect; } break; } } } GeneratorOut = Generator; return(SynthErrorCodes.eSynthDone); }