C# NAudio录音和播放音频文件及实时绘制音频波形图(从音频流数据获取,而非设备获取)
下午写了一篇关于NAudio的录音、播放和波形图的博客,不太满意,感觉写的太乱,又总结了下
NAudio是个相对成熟、开源的C#音频开发工具,它包含录音、播放录音、格式转换、混音调整等功能。本次介绍主要功能有音频、录音文件播放、实时音频流波形图显示等。具体如下:
1. 录音
NAudio录音主要使用WaveIn和WaveFileWriter两个类
1.1 WaveIn
WaveIn的功能是对录音的音频参数进行设置以及对数据的采集,参数如通道数、采样率、平均数据传输速率(WaveFormat)、数据回调事件、录音停止回调函数等参数
其中,DataAvailable为数据回调参数,是在录音时实时将录音数据传递出来,有需要使用录音数据的可以订阅该事件进行接收业务和相关处理。
1.2 WaveFileWriter
该类是创建相对应格式的音频文件,并提供想对应的写入数据方法、保存方法等,具体如下:
public class WaveFileWriter : Stream
{
public WaveFileWriter(Stream outStream, WaveFormat format);
public WaveFileWriter(string filename, WaveFormat format); ~WaveFileWriter(); public override long Position { get; set; }
public override bool CanWrite { get; }
public override bool CanRead { get; }
public WaveFormat WaveFormat { get; }
public TimeSpan TotalTime { get; }
public override long Length { get; }
public string Filename { get; }
public override bool CanSeek { get; } public static void CreateWaveFile(string filename, IWaveProvider sourceProvider);
public static void CreateWaveFile16(string filename, ISampleProvider sourceProvider);
public static void WriteWavFileToStream(Stream outStream, IWaveProvider sourceProvider);
public override void Flush();
public override int Read(byte[] buffer, int offset, int count);
public override long Seek(long offset, SeekOrigin origin);
public override void SetLength(long value);
public override void Write(byte[] data, int offset, int count);
[Obsolete("Use Write instead")]
public void WriteData(byte[] data, int offset, int count);
[Obsolete("Use WriteSamples instead")]
public void WriteData(short[] samples, int offset, int count);
public void WriteSample(float sample);
public void WriteSamples(short[] samples, int offset, int count);
public void WriteSamples(float[] samples, int offset, int count);
protected override void Dispose(bool disposing);
protected virtual void UpdateHeader(BinaryWriter writer);
}
在调用上是先调用WaveIn的DataAvailable回调函数,读取其数据并写入流文件,最后保存到本地。
2. 播放录音
播放录音主要用到AudioFileReader、WaveOut三个类和接口
2.1 AudioFileReader
AudioFileReader主要负责读取音频文件,验证音频文件格式,对外部提供读取数据接口,具体如下:
public class AudioFileReader : WaveStream, ISampleProvider
{
public AudioFileReader(string fileName); public string FileName { get; }
public override WaveFormat WaveFormat { get; }
public override long Length { get; }
public override long Position { get; set; }
public float Volume { get; set; } public override int Read(byte[] buffer, int offset, int count);
public int Read(float[] buffer, int offset, int count);
protected override void Dispose(bool disposing);
}
2.2 WaveOut
WaveOut的工作是播放音频,它调用AudioFileReader.Read进行数据读取,对读取的数据进行播放,主要工作流程是从获取数据,并将数据进行播放成音频
public class WaveOut : IWavePlayer, IDisposable, IWavePosition
{
public WaveOut();
public WaveOut(IntPtr windowHandle);
public WaveOut(WaveCallbackInfo callbackInfo); ~WaveOut(); public static int DeviceCount { get; }
public PlaybackState PlaybackState { get; }
public WaveFormat OutputWaveFormat { get; }
public int DeviceNumber { get; set; }
public int NumberOfBuffers { get; set; }
public int DesiredLatency { get; set; }
public float Volume { get; set; } public event EventHandler<StoppedEventArgs> PlaybackStopped; public static WaveOutCapabilities GetCapabilities(int devNumber);
public void Dispose();
public long GetPosition();
public void Init(IWaveProvider waveProvider);
public void Pause();
public void Play();
public void Resume();
public void Stop();
protected void Dispose(bool disposing);
}
3. 波形图绘制
录音时绘制波形图需要在DataAviliable回调函数中获取音频数据并将其从byte[]转换为float[],然后用float[]数据做为波形图的输入即可,这个过程源码上写一个数据包的波形图数据为waveSource.WaveFormat.SampleRate / 100,原理上我还没搞懂,但是的确是这么操作显示是对的,具体如下:
private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
{
if (waveFile != null)
{
waveFile.Write(e.Buffer, , e.BytesRecorded);
waveFile.Flush(); float[] sts = new float[e.Buffer.Length / ];
int outIndex = ;
for (int n = ; n < e.Buffer.Length; n += )
{
sts[outIndex++] = BitConverter.ToInt16(e.Buffer, n) / 32768f;
} for (int n = ; n < sts.Length; n += channels)
{
Add(sts[n]);
}
}
}
需要注意的是WaveFormat的通道数设置、PCM的格式设置,上述代码都是基于通道数为2、PCM为16bit的情况下,如这两项修改会发生转换和调用失败等问题
可调试Demo:示例Demo
C# NAudio录音和播放音频文件及实时绘制音频波形图(从音频流数据获取,而非设备获取)的更多相关文章
- C# NAudio录音和播放音频文件-实时绘制音频波形图(从音频流数据获取,而非设备获取)
NAudio的录音和播放录音都有对应的类,我在使用Wav格式进行录音和播放录音时使用的类时WaveIn和WaveOut,这两个类是对功能的回调和一些事件触发. 在WaveIn和WaveOut之外还有对 ...
- 解析WAV音频文件----》生成WAV音频文件头
前言:请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i WAV音频文件介绍: WAV文件是在PC机平台上很常见的.最经典的多媒体音频文件,最早于1991年8月出现在Windows3.1操作系统 ...
- iOS中音频的录制与播放(本地音频文件的播放)
iOS功能开发涉及到音频处理时,最常见的时进行录音,以及音频文件的播放.停止播放等的操作.在开发中还要避免同一个音频文件,或不同音频文件之间的处理,比如说正在播放A音频时,可以停止播放A音频,也可以播 ...
- 将音频文件转二进制分包存储到Redis(奇淫技巧操作)
功能需求: 一.获取本地音频文件,进行解析成二进制数据音频流 二.将音频流转化成byte[]数组,按指定大小字节数进行分包 三.将音频流分成若干个包,以List列表形式缓存到redis数据库中 四.从 ...
- 浏览器音频兼容和ffmpeg的音频转码使用
浏览器对各音/视频格式的支持问题 浏览器测试效果图 ffmpeg在音频格式转换,和从视频中提取音频的简单实用 1.百度搜索浏览器对于音频文件的兼容,排在前面的文章大部分是复制粘贴很久以前的文章,容易误 ...
- C# 录音和播放录音-NAudio
在使用C#进行录音和播放录音功能上,使用NAudio是个不错的选择. NAudio是个开源,相对功能比较全面的类库,它包含录音.播放录音.格式转换.混音调整等操作,具体可以去Github上看看介绍和源 ...
- S3C2416裸机开发系列19_Fatfs播放录像wav音频文件
S3C2416裸机开发系列19 Fatfs播放录像wav音频文件 国际象棋男孩 1048272975 多媒体资源,一般都是以文件的形式存储在固化存储器中.Fatfs所支持的fat32为windo ...
- IOS音频1:之采用四种方式播放音频文件(一)AudioToolbox AVFoundation OpenAL AUDIO QUEUE
本文转载至 http://blog.csdn.net/u014011807/article/details/40187737 在本卷你可以学到什么? 采用四种方法设计应用于各种场合的音频播放器: 基于 ...
- VC++中MCI播放音频文件 【转】
MCI播放mp3音频文件例程 源文件中需要包含头文件 Mmsystem.h,在Project->Settings->Link->Object/libray module中加入库 Wi ...
随机推荐
- 为什么我们要让人工智能玩游戏:微软Project AIX
<我的世界>游戏 2016年7月注:Project AIX已正式更名为Project Malmo 注:本文编译自Project AIX: Using Minecraft to build ...
- 初学qt——提示窗体
带选择的窗体 QMessageBox::StandardButton rb = QMessageBox::critical(NULL, QString::fromLocal8Bit("提示& ...
- Git私服搭建
Git私服搭建 一.Git服务器搭建方式 GIT是一个分布式版本管理系统,既然是分布那么必定会涉及远程通信,那么GIT是采用什么协议进行远程通信? Git支持的四种通信协议: Local(本地协议) ...
- 简单的员工管理系统(Mysql+jdbc+Servlet+JSP)
员工管理系统 因为学业要求,需要完成一个过关检测,但是因为检测之前没有做好准备,且想到之前用mysql+jdbc+Struts2+bootstrap做成了一个ATM系统(主要有对数据的增删改查操作), ...
- python 实现各种进度条
1. 时间进度条 class Tiao(object): def __init__(self): self.obj1 = datetime.timedelta(seconds=1) self.var ...
- CentOS 7 国内源配置
CentOS 7 国内源配置 1. 备份自带源 # 首先要确认你有 wget 命令, 并且连着网 # cd /etc/yum.repos.d/ # mkdir repo # mv *.repo rep ...
- SPA那点事
前端猿一天不学习就没饭吃了,后端猿三天不学习仍旧有白米饭摆于桌前.IT行业的快速发展一直在推动着前端技术栈在不断地更新换代,前端的发展成了互联网时代的一个缩影.而单页面应用的发展给前端猿分了一杯羹. ...
- JS基础入门篇(十二)—JSON和Math
1.JSON JSON: 对象格式的字符串 轻量的数据传输格式 注意事项: 键名 需要 使用 双引号 包起来 JOSN有两个方法:JSON.parse和 JSON.stringify. JSON.pa ...
- [LeetCode] 207. Course Schedule 课程表
题目: 分析: 这是一道典型的拓扑排序问题.那么何为拓扑排序? 拓扑排序: 有三件事情A,B,C要完成,A随时可以完成,但B和C只有A完成之后才可完成,那么拓扑排序可以为A>B>C或A&g ...
- 内存:你跑慢点行不行?CPU:跑慢点你养我吗?内存:我不管!(内附超全思维导图)
主存(RAM) 是一件非常重要的资源,必须要认真对待内存.虽然目前大多数内存的增长速度要比 IBM 7094 要快的多,但是,程序大小的增长要比内存的增长还快很多.不管存储器有多大,程序大小的增长速度 ...