Esempio n. 1
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        //  Function:       createUnscaledH
        //
        //  Arguments:      h:           The impulse response.
        //                  fftSize:     The size of the complex vector that will be
        //                               created.
        //
        //  Returns:        A pointer to a newly-allocated vector containing the
        //                  complex spectrum of h.
        //
        //  Description:    This function takes h, an arbitrary impulse response (filter
        //                  kernel), and creates H, the complex spectrum of h. The
        //                  spectrum is put into a complex vector with the length
        //                  of fftSize. If needed, this vector is zero-padded. This
        //                  function creates the unscaled version of H.
        //
        ////////////////////////////////////////////////////////////////////////////////
        private Complex[] createUnscaledH(double[] h, int fftSize)
        {
            // Make sure we have a valid pointer argument
            if (h == null)
            {
                throw new ArgumentNullException("h");
            }

            // Make sure the fft size is as big or bigger than the h vector size
            if (fftSize < h.Length)
            {
                throw new ArgumentOutOfRangeException("h.Length", "" + h.Length);
            }

            // Create the H buffer to hold the FFT of h
            Complex[] H = new Complex[fftSize];

            // Copy h[] into H[] vector, converting from real numbers to complex.
            // Zero padding is already done, since the H vector is filled with zeros
            // when it is created.
            for (int i = 0; i < h.Length; i++)
            {
                H[i] = h[i];
            }

            // Do an in-place unscaled FFT on h, to give H
            FourierAnalysis.complexUnscaledFFT(H);

            // Return a pointer to the newly created complex H vector
            return(H);
        }
Esempio n. 2
0
 private Complex[] createIdentityKernel(int fftSize)
 {
     Complex[] H = new Complex[fftSize];
     H[(int)Math.Floor((double)fftSize / 2.0)] = new Complex(1.0, 0.0);
     FourierAnalysis.complexUnscaledFFT(H);
     return(H);
 }
Esempio n. 3
0
        private void drawFFT(PictureBox pBox, PaintEventArgs e, int channelNum)
        {
            e.Graphics.FillRegion(Brushes.Black, new Region(new Rectangle(0, 0, pBox.Width, pBox.Height)));

            if (sampleTap == null || !chkDrawFFTs.Checked)
            {
                return;
            }

            Complex[] fft = new Complex[sampleData[channelNum].Length];

            for (int i = 0; i < sampleData[channelNum].Length; i++)
            {
                fft[i] = sampleData[channelNum][i];
            }

            FourierAnalysis.complexUnscaledFFT(fft);

            Point[] drawPts = new Point[fft.Length / 2];

            for (int i = 0; i < drawPts.Length && i * 2 < fft.Length; i++)
            {
                double magnitude = 20;

                if (sampleTap.BitsPerSample == 24)
                {
                    magnitude = 15;
                }

                try
                {
                    magnitude *= Math.Log10(Math.Sqrt(fft[i].Real * fft[i].Real + fft[i].Imaginary * fft[i].Imaginary));
                }
                catch (OverflowException)
                {
                    magnitude = 0;
                }

                if (magnitude > pBox.Height || Double.IsInfinity(magnitude) || Double.IsNaN(magnitude))
                {
                    magnitude = pBox.Height;
                }

                double y = pBox.Height - magnitude;

                drawPts[i] = new Point(i, (int)Math.Floor(y));
            }


            e.Graphics.DrawLines(Pens.White, drawPts);
        }
Esempio n. 4
0
        /// <summary>
        /// Performs the convolution on the next input segment.
        /// </summary>
        private void performNextConvolve()
        {
            // We only do the convolution when in the normal state
            if (currentState != States.Normal && currentState != States.LastReadIncomplete)
            {
                throw new Exception("Can only be called when in the Normal or LastReadIncomplete state");
            }

            double[] sourceData = new double[inputSegmentSize * source.NumberOfChannels];

            // Read frames from audio source
            int framesRead = source.read(sourceData, 0, sourceData.Length);

            if (framesRead == 0)
            {
                // If we previously had an incomplete read and now we are EOF, then we are EOF
                if (currentState == States.LastReadIncomplete)
                {
                    currentState = States.EndOfInput;
                    return;
                }

                // TODO: The above if is still not right.  We really should remember framesRead from the
                // final read and then return part of the overlap buffer to complete one final read...
                // ... I think...

                // Otherwise if the last read was complete and EOF lines up with the buffers, then
                // overlap contains the last bit of data
                Array.Copy(overlapLeftWoofer, 0, bufferLeftWoofer, 0, overlapLeftWoofer.Length);
                Array.Copy(overlapLeftMidrange, 0, bufferLeftMidrange, 0, overlapLeftMidrange.Length);
                Array.Copy(overlapLeftUpperMidrange, 0, bufferLeftMidrange, 0, overlapLeftUpperMidrange.Length);
                Array.Copy(overlapLeftTweeter, 0, bufferLeftTweeter, 0, overlapLeftTweeter.Length);
                Array.Copy(overlapRightWoofer, 0, bufferRightWoofer, 0, overlapRightWoofer.Length);
                Array.Copy(overlapRightMidrange, 0, bufferRightMidrange, 0, overlapRightMidrange.Length);
                Array.Copy(overlapRightUpperMidrange, 0, bufferRightMidrange, 0, overlapRightUpperMidrange.Length);
                Array.Copy(overlapRightTweeter, 0, bufferRightTweeter, 0, overlapRightTweeter.Length);

                currentState = States.LastOverlapBuffer;
                return;
            }

            if (framesRead < 0 || framesRead > sourceData.Length)
            {
                throw new Exception("Audio source returned unexpected number of samples: " + framesRead);
            }

            if ((framesRead % source.NumberOfChannels) != 0)
            {
                throw new Exception("Audio source returned uneven number of samples");
            }

            if (framesRead < sourceData.Length)
            {
                currentState = States.LastReadIncomplete;
            }

            // Copy source data into left and right structures
            for (int i = 0; i < framesRead; i += 2)
            {
                bufferLeftWoofer[i / 2]  = sourceData[i];
                bufferRightWoofer[i / 2] = sourceData[i + 1];
            }

            framesRead /= 2;

            // Pad remaining part of these two buffers with zeros
            Array.Clear(bufferLeftWoofer, framesRead, bufferLeftWoofer.Length - framesRead);
            Array.Clear(bufferRightWoofer, framesRead, bufferRightWoofer.Length - framesRead);

            // Do an in-place unscaled FFT on the two buffers, giving us the
            // spectra X of the stereo input signals (i.e. X_left and X_right)
            FourierAnalysis.complexUnscaledFFT(bufferLeftWoofer);
            FourierAnalysis.complexUnscaledFFT(bufferRightWoofer);

            // Copy the left and right spectra into the midrange and tweeter
            // buffers. Once this is done, we will have X_left in three buffers
            // (channels) and X_right the other three buffers.
            Array.Copy(bufferLeftWoofer, bufferLeftMidrange, bufferLeftWoofer.Length);
            Array.Copy(bufferLeftWoofer, bufferLeftUpperMidrange, bufferLeftWoofer.Length);
            Array.Copy(bufferLeftWoofer, bufferLeftTweeter, bufferLeftWoofer.Length);
            Array.Copy(bufferRightWoofer, bufferRightMidrange, bufferRightWoofer.Length);
            Array.Copy(bufferRightWoofer, bufferRightUpperMidrange, bufferRightWoofer.Length);
            Array.Copy(bufferRightWoofer, bufferRightTweeter, bufferRightWoofer.Length);

            // Do the point-by-point complex multiply of H times X, which yields Y
            for (int i = 0; i < bufferLeftWoofer.Length; i++)
            {
                bufferLeftWoofer[i]        *= H_woofer[i];
                bufferLeftMidrange[i]      *= H_midrange[i];
                bufferLeftUpperMidrange[i] *= H_upperMidrange[i];
                bufferLeftTweeter[i]       *= H_tweeter[i];

                bufferRightWoofer[i]        *= H_woofer[i];
                bufferRightMidrange[i]      *= H_midrange[i];
                bufferRightUpperMidrange[i] *= H_upperMidrange[i];
                bufferRightTweeter[i]       *= H_tweeter[i];
            }

            // Do an in-place scaled IFFT on the six buffers containing Y,
            // to yield 6 channels of y
            FourierAnalysis.complexScaledIFFT(bufferLeftWoofer);
            FourierAnalysis.complexScaledIFFT(bufferLeftMidrange);
            FourierAnalysis.complexScaledIFFT(bufferLeftUpperMidrange);
            FourierAnalysis.complexScaledIFFT(bufferLeftTweeter);
            FourierAnalysis.complexScaledIFFT(bufferRightWoofer);
            FourierAnalysis.complexScaledIFFT(bufferRightMidrange);
            FourierAnalysis.complexScaledIFFT(bufferRightUpperMidrange);
            FourierAnalysis.complexScaledIFFT(bufferRightTweeter);

            // Add the contents of the overlap buffers to the first part of the
            // y buffers
            for (int i = 0; i < overlapLeftWoofer.Length; i++)
            {
                bufferLeftWoofer[i]         += overlapLeftWoofer[i];
                bufferLeftMidrange[i]       += overlapLeftMidrange[i];
                bufferLeftUpperMidrange[i]  += overlapLeftUpperMidrange[i];
                bufferLeftTweeter[i]        += overlapLeftTweeter[i];
                bufferRightWoofer[i]        += overlapRightWoofer[i];
                bufferRightMidrange[i]      += overlapRightMidrange[i];
                bufferRightUpperMidrange[i] += overlapRightUpperMidrange[i];
                bufferRightTweeter[i]       += overlapRightTweeter[i];
            }

            Array.Copy(bufferLeftWoofer, inputSegmentSize, overlapLeftWoofer, 0, overlapLeftWoofer.Length);
            Array.Copy(bufferLeftMidrange, inputSegmentSize, overlapLeftMidrange, 0, overlapLeftMidrange.Length);
            Array.Copy(bufferLeftUpperMidrange, inputSegmentSize, overlapLeftUpperMidrange, 0, overlapLeftUpperMidrange.Length);
            Array.Copy(bufferLeftTweeter, inputSegmentSize, overlapLeftTweeter, 0, overlapLeftTweeter.Length);
            Array.Copy(bufferRightWoofer, inputSegmentSize, overlapRightWoofer, 0, overlapRightWoofer.Length);
            Array.Copy(bufferRightMidrange, inputSegmentSize, overlapRightMidrange, 0, overlapRightMidrange.Length);
            Array.Copy(bufferRightUpperMidrange, inputSegmentSize, overlapRightUpperMidrange, 0, overlapRightUpperMidrange.Length);
            Array.Copy(bufferRightTweeter, inputSegmentSize, overlapRightTweeter, 0, overlapRightTweeter.Length);

            return;
        }