Skip to content

Commit b473d4c

Browse files
committed
添加了 readme, 稍微优化了下注释什么的
1 parent 5e74df3 commit b473d4c

6 files changed

Lines changed: 93 additions & 20 deletions

File tree

AudioVisualizer.sln

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfAudioVisualizer", "WpfAu
99
EndProject
1010
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibAudioVisualizer", "LibAudioVisualizer\LibAudioVisualizer.csproj", "{15A2D4B9-BD52-411F-96E9-2BFACFEC4579}"
1111
EndProject
12-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioVisualizerDx", "AudioVisualizerDx\AudioVisualizerDx.csproj", "{20B17F7E-11C3-4E46-9E79-DE9A3B25B640}"
12+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AudioVisualizerDx", "AudioVisualizerDx\AudioVisualizerDx.csproj", "{20B17F7E-11C3-4E46-9E79-DE9A3B25B640}"
13+
EndProject
14+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F54E0AE6-96AB-42EA-AFD1-37F1BCBAD304}"
15+
ProjectSection(SolutionItems) = preProject
16+
readme.md = readme.md
17+
EndProjectSection
1318
EndProject
1419
Global
1520
GlobalSection(SolutionConfigurationPlatforms) = preSolution

AudioVisualizer/MainWindow.cs

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ private Color[] GetAllHsvColors()
6969
}
7070

7171
/// <summary>
72-
///
72+
/// 当捕获有数据的时候, 就怼到可视化器里面
7373
/// </summary>
7474
/// <param name="sender"></param>
7575
/// <param name="e"></param>
@@ -223,6 +223,19 @@ private void DrawCurve(Graphics g, Pen pen, double[] spectrumData, int pointCoun
223223
g.DrawCurve(pen, points);
224224
}
225225

226+
/// <summary>
227+
/// 画简单的圆环线条
228+
/// </summary>
229+
/// <param name="g"></param>
230+
/// <param name="brush"></param>
231+
/// <param name="spectrumData"></param>
232+
/// <param name="stripCount"></param>
233+
/// <param name="xOffset"></param>
234+
/// <param name="yOffset"></param>
235+
/// <param name="radius"></param>
236+
/// <param name="spacing"></param>
237+
/// <param name="rotation"></param>
238+
/// <param name="scale"></param>
226239
private void DrawCircleStrips(Graphics g, Brush brush, double[] spectrumData, int stripCount, double xOffset, double yOffset, double radius, double spacing, double rotation, double scale)
227240
{
228241
double rotationAngle = Math.PI / 180 * rotation;
@@ -258,7 +271,7 @@ private void DrawCircleStrips(Graphics g, Brush brush, double[] spectrumData, in
258271
}
259272

260273
/// <summary>
261-
/// 画圆环条
274+
/// 画圆环渐变条
262275
/// </summary>
263276
/// <param name="g"></param>
264277
/// <param name="inner"></param>
@@ -312,20 +325,30 @@ private void DrawCircleGradientStrips(Graphics g, Color inner, Color outer, doub
312325
PointF outerP = new PointF((p3.X + p4.X) / 2, (p3.Y + p4.Y) / 2);
313326

314327
Vector2 offset = new Vector2(outerP.X - innerP.X, outerP.Y - innerP.Y);
315-
if (MathF.Sqrt(offset.X * offset.X + offset.Y * offset.Y) < 3)
328+
if (MathF.Sqrt(offset.X * offset.X + offset.Y * offset.Y) < 1) // 渐变笔刷两点之间距离不能太小
316329
continue;
317330

318331
try
319332
{
320-
LinearGradientBrush brush = new LinearGradientBrush(innerP, outerP, inner, outer);
321-
g.FillPolygon(brush, polygon);
322-
323-
brush.Dispose();
333+
using LinearGradientBrush brush = new LinearGradientBrush(innerP, outerP, inner, outer); // 这里有玄学 bug, 这个 线性笔刷会 OutMemoryException
334+
g.FillPolygon(brush, polygon); // 但是实际上不应该有这个异常...
324335
}
325336
catch { }
326337
}
327338
}
328339

340+
/// <summary>
341+
/// 画简单的线条
342+
/// </summary>
343+
/// <param name="g"></param>
344+
/// <param name="brush"></param>
345+
/// <param name="spectrumData"></param>
346+
/// <param name="stripCount"></param>
347+
/// <param name="drawingWidth"></param>
348+
/// <param name="xOffset"></param>
349+
/// <param name="yOffset"></param>
350+
/// <param name="spacing"></param>
351+
/// <param name="scale"></param>
329352
private void DrawStrips(Graphics g, Brush brush, double[] spectrumData, int stripCount, int drawingWidth, float xOffset, float yOffset, float spacing, double scale)
330353
{
331354
float stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
@@ -354,6 +377,15 @@ private void DrawStrips(Graphics g, Brush brush, double[] spectrumData, int stri
354377
}
355378
}
356379

380+
/// <summary>
381+
/// 画渐变的边框
382+
/// </summary>
383+
/// <param name="g"></param>
384+
/// <param name="inner"></param>
385+
/// <param name="outer"></param>
386+
/// <param name="area"></param>
387+
/// <param name="scale"></param>
388+
/// <param name="width"></param>
357389
private void DrawGradientBorder(Graphics g, Color inner, Color outer, Rectangle area, double scale, float width)
358390
{
359391
int thickness = (int)(width * scale);
@@ -394,25 +426,24 @@ private void DrawingTimer_Tick(object? sender, EventArgs e)
394426
Color color1 = allColors[colorIndex % allColors.Length];
395427
Color color2 = allColors[(colorIndex + 200) % allColors.Length];
396428

397-
double[] bassArea = Visualizer.TakeSpectrumOfFrequency(spectrumData, capture.WaveFormat.SampleRate, 250);
398-
double bassScale = bassArea.Average() * 100;
399-
double extraScale = Math.Min(drawingPanel.Width, drawingPanel.Height) / 6;
429+
double[] bassArea = Visualizer.TakeSpectrumOfFrequency(spectrumData, capture.WaveFormat.SampleRate, 250); // 低频区域
430+
double bassScale = bassArea.Average() * 100; // 低音导致的缩放 (比例数)
431+
double extraScale = Math.Min(drawingPanel.Width, drawingPanel.Height) / 6; // 低音导致的缩放 (乘上窗口大小)
400432

401433
Rectangle border = new Rectangle(Point.Empty, drawingPanel.Size);
402434

403435
BufferedGraphics buffer = BufferedGraphicsManager.Current.Allocate(drawingPanel.CreateGraphics(), drawingPanel.ClientRectangle);
404436
Graphics g = buffer.Graphics;
405437

406-
if (oldBuffer != null)
407-
{
408-
oldBuffer.Render(buffer.Graphics);
409-
oldBuffer.Dispose();
410-
}
438+
//if (oldBuffer != null) // 如果你想要实现 "留影" 效果, 就取消注释这段代码, 并且将 g.Clear 改为 g.FillRectange(xxx, 半透明的黑色)
439+
//{
440+
// oldBuffer.Render(buffer.Graphics);
441+
// oldBuffer.Dispose();
442+
//}
411443

412-
using Pen pen = new Pen(Color.Pink);
413-
using Brush brush = new SolidBrush(Color.Purple);
444+
using Pen pen = new Pen(Color.Pink); // 画音频采样波形用的笔
414445

415-
g.SmoothingMode = SmoothingMode.HighQuality;
446+
g.SmoothingMode = SmoothingMode.HighQuality; // 嗨嗨害, 那必须得是高质量绘图
416447
g.Clear(drawingPanel.BackColor);
417448

418449
DrawGradientBorder(g, Color.FromArgb(0, color1), color2, border, bassScale, drawingPanel.Width / 10);
@@ -423,7 +454,7 @@ private void DrawingTimer_Tick(object? sender, EventArgs e)
423454

424455
buffer.Render();
425456

426-
oldBuffer = buffer;
457+
oldBuffer = buffer; // 保存一下 buffer (之所以不全局只使用一个 Buffer 是因为,,, 用户可能调整窗口大小, 所以每一帧都必须适应)
427458
}
428459

429460
private void MainWindow_Load(object sender, EventArgs e)

readme.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# 音频可视化器 / AudioVisualizer
2+
3+
分别在 GDI+ 和 Direct2D(SharpDX) 上实现了音频可视化 \
4+
Audio visualization on GDI+ and Direct2D (SharpDX) respectively
5+
6+
你可以学到: 如何实现音频可视化, 如何使用 SharpDX 进行 2D 绘图 \
7+
You can learn: how to implement audio visualization, how to use SharpDX for 2D drawing
8+
9+
![preview](res/preview1.png)
10+
11+
## 主要逻辑 / Main logic
12+
13+
### 音频可视化 / Audio visualization
14+
15+
- 每一帧对旧数据和新数据进行 "渐变", 值不会立即更新为新值, 而是更新为两值的中间值, 也就是说, 每一次刷新, 数据只会 "移动" 一定比例 \
16+
Each frame do lerp operation between the old data and the new data, the value is not updated to the new value immediately, but is updated to the intermediate value of the two values, that is, each refresh, the data will only "move" a certain percentage
17+
- 加个窗函数, 遮盖住低频与高频, 主要展示中间频率 \
18+
Add a window function to cover the low frequency and high frequency, mainly showing the middle frequency
19+
- 将低频区域的值取出来, 单独用来做 "低音" 的视觉效果 \
20+
Take out the value of the low-frequency area and use it separately for the visual effect of "bass"
21+
22+
### WinForm
23+
24+
- 使用 WinForm 的 Timer 实现在单线程的定时频谱数据获取以及界面刷新 \
25+
Using WinForm's Timer to achieve timed spectrum data acquisition and interface refresh in a single thread
26+
27+
### GDI+
28+
29+
- 使用 BufferedGraphics 使绘制时不会闪屏 \
30+
Use BufferedGraphics to draw without flickering
31+
32+
## Enjoy
33+
34+
代码注释很完善, 所以, 学起来呀~ \
35+
The code comments are very perfect, so let's just learn it~
36+
37+
![code](res/code.png)

res/code.png

1.2 MB
Loading

res/preview1.png

101 KB
Loading

res/preview2.png

97.3 KB
Loading

0 commit comments

Comments
 (0)