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 ...
随机推荐
- OPPO招聘-互联网测试
邮 箱:ljy@oppo.com 工作地点:深圳
- android framework 之JNI
Java Native Interface ( JN I)是Java本地接口,所谓的本地(native) —般是指C/C++ ( 以下统称C)语言.当使用Java进行程序设计时,一般主要有三种情况需要 ...
- Swift iOS实现把PCM语音转成MP3格式
最近折腾了swift的语音录制识别和转码,这块还是比较坑的,由于语音识别的准确度实测大概也就80%左右,所以还是需要上传录音文件啊.首先是用讯飞语音SDK实现语音录制和识别(语音听写),第一个坑是讯飞 ...
- nginx图片过滤处理模块http_image_filter_module安装配置
http_image_filter_module是nginx提供的集成图片处理模块,支持nginx-0.7.54以后的版本,在网站访问量不是很高磁盘有限不想生成多余的图片文件的前提下可,就可以用它实时 ...
- FPGA小白学习之路(1) System Verilog的概念以及与verilog的对比(转)
转自CSDN:http://blog.csdn.net/gtatcs/article/details/8970489 SystemVerilog语言简介 SystemVerilog是一种硬件描述和验证 ...
- Roma - Facebook工具链大一统
什么是roma roma,中文名罗马,是Facebook的rn团队的产出,是一个试验性质的javascript工具链,集编译,linter,格式化,打包,测试等等于一体.目标是成为一个处理javasc ...
- 用table类型布局一个新闻网页
<html><head><meta http-equiv="Content-Type" content="text/html; charse ...
- 前端每日实战:62# 视频演示如何用纯 CSS 创作一只蒸锅
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/YvOzNy 可交互视频 此视频是可 ...
- 基础JavaScript练习(一)总结
任务目的 在上一任务基础上继续JavaScript的体验 接触一下JavaScript中的高级选择器 学习JavaScript中的数组对象遍历.读写.排序等操作 学习简单的字符串处理操作 任务描述 参 ...
- java多线程之间的通信
目的 如何让两个线程依次执行? 那如何让 两个线程按照指定方式有序交叉运行呢? 四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的 三个运动员各 ...