Exemple #1
0
 /* put source2 */
 public static void FMSynthMulAddStmtPutDataSource2(
     FMSynthStmtMulAddRec Spec,
     string DataSource2)
 {
     EnsureVariable(
         Spec.Owner,
         DataSource2,
         out Spec.Source2);
 }
Exemple #2
0
 /* put factor2 */
 public static void FMSynthMulAddStmtPutDataFactor2(
     FMSynthStmtMulAddRec Spec,
     string DataFactor2)
 {
     EnsureVariable(
         Spec.Owner,
         DataFactor2,
         out Spec.Factor2);
 }
Exemple #3
0
 /* put data target */
 public static void FMSynthMulAddStmtPutDataTarget(
     FMSynthStmtMulAddRec Spec,
     string DataTarget)
 {
     EnsureVariable(
         Spec.Owner,
         DataTarget,
         out Spec.Target);
 }
Exemple #4
0
        /* apply optimizations */
        public static void FMSynthOptimize(FMSynthSpecRec Spec)
        {
            /* reference disambiguation */

            /* there may be multiple non-overlapping lifetimes for the same variable.  if these */
            /* are not separated, then data rate of one lifetime will apply to all lifetimes, */
            /* resulting in suboptimal performance. */
            /* each update creates a new lifetime for the variable.  while there are more than */
            /* one update of a given variable, rename the 1st update and all references. */

            int cStmts = Spec.Stmts.Length;
            int cVars  = Spec.Variables.Length;

            for (int i = 4 /*zero and one are never written, and refs to left, right vars can't be split*/;
                 i < cVars /*note: vars we add here should never have multiple updates*/;
                 i++)
            {
                /* find first update */
                int iFirstUpdate = 0;
                while (iFirstUpdate < cStmts)
                {
                    if (Spec.Stmts[iFirstUpdate].Target == i)
                    {
                        break;
                    }
                    iFirstUpdate++;
                }
                if (iFirstUpdate == cStmts)
                {
                    /* no updates at all, so don't do anything */
                    continue;
                }

                /* find second update */
                int iSecondUpdate = (iFirstUpdate + 1) % cStmts;
                while (iSecondUpdate != iFirstUpdate)
                {
                    if (Spec.Stmts[iSecondUpdate].Target == i)
                    {
                        break;
                    }
                    iSecondUpdate = (iSecondUpdate + 1) % cStmts;
                }
                if (iSecondUpdate == iFirstUpdate)
                {
                    /* only one update, so don't do anything */
                    continue;
                }

                /* create new anonymous variable */
                int iNewVariable = Spec.Variables.Length;
                Array.Resize(ref Spec.Variables, Spec.Variables.Length + 1);

                /* walk stmt range and update all references */
                int j = iFirstUpdate;
                //goto StartFirstIteration; /* loop is inclusive on both ends */
                j--; // C# can't jump into middle of loop body - so counteract first increment of j
                do
                {
                    j = (j + 1) % cStmts;

StartFirstIteration:
                    FMSynthStmtRootRec Stmt = Spec.Stmts[j];

                    /* for first statement, only update the target */
                    if (j == iFirstUpdate)
                    {
#if DEBUG
                        if (Stmt.Target != i)
                        {
                            //  first update target is wrong
                            Debug.Assert(false);
                            throw new ArgumentException();
                        }
#endif
                        Stmt.Target = iNewVariable;

                        /* inflow vars to first stmt are outside of the lifetime, so */
                        /* they must not be updated */
                    }
                    /* otherwise, update the references */
                    else
                    {
#if DEBUG
                        if ((j != iSecondUpdate) && (Stmt.Target == i))
                        {
                            //  intervening update was missed
                            Debug.Assert(false);
                            throw new ArgumentException();
                        }
#endif
                        switch (Stmt.Type)
                        {
                        default:
                            Debug.Assert(false);
                            throw new ArgumentException();

                        case FMSynthStmtType.eFMSynthWave:
                            FMSynthStmtWaveRec WaveStmt = (FMSynthStmtWaveRec)Stmt;
                            if (WaveStmt.PhaseSource == i)
                            {
                                WaveStmt.PhaseSource = iNewVariable;
                            }
                            if (WaveStmt.PhaseGainSource == i)
                            {
                                WaveStmt.PhaseGainSource = iNewVariable;
                            }
                            break;

                        case FMSynthStmtType.eFMSynthMuladd:
                            FMSynthStmtMulAddRec MuladdStmt = (FMSynthStmtMulAddRec)Stmt;
                            if (MuladdStmt.Source == i)
                            {
                                MuladdStmt.Source = iNewVariable;
                            }
                            if (MuladdStmt.Source2 == i)
                            {
                                MuladdStmt.Source2 = iNewVariable;
                            }
                            if (MuladdStmt.Factor2 == i)
                            {
                                MuladdStmt.Factor2 = iNewVariable;
                            }
                            break;

                        case FMSynthStmtType.eFMSynthEnvelope:
                            /* no inputs */
                            break;
                        }
                    }
                } while (j != iSecondUpdate);
            }

            cVars = Spec.Variables.Length; /* reset cuz we added some vars */


            /* initialize states to unoptimized case */

            FMSynthOptRate[] rgStmtState = new FMSynthOptRate[cStmts];
            for (int i = 0; i < cStmts; i++)
            {
                Spec.Stmts[i].Optimize = true; /* start out assuming everything is control rate */
                rgStmtState[i]         = FMSynthOptRate.FMSYNTH_CONTROLRATE;
            }

            FMSynthOptRate[] rgVarState = new FMSynthOptRate[cVars];
            for (int i = 0; i < cVars; i += 1)
            {
                rgVarState[i] = FMSynthOptRate.FMSYNTH_CONTROLRATE;
            }
            rgVarState[FMSYNTH_LEFT]  = FMSynthOptRate.FMSYNTH_DATARATE;
            rgVarState[FMSYNTH_RIGHT] = FMSynthOptRate.FMSYNTH_DATARATE;


            /* convert control variables to data variables.  those left at the end are */
            /* really control variables. */
            /* rules for statement conversion: */
            /*  - wave is always a data statement */
            /*  - a statement with any data input variables is a data statement */
            /*  - a statement that updates any data variable is a data statement */
            /* rules for variable conversion: */
            /*  - any variable updated by a data statement is a data variable */
            /* note that flow wraps around: a read can occur before a write, which means it */
            /* reads the value written from the previous cycle.  in this case, the 3rd rule */
            /* for statements converts the updating statement into a data statement even if it */
            /* has no data rate dependencies.  In accordance, we treat variables as infinite */
            /* lifetime, so a state change in one place affects the variable everywhere. */
            /* one final rule: */
            /*  - if a control-rate update of a variable occurs after a data rate use of it, */
            /*    then there is a data-rate lifetime wraparound so the update must be data rate. */
            /*    that's because optimization isn't merely control vs. data rate, but also */
            /*    indicates whether the statement can be executed before any data rate statement. */
            bool SomethingChanged = true;
            while (SomethingChanged)
            {
                SomethingChanged = false;

                for (int i = 0; i < cStmts; i += 1)
                {
                    FMSynthStmtRootRec Stmt = Spec.Stmts[i];

                    /* apply statement and variable rules */
                    switch (Stmt.Type)
                    {
                    default:
                        Debug.Assert(false);
                        throw new ArgumentException();

                    case FMSynthStmtType.eFMSynthWave:
                        FMSynthStmtWaveRec WaveStmt = (FMSynthStmtWaveRec)Stmt;

                        /* waves are always data rate */
                        WaveStmt.Optimize = false;
                        SomethingChanged  = SomethingChanged ||
                                            (rgStmtState[i] != FMSynthOptRate.FMSYNTH_DATARATE);
                        rgStmtState[i] = FMSynthOptRate.FMSYNTH_DATARATE;

                        /* mark output variable as data rate */
                        SomethingChanged = SomethingChanged ||
                                           (rgVarState[WaveStmt.Target] != FMSynthOptRate.FMSYNTH_DATARATE);
                        rgVarState[WaveStmt.Target] = FMSynthOptRate.FMSYNTH_DATARATE;

                        /* don't bother checking inputs */

                        break;

                    case FMSynthStmtType.eFMSynthMuladd:
                        FMSynthStmtMulAddRec MuladdStmt = (FMSynthStmtMulAddRec)Stmt;

                        /* if updating a data var, or any input is a data, then stmt is a */
                        /* data and it's output var is */
                        if ((rgStmtState[i] == FMSynthOptRate.FMSYNTH_DATARATE) ||  /* stmt is already data rate */
                            (rgVarState[MuladdStmt.Target] == FMSynthOptRate.FMSYNTH_DATARATE) ||     /* output var is already data rate */
                            (rgVarState[MuladdStmt.Source] == FMSynthOptRate.FMSYNTH_DATARATE) ||     /* any input is data rate */
                            (rgVarState[MuladdStmt.Factor2] == FMSynthOptRate.FMSYNTH_DATARATE) ||     /* any input is data rate */
                            (rgVarState[MuladdStmt.Source2] == FMSynthOptRate.FMSYNTH_DATARATE))        /* any input is data rate */
                        {
                            /* update stmt */
                            MuladdStmt.Optimize = false;
                            SomethingChanged    = SomethingChanged ||
                                                  (rgStmtState[i] != FMSynthOptRate.FMSYNTH_DATARATE);
                            rgStmtState[i] = FMSynthOptRate.FMSYNTH_DATARATE;

                            /* update output var */
                            SomethingChanged = SomethingChanged ||
                                               (rgVarState[MuladdStmt.Target] != FMSynthOptRate.FMSYNTH_DATARATE);
                            rgVarState[MuladdStmt.Target] = FMSynthOptRate.FMSYNTH_DATARATE;
                        }

                        break;

                    case FMSynthStmtType.eFMSynthEnvelope:
                        FMSynthStmtEnvelopeRec EnvStmt = (FMSynthStmtEnvelopeRec)Stmt;

                        /* if updating a data var, then become data stmt (note, no inputs for this one) */
                        if (rgVarState[EnvStmt.Target] == FMSynthOptRate.FMSYNTH_DATARATE)
                        {
                            /* update stmt */
                            EnvStmt.Optimize = false;
                            SomethingChanged = SomethingChanged ||
                                               (rgStmtState[i] != FMSynthOptRate.FMSYNTH_DATARATE);
                            rgStmtState[i] = FMSynthOptRate.FMSYNTH_DATARATE;

                            /* update output var -- not strictly necessary due to if-stmt condition */
                            SomethingChanged = SomethingChanged ||
                                               (rgVarState[EnvStmt.Target] != FMSynthOptRate.FMSYNTH_DATARATE);
                            rgVarState[EnvStmt.Target] = FMSynthOptRate.FMSYNTH_DATARATE;
                        }

                        break;
                    }

                    /* apply wrap-around reordering rule */
                    /* this algorithm assumes all references have been disambiguated.  this */
                    /* is not true of 'left' and 'right', but anything using them will be */
                    /* at data rate already due to the above loop. */
                    if (rgVarState[Stmt.Target] == FMSynthOptRate.FMSYNTH_CONTROLRATE)
                    {
                        /* this is a control update, look for preceding uses (including in */
                        /* the inflow of this statement) */
                        for (int j = 0; j <= i; j++)
                        {
                            FMSynthStmtRootRec PrecStmt = Spec.Stmts[j];
#if DEBUG
                            if ((j < i) && (PrecStmt.Target == Stmt.Target))
                            {
                                // assignment disambiguation incomplete
                                Debug.Assert(false);
                                throw new ArgumentException();
                            }
#endif
                            switch (PrecStmt.Type)
                            {
                            default:
                                Debug.Assert(false);
                                throw new ArgumentException();

                            case FMSynthStmtType.eFMSynthWave:
                                FMSynthStmtWaveRec PrecWaveStmt = (FMSynthStmtWaveRec)PrecStmt;

                                if ((PrecWaveStmt.PhaseSource == Stmt.Target) ||
                                    (PrecWaveStmt.PhaseGainSource == Stmt.Target))
                                {
                                    if (rgStmtState[j] == FMSynthOptRate.FMSYNTH_DATARATE)
                                    {
                                        SomethingChanged = true;
                                        rgStmtState[i]   = FMSynthOptRate.FMSYNTH_DATARATE;
                                    }
                                }

                                break;

                            case FMSynthStmtType.eFMSynthMuladd:
                                FMSynthStmtMulAddRec PrecMuladdStmt = (FMSynthStmtMulAddRec)PrecStmt;

                                if ((PrecMuladdStmt.Source == Stmt.Target) ||
                                    (PrecMuladdStmt.Source2 == Stmt.Target) ||
                                    (PrecMuladdStmt.Factor2 == Stmt.Target))
                                {
                                    if (rgStmtState[j] == FMSynthOptRate.FMSYNTH_DATARATE)
                                    {
                                        SomethingChanged = true;
                                        rgStmtState[i]   = FMSynthOptRate.FMSYNTH_DATARATE;
                                    }
                                }

                                break;

                            case FMSynthStmtType.eFMSynthEnvelope:
                                /* no inputs */
                                break;
                            }
                        }
                    }
                }
            }
        }
Exemple #5
0
 /* change the addend */
 public static void FMSynthMulAddStmtPutAddend(
     FMSynthStmtMulAddRec Spec,
     double Addend)
 {
     Spec.Addend = Addend;
 }
Exemple #6
0
 /* get the addend */
 public static double FMSynthMulAddStmtGetAddend(FMSynthStmtMulAddRec Spec)
 {
     return(Spec.Addend);
 }
Exemple #7
0
 /* change the factor */
 public static void FMSynthMulAddStmtPutFactor(
     FMSynthStmtMulAddRec Spec,
     double Factor)
 {
     Spec.Factor = Factor;
 }
Exemple #8
0
 /* get the factor */
 public static double FMSynthMulAddStmtGetFactor(FMSynthStmtMulAddRec Spec)
 {
     return(Spec.Factor);
 }
Exemple #9
0
 /* get source2 */
 public static int FMSynthMulAddStmtGetDataSource2(FMSynthStmtMulAddRec Spec)
 {
     return(Spec.Source2);
 }
Exemple #10
0
 /* get factor2 */
 public static int FMSynthMulAddStmtGetDataFactor2(FMSynthStmtMulAddRec Spec)
 {
     return(Spec.Factor2);
 }
Exemple #11
0
 /* get data target */
 public static int FMSynthMulAddStmtGetDataTarget(FMSynthStmtMulAddRec Spec)
 {
     return(Spec.Target);
 }
Exemple #12
0
        /* accessors to add a statement */
        public static void FMSynthAddStatement(
            FMSynthSpecRec Spec,
            FMSynthStmtType Type)
        {
            FMSynthStmtRootRec Base;

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

            case FMSynthStmtType.eFMSynthWave:
                FMSynthStmtWaveRec WaveStmt = new FMSynthStmtWaveRec();
                Base = WaveStmt;

                WaveStmt.Type  = FMSynthStmtType.eFMSynthWave;
                WaveStmt.Owner = Spec;

                WaveStmt.FrequencyMultiplier = 1;
                WaveStmt.FrequencyAdder      = 0;
                WaveStmt.FrequencyDivisor    = 1;
                WaveStmt.Target          = -1;
                WaveStmt.PhaseSource     = FMSYNTH_ZERO;
                WaveStmt.PhaseGainSource = FMSYNTH_ONE;
                WaveStmt.SampleSelector  = NewSampleSelectorList(0);
                WaveStmt.IndexEnvelope   = NewEnvelope();
                WaveStmt.IndexLFOList    = NewLFOListSpecifier();

                break;

            case FMSynthStmtType.eFMSynthMuladd:
                FMSynthStmtMulAddRec MuladdStmt = new FMSynthStmtMulAddRec();
                Base = MuladdStmt;

                MuladdStmt.Type  = FMSynthStmtType.eFMSynthMuladd;
                MuladdStmt.Owner = Spec;

                MuladdStmt.Source  = FMSYNTH_ZERO;
                MuladdStmt.Source2 = FMSYNTH_ZERO;
                MuladdStmt.Target  = -1;
                MuladdStmt.Factor  = 1;
                MuladdStmt.Addend  = 0;
                MuladdStmt.Factor2 = FMSYNTH_ONE;

                break;

            case FMSynthStmtType.eFMSynthEnvelope:
                FMSynthStmtEnvelopeRec EnvStmt = new FMSynthStmtEnvelopeRec();
                Base = EnvStmt;

                EnvStmt.Type  = FMSynthStmtType.eFMSynthEnvelope;
                EnvStmt.Owner = Spec;

                EnvStmt.Target   = -1;
                EnvStmt.Envelope = NewEnvelope();
                EnvStmt.LFOList  = NewLFOListSpecifier();

                break;
            }

            Array.Resize(ref Spec.Stmts, Spec.Stmts.Length + 1);
            Spec.Stmts[Spec.Stmts.Length - 1] = Base;
        }