C#中使用WavHelper保存录音数据为wav文件
C#将录音数据文件保存为wav格式文件,这里使用到的是WavHelper工具类。
WavHelper工具类:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace WavHelperTool
{
/// <summary>
/// 生成wav文件的帮助类,本类来自网络,作者不详
/// </summary>
public class WavHelper : IDisposable
{
#region 变量
private MyWaveFormat mWavFormat;
private int mSampleCount = 0;
private string mFileName = "";
private FileStream mWaveFile = null;
private BinaryWriter mWriter = null;
private int _sampleRate = 0;
private short _channels = 0;
private string _filePath = "";
#endregion public WavHelper(string audioFileName, int sampleRate, short channels)
{
_filePath = audioFileName;
_sampleRate = sampleRate;
_channels = channels;
this.mFileName = audioFileName;
mWavFormat = new MyWaveFormat();
mWavFormat.SamplesPerSecond = _sampleRate;
mWavFormat.BitsPerSample = 16;
mWavFormat.Channels = _channels;
mWavFormat.BlockAlign = (short)(mWavFormat.Channels * (mWavFormat.BitsPerSample / 8));
mWavFormat.AverageBytesPerSecond = mWavFormat.BlockAlign * mWavFormat.SamplesPerSecond;
Start();
} /// <summary>
/// 存放的录音文件路径
/// </summary>
public string FilePath
{
get { return _filePath; }
} public void Dispose()
{
Stop();
} /// <summary>
/// 结束写入并关闭文件
/// </summary>
private void Stop()
{
// 写WAV文件尾
mWriter.Seek(4, SeekOrigin.Begin);
mWriter.Write((int)(mSampleCount + 36));
mWriter.Seek(40, SeekOrigin.Begin);
mWriter.Write(mSampleCount); mWriter.Close();
mWaveFile.Close();
mWriter = null;
mWaveFile = null;
} /// <summary>
/// 创建保存的波形文件,并写入必要的文件头.
/// </summary>
private void Start()
{
// Open up the wave file for writing.
mWaveFile = new FileStream(mFileName, FileMode.Create);
mWriter = new BinaryWriter(mWaveFile);
/**************************************************************************
Here is where the file will be created. A
wave file is a RIFF file, which has chunks
of data that describe what the file contains.
A wave RIFF file is put together like this:
The 12 byte RIFF chunk is constructed like this:
Bytes 0 - 3 : 'R' 'I' 'F' 'F'
Bytes 4 - 7 : Length of file, minus the first 8 bytes of the RIFF description.
(4 bytes for "WAVE" + 24 bytes for format chunk length +
8 bytes for data chunk description + actual sample data size.)
Bytes 8 - 11: 'W' 'A' 'V' 'E'
The 24 byte FORMAT chunk is constructed like this:
Bytes 0 - 3 : 'f' 'm' 't' ' '
Bytes 4 - 7 : The format chunk length. This is always 16.
Bytes 8 - 9 : File padding. Always 1.
Bytes 10- 11: Number of channels. Either 1 for mono, or 2 for stereo.
Bytes 12- 15: Sample rate.
Bytes 16- 19: Number of bytes per second.
Bytes 20- 21: Bytes per sample. 1 for 8 bit mono, 2 for 8 bit stereo or 16 bit mono, 4 for 16 bit stereo.
Bytes 22- 23: Number of bits per sample.
The DATA chunk is constructed like this:
Bytes 0 - 3 : 'd' 'a' 't' 'a'
Bytes 4 - 7 : Length of data, in bytes.
Bytes 8 -: Actual sample data.
***************************************************************************/
// Set up file with RIFF chunk info.
char[] ChunkRiff = { 'R', 'I', 'F', 'F' };
char[] ChunkType = { 'W', 'A', 'V', 'E' };
char[] ChunkFmt = { 'f', 'm', 't', ' ' };
char[] ChunkData = { 'd', 'a', 't', 'a' }; short shPad = 1; // File padding
int nFormatChunkLength = 0x10; // Format chunk length.
int nLength = 0; // File length, minus first 8 bytes of RIFF description. This will be filled in later.
short shBytesPerSample = 0; // Bytes per sample. // 一个样本点的字节数目
if (8 == mWavFormat.BitsPerSample && 1 == mWavFormat.Channels)
shBytesPerSample = 1;
else if ((8 == mWavFormat.BitsPerSample && 2 == mWavFormat.Channels) || (16 == mWavFormat.BitsPerSample && 1 == mWavFormat.Channels))
shBytesPerSample = 2;
else if (16 == mWavFormat.BitsPerSample && 2 == mWavFormat.Channels)
shBytesPerSample = 4; // RIFF 块
mWriter.Write(ChunkRiff);
mWriter.Write(nLength);
mWriter.Write(ChunkType); // WAVE块
mWriter.Write(ChunkFmt);
mWriter.Write(nFormatChunkLength);
mWriter.Write(shPad);
mWriter.Write(mWavFormat.Channels);
mWriter.Write(mWavFormat.SamplesPerSecond);
mWriter.Write(mWavFormat.AverageBytesPerSecond);
mWriter.Write(shBytesPerSample);
mWriter.Write(mWavFormat.BitsPerSample); // 数据块
mWriter.Write(ChunkData);
mWriter.Write((int)0); // The sample length will be written in later.
} /// <summary>
/// 每当采集到音频数据时,将其写入
/// </summary>
/// <param name="data"></param>
public void WriteAudioData(byte[] data)
{
mWriter.Write(data, 0, data.Length);
mSampleCount += data.Length;
}
} public class MyWaveFormat
{
/// <summary>
/// 采样率
/// </summary>
public int SamplesPerSecond; /// <summary>
/// 采样位数
/// </summary>
public short BitsPerSample; /// <summary>
/// 通道数
/// </summary>
public short Channels; /// <summary>
/// 单位采样点的字节数
/// </summary>
public short BlockAlign; /// <summary>
/// 每秒平均码率
/// </summary>
public int AverageBytesPerSecond;
}
}
C#保存调用:
//1、定义wav文件生成类
private WavHelper microphoneWav = null; //2、初始化麦克风数据wav文件写入器
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "microphone.wav");//根目录下生成microphone.wav
microphoneWav = new WavHelper(path, sampleRate, channelCount);//保存路径、采样率、频道数 //3、数据写入wav文件中
byte[] data = "xxx";//比特数据
microphoneWav.WriteAudioData(data); //4、关闭写入
microphoneWav.Dispose();
microphoneWav = null;
总结:实践是检验真理的唯一标准。
C#中使用WavHelper保存录音数据为wav文件的更多相关文章
- pcm数据生成wav文件
Qt由pcm数据生成wav文件 void AudioGrabber::saveWave(const QString &fileName, const QByteArray &raw, ...
- JQuery中使用FormData异步提交数据和提交文件
web中数据提交事件是常常发生的,但是大多数情况下我们不希望使用html中的form表单提交,因为form表单提交会中断当前浏览器的操作并且会调到另一个地址(即使这个地址是当前页面),并且会重复加载一 ...
- Qt由pcm数据生成wav文件
void AudioGrabber::saveWave(const QString &fileName, const QByteArray &raw, const QAudioForm ...
- WAV相关:从PCM16 Little Endian数据转WAV文件
数据格式 [0.0, -0.0, -0.0, 0.0, 0.0, 0.0, 5.960464477539063e-08, 5.960464477539063e-08, 1.19209289550781 ...
- 使用jmeter往指定文件中插入一定数量的数据
有一个需求,新建一批账号,把获取的账号相关信息存入文本文件,当文本文件保存的数据达到一定的数量,就自动停止新建账号. 分析下需求: 1.把账号信息保存到文件,需要使用bean shell脚本(bean ...
- 使用jmeter往指定文件中插入一定数量的数据(转)
有一个需求,新建一批账号,把获取的账号相关信息存入文本文件,当文本文件保存的数据达到一定的数量,就自动停止新建账号. 分析下需求: 1.把账号信息保存到文件,需要使用bean shell脚本(bean ...
- Android中使用speex将PCM录音格式转Wav格式
Android中使用speex将PCM录音格式转Wav格式 2013-09-17 17:24:00| 分类: android | 标签:android speex wav |举报|字号 订阅 ...
- HTML5操作麦克风获取音频数据(WAV)的一些基础技能
基于HTML5的新特性,操作其实思路很简单. 首先通过navigator获取设备,然后通过设备监听语音数据,进行原始数据采集. 相关的案例比较多,最典型的就是链接:https://developer. ...
- html 实体转换为字符:转换 UEditor 编辑器 ( 在 ThinkPHP 3.2.2 中 ) 保存的数据
在 ThinkPHP 3.2.2 中使用 UEditor 编辑器保存文章内容时,数据库中保存的数据都被转义成实体,例如:<p><strong>& ...
随机推荐
- python得到当前版本号
import sys print(sys.winver) 3.7 # 导入sys模块的argv,winver成员,并为其指定别名v.wv from sys import argv as v, winv ...
- [善用佳软]Chrome插件之彩云小译
最近公众号新推出个栏目[善用佳软],旨在和大家分享各种小插件和制作开源小软件. 最近在浏览外网时,发现一个贼好用的翻译神器---[彩云小译],在网页端就可以快速的对照翻译出来,经过试用发现无论是速度还 ...
- 【动画消消乐】HTML+CSS 自定义加载动画 064(currentColor的妙用!)
前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 自我介绍ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专 ...
- NestJS WebSocket 开始使用
使用NestJs提供WebSocket服务. 本文会在新建项目的基础上增加2个类 Gateway 实现业务逻辑的地方 WebSocketAdapter WebSocket适配器 新建项目 新建一个项目 ...
- 【NOIP2007】Hanoi双塔问题
题目描述 给定A.B.C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形). 现要将这些圆盘移到C柱上 ...
- Spring Boot的MyBatis注解:@MapperScan和@Mapper(十七)
1.Spring Boot与MyBatis融合的矛盾问题: Spring家族的使命就是为了简化而生,但是随着Spring的发展壮大,有点事与愿违了.为了坚持初心,Spring家族祭出了一大杀器---S ...
- ODOO里视图开发案例---定义一个像tree、form一样的视图
odoo里视图模型MVC模式: 例子:在原来的视图上修改他: var CustomRenderer = KanbanRenderer.extend({ ....});var CustomRendere ...
- Skywalking-04:扩展Metric监控信息
扩展 Metric 监控信息 官方文档 Source and Scope extension for new metrics 案例:JVM Thread 增加 Metrics 修改 Thread 的定 ...
- tomcat与springmvc 结合 之---第17篇 StandContext容器和SpringMVC的WebApplicationContext的联系
writedby 张艳涛, 上一篇分析了,dispatcherservlet通过getServletConfig 方法获取了web.xml定义的<param-init>属性的过程 那么在如 ...
- jvm源码解读--11 ldc指令的解读
写一个java文件 public static void main(String[] args) { String str1="abc"; String str2 ="a ...