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文件的更多相关文章

  1. pcm数据生成wav文件

    Qt由pcm数据生成wav文件 void AudioGrabber::saveWave(const QString &fileName, const QByteArray &raw, ...

  2. JQuery中使用FormData异步提交数据和提交文件

    web中数据提交事件是常常发生的,但是大多数情况下我们不希望使用html中的form表单提交,因为form表单提交会中断当前浏览器的操作并且会调到另一个地址(即使这个地址是当前页面),并且会重复加载一 ...

  3. Qt由pcm数据生成wav文件

    void AudioGrabber::saveWave(const QString &fileName, const QByteArray &raw, const QAudioForm ...

  4. 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 ...

  5. 使用jmeter往指定文件中插入一定数量的数据

    有一个需求,新建一批账号,把获取的账号相关信息存入文本文件,当文本文件保存的数据达到一定的数量,就自动停止新建账号. 分析下需求: 1.把账号信息保存到文件,需要使用bean shell脚本(bean ...

  6. 使用jmeter往指定文件中插入一定数量的数据(转)

    有一个需求,新建一批账号,把获取的账号相关信息存入文本文件,当文本文件保存的数据达到一定的数量,就自动停止新建账号. 分析下需求: 1.把账号信息保存到文件,需要使用bean shell脚本(bean ...

  7. Android中使用speex将PCM录音格式转Wav格式

    Android中使用speex将PCM录音格式转Wav格式 2013-09-17 17:24:00|  分类: android |  标签:android  speex  wav  |举报|字号 订阅 ...

  8. HTML5操作麦克风获取音频数据(WAV)的一些基础技能

    基于HTML5的新特性,操作其实思路很简单. 首先通过navigator获取设备,然后通过设备监听语音数据,进行原始数据采集. 相关的案例比较多,最典型的就是链接:https://developer. ...

  9. html 实体转换为字符:转换 UEditor 编辑器 ( 在 ThinkPHP 3.2.2 中 ) 保存的数据

    在 ThinkPHP 3.2.2 中使用 UEditor 编辑器保存文章内容时,数据库中保存的数据都被转义成实体,例如:&lt;p&gt;&lt;strong&gt;& ...

随机推荐

  1. [刘阳Java]_Spring IoC原理_第2讲

    Spring IoC(DI)是Spring框架的核心,所有对象的生命周期都是由它们来管理.对于弄懂Spring IOC是相当关键,往往我们第一次接触Spring IOC大家都是一头雾水.当然我们这篇文 ...

  2. File类与常用IO流第五章——IO字符流

    字符流,只能操作文本文件,不能操作图片.视频等非文本文件 字符输入流 java.io.Reader 字符输入流中一些共性的成员方法 int read():读取单个字符并返回. int read(cha ...

  3. 北京大公司二面:了解Redis持久化机制吗?

    今日总结 Redis持久化机制:RDB和AOF RDB持久化:定时任务,BGSAVE命令 fork一个子进程生成RDB文件(二进制) AOF持久化:根据配置将写命令存储至日志文件中,顺序写&& ...

  4. Appium和Python实现蚂蚁森林自动化收取能量

    准备环境 Window10系统 Appium1.21.0 AndroidSDK r24.1.1 Python3.7.5 支付宝apk文件 查看支付宝apk包信息 使用android sdk aapt命 ...

  5. Qt开源作品38-无边框窗体方案(无抖动,支持win、linux、mac等系统,侧边半屏顶部全屏)

    一 前言 不知道各位程序员有没有遇到过这样一种困惑,好不容易在开源网站找到了类似的想要的项目代码,结果down下来一编译,我勒个去,几百个错误,根本没法用,熟悉的人还好可以直接阅读代码进行修改(有些只 ...

  6. 记一次错误:mid=front+(rear-front)>>1;

    设rear=6,front=4,mid=front+(rear-front)>>1; mid应该等于5的,但结果却是3. 错误原因:"+"运算符的优先级高于" ...

  7. visibility:hidden和display:none的区别

    一.相同点 disable:none和visibility:hidden都能把网页上的某元素隐藏起来 二.不同点 display:none--不为被隐藏的对象保留其物理空间,即该对象在页面上彻底消失. ...

  8. webpack 命令行报错“webpack” 不是内部或外部命令的解决方法

    1. NodeJS安装,笔者安装在D盘.安装目录中有两个文件夹node_cache,node_global如下: 2. 配置 npm安装路径,输入如下命令: npm config set prefix ...

  9. python 装饰函数2

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Tue May 5 21:40:49 2020 ...

  10. Select、Poll、Epoll IO复用技术

    简介 目前多进程方式实现的服务器端,一次创建多个工作子进程来给客户端提供服务, 但是创建进程会耗费大量资源,导致系统资源不足 IO复用技术就是让一个进程同时为多个客户端端提供服务 IO复用技术 之 S ...