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 ...
随机推荐
- C++走向远洋——60(项目四、立体类族共有的抽象类)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- 并查集(不相交集)的Remove操作
给并查集(不相交集)的添加一个\(Remove(X)\)操作,该操作把\(X\)从当前的集合中除去并把它放到自己的集合中. 实现思想 英文原句 We assume that the tree is i ...
- 史上最全Beyond Compare中文文档.CHM (根据官网整理编辑)
截图如下: 下载地址: 链接:https://pan.baidu.com/s/1Ml98_biT1leXxGLr9fqI_w 提取码:p8jg
- 【技巧】歪脑筋优化flexbox瀑布流布局方案
效果先行 需求 在大量"不定宽"元素并排的布局模式下,上图是我们想要的最佳布局但是FlexBox布局虽然枪弹但并不能完全呈现以上布局,于是我们需要结合FlexBox作下小的改动即可 ...
- 关于Js的那些面试题
1.javascript的typeof返回哪些数据类型 number string boolean Object function underfind 2.例举3种强制类型转换和2种隐式类型转换?强制 ...
- 【django】 接收所有文件,前端展示文件(包括视频,文件,图片)ajax请求
如果是后台上传文件: setting配置: STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ...
- 基于springcloud搭建项目-Ribbon篇(三)
这篇文章主要是介绍一下ribbon的用法,我们都知道ribbon是负载均衡,但是却不知道他是怎么样的负载均衡,怎么用,能干嘛? ● 其实,简单的说,Spring Cloud Ribbon是基于Netf ...
- 一次生产环境搭建11g RAC的记录
一.使用惠普3par工具配置共享存储 该部分可由惠普工作人员协助配置,只需将需求告知即可.如果想自己配置,惠普厂商会发送相关的软件工具以及操作手册给用户. 用putty登陆共享存储,使用showpd ...
- 误删除所有redo日志的一组成员的处理过程
系统中共有3个日志文件组,每个组中各有一个日志文件成员.往系统中添加一个日志文件组,组中日志文件成员数量是2.SQL> alter database add logfile group 4 (' ...
- RAC修改VIP地址
目录 当前环境 1.通过[srvctl config]确认当前VIP地址. 2.关闭dbconsole[对应的em] 3.关闭数据库实例 4.关闭asm实例 5.关闭结点服务 6.修改两个节点的/et ...