Example #1
0
        /* generate effect cycle.  this is called once per envelope tick to apply */
        /* effects to data generated during this envelope clock cycle. */
        public static SynthErrorCodes ApplyOscEffectGenerator(
            OscEffectGenRec Generator,
            float[] workspace,
            int lOffset,
            int rOffset,
            int nActualFrames,
            SynthParamRec SynthParams)
        {
            int count = Generator.count;

            IOscillatorEffect[] List = Generator.List;
            if (unchecked ((uint)count > (uint)List.Length))
            {
                Debug.Assert(false);
                throw new IndexOutOfRangeException();
            }

            for (int i = 0; i < count; i++)
            {
                SynthErrorCodes error = List[i].Apply(
                    workspace,
                    lOffset,
                    rOffset,
                    nActualFrames,
                    SynthParams);
                if (error != SynthErrorCodes.eSynthDone)
                {
                    return(error);
                }
            }

            return(SynthErrorCodes.eSynthDone);
        }
Example #2
0
        /* update envelopes for effects */
        public static SynthErrorCodes OscEffectGeneratorUpdateEnvelopes(
            OscEffectGenRec Generator,
            double OscillatorFrequency,
            SynthParamRec SynthParams)
        {
            int count = Generator.count;

            IOscillatorEffect[] List = Generator.List;
            if (unchecked ((uint)count > (uint)List.Length))
            {
                Debug.Assert(false);
                throw new IndexOutOfRangeException();
            }

            for (int i = 0; i < count; i++)
            {
                SynthErrorCodes error = List[i].OscUpdateEnvelopes(
                    OscillatorFrequency,
                    SynthParams);
                if (error != SynthErrorCodes.eSynthDone)
                {
                    return(error);
                }
            }

            return(SynthErrorCodes.eSynthDone);
        }
Example #3
0
            /* 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);
            }
Example #4
0
            /* update user effect processor state with accent information */
            public SynthErrorCodes OscUpdateEnvelopes(
                double OscillatorFrequency,
                SynthParamRec SynthParams)
            {
                double[] paramResultsTemp = this.paramResultsPrevious;
                this.paramResultsPrevious = this.paramResults;
                this.paramResults         = paramResultsTemp;

                for (int i = 0; i < this.paramCount; i += 1)
                {
                    SynthErrorCodes error = SynthErrorCodes.eSynthDone;
                    this.paramResults[i] = LFOGenUpdateCycle(
                        this.params_Osc[i].LFO,
                        EnvelopeUpdate(
                            this.params_Osc[i].Envelope,
                            OscillatorFrequency,
                            SynthParams,
                            ref error),
                        OscillatorFrequency,
                        SynthParams,
                        ref error);
                    if (error != SynthErrorCodes.eSynthDone)
                    {
                        return(error);
                    }
                }

                return(SynthErrorCodes.eSynthDone);
            }
        /* update control state for effects processors.  this is called once per envelope */
        /* tick, and constitutes the first half of the control-update cycle. */
        /* returns true if successful, or false if it failed. */
        public static SynthErrorCodes UpdateStateTrackEffectGenerator(
            TrackEffectGenRec Generator,
            SynthParamRec SynthParams)
        {
            if (Generator.List != null)
            {
                AccentRec Accents = new AccentRec();
                InitializeAccent(
                    ref Accents,
                    Generator.Accents0.Current,
                    Generator.Accents1.Current,
                    Generator.Accents2.Current,
                    Generator.Accents3.Current,
                    Generator.Accents4.Current,
                    Generator.Accents5.Current,
                    Generator.Accents6.Current,
                    Generator.Accents7.Current);

                OneEffectRec Scan = Generator.List;
                while (Scan != null)
                {
                    SynthErrorCodes error = Scan.u.TrackUpdateState(
                        ref Accents,
                        SynthParams);
                    if (error != SynthErrorCodes.eSynthDone)
                    {
                        return(error);
                    }
                    Scan = Scan.Next;
                }
            }

            return(SynthErrorCodes.eSynthDone);
        }
        /* apply effects to data generated during this envelope clock cycle.  this is the */
        /* second half of the control-update cycle. */
        public static SynthErrorCodes ApplyTrackEffectGenerator(
            TrackEffectGenRec Generator,
            float[] workspace,
            int nActualFrames,
            int lOffset,
            int rOffset,
            SynthParamRec SynthParams)
        {
            OneEffectRec Scan = Generator.List;

            if (Scan != null)
            {
                /* auto-quiescence prepass -- if input exceeds level, then enable */
                if (Generator.AutoQuiescence)
                {
                    AutoQuiescenceDetector(
                        Generator,
                        workspace,
                        lOffset,
                        rOffset,
                        nActualFrames,
                        true /*examining input data*/);
                }

                if (Generator.Enable)
                {
                    while (Scan != null)
                    {
                        SynthErrorCodes error = Scan.u.Apply(
                            workspace,
                            lOffset,
                            rOffset,
                            nActualFrames,
                            SynthParams);
                        if (error != SynthErrorCodes.eSynthDone)
                        {
                            return(error);
                        }
                        Scan = Scan.Next;
                    }

                    /* auto-quiescence postpass -- if effects were applied, then */
                    /* examine the output */
                    if (Generator.AutoQuiescence)
                    {
                        AutoQuiescenceDetector(
                            Generator,
                            workspace,
                            lOffset,
                            rOffset,
                            nActualFrames,
                            false /*examining output data*/);
                    }
                }
            }

            return(SynthErrorCodes.eSynthDone);
        }
Example #7
0
        /* perform a single cycle of the envelope and return the amplitude for it's */
        /* point.  should be called at key-down to obtain initial amplitude. */
        public static double EnvelopeUpdate(
            EvalEnvelopeRec State,
            double OscillatorPitch,
            SynthParamRec SynthParams,
            ref SynthErrorCodes ErrorRef)
        {
            if (ErrorRef != SynthErrorCodes.eSynthDone)
            {
                return(0);
            }

            /* evaluate the segment generator */
            double Temp = State.EnvelopeUpdate(State);

            /* apply optional pitch scaling */
            if (State.PerformGlobalPitchScaling)
            {
                Temp = Temp * Math.Pow(2, -(Math.Log(OscillatorPitch
                                                     / State.Template.GlobalPitchRateNormalization) * Constants.INVLOG2)
                                       * State.Template.GlobalPitchRateRolloff);
            }

            /* apply optional transformation formula */
            if (State.Template.Formula != null)
            {
                AccentRec Accents;
                AccentRec TrackAccents;

                /* get current live accent info */
                State.ParamGetter(
                    State.ParamGetterContext,
                    out Accents,
                    out TrackAccents);

                /* add in the original differential that the note provided */
                AccentAdd(
                    1,
                    ref State.FrozenNoteAccentDifferential,
                    ref Accents,
                    ref Accents);

                /* evaluate */
                SynthErrorCodes error = EnvelopeParamEval(
                    Temp,
                    State.Template.Formula,
                    ref Accents,
                    ref TrackAccents,
                    SynthParams,
                    out Temp);
                if (error != SynthErrorCodes.eSynthDone)
                {
                    ErrorRef = error;
                    return(0);
                }
            }

            return(Temp);
        }
        /* check list of LFOs */
        public static SynthErrorCodes CheckLFOListForUnreferencedSamples(
            LFOListSpecRec LFOList,
            CheckUnrefParamRec Param)
        {
            int Limit = LFOListSpecGetNumElements(LFOList);

            for (int Scan = 0; Scan < Limit; Scan += 1)
            {
                SynthErrorCodes Error = CheckLFOForUnreferencedSamples(
                    LFOListSpecGetLFOSpec(LFOList, Scan),
                    Param);
                if (Error != SynthErrorCodes.eSynthDone)
                {
                    return(Error);
                }
            }

            return(SynthErrorCodes.eSynthDone);
        }
        /* check list of oscillators */
        public static SynthErrorCodes CheckOscillatorListForUnreferencedSamples(
            OscillatorListRec OscillatorList,
            CheckUnrefParamRec Param)
        {
            int Limit = GetOscillatorListLength(OscillatorList);

            for (int Scan = 0; Scan < Limit; Scan += 1)
            {
                SynthErrorCodes Error = CheckOscillatorForUnreferencedSamples(
                    GetOscillatorFromList(OscillatorList, Scan),
                    Param);
                if (Error != SynthErrorCodes.eSynthDone)
                {
                    return(Error);
                }
            }

            return(SynthErrorCodes.eSynthDone);
        }
        /* make sure all instruments in list refer to existing samples and wave tables */
        /* all instruments should be up to date when this is called. */
        public static SynthErrorCodes CheckInstrListForUnreferencedSamples(
            IList <InstrObjectRec> InstrList,
            CheckUnrefParamRec Param)
        {
            for (int Scan = 0; Scan < InstrList.Count; Scan += 1)
            {
                InstrObjectRec  InstrObject          = InstrList[Scan];
                InstrumentRec   InstrumentDefinition = InstrObject.BuiltInstrument;
                SynthErrorCodes Error = CheckInstrumentForUnreferencedSamples(
                    InstrumentDefinition,
                    Param);
                if (Error != SynthErrorCodes.eSynthDone)
                {
                    Param.ErrorInfo.InstrumentName = InstrObject.Name;
                    return(Error);
                }
            }

            return(SynthErrorCodes.eSynthDone);
        }
        /* do a scalar param evaluation */
        public static SynthErrorCodes ScalarParamEval(
            ScalarParamEvalRec Eval,
            ref AccentRec CurrentParameters,
            SynthParamRec SynthParams,
            out double ResultOut)
        {
            ResultOut = 0;

            double Temp = Eval.SpecifiedValue;

            /* ordering is somewhat arbitrary because if user wants it the other way, he can */
            /* always write it into the formula. */

            /* apply accent first */
            Temp = AccentProductAdd(
                Temp,
                ref CurrentParameters,
                ref Eval.SpecifiedAccentModifiers);

            /* compute formula second. */
            if (Eval.SpecifiedFormula != null)
            {
                SynthErrorCodes Error = StaticEval(
                    Temp,
                    Eval.SpecifiedFormula,
                    ref CurrentParameters,
                    SynthParams,
                    out Temp);
                if (Error != SynthErrorCodes.eSynthDone)
                {
                    return(Error);
                }
            }

            ResultOut = Temp;

            return(SynthErrorCodes.eSynthDone);
        }
Example #12
0
            /* update user effect processor state with accent information */
            public SynthErrorCodes TrackUpdateState(
                ref AccentRec Accents,
                SynthParamRec SynthParams)
            {
                double[] paramResultsTemp = this.paramResultsPrevious;
                this.paramResultsPrevious = this.paramResults;
                this.paramResults         = paramResultsTemp;

                for (int i = 0; i < this.paramCount; i += 1)
                {
                    SynthErrorCodes error = ScalarParamEval(
                        this.params_Track[i].Eval,
                        ref Accents,
                        SynthParams,
                        out this.paramResults[i]);
                    if (error != SynthErrorCodes.eSynthDone)
                    {
                        return(error);
                    }
                }

                return(SynthErrorCodes.eSynthDone);
            }
Example #13
0
        /* create a new envelope state record.  Accent factors have no effect with a value */
        /* of 1, attenuate at smaller values, and amplify at larger values. */
        public static EvalEnvelopeRec NewEnvelopeStateRecord(
            EnvelopeRec Template,
            ref AccentRec Accents,
            double FrequencyHertz,
            double Loudness,
            double HurryUp,
            out int PreOriginTime,
            ParamGetterMethod ParamGetter,
            object ParamGetterContext,
            SynthParamRec SynthParams)
        {
            EvalEnvelopeRec State = New(ref SynthParams.freelists.envelopeStateFreeList);

            // must assign all fields: State, State.PhaseVector

            State.NumPhases   = Template.NumPhases;
            State.PhaseVector = New(ref SynthParams.freelists.envelopeOnePhaseFreeList, Template.NumPhases); // cleared

#if DEBUG
            if ((Template.NumPhases != 0) && Template.ConstantShortcut)
            {
                // shouldn't specify shortcut and phase list at the same time
                Debug.Assert(false);
                throw new ArgumentException();
            }
#endif

            State.Template = Template;

            State.CurrentPhase          = -1;
            State.SustainPhase1         = Template.SustainPhase1;
            State.OriginalSustainPhase1 = Template.SustainPhase1;
            State.SustainPhase1Type     = Template.SustainPhase1Type;
            State.SustainPhase2         = Template.SustainPhase2;
            State.OriginalSustainPhase2 = Template.SustainPhase2;
            State.SustainPhase2Type     = Template.SustainPhase2Type;
            State.SustainPhase3         = Template.SustainPhase3;
            State.OriginalSustainPhase3 = Template.SustainPhase3;
            State.SustainPhase3Type     = Template.SustainPhase3Type;
            State.Origin                       = Template.Origin;
            State.ParamGetter                  = ParamGetter;
            State.ParamGetterContext           = ParamGetterContext;
            State.LastOutputtedValue           = 0;
            State.PreOriginTime                = 0;
            State.FrozenNoteAccentDifferential = new AccentRec();

            /* build initial delay transition */
            ResetLinearTransition(
                ref State.LinearTransition,
                0,
                0,
                1);
            State.LinearTransitionCounter       = 0;
            State.LinearTransitionTotalDuration = 0;
            State.EnvelopeUpdate      = _EnvUpdateLinearAbsolute;
            State.EnvelopeHasFinished = false;

            State.PerformGlobalPitchScaling = (0 != Template.GlobalPitchRateRolloff);

            // A note about accents to follow:
            // - The "Accents" parameter to this function comes from the FrozenNote - so they are the accent values in effect
            //   at the time the note was "frozen" (i.e. the accent defaults added to the individual note's adjustments).
            // - The "LiveAccents" parameter is the current accent defaults at time t (which should be equal to "Accents", at the
            //   the a note is initiated, but not necessarily before or after), since this event is occurring at time t.
            // - The "LiveTrackAccents" parameter is the current track effect accent values.
            // There is some redundancy here, but it is not being changed in case this is wrong and there are legacy
            // interactions that need to be preserved.
            AccentRec LiveAccents;
            AccentRec LiveTrackAccents;
#if DEBUG
            bool liveAccentInit = false;
#endif
            if (EnvelopeContainsFormula(Template)) // an optimization
            {
                /* get current live accents that do not contain any info from the note */
                ParamGetter(
                    ParamGetterContext,
                    out LiveAccents,
                    out LiveTrackAccents);
#if DEBUG
                liveAccentInit = true;
#endif
            }
            else
            {
                LiveAccents      = new AccentRec();
                LiveTrackAccents = new AccentRec();
            }

            /* build list of nodes */
            if (Template.ConstantShortcut)
            {
                State.NumPhases           = 0; /* make sure */
                State.CurrentPhase        = 0;
                State.LastOutputtedValue  = Template.ConstantShortcutValue;
                State.EnvelopeUpdate      = _EnvUpdateSustain;
                State.EnvelopeHasFinished = false;
            }
            else
            {
                State.LastOutputtedValue = 0;

                double           accumulatedError = 0;
                OneEnvPhaseRec[] PhaseVector      = State.PhaseVector;
                if (unchecked ((uint)State.NumPhases > (uint)PhaseVector.Length))
                {
                    throw new IndexOutOfRangeException();
                }
                EnvStepRec[] TemplatePhaseArray = Template.PhaseArray;
                if (unchecked ((uint)State.NumPhases > (uint)TemplatePhaseArray.Length))
                {
                    throw new IndexOutOfRangeException();
                }
                for (int i = 0; i < State.NumPhases; i++)
                {
                    Debug.Assert(PhaseVector[i].Equals(new OneEnvPhaseRec())); // verify cleared

                    PhaseVector[i].TransitionType = TemplatePhaseArray[i].TransitionType;
                    PhaseVector[i].TargetType     = TemplatePhaseArray[i].TargetType;
                    /* calculate the total duration.  the effect of accents is this: */
                    /*  - the accent is the base-2 log of a multiplier for the rate.  a value of 0 */
                    /*    does not change the rate.  -1 halves the rate, and 1 doubles the rate. */
                    /*  - the accent scaling factor is the base-2 log for scaling the accent. */
                    /*    a value of 0 eliminates the effect of the accent, a value of 1 does not */
                    /*    scale the accent. */
                    /*  - pitch has two factors:  normalization point and rolloff.  rolloff */
                    /*    determines how much the signal will decrease with each octave.  0 */
                    /*    removes effect, 1 halfs signal with each octave.  normalization point */
                    /*    determines what pitch will be the invariant point. */
                    double Temp;
                    if (TemplatePhaseArray[i].DurationFunction == null)
                    {
                        Temp = TemplatePhaseArray[i].Duration;
                    }
                    else
                    {
#if DEBUG
                        Debug.Assert(liveAccentInit);
#endif
                        SynthErrorCodes error = EnvelopeInitParamEval(
                            TemplatePhaseArray[i].DurationFunction,
                            ref Accents,
                            ref LiveTrackAccents,
                            SynthParams,
                            out Temp);
                        if (error != SynthErrorCodes.eSynthDone)
                        {
                            // TODO:
                        }
                    }
                    double preciseDuration = SynthParams.dEnvelopeRate
                                             * HurryUp
                                             * Temp
                                             * Math.Pow(2, -(AccentProduct(ref Accents, ref TemplatePhaseArray[i].AccentRate)
                                                             + (Math.Log(FrequencyHertz
                                                                         / TemplatePhaseArray[i].FrequencyRateNormalization)
                                                                * Constants.INVLOG2) * TemplatePhaseArray[i].FrequencyRateRolloff))
                                             + accumulatedError;
                    PhaseVector[i].Duration = (int)Math.Round(preciseDuration);
                    accumulatedError        = preciseDuration - PhaseVector[i].Duration;
                    /* the final amplitude scaling values are computed similarly to the rate */
                    /* scaling values. */
                    if (TemplatePhaseArray[i].EndPointFunction == null)
                    {
                        Temp = TemplatePhaseArray[i].EndPoint;
                    }
                    else
                    {
#if DEBUG
                        Debug.Assert(liveAccentInit);
#endif
                        SynthErrorCodes error = EnvelopeInitParamEval(
                            TemplatePhaseArray[i].EndPointFunction,
                            ref Accents,
                            ref LiveTrackAccents,
                            SynthParams,
                            out Temp);
                        if (error != SynthErrorCodes.eSynthDone)
                        {
                            // TODO:
                        }
                    }
                    PhaseVector[i].FinalAmplitude = Temp
                                                    * Template.OverallScalingFactor * Loudness
                                                    * Math.Pow(2, -(AccentProduct(ref Accents, ref TemplatePhaseArray[i].AccentAmp)
                                                                    + (Math.Log(FrequencyHertz
                                                                                / TemplatePhaseArray[i].FrequencyAmpNormalization)
                                                                       * Constants.INVLOG2) * TemplatePhaseArray[i].FrequencyAmpRolloff));

                    /* adjust initial countdown */
                    if (i < Template.Origin)
                    {
                        /* this occurs before the origin, so add it in */
                        State.PreOriginTime += PhaseVector[i].Duration;
                    }
                }
            }
            PreOriginTime = State.PreOriginTime;

            /* compute accent differentials */
            if (State.Template.Formula != null)
            {
#if DEBUG
                Debug.Assert(liveAccentInit);
#endif

                /* subtract composite accents ("Accents") from current live accents */
                AccentAdd(
                    -1,
                    ref Accents,
                    ref LiveAccents,
                    ref State.FrozenNoteAccentDifferential);
            }

            return(State);
        }
            /* generate one sequence of samples */
            public SynthErrorCodes Generate(
                int nActualFrames,
                float[] workspace,
                int RawBufferLOffset,
                int RawBufferROffset,
                int PrivateWorkspaceLOffset,
                int PrivateWorkspaceROffset,
                SynthParamRec SynthParams)
            {
                SynthErrorCodes error = SynthErrorCodes.eSynthDone;

                WaveTableStateRec State = this;

#if DEBUG
                Debug.Assert(!SynthParams.ScratchWorkspace1InUse);
                SynthParams.ScratchWorkspace1InUse = true;
                Debug.Assert(!SynthParams.ScratchWorkspace3InUse);
                SynthParams.ScratchWorkspace3InUse = true;
#endif
                int      loudnessWorkspaceOffset = SynthParams.ScratchWorkspace1LOffset;
                int      indexWorkspaceOffset    = SynthParams.ScratchWorkspace3Offset;
                double[] indexWorkspace          = UnsafeArrayCastLong.AsDoubles(SynthParams.ScratchWorkspace3);

                if (State.PreStartCountdown <= 0)
                {
                    if (State.OscEffectGenerator == null)
                    {
                        /* normal case */
                        if (State.WaveTableWasDefined)
                        {
                            Wave_Stereo(
                                State,
                                nActualFrames,
                                workspace,
                                RawBufferLOffset,
                                RawBufferROffset,
                                loudnessWorkspaceOffset,
                                indexWorkspace,
                                indexWorkspaceOffset);
                        }
                    }
                    else
                    {
                        /* effect postprocessing case */

                        /* initialize private storage */
                        FloatVectorZero(
                            workspace,
                            PrivateWorkspaceLOffset,
                            nActualFrames);
                        FloatVectorZero(
                            workspace,
                            PrivateWorkspaceROffset,
                            nActualFrames);

                        /* generate waveform */
                        if (State.WaveTableWasDefined)
                        {
                            Wave_Stereo(
                                State,
                                nActualFrames,
                                workspace,
                                PrivateWorkspaceLOffset,
                                PrivateWorkspaceROffset,
                                loudnessWorkspaceOffset,
                                indexWorkspace,
                                indexWorkspaceOffset);
                        }

#if DEBUG
                        SynthParams.ScratchWorkspace1InUse = false;
                        SynthParams.ScratchWorkspace3InUse = false;
#endif

                        /* apply processor to it */
                        error = ApplyOscEffectGenerator(
                            State.OscEffectGenerator,
                            workspace,
                            PrivateWorkspaceLOffset,
                            PrivateWorkspaceROffset,
                            nActualFrames,
                            SynthParams);
                        if (error != SynthErrorCodes.eSynthDone)
                        {
                            goto Error;
                        }

                        /* copy out data */
                        FloatVectorAcc(
                            workspace,
                            PrivateWorkspaceLOffset,
                            workspace,
                            RawBufferLOffset,
                            nActualFrames);
                        FloatVectorAcc(
                            workspace,
                            PrivateWorkspaceROffset,
                            workspace,
                            RawBufferROffset,
                            nActualFrames);
                    }
                }


Error:

#if DEBUG
                SynthParams.ScratchWorkspace1InUse = false;
                SynthParams.ScratchWorkspace3InUse = false;
#endif

                return(error);
            }
            /* create a new wave table state object. */
            public SynthErrorCodes NewState(
                double FreqForMultisampling,
                ref AccentRec Accents,
                double Loudness,
                double HurryUp,
                out int PreOriginTimeOut,
                double StereoPosition,
                double InitialFrequency,
                double PitchDisplacementDepthLimit,
                double PitchDisplacementRateLimit,
                int PitchDisplacementStartPoint,
                PlayTrackInfoRec TrackInfo,
                SynthParamRec SynthParams,
                out IOscillator StateOut)
            {
                WaveTableTemplateRec Template = this;

                int OnePreOrigin;

                PreOriginTimeOut = 0;
                StateOut         = null;

                WaveTableStateRec State = New(ref SynthParams.freelists.waveTableStateFreeList);

                // all fields must be assigned: State

                // conservative zero-initialization
                State.WaveTableSamplePositionDifferential = new Fixed64(0);

                State.Template = Template;

                int MaxPreOrigin = 0;

                State.WaveTableSamplePosition = new Fixed64(0);
                /* State.WaveTableSamplePositionDifferential specified in separate call */

                State.NoteLoudnessScaling = Loudness * Template.OverallOscillatorLoudness;

                int NumberOfTables;

                State.WaveTableWasDefined = GetMultiWaveTableReference(
                    Template.WaveTableSourceSelector,
                    FreqForMultisampling,
                    out State.WaveTableMatrix,
                    out State.FramesPerTable,
                    out NumberOfTables);
                State.NumberOfTablesMinus1 = NumberOfTables - 1;

                State.FramesPerTableOverFinalOutputSamplingRate
                    = (double)State.FramesPerTable / SynthParams.dSamplingRate;

                /* State.FramesPerTable > 0: */
                /*   if the wave table is empty, then we don't do any work (and we must not, */
                /*   since array accesses would cause a crash) */
                if (State.WaveTableWasDefined)
                {
                    if (!(State.FramesPerTable > 0))
                    {
                        State.WaveTableWasDefined = false;
                    }
                }

                State.PreStartCountdown = (int)((Template.TimeDisplacement
                                                 * SynthParams.dEnvelopeRate) + 0.5);
                if (-State.PreStartCountdown > MaxPreOrigin)
                {
                    MaxPreOrigin = -State.PreStartCountdown;
                }

                /* State.WaveTableIndex determined by envelope update */
                State.WaveTableIndexEnvelope = NewEnvelopeStateRecord(
                    Template.IndexEnvelopeTemplate,
                    ref Accents,
                    InitialFrequency,
                    1,
                    HurryUp,
                    out OnePreOrigin,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }
                State.IndexLFOGenerator = NewLFOGenerator(
                    Template.IndexLFOTemplate,
                    out OnePreOrigin,
                    ref Accents,
                    InitialFrequency,
                    HurryUp,
                    1,
                    1,
                    FreqForMultisampling,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }
                State.PreviousWaveTableIndex = 0;
                State.WaveTableIndex         = 0;

                /* State.MonoLoudness, State.LeftLoudness, State.RightLoudness */
                /* are determined by the envelope update */
                StereoPosition += Template.StereoBias;
                if (StereoPosition < -1)
                {
                    StereoPosition = -1;
                }
                else if (StereoPosition > 1)
                {
                    StereoPosition = 1;
                }
                State.Panning = (float)StereoPosition;
                State.WaveTableLoudnessEnvelope = NewEnvelopeStateRecord(
                    Template.LoudnessEnvelopeTemplate,
                    ref Accents,
                    InitialFrequency,
                    1,
                    HurryUp,
                    out OnePreOrigin,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }
                State.LoudnessLFOGenerator = NewLFOGenerator(
                    Template.LoudnessLFOTemplate,
                    out OnePreOrigin,
                    ref Accents,
                    InitialFrequency,
                    HurryUp,
                    1,
                    1,
                    FreqForMultisampling,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }
                State.PreviousLoudness = 0;
                State.Loudness         = 0;

                State.PitchLFO = NewLFOGenerator(
                    Template.PitchLFOTemplate,
                    out OnePreOrigin,
                    ref Accents,
                    InitialFrequency,
                    HurryUp,
                    PitchDisplacementDepthLimit,
                    PitchDisplacementRateLimit,
                    FreqForMultisampling,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }
                State.PitchLFOStartCountdown = PitchDisplacementStartPoint;

                State.OscEffectGenerator = null;
                if (Template.OscEffectTemplate != null)
                {
                    SynthErrorCodes Result = NewOscEffectGenerator(
                        Template.OscEffectTemplate,
                        ref Accents,
                        HurryUp,
                        InitialFrequency,
                        FreqForMultisampling,
                        out OnePreOrigin,
                        TrackInfo,
                        SynthParams,
                        out State.OscEffectGenerator);
                    if (Result != SynthErrorCodes.eSynthDone)
                    {
                        return(Result);
                    }
                    if (OnePreOrigin > MaxPreOrigin)
                    {
                        MaxPreOrigin = OnePreOrigin;
                    }
                }

                State.EnableCrossWaveTableInterpolation = Template.EnableCrossWaveTableInterpolation;

                PreOriginTimeOut = MaxPreOrigin;
                StateOut         = State;
                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);
        }
Example #17
0
            /* 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);
            }
Example #18
0
            /* create a new convolver */
            public static SynthErrorCodes NewConvolver(
                ConvolverSpecRec Template,
                SynthParamRec SynthParams,
                out ConvolverRec ConvolverOut)
            {
                ConvolverOut = null;

                ConvolverRec Convolver = new ConvolverRec();

                Convolver.Type = ConvolverSpecGetSourceType(Template);
                ConvRuleRec[] RuleArray;
                switch (Convolver.Type)
                {
                default:
                    Debug.Assert(false);
                    throw new ArgumentException();

                case ConvolveSrcType.eConvolveMono:
                    RuleArray = ConvMonoRule;
                    break;

                case ConvolveSrcType.eConvolveStereo:
                    RuleArray = ConvStereoRule;
                    break;

                case ConvolveSrcType.eConvolveBiStereo:
                    RuleArray = ConvBiStereoRule;
                    break;
                }

                int?Latency = null;

                if (ConvolverSpecGetLatencySpecified(Template))
                {
                    Latency = (int)(ConvolverSpecGetLatency(Template) * SynthParams.dSamplingRate);
                    if (Latency.Value < 0)
                    {
                        Latency = 0;
                    }
                }

                // validation pass
                int maximumImpulseResponseLength = 0;

                float[][] Data   = new float[RuleArray.Length][];
                int[]     Frames = new int[RuleArray.Length];
                for (int i = 0; i < RuleArray.Length; i += 1)
                {
                    NumChannelsType NumChannels;
                    int             SamplingRate;
                    int             unusedInt;
                    double          unusedDouble;
                    bool            unusedBool;

                    string ImpulseResponseName = RuleArray[i].ConvolverSpecGetImpulseResponse(Template);
                    if (!WaveSampDictGetSampleInfo(
                            SynthParams.Dictionary,
                            ImpulseResponseName,
                            out Data[i],
                            out Frames[i],
                            out NumChannels,
                            out unusedInt,
                            out unusedInt,
                            out unusedInt,
                            out unusedInt,
                            out unusedInt,
                            out unusedInt,
                            out unusedInt,
                            out unusedDouble,
                            out SamplingRate,
                            out unusedBool,
                            out unusedBool,
                            out unusedBool))
                    {
                        // should never be provided with name of non-existent sample data
                        Debug.Assert(false);
                        throw new ArgumentException();
                    }

                    if (SamplingRate * SynthParams.iOversampling != SynthParams.iSamplingRate)
                    {
                        SynthParams.ErrorInfo.ErrorEx    = SynthErrorSubCodes.eSynthErrorExConvolverBadSamplingRate;
                        SynthParams.ErrorInfo.SampleName = ImpulseResponseName;
                        return(SynthErrorCodes.eSynthErrorEx);
                    }
                    if (NumChannels != NumChannelsType.eSampleMono)
                    {
                        SynthParams.ErrorInfo.ErrorEx    = SynthErrorSubCodes.eSynthErrorExConvolverBadNumChannels;
                        SynthParams.ErrorInfo.SampleName = ImpulseResponseName;
                        return(SynthErrorCodes.eSynthErrorEx);
                    }

                    maximumImpulseResponseLength = Math.Max(maximumImpulseResponseLength, Frames[i]);
                }
                if (!Latency.HasValue)
                {
                    Latency = maximumImpulseResponseLength * SynthParams.iOversampling;
                }

                for (int i = 0; i < RuleArray.Length; i += 1)
                {
                    IConvolution    ConvStream;
                    SynthErrorCodes result = ConvolveStreamFactory.NewConvStream(
                        Data[i],
                        Frames[i],
                        ConvolverSpecGetLatencySpecified(Template),
                        Latency.Value,
                        SynthParams.iOversampling,
                        SynthParams.ErrorInfo,
                        out ConvStream);
                    if (result != SynthErrorCodes.eSynthDone)
                    {
                        return(result);
                    }
                    switch (i)
                    {
                    default:
                        Debug.Assert(false);
                        throw new InvalidOperationException();

                    case 0:
                        Convolver.ConvStream0 = ConvStream;
                        break;

                    case 1:
                        Convolver.ConvStream1 = ConvStream;
                        break;

                    case 2:
                        Convolver.ConvStream2 = ConvStream;
                        break;

                    case 3:
                        Convolver.ConvStream3 = ConvStream;
                        break;
                    }
                }

                ConvolverSpecGetDirectGain(
                    Template,
                    out Convolver.DirectGain);
                ConvolverSpecGetProcessedGain(
                    Template,
                    out Convolver.ProcessedGain);

                /* done successfully */
                ConvolverOut = Convolver;
                return(SynthErrorCodes.eSynthDone);
            }
Example #19
0
        /* 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);
        }
Example #20
0
            /* create a new FOF state object. */
            public SynthErrorCodes NewState(
                double FreqForMultisampling,
                ref AccentRec Accents,
                double Loudness,
                double HurryUp,
                out int PreOriginTimeOut,
                double StereoPosition,
                double InitialFrequency,
                double PitchDisplacementDepthLimit,
                double PitchDisplacementRateLimit,
                int PitchDisplacementStartPoint,
                PlayTrackInfoRec TrackInfo,
                SynthParamRec SynthParams,
                out IOscillator StateOut)
            {
                FOFTemplateRec Template = this;

                int OnePreOrigin;
                int NumberOfTables;

                PreOriginTimeOut = 0;
                StateOut         = null;

                FOFStateRec State = New(ref SynthParams.freelists.FOFStateRecFreeList);

                // must initilize all fields: State

                State.WaveTableSamplePosition             = new Fixed64(0);
                State.WaveTableSamplePositionDifferential = new Fixed64(0);
                State.WaveTableIndex         = 0;
                State.LeftLoudness           = 0;
                State.RightLoudness          = 0;
                State.FOFSamplingRateContour = 0;

                State.Template = Template;

                int MaxPreOrigin = 0;

                State.ActiveGrainList = null; /* no grains to begin with */

                State.NoteLoudnessScaling = Loudness * Template.OverallOscillatorLoudness;

                State.WaveTableWasDefined = GetMultiWaveTableReference(
                    Template.WaveTableSourceSelector,
                    FreqForMultisampling,
                    out State.WaveTableMatrix,
                    out State.FramesPerTable,
                    out NumberOfTables);
                State.NumberOfTablesMinus1 = NumberOfTables - 1;

                if (State.WaveTableWasDefined)
                {
                    /* we want the first grain to go on the first sampling point, so we */
                    /* set this up to start on the next interval. */
                    State.WaveTableSamplePosition = new Fixed64(State.FramesPerTable - State.FramesPerTable
                                                                * (InitialFrequency / SynthParams.dSamplingRate));
                }
                /* State.WaveTableSamplePositionDifferential specified in separate call */

                /* State.FramesPerTable > 0: */
                /*   if the wave table is empty, then we don't do any work (and we must not, */
                /*   since array accesses would cause a crash) */
                if (State.WaveTableWasDefined)
                {
                    if (!(State.FramesPerTable > 0))
                    {
                        State.WaveTableWasDefined = false;
                    }
                }

                /* State.WaveTableWasDefined: */
                /*   if there is no wave table defined for the current pitch, then we don't */
                /*   bother generating any data */
                /* (no action required) */

                State.PreStartCountdown = (int)(Template.TimeDisplacement * SynthParams.dEnvelopeRate + 0.5);
                if (-State.PreStartCountdown > MaxPreOrigin)
                {
                    MaxPreOrigin = -State.PreStartCountdown;
                }

                /* State.WaveTableIndex determined by envelope update */
                State.WaveTableIndexEnvelope = NewEnvelopeStateRecord(
                    Template.IndexEnvelopeTemplate,
                    ref Accents,
                    InitialFrequency,
                    1,
                    HurryUp,
                    out OnePreOrigin,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }

                State.IndexLFOGenerator = NewLFOGenerator(
                    Template.IndexLFOTemplate,
                    out OnePreOrigin,
                    ref Accents,
                    InitialFrequency,
                    HurryUp,
                    1,
                    1,
                    FreqForMultisampling,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }

                /* State.MonoLoudness, State.LeftLoudness, State.RightLoudness */
                /* are determined by the envelope update */
                StereoPosition += Template.StereoBias;
                if (StereoPosition < -1)
                {
                    StereoPosition = -1;
                }
                else if (StereoPosition > 1)
                {
                    StereoPosition = 1;
                }
                State.Panning = (float)StereoPosition;

                State.WaveTableLoudnessEnvelope = NewEnvelopeStateRecord(
                    Template.LoudnessEnvelopeTemplate,
                    ref Accents,
                    InitialFrequency,
                    1,
                    HurryUp,
                    out OnePreOrigin,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }

                State.LoudnessLFOGenerator = NewLFOGenerator(
                    Template.LoudnessLFOTemplate,
                    out OnePreOrigin,
                    ref Accents,
                    InitialFrequency,
                    HurryUp,
                    1,
                    1,
                    FreqForMultisampling,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }

                State.PitchLFO = NewLFOGenerator(
                    Template.PitchLFOTemplate,
                    out OnePreOrigin,
                    ref Accents,
                    InitialFrequency,
                    HurryUp,
                    PitchDisplacementDepthLimit,
                    PitchDisplacementRateLimit,
                    FreqForMultisampling,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }
                State.PitchLFOStartCountdown = PitchDisplacementStartPoint;

                State.FOFSamplingRateEnvelope = NewEnvelopeStateRecord(
                    Template.FOFSamplingRateEnvelopeTemplate,
                    ref Accents,
                    InitialFrequency,
                    1,
                    HurryUp,
                    out OnePreOrigin,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }

                State.FOFSamplingRateLFOGenerator = NewLFOGenerator(
                    Template.FOFSamplingRateLFOTemplate,
                    out OnePreOrigin,
                    ref Accents,
                    InitialFrequency,
                    HurryUp,
                    1,
                    1,
                    FreqForMultisampling,
                    _PlayTrackParamGetter,
                    TrackInfo,
                    SynthParams);
                if (OnePreOrigin > MaxPreOrigin)
                {
                    MaxPreOrigin = OnePreOrigin;
                }

                State.OscEffectGenerator = null;
                if (Template.OscEffectTemplate != null)
                {
                    SynthErrorCodes Result = NewOscEffectGenerator(
                        Template.OscEffectTemplate,
                        ref Accents,
                        HurryUp,
                        InitialFrequency,
                        FreqForMultisampling,
                        out OnePreOrigin,
                        TrackInfo,
                        SynthParams,
                        out State.OscEffectGenerator);
                    if (Result != SynthErrorCodes.eSynthDone)
                    {
                        return(Result);
                    }
                    if (OnePreOrigin > MaxPreOrigin)
                    {
                        MaxPreOrigin = OnePreOrigin;
                    }
                }

                PreOriginTimeOut = MaxPreOrigin;
                StateOut         = State;
                return(SynthErrorCodes.eSynthDone);
            }
        /* check list of effects */
        public static SynthErrorCodes CheckEffectListForUnreferencedSamples(
            EffectSpecListRec EffectList,
            CheckUnrefParamRec Param)
        {
            int Limit = GetEffectSpecListLength(EffectList);

            for (int Scan = 0; Scan < Limit; Scan += 1)
            {
                SynthErrorCodes Error = SynthErrorCodes.eSynthDone;
                switch (GetEffectSpecListElementType(EffectList, Scan))
                {
                default:
                    Debug.Assert(false);
                    throw new ArgumentException();

                case EffectTypes.eDelayEffect:
                    Error = CheckDelayEffectForUnreferencedSamples(
                        GetDelayEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eNLProcEffect:
                    Error = CheckNonlinearEffectForUnreferencedSamples(
                        GetNLProcEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eFilterEffect:
                    Error = CheckFilterEffectForUnreferencedSamples(
                        GetFilterEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eAnalyzerEffect:
                    Error = CheckAnalyzerEffectForUnreferencedSamples(
                        GetAnalyzerEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eHistogramEffect:
                    Error = CheckHistogramEffectForUnreferencedSamples(
                        GetHistogramEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eResamplerEffect:
                    Error = CheckResamplerEffectForUnreferencedSamples(
                        GetResamplerEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eCompressorEffect:
                    Error = CheckCompressorEffectForUnreferencedSamples(
                        GetCompressorEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eVocoderEffect:
                    Error = CheckVocoderEffectForUnreferencedSamples(
                        GetVocoderEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eIdealLowpassEffect:
                    Error = CheckIdealLowpassEffectForUnreferencedSamples(
                        GetIdealLPEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eConvolverEffect:
                    Error = CheckConvolverEffectForUnreferencedSamples(
                        GetConvolverEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.eUserEffect:
                    Error = CheckUserEffectForUnreferencedSamples(
                        GetUserEffectFromEffectSpecList(EffectList, Scan),
                        Param);
                    break;

                case EffectTypes.ePluggableEffect:
                    PluggableSpec PluggableEffect = GetPluggableEffectFromEffectSpecList(EffectList, Scan);
                    Error = PluggableEffect.PluggableTemplate.CheckUnreferencedObjects(
                        PluggableEffect.GetStaticStrings(),
                        Param);
                    break;
                }

                if (Error != SynthErrorCodes.eSynthDone)
                {
                    return(Error);
                }
            }

            return(SynthErrorCodes.eSynthDone);
        }
        /* check oscillator */
        public static SynthErrorCodes CheckOscillatorForUnreferencedSamples(
            OscillatorRec Oscillator,
            CheckUnrefParamRec Param)
        {
            SynthErrorCodes Error = SynthErrorCodes.eSynthDone;

            switch (OscillatorGetWhatKindItIs(Oscillator))
            {
            default:
                Debug.Assert(false);
                throw new ArgumentException();

            case OscillatorTypes.eOscillatorSampled:
                Error = CheckSampleSelectorForUnreferencedSamples(
                    OscillatorGetSampleIntervalList(Oscillator),
                    Param);
                break;

            case OscillatorTypes.eOscillatorWaveTable:
            case OscillatorTypes.eOscillatorFOF:
                Error = CheckWaveTableSelectorForUnreferencedSamples(
                    OscillatorGetSampleIntervalList(Oscillator),
                    Param);
                break;

            case OscillatorTypes.eOscillatorAlgorithm:
                break;

            case OscillatorTypes.eOscillatorFMSynth:
                Error = CheckFMNetworkForUnreferencedSamples(
                    OscillatorGetFMSynthSpec(Oscillator),
                    Param);
                break;

            case OscillatorTypes.eOscillatorPluggable:
                IPluggableProcessorTemplate pluggable = GetOscillatorPluggableSpec(Oscillator).PluggableTemplate;
                Error = pluggable.CheckUnreferencedObjects(
                    GetOscillatorPluggableSpec(Oscillator).GetStaticStrings(),
                    Param);
                break;
            }
            if (Error != SynthErrorCodes.eSynthDone)
            {
                return(Error);
            }

            Error = CheckEnvelopeForUnreferencedSamples(
                OscillatorGetLoudnessEnvelope(Oscillator),
                Param);
            if (Error != SynthErrorCodes.eSynthDone)
            {
                return(Error);
            }

            Error = CheckLFOListForUnreferencedSamples(
                OscillatorGetLoudnessLFOList(Oscillator),
                Param);
            if (Error != SynthErrorCodes.eSynthDone)
            {
                return(Error);
            }

            Error = CheckEnvelopeForUnreferencedSamples(
                OscillatorGetExcitationEnvelope(Oscillator),
                Param);
            if (Error != SynthErrorCodes.eSynthDone)
            {
                return(Error);
            }

            Error = CheckLFOListForUnreferencedSamples(
                OscillatorGetExcitationLFOList(Oscillator),
                Param);
            if (Error != SynthErrorCodes.eSynthDone)
            {
                return(Error);
            }

            Error = CheckLFOListForUnreferencedSamples(
                GetOscillatorFrequencyLFOList(Oscillator),
                Param);
            if (Error != SynthErrorCodes.eSynthDone)
            {
                return(Error);
            }

            Error = CheckEffectListForUnreferencedSamples(
                GetOscillatorEffectList(Oscillator),
                Param);
            if (Error != SynthErrorCodes.eSynthDone)
            {
                return(Error);
            }

            Error = CheckEnvelopeForUnreferencedSamples(
                OscillatorGetFOFRateEnvelope(Oscillator),
                Param);
            if (Error != SynthErrorCodes.eSynthDone)
            {
                return(Error);
            }

            Error = CheckLFOListForUnreferencedSamples(
                OscillatorGetFOFRateLFOList(Oscillator),
                Param);
            if (Error != SynthErrorCodes.eSynthDone)
            {
                return(Error);
            }

            return(SynthErrorCodes.eSynthDone);
        }
Example #23
0
        /* retrigger envelopes from the origin point */
        public static void EnvelopeRetriggerFromOrigin(
            EvalEnvelopeRec State,
            ref AccentRec Accents,
            double FrequencyHertz,
            double Loudness,
            double HurryUp,
            bool ActuallyRetrigger,
            SynthParamRec SynthParams)
        {
            /* if we actually retrigger, then reset the state */
            if (ActuallyRetrigger)
            {
                State.CurrentPhase        = -1;
                State.EnvelopeHasFinished = false;
                while (State.CurrentPhase < State.Origin - 1)
                {
                    State.CurrentPhase += 1;
                }
                State.SustainPhase1           = State.OriginalSustainPhase1;
                State.SustainPhase2           = State.OriginalSustainPhase2;
                State.SustainPhase3           = State.OriginalSustainPhase3;
                State.LinearTransitionCounter = 0; /* force transition on next update */
                State.EnvelopeUpdate          = _EnvUpdateLinearAbsolute;
            }

            // A note about accents to follow:
            // - The "Accents" parameter to this function comes from the FrozenNote - so they are the accent values in effect
            //   at the time the note was "frozen" (i.e. the accent defaults added to the individual note's adjustments).
            // - The "LiveAccents" parameter is the current accent defaults at time t (which should be equal to "Accents", at the
            //   the a note is initiated, but not necessarily before or after), since this event is occurring at time t.
            // - The "LiveTrackAccents" parameter is the current track effect accent values.
            // There is some redundancy here, but it is not being changed in case this is wrong and there are legacy
            // interactions that need to be preserved.
            AccentRec LiveAccents;
            AccentRec LiveTrackAccents;

#if DEBUG
            bool liveAccentInit = false;
#endif
            if (EnvelopeContainsFormula(State.Template)) // an optimization
            {
                /* get current live accents that do not contain any info from the note */
                State.ParamGetter(
                    State.ParamGetterContext,
                    out LiveAccents,
                    out LiveTrackAccents);
#if DEBUG
                liveAccentInit = true;
#endif
            }
            else
            {
                LiveAccents      = new AccentRec();
                LiveTrackAccents = new AccentRec();
            }

            OneEnvPhaseRec[] PhaseVector = State.PhaseVector;
            if (unchecked ((uint)State.NumPhases > (uint)PhaseVector.Length))
            {
                throw new IndexOutOfRangeException();
            }
            EnvStepRec[] TemplatePhaseArray = State.Template.PhaseArray;
            if (unchecked ((uint)State.NumPhases > (uint)TemplatePhaseArray.Length))
            {
                throw new IndexOutOfRangeException();
            }

            /* no matter what, refill the parameters */
            double accumulatedError = 0;
            for (int i = 0; i < State.NumPhases; i++)
            {
                /* calculate the total duration.  the effect of accents is this: */
                /*  - the accent is the base-2 log of a multiplier for the rate.  a value of 0 */
                /*    does not change the rate.  -1 halves the rate, and 1 doubles the rate. */
                /*  - the accent scaling factor is the base-2 log for scaling the accent. */
                /*    a value of 0 eliminates the effect of the accent, a value of 1 does not */
                /*    scale the accent. */
                /*  - pitch has two factors:  normalization point and rolloff.  rolloff */
                /*    determines how much the signal will decrease with each octave.  0 */
                /*    removes effect, 1 halfs signal with each octave.  normalization point */
                /*    determines what pitch will be the invariant point. */
                double Temp;
                if (TemplatePhaseArray[i].DurationFunction == null)
                {
                    Temp = TemplatePhaseArray[i].Duration;
                }
                else
                {
#if DEBUG
                    Debug.Assert(liveAccentInit);
#endif
                    SynthErrorCodes error = EnvelopeInitParamEval(
                        TemplatePhaseArray[i].DurationFunction,
                        ref Accents,
                        ref LiveTrackAccents,
                        SynthParams,
                        out Temp);
                    if (error != SynthErrorCodes.eSynthDone)
                    {
                        // TODO:
                    }
                }
                double preciseDuration = SynthParams.dEnvelopeRate
                                         * HurryUp
                                         * Temp
                                         * Math.Pow(2, -(AccentProduct(ref Accents, ref TemplatePhaseArray[i].AccentRate)
                                                         + (Math.Log(FrequencyHertz
                                                                     / TemplatePhaseArray[i].FrequencyRateNormalization)
                                                            * Constants.INVLOG2) * TemplatePhaseArray[i].FrequencyRateRolloff))
                                         + accumulatedError;
                PhaseVector[i].Duration = (int)Math.Round(preciseDuration);
                accumulatedError        = preciseDuration - PhaseVector[i].Duration;
                /* the final amplitude scaling values are computed similarly to the rate */
                /* scaling values. */
                if (TemplatePhaseArray[i].EndPointFunction == null)
                {
                    Temp = TemplatePhaseArray[i].EndPoint;
                }
                else
                {
#if DEBUG
                    Debug.Assert(liveAccentInit);
#endif
                    SynthErrorCodes error = EnvelopeInitParamEval(
                        TemplatePhaseArray[i].EndPointFunction,
                        ref Accents,
                        ref LiveTrackAccents,
                        SynthParams,
                        out Temp);
                    if (error != SynthErrorCodes.eSynthDone)
                    {
                        // TODO:
                    }
                }
                PhaseVector[i].FinalAmplitude = Temp
                                                * State.Template.OverallScalingFactor * Loudness
                                                * Math.Pow(2, -(AccentProduct(ref Accents, ref TemplatePhaseArray[i].AccentAmp)
                                                                + (Math.Log(FrequencyHertz
                                                                            / TemplatePhaseArray[i].FrequencyAmpNormalization)
                                                                   * Constants.INVLOG2) * TemplatePhaseArray[i].FrequencyAmpRolloff));
            }

            /* recompute accent differentials incorporating new note's info */
            if (State.Template.Formula != null)
            {
#if DEBUG
                Debug.Assert(liveAccentInit);
#endif

                /* subtract composite accents ("Accents") from current live accents */
                AccentAdd(
                    -1,
                    ref Accents,
                    ref LiveAccents,
                    ref State.FrozenNoteAccentDifferential);
            }
        }
Example #24
0
        /* construct a new oscillator bank state object based on the note.  the note is */
        /* assumed to start "now" in terms of the parameters in the ParameterUpdator.  */
        /* the ScanningGapWidth is the number of envelope clock ticks in the current scanning */
        /* gap.  this is used to determine how far later than "now" in terms of the back */
        /* edge of the scanning gap (different from above) the osc bank should start playing. */
        /* *WhenToStartPlayingOut returns the number of envelope ticks after the back edge */
        /* of the scanning gap that the note should be started. */
        /*     <already played>       |    <scanning gap>     |    <not yet analyzed> */
        /*   time ---.    time ---.    time ---.    time ---.    time ---.   time ---. */
        /*                            ^A                      ^B     */
        /* point A is the back edge of the scanning gap.  as this edge moves forward in time, */
        /*   oscillator bank state objects are removed from the queue and playback is commenced */
        /*   for them. */
        /* point B is the front edge of the scanning gap.  as this edge moves forward in time, */
        /*   notes are extracted from the track and state bank objects are created for them. */
        /*   ParameterUpdator always reflects parameters at this point in time. */
        public static SynthErrorCodes NewOscBankState(
            OscBankTemplateRec Template,
            out int WhenToStartPlayingOut,
            NoteNoteObjectRec Note,
            double EnvelopeTicksPerDurationTick,
            short PitchIndexAdjust,
            PlayTrackInfoRec TrackInfo,
            SynthParamRec SynthParams,
            out OscStateBankRec StateOut)
        {
            int ThisPreOriginTime;
            int StartPointAdjust;

            WhenToStartPlayingOut = 0;
            StateOut = null;

            int MaxOscillatorPreOriginTime = 0;

            OscStateBankRec State = New(ref SynthParams.freelists.oscStateBankFreeList);

            // all fields must be assigned: State

            State.PortamentoHertz      = false;
            State.TotalPortamentoTicks = 0;
            State.InitialFrequency     = 0;
            State.FinalFrequency       = 0;

            State.BankTemplate = Template;

            /* freeze the parameters */
            FrozenNoteRec FrozenNote = new FrozenNoteRec();

            FixNoteParameters(
                Template.ParamUpdator,
                Note,
                out StartPointAdjust,
                EnvelopeTicksPerDurationTick,
                PitchIndexAdjust,
                ref FrozenNote,
                SynthParams);


            /* this calculates the differential values for periodic pitch displacements */
            State.PitchLFO = NewLFOGenerator(
                Template.PitchLFOTemplate,
                out ThisPreOriginTime,
                ref FrozenNote.Accents,
                FrozenNote.NominalFrequency,
                FrozenNote.HurryUpFactor,
                FrozenNote.PitchDisplacementDepthLimit,
                FrozenNote.PitchDisplacementRateLimit,
                FrozenNote.MultisampleFrequency,
                _PlayTrackParamGetter,
                TrackInfo,
                SynthParams);
            if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
            {
                MaxOscillatorPreOriginTime = ThisPreOriginTime;
            }

            /* list of oscillators that this oscillator bank is comprised of */
            State.OscillatorList = null;
            for (int i = 0; i < Template.NumOscillatorsInBank; i++)
            {
                OscStateRec OneState = New(ref SynthParams.freelists.oscStateFreeList);

                // all fields must be assigned: OneState

                /* link it in */
                OneState.Next        = State.OscillatorList;
                State.OscillatorList = OneState;

                /* copy over the function vectors */
                OneState.Template = Template.TemplateArray[i];

                /* create the oscillator */
                SynthErrorCodes Result = OneState.Template.TemplateReference.NewState(
                    FrozenNote.MultisampleFrequency,
                    ref FrozenNote.Accents,
                    FrozenNote.LoudnessAdjust * Template.InstrOverallLoudness,
                    FrozenNote.HurryUpFactor,
                    out ThisPreOriginTime,
                    FrozenNote.StereoPosition,
                    FrozenNote.NominalFrequency,
                    FrozenNote.PitchDisplacementDepthLimit,
                    FrozenNote.PitchDisplacementRateLimit,
                    FrozenNote.PitchDisplacementStartPoint,
                    TrackInfo,
                    SynthParams,
                    out OneState.StateReference);
                if (Result != SynthErrorCodes.eSynthDone)
                {
                    return(Result);
                }
                if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
                {
                    MaxOscillatorPreOriginTime = ThisPreOriginTime;
                }
            }

            State.CombinedOscEffectGenerator = null;
            if ((Template.CombinedOscillatorEffects != null) && (GetEffectSpecListLength(Template.CombinedOscillatorEffects) > 0))
            {
                SynthErrorCodes Result = NewOscEffectGenerator(
                    Template.CombinedOscillatorEffects,
                    ref FrozenNote.Accents,
                    FrozenNote.HurryUpFactor,
                    FrozenNote.NominalFrequency,
                    FrozenNote.MultisampleFrequency,
                    out ThisPreOriginTime,
                    TrackInfo,
                    SynthParams,
                    out State.CombinedOscEffectGenerator);
                if (Result != SynthErrorCodes.eSynthDone)
                {
                    return(Result);
                }
                if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
                {
                    MaxOscillatorPreOriginTime = ThisPreOriginTime;
                }
            }
            /* else no combined oscillator effects, State.CombinedOscEffectGenerator is null */

            /* if this object ties to a note, then this is the note */
            /* to tie to.  this is used for finding existing oscillators */
            /* for tie continuations. */
            State.TieToNote = Note._Tie;

            /* portamento control parameters */
            State.PortamentoCounter = 0;
            State.CurrentFrequency  = FrozenNote.NominalFrequency;


            /* fix up pre-origin times */
            OscStateRec StateScan = State.OscillatorList;

            while (StateScan != null)
            {
                StateScan.StateReference.FixUpPreOrigin(
                    MaxOscillatorPreOriginTime);
                StateScan = StateScan.Next;
            }
            LFOGeneratorFixEnvelopeOrigins(
                State.PitchLFO,
                MaxOscillatorPreOriginTime);
            if (State.CombinedOscEffectGenerator != null)
            {
                FixUpOscEffectGeneratorPreOrigin(
                    State.CombinedOscEffectGenerator,
                    MaxOscillatorPreOriginTime);
            }

            /* various counters (in terms of envelope ticks) */
            if (State.TieToNote == null)
            {
                State.Release1Countdown = FrozenNote.ReleasePoint1 + MaxOscillatorPreOriginTime;
                State.Release2Countdown = FrozenNote.ReleasePoint2 + MaxOscillatorPreOriginTime;
                State.Release3Countdown = FrozenNote.ReleasePoint3 + MaxOscillatorPreOriginTime;
            }
            else
            {
                /* for ties, only honor releases from start */
                if (FrozenNote.Release1FromStart)
                {
                    State.Release1Countdown = FrozenNote.ReleasePoint1 + MaxOscillatorPreOriginTime;
                }
                else
                {
                    State.Release1Countdown = -1;
                }
                if (FrozenNote.Release2FromStart)
                {
                    State.Release2Countdown = FrozenNote.ReleasePoint2 + MaxOscillatorPreOriginTime;
                }
                else
                {
                    State.Release2Countdown = -1;
                }
                if (FrozenNote.Release3FromStart)
                {
                    State.Release3Countdown = FrozenNote.ReleasePoint3 + MaxOscillatorPreOriginTime;
                }
                else
                {
                    State.Release3Countdown = -1;
                }
            }
            State.PitchLFOStartCountdown = FrozenNote.PitchDisplacementStartPoint
                                           /*+ MaxOscillatorPreOriginTime*/;
            /* pre origin relationship must be preserved for */
            /* pitch LFO trigger */

            /* done */
            WhenToStartPlayingOut = StartPointAdjust - MaxOscillatorPreOriginTime;
            StateOut = State;
            return(SynthErrorCodes.eSynthDone);
        }
Example #25
0
            /* generate a sequence of samples (called for each envelope clock) */
            public SynthErrorCodes Generate(
                int nActualFrames,
                float[] workspace,
                int RawBufferLOffset,
                int RawBufferROffset,
                int PrivateWorkspaceLOffset,
                int PrivateWorkspaceROffset,
                SynthParamRec SynthParams)
            {
                FOFStateRec State = this;

                if (State.PreStartCountdown <= 0)
                {
                    if (State.OscEffectGenerator == null)
                    {
                        /* non-effects case */

                        /* generate waveform */
                        FOFGeneratorStereo(
                            State,
                            nActualFrames,
                            workspace,
                            RawBufferLOffset,
                            RawBufferROffset,
                            SynthParams);
                    }
                    else
                    {
                        /* effect postprocessing case */

                        /* initialize private storage */
                        FloatVectorZero(
                            workspace,
                            PrivateWorkspaceLOffset,
                            nActualFrames);
                        FloatVectorZero(
                            workspace,
                            PrivateWorkspaceROffset,
                            nActualFrames);

                        /* generate waveform */
                        FOFGeneratorStereo(
                            State,
                            nActualFrames,
                            workspace,
                            PrivateWorkspaceLOffset,
                            PrivateWorkspaceROffset,
                            SynthParams);

                        /* apply processor to it */
                        SynthErrorCodes error = ApplyOscEffectGenerator(
                            State.OscEffectGenerator,
                            workspace,
                            PrivateWorkspaceLOffset,
                            PrivateWorkspaceROffset,
                            nActualFrames,
                            SynthParams);
                        if (error != SynthErrorCodes.eSynthDone)
                        {
                            return(error);
                        }

                        /* copy out data */
                        FloatVectorAcc(
                            workspace,
                            PrivateWorkspaceLOffset,
                            workspace,
                            RawBufferLOffset,
                            nActualFrames);
                        FloatVectorAcc(
                            workspace,
                            PrivateWorkspaceROffset,
                            workspace,
                            RawBufferROffset,
                            nActualFrames);
                    }
                }

                return(SynthErrorCodes.eSynthDone);
            }
Example #26
0
        /* use the state of the object to generate a cycle of waveform. */
        public static SynthErrorCodes ApplyOscStateBank(
            OscStateBankRec State,
            float[] workspace,
            int nActualFrames,
            int OutputDataLOffset,
            int OutputDataROffset,
            int PrivateOscillatorWorkspaceLOffset,
            int PrivateOscillatorWorkspaceROffset,
            int PrivateCombinedOscillatorWorkspaceLOffset,
            int PrivateCombinedOscillatorWorkspaceROffset,
            SynthParamRec SynthParams)
        {
            OscStateRec OneStateScan;

            OneStateScan = State.OscillatorList;
            if (State.CombinedOscEffectGenerator != null)
            {
                /* resampling when you have combined oscillator effects */

                /* initialize combined workspace */
                FloatVectorZero(
                    workspace,
                    PrivateCombinedOscillatorWorkspaceLOffset,
                    nActualFrames);
                FloatVectorZero(
                    workspace,
                    PrivateCombinedOscillatorWorkspaceROffset,
                    nActualFrames);

                /* do oscillator processing */
                while (OneStateScan != null)
                {
                    OneStateScan.StateReference.Generate(
                        nActualFrames,
                        workspace,
                        PrivateCombinedOscillatorWorkspaceLOffset,
                        PrivateCombinedOscillatorWorkspaceROffset,
                        PrivateOscillatorWorkspaceLOffset,
                        PrivateOscillatorWorkspaceROffset,
                        SynthParams);
                    OneStateScan = OneStateScan.Next;
                }

                /* process combined effects */
                SynthErrorCodes error = ApplyOscEffectGenerator(
                    State.CombinedOscEffectGenerator,
                    workspace,
                    PrivateCombinedOscillatorWorkspaceLOffset,
                    PrivateCombinedOscillatorWorkspaceROffset,
                    nActualFrames,
                    SynthParams);
                if (error != SynthErrorCodes.eSynthDone)
                {
                    return(error);
                }

                /* accumulate combined oscillator buffer to output buffer */
                FloatVectorAcc(
                    workspace,
                    PrivateCombinedOscillatorWorkspaceLOffset,
                    workspace,
                    OutputDataLOffset,
                    nActualFrames);
                FloatVectorAcc(
                    workspace,
                    PrivateCombinedOscillatorWorkspaceROffset,
                    workspace,
                    OutputDataROffset,
                    nActualFrames);
            }
            else
            {
                /* resampling without combined oscillator effects */
                while (OneStateScan != null)
                {
                    OneStateScan.StateReference.Generate(
                        nActualFrames,
                        workspace,
                        OutputDataLOffset,
                        OutputDataROffset,
                        PrivateOscillatorWorkspaceLOffset,
                        PrivateOscillatorWorkspaceROffset,
                        SynthParams);
                    OneStateScan = OneStateScan.Next;
                }
            }

            return(SynthErrorCodes.eSynthDone);
        }