예제 #1
0
            /* band-limited upsampling for integer multiples of base sampling rate */
            public static float[] RateConvert(
                float[] data,
                int length,
                int factor)
            {
#if DEBUG
                if (factor < 2)
                {
                    Debug.Assert(false);
                    throw new ArgumentException();
                }
#endif

                int count = 1;
                int newLength;
                while ((newLength = (1 << count)) < length * factor + 1 /*one extra at end*/)
                {
                    if (count == 31)
                    {
                        Debug.Assert(false);
                        throw new ArgumentException();
                    }
                    count += 1;
                }

                float[] newData;
                using (FFT fft = FFT.Create(newLength))
                {
                    float[] b      = fft.Base;
                    int     offset = fft.Offset;
                    for (int i = 0; i < length; i++)
                    {
                        b[offset + i * factor + (factor - 1)] = data[i];
                    }

                    fft.FFTfwd();
                    //b[offset + 1] = 0; /* kill top frequency bin */
                    /* kill all bins above original cutoff */
                    for (int i = ((newLength / factor) & ~1); i < newLength + 2; i += 2)
                    {
                        b[offset + i + 0] = 0;
                        b[offset + i + 1] = 0;
                    }
                    fft.FFTinv();

                    newData = new float[newLength];
                    for (int i = 0; i < newLength; i++)
                    {
                        newData[i] = b[offset + i] * fft.ScaleFactor;
                    }
                }

                return(newData);
            }
예제 #2
0
            private FFT fft;                            // BlockLength*4+2


            /* initialize convolver stream.  The impulse response should be sampled at */
            /* the nominal rate.  If oversampling is being employed, it will check SynthParams */
            /* and interpolate the impulse response to the real sampling rate. */
            public ConvolveStreamSimple(
                float[] impulseResponse,
                int impulseResponseLength,
                int latency,
                int lOversampling)
            {
                if (lOversampling > 1)
                {
                    float[] impulseResponseConverted = RateConvert(
                        impulseResponse,
                        impulseResponseLength,
                        lOversampling);
                    impulseResponse        = impulseResponseConverted;
                    impulseResponseLength *= lOversampling;
                }

                /* compute truncated latency (smallest block size we need to process) */
                Debug.Assert(latency >= impulseResponseLength);
                latency |= latency >> 1;
                latency |= latency >> 2;
                latency |= latency >> 4;
                latency |= latency >> 8;
                latency |= latency >> 16;

                blockLength = latency + 1;

                inBuf              = new AlignedWorkspace(this.blockLength * 2);
                outBuf             = new AlignedWorkspace(this.blockLength * 4 + 2 /*for convlv*/);
                impulseResponseFFT = new AlignedWorkspace(this.blockLength * 4 + 2 /*for convlv*/);

                fft = FFT.Create(this.blockLength * 4);

                /* transform impulse response section to frequency domain */
                FloatVectorCopyUnaligned(
                    impulseResponse, // not guarranteed to be vector-aligned
                    0,
                    fft.Base,
                    fft.Offset,
                    impulseResponseLength);
                fft.FFTfwd();
                FloatVectorCopy(
                    fft.Base,
                    fft.Offset,
                    impulseResponseFFT.Base,
                    impulseResponseFFT.Offset,
                    blockLength * 4 + 2);
            }