Пример #1
0
            /* wave resampler helper */
            private static void FOFGeneratorStereo(
                FOFStateRec State,
                int nActualFrames,
                float[] workspace,
                int lOffset,
                int rOffset,
                SynthParamRec SynthParams)
            {
                /* see if we shouldn't be here */
                if (!State.WaveTableWasDefined)
                {
                    return;
                }

                /* do some setup */
                bool EnvelopeFinished        = IsEnvelopeAtEnd(State.WaveTableLoudnessEnvelope);
                int  LocalSamplePositionMask = State.FramesPerTable - 1;

                /* iterate over samples */
                for (int Scan = 0; Scan < nActualFrames; Scan++)
                {
                    /* check for launching */
                    GrainLaunchCheck(
                        State,
                        EnvelopeFinished,
                        SynthParams);

                    /* prepare point */
                    float CurrentLeft  = workspace[Scan + lOffset];
                    float CurrentRight = workspace[Scan + rOffset];

                    /* generate sounds for all registered grains */
                    FOFGrainRec GrainScan = State.ActiveGrainList;
                    FOFGrainRec GrainLag  = null;
                    while (GrainScan != null)
                    {
                        /* wave generation */

                        float RightWeight    = GrainScan.FOFSamplePosition.FracF;
                        int   ArraySubscript = GrainScan.FOFSamplePosition.Int & LocalSamplePositionMask;

                        /* L+F(R-L) */
                        float Left0Value    = GrainScan.WaveData0[ArraySubscript];
                        float Right0Value   = GrainScan.WaveData0[ArraySubscript + 1];
                        float CombinedValue = Left0Value + (RightWeight * (Right0Value - Left0Value));

                        if ((GrainScan.WaveData1 != null) && State.Template.EnableCrossWaveTableInterpolation)
                        {
                            /* L+F(R-L) -- applied twice */
                            float Left1Value  = GrainScan.WaveData1[ArraySubscript];
                            float Right1Value = GrainScan.WaveData1[ArraySubscript + 1];
                            float Wave0Temp   = CombinedValue;
                            CombinedValue = Wave0Temp + (GrainScan.Wave1Weight * (Left1Value
                                                                                  + (RightWeight * (Right1Value - Left1Value)) - Wave0Temp));
                        }
                        /* else index == 1, so no right hand wave to use */

                        CurrentLeft  += GrainScan.LeftLoudness * CombinedValue;
                        CurrentRight += GrainScan.RightLoudness * CombinedValue;


                        /* increment phase */

                        bool Advance = true;
                        GrainScan.FOFSamplePosition += GrainScan.FOFSamplePositionDifferential;
                        if (GrainScan.FOFSamplePosition.Int >= State.FramesPerTable)
                        {
                            GrainScan.FOFSamplePosition.MaskInt64HighHalf(LocalSamplePositionMask);
                            if (State.Template.FOFExpansion == OscFOFExpandType.eOscFOFSilenceFill)
                            {
                                /* silence fill. */
                                /* for silence fill, we now terminate this oscillator. */
                                Advance = false;
                                FOFGrainRec Temp = GrainScan;
                                GrainScan = GrainScan.Next;
                                if (GrainLag != null)
                                {
                                    GrainLag.Next = GrainScan;
                                }
                                else
                                {
                                    State.ActiveGrainList = GrainScan;
                                }
                                Free(ref SynthParams.freelists.FOFGrainRecFreeList, ref Temp);
                            }
                            else
                            {
                                /* loop around. */
                                /* we only terminate the oscillator if it's not the first */
                                /* one, otherwise we allow it to restart */
                                if (GrainLag != null)
                                {
                                    /* not the first one */
                                    Advance = false;
                                    FOFGrainRec Temp = GrainScan;
                                    GrainScan     = GrainScan.Next;
                                    GrainLag.Next = GrainScan;
                                    Free(ref SynthParams.freelists.FOFGrainRecFreeList, ref Temp);
                                }
                            }
                        }

                        if (Advance)
                        {
                            GrainLag  = GrainScan;
                            GrainScan = GrainScan.Next;
                        }
                    }

                    /* send value back */
                    workspace[Scan + lOffset] = CurrentLeft;
                    workspace[Scan + rOffset] = CurrentRight;
                }
            }
Пример #2
0
            /* fof pitch start pulse: */
            /* |              |              |              |              |              |    */
            /* 0.0 1.1 2.1 3.2 0.3 1.4 2.4 3.5 0.6 1.6 2.7 3.7 0.8 1.9 2.9 0.0 1.1 2.1 3.2 0.3 */
            /* sampling period pulse: */
            /* *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   */
            /* no interpolation of grains: */
            /* 0   1   2       0   1   2       0   1   2       0   1   2   0   1   2       0   */
            /* with interpolation of grains: */
            /* 0.0 1.0 2.0     0.3 1.3 2.3     0.5 1.5 2.5     0.7 1.7 2.7 0.0 1.0 2.0     0.3 */
            /* pitch start pulse and grain sampling pulse have same units to allow */
            /* start pulse fraction to be used for initial grain fraction. */

            /* check to see if we should launch a new grain */
            private static void GrainLaunchCheck(
                FOFStateRec State,
                bool EnvelopeFinished,
                SynthParamRec SynthParams)
            {
                /* first, handle grain launching.  do this by adding the pitch differential */
                /* to the accumulator and checking for overflow. */
                State.WaveTableSamplePosition += State.WaveTableSamplePositionDifferential;

                /* if this overflows, then truncate it and launch a new grain */
                if (State.WaveTableSamplePosition.Int >= State.FramesPerTable)
                {
                    /* time to launch a new grain */

                    /* truncate grain pitch index to keep wave table index inside */
                    State.WaveTableSamplePosition.MaskInt64HighHalf(State.FramesPerTable - 1);

                    /* check for discard mode */
                    if (State.Template.FOFCompression == OscFOFCompressType.eOscFOFDiscard)
                    {
                        /* if we are in discard mode, then dump any active grains */
                        FOFGrainRec Scan = State.ActiveGrainList;
                        while (Scan != null)
                        {
                            FOFGrainRec one = Scan;
                            Scan = Scan.Next;
                            Free(ref SynthParams.freelists.FOFGrainRecFreeList, ref one);
                        }
                        State.ActiveGrainList = null;
                    }

                    /* creating new grain, but only if the envelope generator hasn't terminated */
                    if (!EnvelopeFinished)
                    {
                        /* initialize grain differential to the sampling rate */
                        /* note that grain differential is independent of the */
                        /* number of frames in the table. */
                        Fixed64 FOFSamplePositionDifferential = new Fixed64(
                            State.FOFSamplingRateContour * State.Template.FOFSamplingRate
                            / SynthParams.dSamplingRate);

                        // create new grain, but only if differential isn't really close to zero
                        if (!((FOFSamplePositionDifferential.FracI < 0x00010000) &&
                              (FOFSamplePositionDifferential.Int == 0)))
                        {
                            FOFGrainRec NewGrain = New(ref SynthParams.freelists.FOFGrainRecFreeList);

                            // must initialize all fields: NewGrain

                            /* set up grain's phase index */
                            NewGrain.FOFSamplePosition = State.WaveTableSamplePosition;

                            /* set up wave data pointers using current wave table index */
#if DEBUG
                            if ((State.WaveTableIndex < 0) || (State.WaveTableIndex > State.NumberOfTablesMinus1))
                            {
                                // table index out of range
                                Debug.Assert(false);
                                throw new InvalidOperationException();
                            }
#endif
                            NewGrain.WaveData0   = State.WaveTableMatrix[(int)(State.WaveTableIndex)];
                            NewGrain.WaveData1   = null;
                            NewGrain.Wave1Weight = 0;
                            if ((int)(State.WaveTableIndex) < State.NumberOfTablesMinus1)
                            {
                                NewGrain.WaveData1   = State.WaveTableMatrix[(int)(State.WaveTableIndex) + 1];
                                NewGrain.Wave1Weight = (float)(State.WaveTableIndex - (int)(State.WaveTableIndex));
                            }

                            /* set up amplitudes */
                            NewGrain.LeftLoudness  = State.LeftLoudness;
                            NewGrain.RightLoudness = State.RightLoudness;

                            NewGrain.FOFSamplePositionDifferential = FOFSamplePositionDifferential;

                            NewGrain.Next = null;

                            /* inserted at front of list (important later) */
                            NewGrain.Next         = State.ActiveGrainList;
                            State.ActiveGrainList = NewGrain;
                        }
                    }
                }
            }