Пример #1
0
 public Recording(FPCM buffer, int offset)
 {
     this.buffer      = buffer;
     this.cachedStart = offset;
     this.length      = this.buffer.buffer.Length;
     this.cachedEnd   = offset + this.length;
 }
Пример #2
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBufSz, FPCMFactoryGenLimit pcmFactory)
            {
                FPCM fa = pcmFactory.GetZeroedFPCM(start, size);

                float [] a = fa.buffer;

                fixed(float *pa = a)
                {
                    this.input.Accumulate(pa, start, size, prefBufSz, pcmFactory);

                    for (int i = start; i < start + size; ++i)
                    {
                        float s = pa[i];
                        if (s == 0.0)
                        {
                            data[i] = 0.0f;
                        }
                        else if (s > 0.0)
                        {
                            data[i] = 1.0f;
                        }
                        else
                        {
                            data[i] = 0.0f;
                        }
                    }
                }
            }
Пример #3
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBuffSz, FPCMFactoryGenLimit pcmFactory)
            {
                if (this.batch.Length == 0)
                {
                    return;
                }

                float inv = 1.0f / this.batch.Length;

                FPCM fpcm = null;

                foreach (GenBase gb in this.batch)
                {
                    if (fpcm == null)
                    {
                        fpcm = pcmFactory.GetZeroedFPCM(start, size);
                    }
                    else
                    {
                        fpcm.Zero(start, size);
                    }

                    float [] rf = fpcm.buffer;

                    fixed(float *prf = rf)
                    {
                        gb.Accumulate(prf, start, size, prefBuffSz, pcmFactory);

                        for (int i = start; i < start + size; ++i)
                        {
                            data[i] += prf[i] * inv;
                        }
                    }
                }
            }
Пример #4
0
            public FPCM GetFPCM(int samples)
            {
                if (samples < 1)
                {
                    return(null);
                }

                List <FPCM> lst;

                if (this.entries.TryGetValue(samples, out lst) == false)
                {
                    FPCM newRet = new FPCM(this, new float[samples]);
                    return(newRet);
                }

                int  lastIdx = lst.Count - 1;
                FPCM ret     = lst[lastIdx];

                lst.RemoveAt(lastIdx);

                if (lst.Count == 0)
                {
                    this.entries.Remove(samples);
                }

                return(ret);
            }
Пример #5
0
            FPCM IFPCMFactory.GetZeroedGlobalFPCM(int samples, int start, int size)
            {
                FPCM fpcm = this.GetFPCM(samples);

                fpcm.Zero(start, size);
                return(fpcm);
            }
Пример #6
0
 public BufferedFPCM(FPCM fpcm, int offset)
 {
     this.buffer    = fpcm;
     this.offset    = offset;
     this.cachedLen = fpcm.buffer.Length;
     this.cachedEnd = offset + this.cachedLen;
     this.readLeft  = this.cachedLen;
 }
Пример #7
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBuffSz, FPCMFactoryGenLimit pcmFactory)
            {
                if (this.passed == true)
                {
                    this.gen.Accumulate(data, start, size, prefBuffSz, pcmFactory);
                    return;
                }

                if (this.offset > 0)
                {
                    int burn = Min(size, this.offset);
                    start       += burn;
                    size        -= burn;
                    this.offset -= burn;

                    if (size <= 0)
                    {
                        return;
                    }
                }

                FPCM fa = pcmFactory.GetZeroedFPCM(start, size);

                float [] a = fa.buffer;

                fixed(float *pa = a)
                {
                    this.gen.Accumulate(pa, start, size, prefBuffSz, pcmFactory);

                    float at     = this.itAttack;
                    float tot    = (float)this.totalAttackSamples;
                    int   sampCt = Min(size, totalAttackSamples - itAttack);

                    for (int i = start; i < start + sampCt; ++i)
                    {
                        float v = at / tot;
                        at += 1.0f;

                        data[i] = pa[i] * v;
                    }

                    start         += sampCt;
                    size          -= sampCt;
                    this.itAttack += sampCt;

                    if (this.itAttack >= this.totalAttackSamples)
                    {
                        this.passed = true;
                    }

                    for (int i = start; i < start + size; ++i)
                    {
                        data[i] = pa[i];
                    }
                }
            }
Пример #8
0
            FPCM IFPCMFactory.GetGlobalFPCM(int samples, bool zero)
            {
                FPCM fpcm = this.GetFPCM(samples);

                if (zero == true)
                {
                    fpcm.Zero();
                }

                return(fpcm);
            }
Пример #9
0
            FPCM IFPCMFactory.GetFPCM(int samples, bool zero)
            {
                FPCM ret = this.parent.GetFPCM(samples, zero);

                if (ret == null)
                {
                    return(null);
                }

                this.allocated.Add(ret);
                return(ret);
            }
Пример #10
0
            FPCM IFPCMFactory.GetZeroedFPCM(int samples, int start, int size)
            {
                FPCM ret = this.parent.GetZeroedFPCM(samples, start, size);

                if (ret == null)
                {
                    return(null);
                }

                this.allocated.Add(ret);
                return(ret);
            }
Пример #11
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBuffSz, FPCMFactoryGenLimit pcmFactory)
            {
                FPCM fa = pcmFactory.GetZeroedFPCM(start, size);

                float [] a = fa.buffer;

                fixed(float *pa = a)
                {
                    this.input.Accumulate(pa, start, size, prefBuffSz, pcmFactory);

                    for (int i = start; i < start + size; ++i)
                    {
                        data[i] = ((float)(int)(pa[i] * factor)) * invFactor;
                    }
                }
            }
Пример #12
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBuffSz, FPCMFactoryGenLimit pcmFactory)
            {
                while (size > 0)
                {
                    if (this.playing == true)
                    {
                        int burn = Min(size, this.samplesLeft);

                        this.input.Accumulate(data, start, size, prefBuffSz, pcmFactory);

                        this.samplesLeft -= burn;
                        size             -= burn;
                        start            += burn;

                        if (this.samplesLeft == 0)
                        {
                            this.playing     = false;
                            this.samplesLeft = this.holdSamples;
                        }
                    }
                    else
                    {
                        int burn = Min(size, this.samplesLeft);

                        // A true burn, pulling the samples just to do absolutely nothing
                        // with them, but we need to get time to pass for the rest of the hierarchy.
                        FPCM    fa = pcmFactory.GetZeroedFPCM(start, size);
                        float[] a  = fa.buffer;

                        fixed(float *pa = a)
                        {
                            this.input.Accumulate(pa, start, size, prefBuffSz, pcmFactory);
                        }

                        this.samplesLeft -= burn;
                        size             -= burn;
                        start            += burn;

                        if (this.samplesLeft == 0)
                        {
                            this.playing     = true;
                            this.samplesLeft = this.playSamples;
                        }
                    }
                }
            }
Пример #13
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBuffSz, FPCMFactoryGenLimit pcmFactory)
            {
                if (this.active == false)
                {
                    // If not ready, just relay as if we weren't here
                    this.input.Accumulate(data, start, size, prefBuffSz, pcmFactory);
                    return;
                }

                // if we've passed the end of release, we're still going to add silent
                // data for a while and record for how long we've been doing that.
                //
                // See this.Finished() for more information.
                if (this.curLen <= 0)
                {
                    this.curLen -= size;
                    return;
                }

                FPCM fa = pcmFactory.GetZeroedFPCM(start, size);

                float[] a = fa.buffer;

                fixed(float *pa = a)
                {
                    this.input.Accumulate(pa, start, size, prefBuffSz, pcmFactory);

                    float c  = this.curLen;
                    int   sz = Mathf.Min(this.curLen, size);

                    this.curLen -= sz;

                    float fmax = (float)this.maxLen;

                    for (int i = start; i < start + sz; ++i)
                    {
                        c -= 1.0f;
                        float lam = c / fmax;
                        lam     = lam * lam;
                        data[i] = lam * pa[i];
                    }
                }
            }
Пример #14
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBuffSz, FPCMFactoryGenLimit pcmFactory)
            {
                FPCM fa = pcmFactory.GetZeroedFPCM(start, size);
                FPCM fb = pcmFactory.GetZeroedFPCM(start, size);

                float [] a = fa.buffer;
                float [] b = fb.buffer;

                fixed(float *pa = a, pb = b)
                {
                    this.gma.Accumulate(pa, start, size, prefBuffSz, pcmFactory);
                    this.gmb.Accumulate(pb, start, size, prefBuffSz, pcmFactory);

                    for (int i = start; i < start + size; ++i)
                    {
                        data[i] = pa[i] + pb[i];
                    }
                }
            }
Пример #15
0
            /// <summary>
            /// Add an FPCM back into the pool
            /// </summary>
            /// <param name="fpcm">The FPCM to add back.</param>
            /// <returns>If true, the FPCM was successfully added.</returns>
            public bool ReturnFPCM(FPCM fpcm)
            {
                if (fpcm.buffer == null || fpcm.buffer.Length == 0)
                {
                    return(false);
                }

                int samples = fpcm.buffer.Length;

                List <FPCM> lst;

                if (this.entries.TryGetValue(samples, out lst) == false)
                {
                    lst = new List <FPCM>();
                    this.entries.Add(samples, lst);
                }

                lst.Add(fpcm);
                return(true);
            }
Пример #16
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBufSz, FPCMFactoryGenLimit pcmFactory)
            {
                // Early release
                if (this.released == true)
                {
                    if (this.releaseLeft > 0)
                    {
                        FPCM    fpcmRl = pcmFactory.GetZeroedFPCM(start, size);
                        float[] fprl   = fpcmRl.buffer;

                        int sampsCt = Mathf.Min(this.releaseLeft, size);

                        // We could probably optimize this by only calling AccumulateImpl_NonReleasePart()
                        // when we're not in sustain yet.
                        fixed(float *pfprl = fprl)
                        {
                            this.AccumulateImpl_NonReleasePart(pfprl, start, size, prefBufSz, pcmFactory);

                            float total = this.releaseTotal;
                            float left  = this.releaseLeft;

                            for (int ei = start; ei < start + sampsCt; ++ei)
                            {
                                data[ei] = pfprl[ei] * (left / total);
                                left    -= 1.0f;
                            }
                        }

                        this.releaseLeft -= sampsCt;
                        return;
                    }
                    else if (this.saftey > 0)
                    {
                        this.saftey -= size;
                    }
                }
                else
                {
                    this.AccumulateImpl_NonReleasePart(data, start, size, prefBufSz, pcmFactory);
                }
            }
Пример #17
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBuffSz, FPCMFactoryGenLimit pcmFactory)
            {
                FPCM fa = pcmFactory.GetZeroedFPCM(start, size);

                float[] a = fa.buffer;

                fixed(float *pa = a)
                {
                    this.input.Accumulate(pa, start, size, prefBuffSz, pcmFactory);

                    for (int i = start; i < start + size; ++i)
                    {
                        this.valAccum += this.integrateFactor * pa[i];
                        this.wtAccum  += this.integrateFactor;

                        data[i] += this.valAccum / this.wtAccum;

                        this.wtAccum  *= this.decayFactor;
                        this.valAccum *= this.decayFactor;
                    }
                }
            }
Пример #18
0
            unsafe public void AccumulateImpl_NonReleasePart(float *data, int start, int size, int prefBufSz, FPCMFactoryGenLimit pcmFactory)
            {
                FPCM fpcm = pcmFactory.GetZeroedFPCM(start, size);

                float[] fp = fpcm.buffer;

                fixed(float *pfp = fp)
                {
                    this.input.Accumulate(pfp, start, size, prefBufSz, pcmFactory);


                    if (this.offset > 0)
                    {
                        int ofrm = Mathf.Min(this.offset, size);
                        this.offset -= ofrm;
                        start       += ofrm;
                        size        -= ofrm;

                        if (size <= 0)
                        {
                            return;
                        }
                    }

                    // ATTACK
                    if (this.attackIt < this.attackTotal)
                    {
                        int   atrm    = Mathf.Min(this.attackTotal - this.attackIt, size);
                        int   end     = start + atrm;
                        float totalAt = this.attackTotal;
                        float at      = this.attackIt;
                        for (int i = start; i < end; ++i)
                        {
                            data[i] = pfp[i] * (at / totalAt);
                            at     += 1.0f;
                        }

                        this.attackIt += atrm;

                        size  -= atrm;
                        start += atrm;
                        if (size <= 0)
                        {
                            return;
                        }
                    }

                    // DECAY
                    if (this.decayLeft > 0)
                    {
                        int   dcrm    = Mathf.Min(this.decayLeft, size);
                        int   dcend   = start + dcrm;
                        float totalDc = this.decayTotal;
                        float cd      = this.decayLeft;
                        float susDiff = 1.0f - this.sustain;
                        for (int i = start; i < dcend; ++i)
                        {
                            data[i] = pfp[i] * (this.sustain + (cd / totalDc) * susDiff);
                            cd     -= 1.0f;
                        }

                        this.decayLeft -= dcrm;

                        size  -= dcrm;
                        start += dcrm;
                        if (size <= 0)
                        {
                            return;
                        }
                    }

                    // If we're still here, all that's left is sustain
                    for (int i = start; i < start + size; ++i)
                    {
                        data[i] = pfp[i] * this.sustain;
                    }
                }
            }
Пример #19
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBuffSz, FPCMFactoryGenLimit pcmFactory)
            {
                if (this.offset > 0)
                {
                    int of = Min(this.offset, size);
                    if (this.passOffset == OffsetPass.Silent)
                    {
                        // If silent, we still need to let time pass for it, so
                        // we need to burn it.
                        FPCM     fpcm = pcmFactory.GetZeroedFPCM(start, size);
                        float [] a    = fpcm.buffer;

                        fixed(float *pa = a)
                        {
                            this.input.Accumulate(pa, start, of, prefBuffSz, pcmFactory);
                        }
                    }
                    else if (this.passOffset == OffsetPass.Pass)
                    {
                        this.input.Accumulate(data, start, of, prefBuffSz, pcmFactory);
                    }
                    else if (this.passOffset == OffsetPass.Hold)
                    {
                    }   // Do nothing

                    this.offset -= of;
                    start       += of;
                    size        -= of;

                    if (size == 0)
                    {
                        return;
                    }
                }

                if (this.recordingIt < this.rfs.Length)
                {
                    int recAmt = Min(size, this.rfs.Length - this.recordingIt);

                    FPCM     fpcm = pcmFactory.GetZeroedFPCM(0, size);
                    float [] lbuf = fpcm.buffer;

                    fixed(float *plbuf = lbuf)
                    {
                        this.input.Accumulate(plbuf, 0, recAmt, prefBuffSz, pcmFactory);

                        for (int i = 0; i < recAmt; ++i)
                        {
                            data[start + i]      = plbuf[i];
                            rfs[recordingIt + i] = plbuf[i];
                        }
                    }

                    this.recordingIt += recAmt;
                    start            += recAmt;
                    size             -= recAmt;

                    if (this.recordingIt == this.rfs.Length)
                    {
                        // If the buffer size is tiny, we're going to duplicate it to a sane amount
                        // so we don't have many tiny cycles when it comes to replaying it.
                        if (this.rfs.Length < prefBuffSz)
                        {
                            int repCt = this.rfs.Length / prefBuffSz;
                            if (repCt > 1)
                            {
                                float [] rfOld = this.rfs;
                                int      oldSz = this.rfs.Length;

                                // Repeat the buffer
                                this.rfs = new float[oldSz * repCt];
                                for (int i = 1; i < repCt; ++i)
                                {
                                    int baseIdx = i * oldSz;
                                    for (int j = 0; j < oldSz; ++j)
                                    {
                                        this.rfs[baseIdx + j] = rfOld[j];
                                    }
                                }
                            }
                        }
                    }
                }

                while (size > 0)
                {
                    this.playbackIt %= this.rfs.Length;

                    int sameCt = Min(this.rfs.Length - this.playbackIt, size);

                    for (int i = 0; i < sameCt; ++i)
                    {
                        data[start + i] = rfs[this.playbackIt + i];
                    }

                    this.playbackIt += sameCt;
                    start           += sameCt;
                    size            -= sameCt;
                }
            }
Пример #20
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBuffSz, FPCMFactoryGenLimit pcmFactory)
            {
                if (this.durationSamples <= 0)
                {
                    if (this.sustain == 0.0f)
                    {
                        // If duration is over and we don't have sustain, early exit. We account
                        // for what we would have written as a timer for Finished() do it doesn't
                        // exit too early.
                        this.durationSamples -= size;
                    }
                    else
                    {
                        // If duration is over, we're in sustain
                        FPCM    fsus = pcmFactory.GetZeroedFPCM(start, size);
                        float[] sus  = fsus.buffer;

                        fixed(float *psus = sus)
                        {
                            this.gen.Accumulate(psus, start, size, prefBuffSz, pcmFactory);
                            for (int i = start; i < start + size; ++i)
                            {
                                data[i] = psus[i] * this.sustain;
                            }
                        }
                    }
                    return;
                }

                // Are we at a time before the decay is activated?
                // If it's going to be that way for the entire decay, just
                // relay it.
                if (this.offsetSamples > size)
                {
                    this.offsetSamples -= size;
                    this.gen.Accumulate(data, start, size, prefBuffSz, pcmFactory);
                    return;
                }

                FPCM fa = pcmFactory.GetZeroedFPCM(start, size);

                float[] a = fa.buffer;

                fixed(float *pa = a)
                {
                    this.gen.Accumulate(pa, start, size, prefBuffSz, pcmFactory);

                    // Are we at a time before the decay is activated, but
                    // will need to start the decay before we exit?
                    if (this.offsetSamples > 0)
                    {
                        int endOS = start + this.offsetSamples;
                        for (int i = start; i < start + endOS; ++i)
                        {
                            data[i] = pa[i];
                        }

                        size  -= this.offsetSamples;
                        start += this.offsetSamples;
                        this.offsetSamples = 0;
                    }

                    // The decay. We have two versions, because if the sustain ramps to zero, we can
                    // avoid some lerp math.
                    float total    = totalDurationSamples;
                    int   decSamps = Mathf.Min(size, this.durationSamples);
                    int   end      = start + decSamps;

                    if (this.sustain == 0.0f)
                    {
                        float durs = (float)this.durationSamples;
                        for (int i = start; i < end; ++i)
                        {
                            float lam = durs / total;
                            data[i] = pa[i] * lam;
                            durs   -= 1.0f;
                        }
                        durationSamples -= decSamps;
                    }
                    else
                    {
                        float durs = (float)this.durationSamples;
                        for (int i = start; i < end; ++i)
                        {
                            float lam = sustain + durs / total * this.invSustain;
                            data[i] += pa[i] * lam;
                            durs    -= 1.0f;
                        }
                        start += decSamps;
                        size  -= decSamps;
                        this.durationSamples -= decSamps;

                        // If we finish the ramp in the middle, we need to fill the rest with sustain
                        for (int i = start; i < start + size; ++i)
                        {
                            data[i] = pa[i] * this.sustain;
                        }
                    }
                }
            }
Пример #21
0
            unsafe public override void AccumulateImpl(float *data, int start, int size, int prefBufSz, FPCMFactoryGenLimit pcmFactory)
            {
                //  BYPASS IF NO POINT NOT TO
                ////////////////////////////////////////////////////////////////////////////////
                if (this.voices <= 1)
                {
                    // This will probably rarely ever happen because it defeats the purpose of using
                    // this node, but I'll take the optimization where I can get it.
                    this.input.Accumulate(data, start, size, prefBufSz, pcmFactory);
                    return;
                }

                //  READ IN NEW INFORMATION BY APPENDING BUFFERS
                ////////////////////////////////////////////////////////////////////////////////
                int readAmt = size;

                while (readAmt > 0)
                {
                    if (buffers.Count == 0)
                    {
                        FPCM         firstEntry = pcmFactory.GetZeroedGlobalFPCM(0, prefBufSz);
                        BufferedFPCM bfpmFirst  = new BufferedFPCM(firstEntry, this.nextOffset);
                        this.nextOffset += firstEntry.buffer.Length;

                        this.buffers.Add(bfpmFirst);
                    }

                    int          lastIdx = this.buffers.Count - 1;
                    BufferedFPCM last    = this.buffers[lastIdx];

                    int readBufAmt = Min(readAmt, last.readLeft);
                    if (readBufAmt != 0)
                    {
                        int readHead = last.cachedLen - last.readLeft;
                        // Read the new stuff requested
                        float [] wbuf = last.buffer.buffer;
                        fixed(float *pwbuf = wbuf)
                        {
                            this.input.Accumulate(
                                &pwbuf[readHead],
                                0,
                                readBufAmt,
                                prefBufSz,
                                pcmFactory);
                        }

                        // Update and save it back
                        last.readLeft        -= readBufAmt;
                        this.buffers[lastIdx] = last;
                        readAmt -= readBufAmt;
                    }

                    if (readAmt <= 0)
                    {
                        break;
                    }

                    // If it's not enough, create another buffer and continue. We
                    // only create it here, because it will be filled the next
                    // round-about in this loop.
                    //
                    // Exact same as above.
                    FPCM         newEntry = pcmFactory.GetZeroedGlobalFPCM(0, prefBufSz);
                    BufferedFPCM bfpm     = new BufferedFPCM(newEntry, this.nextOffset);
                    this.nextOffset += newEntry.buffer.Length;
                    this.buffers.Add(bfpm);
                }

                //  WRITE INTO OUTPUT BUFFER
                ////////////////////////////////////////////////////////////////////////////////

                int lowestIndexVal = int.MaxValue;

                for (int buffIt = 0; buffIt < this.rbuffRef.Length; ++buffIt)
                {
                    int bsize  = size;
                    int bstart = start;

                    BufferRef br = this.rbuffRef[buffIt];

                    while (bsize > 0)
                    {
                        if (br.totalOffset < 0)
                        {
                            int toSkip = Min(-br.totalOffset, bsize);
                            bsize          -= toSkip;
                            bstart         += toSkip;
                            br.totalOffset += toSkip;

                            if (bsize <= 0)
                            {
                                break;
                            }
                        }

                        int          endOffset = br.totalOffset + bsize;
                        BufferedFPCM buffer    = this.buffers[br.idx];
                        float []     a         = buffer.buffer.buffer; // Hmm, tic tac toe
                        int          endBuffer = buffer.cachedEnd;
                        // Either going to read to the end of the buffer, or the
                        // end of the requested stream read, whichever comes first
                        int canReadLeft = Min(endOffset, endBuffer) - br.totalOffset;

                        int startingOffset = br.totalOffset - buffer.offset;
                        for (int i = 0; i < canReadLeft; ++i)
                        {
                            data[bstart + i] += br.atten * a[startingOffset + i];
                        }

                        bstart         += canReadLeft;
                        bsize          -= canReadLeft;
                        br.totalOffset += canReadLeft;

                        // If there's still more to read, that needs to be done
                        // through the next buffer.
                        if (bsize > 0)
                        {
                            ++br.idx;
                        }
                    }

                    lowestIndexVal        = Min(lowestIndexVal, br.idx);
                    this.rbuffRef[buffIt] = br;
                }
                // MAINTENENCE, GET RID OF OLD GRODY STUFF
                ////////////////////////////////////////////////////////////////////////////////
                if (lowestIndexVal != 0)
                {
                    for (int i = 0; i < lowestIndexVal; ++i)
                    {
                        this.buffers[i].buffer.Release();
                    }

                    this.buffers.RemoveRange(0, lowestIndexVal);

                    for (int i = 0; i < this.rbuffRef.Length; ++i)
                    {
                        this.rbuffRef[i].idx -= lowestIndexVal;
                    }
                }
            }