由于项目需要音频波形显示,所以仿照 Cool Edit 实现一个简易的音频播放器。

部分代码参考:GitHub - naudio/NAudio.WaveFormRenderer: Simple utility to render waveforms of audio files in various styles using System.Drawing

效果图

*(空格键播放选中区域)

核心代码

using System;
using System.Drawing;
using System.Windows.Forms;namespace JAudioWave
{public partial class JAudioWave : UserControl{private Pen gridPen;private Pen topPeakPen;private Pen bottomPeakPen;private MaxPeakProvider _maxPeakProvider;private WaveAudioRendererSettings _settings;private bool isMouseDown = false;private bool isStartMove = false;private int moveStartX = 0; // 每一次滑动蕲艾private int gStartX = 0; // 音频区域起点private int gEndX = 0; // 音频区域终点private int direction = 0; // 0:反方向 1:正方向public Action<int, int> OnSelectedAudioArea;public JAudioWave(){SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);// 不闪烁 支持双缓存InitializeComponent();init();}private void init(){initPen();TopHeight = 150;BottomHeight = 150;_maxPeakProvider = new MaxPeakProvider();}private void initPen(){gridPen = new Pen(Color.FromArgb(18, 59, 40));topPeakPen = new Pen(Color.FromArgb(75, 243, 167));bottomPeakPen = new Pen(Color.FromArgb(75, 243, 167));}private WaveAudioRendererSettings getSettings(){if (_settings != null)return _settings;_settings = new WaveAudioRendererSettings();_settings.TopHeight = TopHeight;_settings.BottomHeight = BottomHeight;_settings.Width = this.Width;_settings.TopPeakPen = topPeakPen;_settings.BottomPeakPen = bottomPeakPen;return _settings;}protected override void OnPaint(PaintEventArgs e){Console.WriteLine("OnPaint");base.OnPaint(e);draw(e.Graphics);//_maxPeakProvider.ResetPeakInfoStatus();}private void draw(Graphics g){// 背景WaveAudioRendererSettings settings = getSettings();g.FillRectangle(settings.BackgroundBrush, 0, 0, this.Width, this.Height);// 网格drawGraid(g, this.Width, this.Height);// 波形var midPoint = settings.TopHeight;int x = 0;WavePeakInfo currentPeak = _maxPeakProvider.GetPeakInfo(x);if (currentPeak == null)return;while (x < settings.Width){WavePeakInfo nextPeak = _maxPeakProvider.GetPeakInfo(x);for (int n = 0; n < settings.PixelsPerPeak; n++){float lineHeight = settings.TopHeight * currentPeak.Max;g.DrawLine(settings.TopPeakPen, x, midPoint, x, midPoint - lineHeight);lineHeight = settings.BottomHeight * currentPeak.Min;g.DrawLine(settings.BottomPeakPen, x, midPoint, x, midPoint - lineHeight);x++;}for (int n = 0; n < settings.SpacerPixels; n++){float max = Math.Min(currentPeak.Max, nextPeak.Max);float min = Math.Max(currentPeak.Min, nextPeak.Min);float lineHeight = settings.TopHeight * max;g.DrawLine(settings.TopSpacerPen, x, midPoint, x, midPoint - lineHeight);lineHeight = settings.BottomHeight * min;g.DrawLine(settings.BottomSpacerPen, x, midPoint, x, midPoint - lineHeight);x++;}currentPeak = nextPeak;}drawRect(g, gEndX - gStartX, this.Height, gStartX, gEndX);}public void drawGraid(Graphics g, int width, int height){//垂直for (int i = 0; i < width;){g.DrawLine(gridPen, new Point(i, 0), new Point(i, width));i += 45;}//水平for (int j = 0; j < height;){g.DrawLine(gridPen, new Point(0, j), new Point(width, j));j += 45;}}private void drawSelectRect(int startX, int endX){Graphics g = Graphics.FromHwnd(this.Handle);drawRect(g, endX - startX, this.Height, startX, endX);}private void drawRect(Graphics g, int width, int height, int startX, int endX){if (direction == 0) // 反方向{if (startX < endX){#region 反向int diff = endX - startX;WaveAudioRendererSettings settings = getSettings();g.FillRectangle(settings.BackgroundBrush, startX, 0, diff, this.Height);int num = startX / 45;int a = startX % 45;int start = a == 0 ? num * 45 : num * 45 + 45;//Pen myPen = new Pen(Color.FromArgb(10, 215, 221, 224));Pen myPen = new Pen(Color.DarkBlue);//垂直for (int i = start; i < endX;){g.DrawLine(gridPen, new Point(i, 0), new Point(i, height));i += 45;}if (diff > 0){//水平for (int j = 0; j < height;){g.DrawLine(gridPen, new Point(startX, j), new Point(endX - 1, j));j += 45;}}//水平//for (int j = 0; j < height;)//{//    g.DrawLine(gridPen, new Point(startX, j), new Point(endX, j));//    j += 45;//}WavePeakInfo currentPeak = _maxPeakProvider.GetPeakInfo(startX);if (currentPeak == null)return;var midPoint = settings.TopHeight;for (int x = startX; x < endX; x++){WavePeakInfo nextPeak = _maxPeakProvider.GetPeakInfo(x);Pen _p = new Pen(Color.FromArgb(18, 59, 40));if (nextPeak.IsSelected){_p = topPeakPen;}else{_p = new Pen(Color.FromArgb(18, 59, 40));}var lineHeight = settings.TopHeight * currentPeak.Max;g.DrawLine(topPeakPen, x, midPoint, x, midPoint - lineHeight);lineHeight = settings.BottomHeight * currentPeak.Min;g.DrawLine(topPeakPen, x, midPoint, x, midPoint - lineHeight);//_maxPeakProvider.UpdatePeakInfoStatus(x);currentPeak = nextPeak;}#endregion}else{int diff = startX - endX;Rectangle rect = new Rectangle();rect.Width = diff;rect.Height = height;rect.Location = new Point(endX, 0);SolidBrush mysbrush1 = new SolidBrush(Color.FromArgb(180, 238, 238, 247));g.FillRectangle(mysbrush1, rect);}}else // 正方向{if (startX > endX){#region 反向int diff = startX - endX;WaveAudioRendererSettings settings = getSettings();g.FillRectangle(settings.BackgroundBrush, endX, 0, diff, this.Height);int num = endX / 45;int a = endX % 45;int start = a == 0 ? num * 45 : num * 45 + 45;Pen myPen = new Pen(Color.DarkBlue);//垂直for (int i = start; i < startX;){g.DrawLine(gridPen, new Point(i, 0), new Point(i, height));i += 45;}if (diff > 0){//水平for (int j = 0; j < height;){g.DrawLine(gridPen, new Point(endX, j), new Point(startX - 1, j));j += 45;}}WavePeakInfo currentPeak = _maxPeakProvider.GetPeakInfo(endX);if (currentPeak == null)return;var midPoint = settings.TopHeight;for (int x = endX; x < startX; x++){WavePeakInfo nextPeak = _maxPeakProvider.GetPeakInfo(x);Pen _p = new Pen(Color.FromArgb(18, 59, 40));if (nextPeak.IsSelected){_p = topPeakPen;}else{_p = new Pen(Color.FromArgb(18, 59, 40));}var lineHeight = settings.TopHeight * currentPeak.Max;g.DrawLine(topPeakPen, x, midPoint, x, midPoint - lineHeight);lineHeight = settings.BottomHeight * currentPeak.Min;g.DrawLine(topPeakPen, x, midPoint, x, midPoint - lineHeight);//_maxPeakProvider.UpdatePeakInfoStatus(x);currentPeak = nextPeak;}#endregion}else{int diff = endX - startX;Rectangle rect = new Rectangle();rect.Width = diff;rect.Height = height;rect.Location = new Point(startX, 0);SolidBrush mysbrush1 = new SolidBrush(Color.FromArgb(180, 238, 238, 247));g.FillRectangle(mysbrush1, rect);}}}public void refresh(){gStartX = 0;gEndX = 0;this.Refresh();}public int TopHeight { get; set; }public int BottomHeight { get; set; }public int Bit { get; set; }private void JAudioWave_MouseDown(object sender, MouseEventArgs e){refresh();isMouseDown = true;string x = e.X.ToString(); //x坐标string y = e.Y.ToString(); //Y坐标moveStartX = e.X;gStartX = e.X;isStartMove = true;}private void JAudioWave_MouseMove(object sender, MouseEventArgs e){if (!isMouseDown)return;string x = e.X.ToString(); //x坐标string y = e.Y.ToString(); //Y坐标if (isStartMove){direction = moveStartX > e.X ? 0 : 1;isStartMove = false;}drawSelectRect(moveStartX, e.X);moveStartX = e.X;}private void JAudioWave_MouseUp(object sender, MouseEventArgs e){if (!isMouseDown)return;isMouseDown = false;gEndX = e.X;if (OnSelectedAudioArea != null && gStartX != gEndX){int sx = gStartX;int ex = gEndX;if (direction == 0){sx = gEndX;ex = gStartX;}else{sx = gStartX;ex = gEndX;}OnSelectedAudioArea.BeginInvoke(_maxPeakProvider.GetSize(sx), _maxPeakProvider.GetSize(ex), null, null);}}private void JAudioWave_Load(object sender, EventArgs e){}// ============================ 对外接口 ===========================================public void LoadAudio(string file, int bitsPerSample){gStartX = 0;gEndX = 0;WaveAudioRendererSettings settings = getSettings();_maxPeakProvider.Init(bitsPerSample, file);_maxPeakProvider.Load(settings);}}}

功能

  1. 加载音频,显示出音频波形
  2. 左右滑动鼠标选择区域,空格键播放选中区域音频。

TODO

  1. 来回滑动, 波形存在细微变动,暂未找到原因。
  2. 滑动过快, 波形容易造成短暂异常。
  3. 音频播放通过系统api接口简单实现(将选中区域保存本地,来进行播放),有待改善。

*** 以上1.2 问题, 如有大侠解决,望指导一二,不胜感激。

原版 cool edit 效果图

**  哪位大侠能实现这个效果,也希望能共享下。不胜感激。(可左右来回滑动来选择区域,而且不卡顿.)

完整demo  仿照CoolEdit样式,绘制音频波形图-互联网文档类资源-CSDN下载


C# 参考 cool edit 样式, 绘制音频波形图相关推荐

  1. c语言编程绘制动态波形,绘制wav波形图

    注:本文为原创,转载请注明出处.来自CSDN,作者:Midfar Sun 最近研究了如何在iOS上绘制wav波形图.查了很多资料,都没能找到一个很完整的介绍,我这里总结一下一些经验. 首先需要了解wa ...

  2. 将串口接收的数据绘制成波形图(使用matlab或Visual Scope)

    一. 串口通信配置 结合stm32固件库(或其它类型单片机)中usart相关的函数,配置好串口通信的寄存器,确定(数据位.停止位.波特率等等),本文主要介绍两种方法将采集到的串口数据绘制成波形图. 二 ...

  3. OpenGL 绘制音频波形

    一.音频采样数据的获取 二 .音频采样数据的处理 三.使用OpenGL来绘制波形 3.1 准备三种方法的音频采样数据 3.2 绘制音频波形   在音视频编辑软件中直观的看到一个素材的音频波形后,就可以 ...

  4. Audacity Mac版教程,使用Audacity编辑音频波形图的方法步骤

    Audacity是一个免费的录音机/编辑/混音器.您可以录制声音,播放声音,导入和导出WAV,AIFF和MP3文件等等.使用剪切,复制和粘贴(无限撤销)编辑您的声音,混合曲目,或将效果应用到您的录音. ...

  5. Python-Matplotlib可视化(3)——自定义样式绘制精美统计图

    Python-Matplotlib可视化(3)--自定义样式绘制精美统计图 前言 控制线条样式和线宽 线条样式 线宽 控制填充样式 控制标记样式 控制标记大小 创建自定义标记 总结--对标记进行更精细 ...

  6. matlab读取wav,播放wav,绘制语音波形图

    1.读取wav [x,fs] = audioread(' 000.wav');% fs为采样频率 2.播放wav sound(x,fs); 3.以时间为横坐标,绘制语音波形图 subplot(2,1, ...

  7. wpf 音频波形图_wpf波形图 - IT屋-程序员软件开发技术分享社区

    我正在使用.net WPF几何图形类来绘制波形图.我一直在使用矩阵变换将屏幕坐标空间转换为波形的坐标空间.一切都很好,而且跟踪窗口和缩放比例等非常简单.我什至可以使用逆变换来根据坐标空间计算鼠标位置. ...

  8. Wavesurfer.js 生成音频波形图

    Wavesurfer.js 生成音浪波形图 (vue) 代码如下,可直接复制 <template><div class="mixin-components-containe ...

  9. 导出期刊对应格式的参考_EndNote 输出样式模板(根据国家标准制订)

    1. 模板下载 请注意:这个模板输出的参考文献格式为按照引用在文中的出现顺序以数字编号的形式,例如: [1] 作者. 文章名称...... [2] ...... 附件是压缩文件,下载后请解压,里面名为 ...

最新文章

  1. 【Network Security!】IP地址详解(看不懂你来打我)
  2. Python matplotlib 和PIL
  3. TensorFlow 教程——基本分类:对服装图像进行分类
  4. 快速傅立叶变换(FFT)的海面模拟
  5. 外部数据源的使用汇总
  6. ORA-02290:违反检查约束条件(sys_c0011321)什么原因
  7. java证书验证失败_Java 跳过 HTTPS 请求过程中证书验证问题
  8. Eclipse添加JBOSS支持
  9. 人是中国开源产业发展的战略制高点
  10. 深入思考内积运算,再看傅里叶系数、伽辽金法本质
  11. win7/win10 密码忘了?没关系,利用5次shift,9步轻松破解密码
  12. 《智慧城市》顶层设计解读
  13. 网站SEO优化中tilte与h1的区别、b与strong的区别、i与em的区别
  14. String 源码浅析————终结篇
  15. linux服务器如何查看mac地址,linux如何查看mac地址_查看mac地址 linux_linux查看mac地址...
  16. GPU和CPU芯片区别:为何要用GPU挖矿?
  17. python3小说爬虫之起点女生网
  18. 群晖Docker配置阿里云国际域名DDNS实现外网访问
  19. 博达工业云与阿里云对比
  20. QT 系列博客:为什么要用QT?

热门文章

  1. Linux的top命令详解
  2. 微信支付结算费率怎么降低至0.2~0.35操作方法
  3. 自然语言处理研究报告
  4. 学ajax要学php吗,javascript – Ajax新手学习(PHP JQuery)
  5. HTML 打印table分页
  6. 利用js制作html table分页示例(js实现分页)
  7. C# CultureInfo列表
  8. GC finalize方法
  9. jQuery功能简述
  10. MYSQL 按名字分组查询最好成绩