예제 #1
0
        private void HandleFftData(object sender, FftDataAvailableHandlerArgs e) {
            float[] rawFft = e.FftData;

            float deltaFreq = (float)AudioIn.SAMPLE_RATE / FftProcessor.FFT_LENGTH;
            // Operate only on frequencies through MAX_FREQ that may be involved in formants
            float[] newFft = rawFft.Take((int)(Analyzer.MAX_FREQ / deltaFreq + 0.5f)).ToArray();
            // Normalize the fft
            newFft = newFft.Select(a => (float)(a / Math.Sqrt(FftProcessor.FFT_LENGTH))).ToArray();
            // Negative values differ only by phase, use positive ones instead
            newFft = newFft.Select(a => Math.Abs(a)).ToArray();
            // Remove DC component (and close to it)
            newFft[0] = newFft[1] = newFft[2] = 0;

            fft = newFft;
            prepareVisualization();
        }
예제 #2
0
        private void HandleFftData(object sender, FftDataAvailableHandlerArgs e) {
            float[] rawFft = e.FftData;
            float[] newFft = new float[fft.Length];

            // Normalize and then square for power instead of amplitude
            for (int i = 0; i < newFft.Length; i++) {
                float n = rawFft[i] / (float)Math.Sqrt(FftProcessor.FFT_LENGTH);
                newFft[i] = n * n;
            }
            // Remove DC component (and close to it)
            newFft[0] = newFft[1] = newFft[2] = 0;

            // Remove noise in the fft with a high-pass filter
            float lastIn = newFft[0];
            float lastOut = lastIn;
            float alpha = 0.96f;
            for (int i = 1; i < newFft.Length; i++) {
                float inValue = newFft[i];
                float outValue = alpha * (lastOut + inValue - lastIn);
                lastIn = inValue;
                lastOut = outValue;
                newFft[i] = outValue;
            }

            // Z-score it, put negative values at 0.
            float average = newFft.Average();
            float sumSquareDiffs = 0;
            for (int i = 0; i < newFft.Length; i++) {
                sumSquareDiffs += (newFft[i] - average) * (newFft[i] - average);
            }
            float stdDev = (float)Math.Sqrt(sumSquareDiffs / newFft.Length);
            for (int i = 0; i < newFft.Length; i++) {
                newFft[i] = (newFft[i] - average) / stdDev;
            }

            // Consider it noise/silence if the stdDev is too low
            Debug.WriteLine(stdDev);
            if (stdDev > 1e7) {
                fft = newFft;

                // Shift in the new fft
                Array.Copy(lastFfts, 1, lastFfts, 0, lastFfts.Length - 1);
                lastFfts[lastFfts.Length - 1] = fft;

                // Shift in new fundamental
                Array.Copy(lastFundamentals, 1, lastFundamentals, 0, lastFundamentals.Length - 1);
                lastFundamentals[lastFundamentals.Length - 1] = IdentifyFundamental(fft);

                prepareVisualization();
            } else {
                // Shift in null and 0 values to clear out the buffer.
                Array.Copy(lastFfts, 1, lastFfts, 0, lastFfts.Length - 1);
                lastFfts[lastFfts.Length - 1] = null;
                Array.Copy(lastFundamentals, 1, lastFundamentals, 0, lastFundamentals.Length - 1);
                lastFundamentals[lastFundamentals.Length - 1] = 0;

                Array.Copy(lastDrawnPointsRoundness, 1, lastDrawnPointsRoundness, 0, lastDrawnPointsRoundness.Length - 1);
                lastDrawnPointsRoundness[lastDrawnPointsRoundness.Length - 1] = Tuple.Create(new PointF(-1, -1), 0f); // Set to not draw it

                updateUI();
            }
        }