コード例 #1
0
        public override void tick()
        {
            if (fft == null)
            {
                fft = new FFTProcessor(FFTProcessor.ProcessorMode.Bidirectional, blockSize, owner.sampleRate, FFTProcessor.WindowType.Hann);
            }

            SignalBuffer dbout = getSignalOutputBuffer(ioO);
            SignalBuffer dbin  = getSignalInputBuffer(ioI);

            if (!_active)
            {
                return;
            }

            if ((dbout == null) && (dbin == null))
            {
                return;
            }

            if (buffIn == null)
            {
                buffIn  = new double[blockSize];
                buffOut = new double[blockSize];
                fftOut  = new double[blockSize];
                re      = new double[blockSize / 2];
                im      = new double[blockSize / 2];

                buffInFill  = 0;
                buffOutFill = 0;
                buffOutRead = 0;
            }

            if (dbin != null)
            {
                Array.Copy(dbin.data, 0, buffIn, buffInFill, owner.blockSize);
                buffInFill += owner.blockSize;

                if (buffInFill == blockSize)
                {
                    fft.runFFT(ref buffIn, true, ref re, ref im);
                    Array.Copy(buffIn, blockSize / 2, buffIn, 0, buffInFill - blockSize / 2);
                    buffInFill -= blockSize / 2;
                    // Process FFT
                    int    n1, n2;
                    double s, c;
                    switch (filterMode)
                    {
                    case FFTFilterMode.LowPass:
                        n1 = (int)Math.Floor(f1 / (double)owner.sampleRate * blockSize);
                        if (n1 < 0)
                        {
                            n1 = 0;
                        }
                        for (int i = n1; i < blockSize / 2; i++)
                        {
                            re[i] = im[i] = 0;
                        }
                        break;

                    case FFTFilterMode.HighPass:
                        n1 = (int)Math.Ceiling(f1 / (double)owner.sampleRate * blockSize);
                        if (n1 >= blockSize / 2)
                        {
                            n1 = blockSize / 2 - 1;
                        }
                        for (int i = 0; i < n1; i++)
                        {
                            re[i] = im[i] = 0;
                        }
                        break;

                    case FFTFilterMode.BandPass:
                        n1 = (int)Math.Floor(f1 / (double)owner.sampleRate * blockSize);
                        n2 = (int)Math.Ceiling(f2 / (double)owner.sampleRate * blockSize);
                        if (n1 < 0)
                        {
                            n1 = 0;
                        }
                        if (n2 >= blockSize / 2)
                        {
                            n2 = blockSize / 2 - 1;
                        }
                        for (int i = 0; i < n1; i++)
                        {
                            re[i] = im[i] = 0;
                        }
                        for (int i = n2 + 1; i < blockSize / 2; i++)
                        {
                            re[i] = im[i] = 0;
                        }
                        break;

                    case FFTFilterMode.BandStop:
                        n1 = (int)Math.Floor(f1 / (double)owner.sampleRate * blockSize);
                        n2 = (int)Math.Ceiling(f2 / (double)owner.sampleRate * blockSize);
                        if (n1 < 0)
                        {
                            n1 = 0;
                        }
                        if (n2 >= blockSize / 2)
                        {
                            n2 = blockSize / 2 - 1;
                        }
                        for (int i = n1 + 1; i < n2; i++)
                        {
                            re[i] = im[i] = 0;
                        }
                        break;

                    case FFTFilterMode.AllPass:
                        s = Math.Sin(phi);
                        c = Math.Cos(phi);
                        for (int i = 1; i < blockSize / 2; i++)
                        {
                            double _re = re[i] * c - im[i] * s;
                            double _im = re[i] * s + im[i] * c;
                            re[i] = _re;
                            im[i] = _im;
                        }
                        break;

                    case FFTFilterMode.FrequencyShifter:
                        n1 = (int)Math.Floor(f1 / (double)owner.sampleRate * blockSize + 0.5);
                        if (n1 > 0)
                        {                                                             // positive shift
                            double df = (double)owner.sampleRate / (double)blockSize; // Bin Spacing
                            Array.Copy(re, 1, re, 1 + n1, blockSize / 2 - 1 - n1);
                            Array.Copy(im, 1, im, 1 + n1, blockSize / 2 - 1 - n1);
                            Array.Clear(re, 1, n1);
                            Array.Clear(im, 1, n1);
                            for (int i = 1 + n1; i < blockSize / 2; i++)
                            {
                                double T    = 1.0 / i / df;
                                double T2   = 1.0 / (i + n1) / df;
                                double dphi = -2.0 * Math.PI * (T - T2) * (i + n1) * df;
                                s = Math.Sin(dphi);
                                c = Math.Cos(dphi);
                                double _re = re[i] * c - im[i] * s;
                                double _im = re[i] * s + im[i] * c;
                                re[i] = _re;
                                im[i] = _im;
                            }
                        }
                        if (n1 < 0)
                        {
                            n1 = -n1;
                            Array.Copy(re, n1 + 1, re, 1, blockSize / 2 - n1 - 1);
                            Array.Copy(im, n1 + 1, im, 1, blockSize / 2 - n1 - 1);
                            Array.Clear(re, blockSize / 2 - 1 - n1, n1);
                            Array.Clear(im, blockSize / 2 - 1 - n1, n1);
                        }
                        break;
                    }

                    // Transfer Back
                    fft.runIFFT(ref re, ref im, ref fftOut);
                    Array.Copy(buffOut, blockSize / 2, buffOut, 0, blockSize / 2);
                    Array.Clear(buffOut, blockSize / 2, blockSize / 2);
                    for (int i = 0; i < blockSize; i++)
                    {
                        buffOut[i] += fftOut[i];
                    }
                    buffOutFill = blockSize / 2;
                    buffOutRead = 0;
                }
                if (buffOutFill > 0)
                {
                    if (dbout != null)
                    {
                        Array.Copy(buffOut, buffOutRead, dbout.data, 0, owner.blockSize);
                        buffOutRead += owner.blockSize;
                    }
                }
            }
        }