Skip to content

Commit 10680f1

Browse files
committed
API rework
1 parent 557ece1 commit 10680f1

8 files changed

Lines changed: 160 additions & 121 deletions

File tree

src/AudioMonitor/Form1.Designer.cs

Lines changed: 12 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/AudioMonitor/Form1.cs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ private void OnDataAvailable(object sender, NAudio.Wave.WaveInEventArgs args)
5454
float[] buffer = new float[args.BytesRecorded / bytesPerSample];
5555
for (int i = 0; i < buffer.Length; i++)
5656
buffer[i] = BitConverter.ToInt16(args.Buffer, i * bytesPerSample);
57-
spec.Add(buffer);
57+
spec.Add(buffer, fixedSize: pictureBox1.Width);
5858
renderNeeded = true;
5959
}
6060

@@ -67,25 +67,20 @@ private void AudioMonitorInitialize(
6767
)
6868
{
6969
int fftSize = 1024;
70-
int stepSize = 300;
71-
int pixelUpper = 200;
7270

7371
switch (cbDisplay.Text)
7472
{
7573
case "waterfall":
76-
spec = new Spectrogram.Spectrogram(sampleRate, fftSize: fftSize, stepSize: stepSize, pixelUpper: pixelUpper,
77-
fixedSize: pictureBox1.Height, scroll: true, vertical: true);
74+
spec = new Spectrogram.Spectrogram(sampleRate, fftSize);
7875
break;
7976

8077
case "horizontal repeat":
81-
spec = new Spectrogram.Spectrogram(sampleRate, fftSize: fftSize, stepSize: stepSize, pixelUpper: pixelUpper,
82-
fixedSize: pictureBox1.Width, scroll: false);
78+
spec = new Spectrogram.Spectrogram(sampleRate, fftSize);
8379
break;
8480

8581
default:
8682
throw new NotImplementedException("unknown display type");
8783
}
88-
nudIntensity.Value = (decimal)spec.intensity;
8984

9085
wvin = new NAudio.Wave.WaveInEvent();
9186
wvin.DeviceNumber = DeviceIndex;
@@ -104,24 +99,35 @@ private void Timer1_Tick(object sender, EventArgs e)
10499
if ((spec == null) || (spec.ffts.Count == 0))
105100
return;
106101

107-
pictureBox1.BackgroundImage = spec.GetBitmap();
108-
lblStatus.Text = $"spectrogram has {spec.ffts.Count} FFT columns | last render: {spec.lastRenderMsec} ms";
109-
renderNeeded = false;
110-
}
102+
try
103+
{
104+
pictureBox1.BackgroundImage = spec.GetBitmap(
105+
intensity: (float)nudIntensity.Value,
106+
decibels: cbDecibels.Checked,
107+
pixelLower: spec.GetFftIndex(0),
108+
pixelUpper: spec.GetFftIndex(4000),
109+
vertical: (cbDisplay.Text == "waterfall"),
110+
scroll: (cbDisplay.Text == "waterfall")
111+
);
112+
lblStatus.Text = $"spectrogram contains {spec.ffts.Count} FFT samples | last render: {spec.lastRenderMsec} ms";
113+
renderNeeded = false;
114+
}
115+
catch (Exception ex)
116+
{
117+
Console.WriteLine(ex);
118+
lblStatus.Text = ex.ToString();
119+
}
111120

112-
private void NudIntensity_ValueChanged(object sender, EventArgs e)
113-
{
114-
spec.intensity = (float)nudIntensity.Value;
115121
}
116122

117123
private void TbIntensity_Scroll(object sender, EventArgs e)
118124
{
119125
nudIntensity.Value = tbIntensity.Value;
120126
}
121127

122-
private void CheckBox1_CheckedChanged(object sender, EventArgs e)
128+
private void PictureBox1_Click(object sender, EventArgs e)
123129
{
124-
spec.decibels = checkBox1.Checked;
130+
MessageBox.Show(spec.GetConfigDetails(), "Configuration Details");
125131
}
126132
}
127133
}

src/ConsoleDemo/ConsoleDemo.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<ItemGroup>
3838
<Reference Include="System" />
3939
<Reference Include="System.Core" />
40+
<Reference Include="System.Drawing" />
4041
<Reference Include="System.Xml.Linq" />
4142
<Reference Include="System.Data.DataSetExtensions" />
4243
<Reference Include="Microsoft.CSharp" />

src/ConsoleDemo/Program.cs

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Drawing;
34
using System.Linq;
45
using System.Text;
56
using System.Threading.Tasks;
@@ -10,40 +11,50 @@ class Program
1011
{
1112
static void Main(string[] args)
1213
{
13-
//DemoMozart();
14+
DemoMozart();
1415
DemoQRSS();
16+
DemoTiming();
17+
}
18+
19+
static void DemoTiming()
20+
{
21+
var spec = new Spectrogram.Spectrogram(sampleRate: 8000, fftSize: 2048);
22+
23+
float[] values = Spectrogram.WavFile.Read("mozart.wav");
24+
spec.Add(values);
25+
26+
Console.WriteLine(spec);
27+
Console.WriteLine(spec.GetConfigDetails());
1528
}
1629

1730
static void DemoMozart()
1831
{
1932
using (var benchmark = new Spectrogram.Benchmark())
2033
{
21-
var spec = new Spectrogram.Spectrogram(
22-
fftSize: 2048,
23-
stepSize: 500,
24-
pixelUpper: 300,
25-
intensity: 2
26-
);
34+
var spec = new Spectrogram.Spectrogram(sampleRate: 8000, fftSize: 2048);
35+
2736
float[] values = Spectrogram.WavFile.Read("mozart.wav");
2837
spec.Add(values);
29-
spec.SaveImage("mozart.jpg");
38+
39+
Bitmap bmp = spec.GetBitmap();
40+
spec.SaveBitmap(bmp, "mozart.jpg");
3041
}
3142
}
3243

3344
static void DemoQRSS()
3445
{
3546
using (var benchmark = new Spectrogram.Benchmark())
3647
{
37-
var spec = new Spectrogram.Spectrogram(
38-
fftSize: 8192,
39-
stepSize: 5000,
40-
intensity: 2,
41-
pixelLower: 1250,
42-
pixelUpper: 1500
43-
);
48+
var spec = new Spectrogram.Spectrogram(sampleRate: 8000, fftSize: 8192*2);
49+
4450
float[] values = Spectrogram.WavFile.Read("qrss.wav");
45-
spec.Add(values);
46-
spec.SaveImage("qrss.jpg");
51+
spec.Add(values, stepSize: spec.fftSize/4);
52+
53+
Bitmap bmp = spec.GetBitmap(intensity: 2,
54+
pixelLower: spec.GetFftIndex(1200),
55+
pixelUpper: spec.GetFftIndex(1500)
56+
);
57+
spec.SaveBitmap(bmp, "qrss.jpg");
4758
}
4859
}
4960
}

src/Spectrogram/Benchmark.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
34
using System.Text;
45

56
namespace Spectrogram
67
{
78
public class Benchmark : IDisposable
89
{
9-
System.Diagnostics.Stopwatch stopwatch;
10+
Stopwatch stopwatch;
11+
12+
public double elapsedMilliseconds { get { return stopwatch.ElapsedTicks * 1000.0 / Stopwatch.Frequency; } }
1013

1114
public Benchmark()
1215
{
@@ -16,8 +19,8 @@ public Benchmark()
1619
public void Dispose()
1720
{
1821
stopwatch.Stop();
19-
double elapsedMsec = stopwatch.ElapsedTicks * 1000.0 / System.Diagnostics.Stopwatch.Frequency;
20-
System.Console.WriteLine(string.Format("completed in {0:0.00} ms", elapsedMsec));
22+
Console.WriteLine(string.Format("completed in {0:0.00} ms", elapsedMilliseconds));
2123
}
24+
2225
}
2326
}

src/Spectrogram/Image.cs

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,16 @@ class Image
1111
{
1212
public static Bitmap BitmapFromFFTs(
1313
List<float[]> ffts,
14-
int? fixedWidth = null,
15-
int? verticalLine = null,
16-
int? pixelLow = null,
17-
int? pixelHigh = null,
18-
float intensity = 100
14+
int? pixelLow,
15+
int? pixelHigh,
16+
float intensity,
17+
bool decibels
1918
)
2019
{
2120

2221
if (ffts == null || ffts.Count == 0)
2322
throw new ArgumentException("ffts must contain float arrays");
2423

25-
int width = (fixedWidth == null) ? ffts.Count : (int)fixedWidth;
26-
2724
int fftHeight;
2825
if (ffts[0] != null)
2926
fftHeight = ffts[0].Length;
@@ -42,7 +39,11 @@ public static Bitmap BitmapFromFFTs(
4239
else
4340
pixelHigh = Math.Min((int)pixelHigh, fftHeight);
4441

42+
if ((int)pixelHigh <= (int)pixelLow)
43+
throw new ArgumentException("pixelHigh must be greater than pixelLow");
44+
4545
int height = (int)pixelHigh - (int)pixelLow;
46+
int width = ffts.Count;
4647

4748
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
4849
Palette.ApplyLUT(bmp, Palette.LUT.viridis);
@@ -63,18 +64,12 @@ public static Bitmap BitmapFromFFTs(
6364
{
6465
int bytePosition = (bmp.Height - 1 - row) * bitmapData.Stride + col;
6566
float pixelValue;
66-
67-
if ((verticalLine != null) && (col == verticalLine))
68-
{
69-
pixelValue = byte.MaxValue;
70-
}
71-
else
72-
{
73-
pixelValue = ffts[col][row + (int)pixelLow];
74-
pixelValue = pixelValue * intensity;
75-
pixelValue = Math.Max(0, pixelValue);
76-
pixelValue = Math.Min(255, pixelValue);
77-
}
67+
pixelValue = ffts[col][row + (int)pixelLow];
68+
if (decibels)
69+
pixelValue = (float)(Math.Log10(pixelValue) * 20);
70+
pixelValue = (pixelValue * intensity);
71+
pixelValue = Math.Max(0, pixelValue);
72+
pixelValue = Math.Min(255, pixelValue);
7873
pixels[bytePosition] = (byte)(pixelValue);
7974
}
8075
}

src/Spectrogram/Operations.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public static double TriangleWindow(int n, int frameSize)
3232
return fractionFromEdge;
3333
}
3434

35-
public static float[] FFT(float[] values, WindowFunction window = WindowFunction.hanning, bool decibels = false)
35+
public static float[] FFT(float[] values, WindowFunction window = WindowFunction.hanning)
3636
{
3737
int fftSize = values.Length;
3838
if (!IsPowerOfTwo(fftSize))
@@ -70,11 +70,7 @@ public static float[] FFT(float[] values, WindowFunction window = WindowFunction
7070
// note that this is different than just taking the absolute value
7171
float absL = (float)Math.Sqrt(fftL.X * fftL.X + fftL.Y * fftL.Y);
7272
float absR = (float)Math.Sqrt(fftR.X * fftR.X + fftR.Y * fftR.Y);
73-
7473
fft[i] = (absL + absR) / 2;
75-
76-
if (decibels)
77-
fft[i] = (float)(Math.Log(fft[i]) * 20);
7874
}
7975

8076
return fft;

0 commit comments

Comments
 (0)