Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spectrogram 1.1.6 #45

Merged
merged 3 commits into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 0 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,58 +153,6 @@ Bitmap bmp = sg.GetBitmapMel(melSizePoints: 250);
bmp.Save("halMel.png", ImageFormat.Png);
```

## Spectrogram File Format (SFF)

The Spectrogram library has methods which can read and write SFF files, a file format specifically designed for storing spectrogram data. SFF files contain 2D spectrogram data (repeated FFTs) with a [small header](dev/sff) describing the audio and FFT settings suitable for deriving scale information.

SFF files store `double` values (8-byte floating-point data) which is far superior to saving spectrograms as indexed color images (which represent intensity with a single `byte` per pixel).

SFF files be saved using `Complex` data format (with real and imaginary values for each point) to faithfully represent the FFT output, or `double` format to represent magnitude (with an optional pre-conversion to Decibels to represent power).

### Create SFF Files with C#

This example creates a spectrogram but saves it using the SFF file format instead of saving it as an image. The SFF file can then be read in any language.

```cs
(double[] audio, int sampleRate) = ReadWavMono("hal.wav");
var sg = new SpectrogramGenerator(sampleRate, fftSize: 4096, stepSize: 700, maxFreq: 2000);
sg.Add(audio);
sg.SaveData("hal.sff");
```

### Display SFF Files with C#
Spectrogram data can be loaded from SFF files to facilitate rapid recall of data which can otherwise be resource-intensive to calculate. Spectrogram's `SFF` module facilitates this operation and has methods which can directly convert spectrograms to Bitmaps with options to customize the colormap, intensity, and Decibel scaling.

![](dev/sff/SffViewer/screenshot.png)

A simple SFF file viewer has been added to [dev/sff](dev/sff) and serves as a demonstration of how the `SFF` module can be used to generate spectrogram images from SFF files.

### Read SFF Files with Python
A Python module to read SFF files has been created (in [dev/sff/python](dev/sff/python)) which allows Spectrograms created by this library and stored in SFF format to be loaded as 2D numpy arrays in Python.

This example demonstrates how the SFF file created in the previous C# example can be loaded into Python and displayed with matplotlib. This example has a few lines related to styling omitted for brevity, but the full Python demo can be found in [dev/sff/python](dev/sff/python).

```python
import matplotlib.pyplot as plt
import sffLib

# load spectrogram data as a 2D numpy array
sf = sffLib.SpectrogramFile("hal.sff")

# display the spectrogram as a pseudocolor mesh
plt.pcolormesh(freqs, times, sf.values)
plt.colorbar()
plt.show()
```

![](dev/sff/python/hal.sff.png)

## Resources
* [FftSharp](https://github.com/swharden/FftSharp) - the module which actually performs the FFT and related transformations
* [MP3Sharp](https://github.com/ZaneDubya/MP3Sharp) - a library I use to read MP3 files during testing
* [FSKview](https://github.com/swharden/FSKview) - a real-time spectrogram for viewing frequency-shift-keyed (FSK) signals from audio transmitted over radio frequency.
* [NAudio](https://github.com/naudio/NAudio) - an open source .NET library which makes it easy to get samples from the microphone or sound card in real time

## Read data from a WAV File

You should customize your file-reading method to suit your specific application. I frequently use the NAudio package to read data from WAV and MP3 files. This function reads audio data from a mono WAV file and will be used for the examples on this page.
Expand Down
2 changes: 1 addition & 1 deletion src/Spectrogram.MicrophoneDemo/Spectrogram.Demo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<ProjectReference Include="..\Spectrogram\Spectrogram.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FftSharp" Version="1.1.2" />
<PackageReference Include="FftSharp" Version="1.1.6" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="NAudio" Version="1.10.0" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
Expand Down
97 changes: 0 additions & 97 deletions src/Spectrogram.Tests/FileFormat.cs

This file was deleted.

5 changes: 4 additions & 1 deletion src/Spectrogram/SFF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

namespace Spectrogram
{
// Spectrogram File Format reader/writer
[Obsolete("The SFF file format is obsolete. " +
"Users are encouraged to write their own IO routines specific to their application. "+
"To get a copy of the original SFF reader/writer see https://github.com/swharden/Spectrogram/issues/44",
error: true)]
public class SFF
{
public readonly byte VersionMajor = 1;
Expand Down
6 changes: 3 additions & 3 deletions src/Spectrogram/Spectrogram.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>1.4.4</Version>
<Version>1.5.0</Version>
<Description>A .NET Standard library for creating spectrograms</Description>
<Authors>Scott Harden</Authors>
<Company>Harden Technologies, LLC</Company>
Expand All @@ -29,10 +29,10 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="FftSharp" Version="1.1.2" />
<PackageReference Include="FftSharp" Version="1.1.6" />
<PackageReference Include="System.Drawing.Common" Version="4.6.1" />
<PackageReference Include="runtime.osx.10.10-x64.CoreCompat.System.Drawing" Version="5.8.64" Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
4 changes: 4 additions & 0 deletions src/Spectrogram/SpectrogramGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,10 @@ public Bitmap GetBitmapMax(double intensity = 1, bool dB = false, double dBScale
return Image.GetBitmap(ffts2, Colormap, intensity, dB, dBScale, roll, NextColumnIndex);
}

[Obsolete("The SFF file format is obsolete. " +
"Users are encouraged to write their own IO routines specific to their application. " +
"To get a copy of the original SFF reader/writer see https://github.com/swharden/Spectrogram/issues/44",
error: true)]
/// <summary>
/// Export spectrogram data using the Spectrogram File Format (SFF)
/// </summary>
Expand Down
13 changes: 13 additions & 0 deletions src/Spectrogram/Tools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ namespace Spectrogram
{
public static class Tools
{
[Obsolete("The SFF file format is obsolete. " +
"Users are encouraged to write their own IO routines specific to their application. " +
"To get a copy of the original SFF reader/writer see https://github.com/swharden/Spectrogram/issues/44",
error: true)]
/// <summary>
/// Collapse the 2D spectrogram into a 1D array (mean power of each frequency)
/// </summary>
Expand All @@ -31,6 +35,11 @@ public static double[] SffMeanFFT(SFF sff, bool dB = false)
return mean;
}


[Obsolete("The SFF file format is obsolete. " +
"Users are encouraged to write their own IO routines specific to their application. " +
"To get a copy of the original SFF reader/writer see https://github.com/swharden/Spectrogram/issues/44",
error: true)]
/// <summary>
/// Collapse the 2D spectrogram into a 1D array (mean power of each time point)
/// </summary>
Expand All @@ -48,6 +57,10 @@ public static double[] SffMeanPower(SFF sff, bool dB = false)
return power;
}

[Obsolete("The SFF file format is obsolete. " +
"Users are encouraged to write their own IO routines specific to their application. " +
"To get a copy of the original SFF reader/writer see https://github.com/swharden/Spectrogram/issues/44",
error: true)]
public static double GetPeakFrequency(SFF sff, bool firstFftOnly = false)
{
double[] freqs = firstFftOnly ? sff.Ffts[0] : SffMeanFFT(sff, false);
Expand Down