HamBook – Blame information for rev 59

Subversion Repositories:
Rev:
Rev Author Line No. Line
54 office 1 using System;
10 office 2 using System.Drawing;
54 office 3 using System.Drawing.Imaging;
10 office 4 using System.Linq;
5 using System.Runtime.InteropServices;
6 using System.Threading;
7 using System.Windows.Forms;
54 office 8 using HamBook.Utilities;
9 using NAudio.Wave;
10 using Spectrogram;
10 office 11  
12 namespace HamBook
13 {
14 public partial class SpectrogramForm : Form
15 {
54 office 16 private readonly CancellationToken _renderCancellationToken;
17 private readonly CancellationTokenSource _renderCancellationTokenSource;
18 private readonly SpectrogramGenerator _spectrogramGenerator;
19 private readonly ScheduledContinuation _windowZOrderScheduledContinuation;
10 office 20 private CancellationToken _cancellationToken;
54 office 21 private Point _formLocation;
22 private volatile bool _mouseDown;
10 office 23 private WaveIn _waveIn;
24  
25 public SpectrogramForm()
26 {
27 InitializeComponent();
28  
29 _renderCancellationTokenSource = new CancellationTokenSource();
30 _renderCancellationToken = _renderCancellationTokenSource.Token;
31 _windowZOrderScheduledContinuation = new ScheduledContinuation();
32 }
33  
34 public SpectrogramForm(Configuration.Configuration configuration, CancellationToken cancellationToken) : this()
35 {
15 office 36 Configuration = configuration;
10 office 37 _cancellationToken = cancellationToken;
14 office 38  
56 office 39 _spectrogramGenerator = new SpectrogramGenerator(Configuration.Visualizations.Spectrogram.SampleRate,
40 Configuration.Visualizations.Spectrogram.FftSamples,
41 Configuration.Visualizations.Spectrogram.FftSamples /
42 Configuration.Visualizations.Spectrogram.AudioBufferTimespan);
14 office 43 _spectrogramGenerator.Colormap = Colormap.Viridis;
44  
45 pictureBox2.Image = _spectrogramGenerator.GetVerticalScale(pictureBox2.Width);
10 office 46 }
47  
54 office 48 private Configuration.Configuration Configuration { get; }
49  
10 office 50 /// <summary>
54 office 51 /// Clean up any resources being used.
10 office 52 /// </summary>
53 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
54 protected override void Dispose(bool disposing)
55 {
54 office 56 if (disposing && components != null)
10 office 57 {
54 office 58 if (_waveIn != null)
10 office 59 {
54 office 60 if (_renderCancellationTokenSource != null) _renderCancellationTokenSource.Cancel();
10 office 61  
62 _waveIn.DataAvailable -= _waveIn_DataAvailable;
63 _waveIn.StopRecording();
64 _waveIn.Dispose();
65 _waveIn = null;
66 }
67  
68 components.Dispose();
69 }
54 office 70  
10 office 71 base.Dispose(disposing);
72 }
73  
74 private void SpectrogramForm_Load(object sender, EventArgs e)
75 {
59 office 76 Utilities.WindowState.FormTracker.Track(this);
77  
56 office 78 pinToDesktopToolStripMenuItem.Checked = Configuration.Visualizations.Spectrogram.PinToDesktop;
14 office 79  
56 office 80 if (Configuration.Visualizations.Spectrogram.PinToDesktop)
54 office 81 _windowZOrderScheduledContinuation.Schedule(TimeSpan.FromSeconds(1),
82 () =>
14 office 83 {
54 office 84 this.InvokeIfRequired(form =>
85 {
86 SetWindowPos(Handle, HwndBottom, 0, 0, Location.X, Location.Y,
87 SwpNomove | SwpNosize | SwpNoactivate);
88 });
89 }, _renderCancellationToken);
10 office 90  
91 foreach (var deviceNumber in Enumerable.Range(0, WaveIn.DeviceCount))
92 {
93 var capabilities = WaveIn.GetCapabilities(deviceNumber);
54 office 94 if (!string.Equals(capabilities.ProductName, Configuration.Audio.InputDeviceFriendlyName)) continue;
10 office 95  
96 _waveIn = new WaveIn();
97 _waveIn.DeviceNumber = deviceNumber;
56 office 98 _waveIn.BufferMilliseconds = Configuration.Visualizations.Spectrogram.AudioBufferTimespan;
10 office 99  
100 _waveIn.DataAvailable += _waveIn_DataAvailable;
101 _waveIn.StartRecording();
102 break;
103 }
104 }
105  
106 private void _waveIn_DataAvailable(object sender, WaveInEventArgs e)
107 {
54 office 108 var bytesPerSample = _waveIn.WaveFormat.BitsPerSample / 8;
109 var newSampleCount = e.BytesRecorded / bytesPerSample;
110 var buffer = new double[newSampleCount];
10 office 111 double peak = 0;
54 office 112 for (var i = 0; i < newSampleCount; i++)
10 office 113 {
114 buffer[i] = BitConverter.ToInt16(e.Buffer, i * bytesPerSample);
115 peak = Math.Max(peak, buffer[i]);
116 }
117  
54 office 118 var amplitudeFrac = peak / (1 << 15);
10 office 119  
120 _spectrogramGenerator.Add(buffer, false);
121 }
122  
123 private void timer1_Tick(object sender, EventArgs e)
124 {
54 office 125 if (_spectrogramGenerator.FftsToProcess == 0) return;
10 office 126  
127 _spectrogramGenerator.Process();
128 _spectrogramGenerator.SetFixedWidth(pictureBox1.Width);
54 office 129 var bmpSpec = new Bitmap(_spectrogramGenerator.Width, _spectrogramGenerator.Height,
130 PixelFormat.Format32bppPArgb);
131 using (var bmpSpecIndexed =
56 office 132 _spectrogramGenerator.GetBitmap(Configuration.Visualizations.Spectrogram.SpectrumIntensity))
10 office 133 using (var gfx = Graphics.FromImage(bmpSpec))
134 using (var pen = new Pen(Color.White))
135 {
136 gfx.DrawImage(bmpSpecIndexed, 0, 0);
137 if (false)
138 {
139 //gfx.DrawLine(pen, spec.NextColumnIndex, 0, spec.NextColumnIndex, pbSpectrogram.Height);
140 }
141 }
142  
143 pictureBox1.Image?.Dispose();
144 pictureBox1.Image = bmpSpec;
145 }
146  
147 private void SpectrogramForm_MouseClick(object sender, MouseEventArgs e)
148 {
54 office 149 switch (e.Button)
10 office 150 {
151 case MouseButtons.Right:
152 var control = (Control)sender;
153 var screenPoint = control.PointToScreen(e.Location);
154 contextMenuStrip1.Show(screenPoint);
155 break;
156 case MouseButtons.Left:
157 break;
158 }
159 }
160  
161 private void closeToolStripMenuItem_Click(object sender, EventArgs e)
162 {
163 Close();
164 }
165  
166 private void SpectrogramForm_MouseDown(object sender, MouseEventArgs e)
167 {
54 office 168 if (e.Button != MouseButtons.Left) return;
10 office 169  
54 office 170 if (e.Clicks != 1) return;
10 office 171  
172 _mouseDown = true;
173 _formLocation = new Point(e.X, e.Y);
174 }
175  
176 private void SpectrogramForm_MouseMove(object sender, MouseEventArgs e)
177 {
54 office 178 if (e.Button != MouseButtons.Left) return;
10 office 179  
54 office 180 if (!_mouseDown) return;
10 office 181  
182 var control = (Control)sender;
183 var screenPoint = control.PointToScreen(e.Location);
184  
185 Location = new Point(screenPoint.X - _formLocation.X, screenPoint.Y - _formLocation.Y);
186 }
187  
188 private void SpectrogramForm_MouseUp(object sender, MouseEventArgs e)
189 {
54 office 190 if (e.Button != MouseButtons.Left) return;
10 office 191  
192 _mouseDown = false;
193 }
194  
195 private void SpectrogramForm_Activated(object sender, EventArgs e)
196 {
197 // Make form bottom most.
198 //SetWindowPos(Handle, HWND_BOTTOM, 0, 0, Location.X, Location.Y, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
199 }
200  
201 private void SpectrogramForm_MouseEnter(object sender, EventArgs e)
202 {
56 office 203 if (Configuration.Visualizations.Spectrogram.PinToDesktop)
54 office 204 _windowZOrderScheduledContinuation.Schedule(TimeSpan.FromSeconds(1),
205 () =>
14 office 206 {
54 office 207 this.InvokeIfRequired(form =>
208 {
209 SetWindowPos(Handle, HwndTop, 0, 0, Location.X, Location.Y,
210 SwpNomove | SwpNosize | SwpNoactivate);
211 });
212 }, _renderCancellationToken);
10 office 213 }
214  
215 private void SpectrogramForm_MouseLeave(object sender, EventArgs e)
216 {
56 office 217 if (Configuration.Visualizations.Spectrogram.PinToDesktop)
54 office 218 _windowZOrderScheduledContinuation.Schedule(TimeSpan.FromSeconds(1),
219 () =>
14 office 220 {
54 office 221 this.InvokeIfRequired(form =>
222 {
223 SetWindowPos(form.Handle, HwndBottom, 0, 0, Location.X, Location.Y,
224 SwpNomove | SwpNosize | SwpNoactivate);
225 });
226 }, _renderCancellationToken);
10 office 227 }
14 office 228  
229 private void pinToDesktopToolStripMenuItem_CheckStateChanged(object sender, EventArgs e)
230 {
231 var toolStripMenuItem = (ToolStripMenuItem)sender;
232  
54 office 233 switch (toolStripMenuItem.CheckState)
14 office 234 {
235 case CheckState.Checked:
56 office 236 Configuration.Visualizations.Spectrogram.PinToDesktop = true;
14 office 237 break;
238 case CheckState.Unchecked:
56 office 239 Configuration.Visualizations.Spectrogram.PinToDesktop = false;
14 office 240 break;
241 }
242 }
54 office 243  
244 #region Natives
245  
246 [DllImport("user32.dll")]
247 private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy,
248 uint uFlags);
249  
250 private static readonly IntPtr HwndBottom = new IntPtr(1);
251 private static readonly IntPtr HwndTop = new IntPtr(0);
252 private const uint SwpNosize = 0x0001;
253 private const uint SwpNomove = 0x0002;
254 private const uint SwpNoactivate = 0x0010;
255  
256 #endregion
10 office 257 }
54 office 258 }