{"id":19728755,"url":"https://github.com/swharden/fftsharp","last_synced_at":"2025-05-14T18:07:04.917Z","repository":{"id":37802709,"uuid":"266640089","full_name":"swharden/FftSharp","owner":"swharden","description":"A .NET Standard library for computing the Fast Fourier Transform (FFT) of real or complex data","archived":false,"fork":false,"pushed_at":"2024-11-16T20:30:37.000Z","size":3415,"stargazers_count":347,"open_issues_count":3,"forks_count":52,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-05-14T18:06:59.299Z","etag":null,"topics":["audio","fft","frequency","signal","signal-processing","spectrogram"],"latest_commit_sha":null,"homepage":"https://nuget.org/packages/FftSharp","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/swharden.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-24T23:10:33.000Z","updated_at":"2025-05-06T06:03:20.000Z","dependencies_parsed_at":"2024-12-11T07:00:45.373Z","dependency_job_id":"c97608c4-218f-44bf-8faf-3f995e371ac0","html_url":"https://github.com/swharden/FftSharp","commit_stats":{"total_commits":224,"total_committers":5,"mean_commits":44.8,"dds":"0.022321428571428603","last_synced_commit":"8015e0dc504edd01c02ae6b9c9d334dc33d9bda5"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swharden%2FFftSharp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swharden%2FFftSharp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swharden%2FFftSharp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swharden%2FFftSharp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swharden","download_url":"https://codeload.github.com/swharden/FftSharp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198515,"owners_count":22030966,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio","fft","frequency","signal","signal-processing","spectrogram"],"created_at":"2024-11-12T00:07:38.825Z","updated_at":"2025-05-14T18:06:59.905Z","avatar_url":"https://github.com/swharden.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg src=\"dev/icon/v3/fftsharp-icon-24.png\" height=\"24\" width=\"24\"\u003e FftSharp\n\n[![CI/CD](https://github.com/swharden/FftSharp/actions/workflows/ci.yaml/badge.svg)](https://github.com/swharden/FftSharp/actions/workflows/ci.yaml)\n\n**FftSharp is a collection of Fast Fourier Transform (FFT) tools for .NET.** FftSharp is provided under the permissive [MIT license](LICENSE) so it is suitable for use in commercial applications. FftSharp targets .NET Standard and has no dependencies so it can be easily used in cross-platform .NET Framework and .NET Core applications.\n\n### Quickstart\n\n```cs\n// Begin with an array containing sample data\ndouble[] signal = FftSharp.SampleData.SampleAudio1();\n\n// Shape the signal using a Hanning window\nvar window = new FftSharp.Windows.Hanning();\nwindow.ApplyInPlace(signal);\n\n// Calculate the FFT as an array of complex numbers\nSystem.Numerics.Complex[] spectrum = FftSharp.FFT.Forward(signal);\n\n// or get the magnitude (units²) or power (dB) as real numbers\ndouble[] magnitude = FftSharp.FFT.Magnitude(spectrum);\ndouble[] power = FftSharp.FFT.Power(spectrum);\n```\n\nSignal | Windowed Signal | FFT\n---|---|---\n![](dev/quickstart/audio.png)|![](dev/quickstart/audio-windowed.png)|![](dev/quickstart/fft-windowed.png)\n\n## Sample Data\n\n```cs\n// sample audio with tones at 2, 10, and 20 kHz plus white noise\ndouble[] signal = FftSharp.SampleData.SampleAudio1();\nint sampleRate = 48_000;\ndouble samplePeriod = sampleRate / 1000.0;\n\n// plot the sample audio\nScottPlot.Plot plt = new();\nplt.Add.Signal(signal, samplePeriod);\nplt.YLabel(\"Amplitude\");\nplt.SavePng(\"time-series.png\", 500, 200);\n```\n\n\u003cdiv align=\"center\"\u003e\n\n![](dev/quickstart/time-series.png)\n\n\u003c/div\u003e\n\n## Spectral Magnitude and Power Density\n\nMost people performing FFT operations are interested in calculating magnitude or power of their signal with respect to frequency. Magnitude units are the square of the original units, and power is in decibels.\n\nFrequency of each point is a linear range between zero and half the sample rage (Nyquist frequency). A helper function makes it easy to get an array of frequencies (Hz units) to match the FFT that was generated.\n\n```cs\n// sample audio with tones at 2, 10, and 20 kHz plus white noise\ndouble[] signal = FftSharp.SampleData.SampleAudio1();\nint sampleRate = 48_000;\n\n// calculate the power spectral density using FFT\nSystem.Numerics.Complex[] spectrum = FftSharp.FFT.Forward(signal);\ndouble[] psd = FftSharp.FFT.Power(spectrum);\ndouble[] freq = FftSharp.FFT.FrequencyScale(psd.Length, sampleRate);\n\n// plot the sample audio\nScottPlot.Plot plt = new();\nplt.Add.ScatterLine(freq, psd);\nplt.YLabel(\"Power (dB)\");\nplt.XLabel(\"Frequency (Hz)\");\nplt.SavePng(\"periodogram.png\", 500, 200);\n```\n\n\u003cdiv align=\"center\"\u003e\n\n![](dev/quickstart/periodogram.png)\n\n\u003c/div\u003e\n\n## FFT using Complex Numbers\n\nIf you are writing a performance application or just enjoy working with real and imaginary components of complex numbers, you can build your own complex array perform FFT operations on it in place:\n\n```cs\nSystem.Numerics.Complex[] buffer =\n{\n    new(real: 42, imaginary: 12),\n    new(real: 96, imaginary: 34),\n    new(real: 13, imaginary: 56),\n    new(real: 99, imaginary: 78),\n};\n\nFftSharp.FFT.Forward(buffer);\n```\n\n## Filtering\n\nThe `FftSharp.Filter` module has methods to apply low-pass, high-pass, band-pass, and band-stop filtering. This works by converting signals to the frequency domain (using FFT), zeroing-out the desired ranges, performing the inverse FFT (iFFT), and returning the result.\n\n```cs\ndouble[] audio = FftSharp.SampleData.SampleAudio1();\ndouble[] filtered = FftSharp.Filter.LowPass(audio, sampleRate: 48000, maxFrequency: 2000);\n```\n\n\u003cdiv align=\"center\"\u003e\n\n![](dev/lowpass.png)\n\n\u003c/div\u003e\n\n## Windowing\n\nSignals are often _windowed_ prior to FFT analysis. Windowing is essentially multiplying the waveform by a bell-shaped curve prior to analysis, improving the frequency resolution of the FFT output.\n\n\u003cdiv align=\"center\"\u003e\n\n![](dev/windows.png)\n\n\u003c/div\u003e\n\nThe Hanning window is the most common window function for general-purpose FFT analysis. Other window functions may have different _scallop loss_ or _spectral leakage_ properties. For more information review [window functions](https://en.wikipedia.org/wiki/Window_function) on Wikipedia.\n\n```cs\ndouble[] signal = FftSharp.SampleData.SampleAudio1();\n\nvar window = new FftSharp.Windows.Hanning();\ndouble[] windowed = window.Apply(signal);\n```\n\nHanning Window | Power Spectral Density\n---|---\n![](dev/quickstart/audio-windowed.png)|![](dev/quickstart/fft-windowed.png)\n\nWindowing signals prior to calculating the FFT improves signal-to-noise ratio at lower frequencies, making power spectrum peaks easier to resolve.\n\nNo Window | Power Spectral Density\n---|---\n![](dev/quickstart/audio.png)|![](dev/quickstart/fft.png)\n\n### Window Functions\n\nThis chart (adapted from [Understanding FFT Windows](https://www.egr.msu.edu/classes/me451/me451_labs/Fall_2013/Understanding_FFT_Windows.pdf)) summarizes windows commonly used for FFT analysis.\n\nWindow           | Use Case       | Frequency Resolution | Spectral Leakage | Amplitude Accuracy\n-----------------|----------------|------|------|-----\nBarlett          | Random         | Good | Fair | Fair\nBlackman         | Random         | Poor | Best | Good\nCosine           | Random         | Fair | Fair | Fair\nFlat Top         | Sine waves     | Poor | Good | Best\nHanning          | Random         | Good | Good | Fair\nHamming          | Random         | Good | Fair | Fair\nKaiser           | Random         | Fair | Good | Good\nRectangular      | Transient      | Best | Poor | Poor\nTukey            | Transient      | Good | Poor | Poor\nWelch            | Random         | Good | Good | Fair\n\n## Demo Application\n\nA sample application is included with this project that interactively displays an audio signal next to its FFT using different windowing functions.\n\n\u003cdiv align=\"center\"\u003e\n\n![](dev/demo.png)\n\n\u003c/div\u003e\n\n### Microphone Demo\n\nOne of the demos included is a FFT microphone analyzer which continuously monitors a sound card input device and calculates the FFT and displays it in real time.\n\n![](dev/microphone-fft.gif)\n\n## Spectrogram\n\nA spectrogram is a visual representation of the spectrum of frequencies of a signal as it varies with time. Spectrograms are created by computing power spectral density of a small window of an audio signal, moving the window forward in time, and repeating until the end of the signal is reached. In a spectrogram the horizontal axis represents time, the vertical axis represents frequency, and the pixel intensity represents spectral magnitude or power.\n\n[**Spectrogram**](https://github.com/swharden/Spectrogram) is a .NET library for creating spectrograms.\n\n\u003cdiv align=\"center\"\u003e\n\n![](dev/spectrogram.png)\n\n_I'm sorry Dave... I'm afraid I can't do that_\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswharden%2Ffftsharp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswharden%2Ffftsharp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswharden%2Ffftsharp/lists"}