win32 - 将原始音频样本转换为wav文件
需要先从麦克风中采样,代码样本可以参考官方示例: WASAPI Capture Shared Event Driven
官方示例采样10s, 我们需要在WriteWaveFile函数下添加生成原始音频的代码。
// Write the contents of a WAV file. We take as input the data to write and the format of that data.
//
bool WriteWaveFile(HANDLE FileHandle, const BYTE *Buffer, const size_t BufferSize, const WAVEFORMATEX *WaveFormat)
{
FILE* _file;
int16_t* _data;
_data = (int16_t*)Buffer;
_file = fopen("utterance.raw", "wb +");
fwrite(_data, 1, BufferSize, _file);
fclose(_file); ...
得到utterance.raw原始音频样本之后,我们需要对其添加wav的头结构来重新生成wav文件
#include <Windows.h>
#include <stdio.h>
#include <MMDeviceAPI.h>
#include <AudioClient.h>
#include <assert.h>
#include <avrt.h>
#include <strsafe.h>
#include <fstream> using namespace std; #pragma warning(disable:4996) struct WAVEHEADER
{
DWORD dwRiff; // "RIFF"
DWORD dwSize; // Size
DWORD dwWave; // "WAVE"
DWORD dwFmt; // "fmt "
DWORD dwFmtSize; // Wave Format Size
}; const BYTE WaveHeader[] =
{
'R', 'I', 'F', 'F', 0x00, 0x00, 0x00, 0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', 0x00, 0x00, 0x00, 0x00
}; const BYTE WaveData[] = { 'd', 'a', 't', 'a' }; bool WriteWaveFile(HANDLE FileHandle, const BYTE* Buffer, const size_t BufferSize, WAVEFORMATEX* WaveFormat)
{
DWORD waveFileSize = sizeof(WAVEHEADER) + sizeof(WAVEFORMATEX) + WaveFormat->cbSize + sizeof(WaveData) + sizeof(DWORD) + static_cast<DWORD>(BufferSize);
BYTE* waveFileData = new (std::nothrow) BYTE[waveFileSize];
BYTE* waveFilePointer = waveFileData;
WAVEHEADER* waveHeader = reinterpret_cast<WAVEHEADER*>(waveFileData); if (waveFileData == NULL)
{
printf("Unable to allocate %d bytes to hold output wave data\n", waveFileSize);
return false;
} //
// Copy in the wave header - we'll fix up the lengths later.
//
CopyMemory(waveFilePointer, WaveHeader, sizeof(WaveHeader));
waveFilePointer += sizeof(WaveHeader); //
// Update the sizes in the header.
//
waveHeader->dwSize = waveFileSize - (2 * sizeof(DWORD));
waveHeader->dwFmtSize = sizeof(WAVEFORMATEX) + WaveFormat->cbSize; //
// Next copy in the WaveFormatex structure.
//
CopyMemory(waveFilePointer, WaveFormat, sizeof(WAVEFORMATEX) + WaveFormat->cbSize);
waveFilePointer += sizeof(WAVEFORMATEX) + WaveFormat->cbSize; //
// Then the data header.
//
CopyMemory(waveFilePointer, WaveData, sizeof(WaveData));
waveFilePointer += sizeof(WaveData);
*(reinterpret_cast<DWORD*>(waveFilePointer)) = static_cast<DWORD>(BufferSize);
waveFilePointer += sizeof(DWORD); //
// And finally copy in the audio data.
// CopyMemory(waveFilePointer, Buffer, BufferSize);
//
// Last but not least, write the data to the file.
//
DWORD bytesWritten;
if (!WriteFile(FileHandle, waveFileData, waveFileSize, &bytesWritten, NULL))
{
printf("Unable to write wave file: %d\n", GetLastError());
delete[]waveFileData;
return false;
} if (bytesWritten != waveFileSize)
{
printf("Failed to write entire wave file\n");
delete[]waveFileData;
return false;
}
delete[]waveFileData;
return true;
} //
// Write the captured wave data to an output file so that it can be examined later.
//
void SaveWaveData(BYTE* CaptureBuffer, size_t BufferSize, WAVEFORMATEX* WaveFormat)
{
wchar_t waveFileName[MAX_PATH];
HRESULT hr = StringCbCopy(waveFileName, sizeof(waveFileName), L"WASAPICaptureEventDriven-");
if (SUCCEEDED(hr))
{
GUID testGuid;
if (SUCCEEDED(CoCreateGuid(&testGuid)))
{
wchar_t* guidString;
if (SUCCEEDED(StringFromCLSID(testGuid, &guidString)))
{
hr = StringCbCat(waveFileName, sizeof(waveFileName), guidString);
if (SUCCEEDED(hr))
{
hr = StringCbCat(waveFileName, sizeof(waveFileName), L".WAV");
if (SUCCEEDED(hr))
{
HANDLE waveHandle = CreateFile(waveFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (waveHandle != INVALID_HANDLE_VALUE)
{
if (WriteWaveFile(waveHandle, CaptureBuffer, BufferSize, WaveFormat))
{
printf("Successfully wrote WAVE data to %S\n", waveFileName);
}
else
{
printf("Unable to write wave file\n");
}
CloseHandle(waveHandle);
}
else
{
printf("Unable to open output WAV file %S: %d\n", waveFileName, GetLastError());
}
}
}
CoTaskMemFree(guidString);
}
}
}
} int main()
{
long buffersize = 3528000;// For 10s audio sample, we can set the value of buffersize to 3528000
BYTE* captureBuffer = new (std::nothrow) BYTE[buffersize]; FILE* _file;
_file = fopen("utterance.raw", "rb"); //raw audio path
fread(captureBuffer, 1, buffersize, _file);
fclose(_file); WAVEFORMATEX wavformat;
wavformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
wavformat.nChannels = 2;
wavformat.nSamplesPerSec = 44100;
wavformat.nAvgBytesPerSec = 352800;
wavformat.nBlockAlign = 8;
wavformat.wBitsPerSample = 32;
wavformat.cbSize = 22;
SaveWaveData(captureBuffer, buffersize, &wavformat); return 0;
}
通过将样本的路径添加给fopen,经过一些处理就可以得到了。
补充:
我们也可以使用ofstream来采样,代码见下:
// Write the contents of a WAV file. We take as input the data to write and the format of that data.
//
bool WriteWaveFile(HANDLE FileHandle, const BYTE *Buffer, const size_t BufferSize, const WAVEFORMATEX *WaveFormat)
{
ofstream binaryFile("file.raw", ios::out | ios::binary);
binaryFile.write((char*)Buffer, BufferSize);
binaryFile.close();
...
再使用ifstream获取样本,添加wav的头结构来重新编码。
ifstream infile("file.raw", std::ifstream::binary);
// get size of file
infile.seekg(0, infile.end);
long size = infile.tellg();
infile.seekg(0);
BYTE* captureBuffer = new (std::nothrow) BYTE[size];
infile.read((char*)captureBuffer, size);
infile.close();
WAVEFORMATEX wavformat;
wavformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
wavformat.nChannels = 2;
wavformat.nSamplesPerSec = 44100;
wavformat.nAvgBytesPerSec = 352800;
wavformat.nBlockAlign = 8;
wavformat.wBitsPerSample = 32;
wavformat.cbSize = 22;
SaveWaveData(captureBuffer, size, &wavformat);
win32 - 将原始音频样本转换为wav文件的更多相关文章
- 基于Linux ALSA音频驱动的wav文件解析及播放程序 2012
本设计思路:先打开一个普通wav音频文件,从定义的文件头前面的44个字节中,取出文件头的定义消息,置于一个文件头的结构体中.然后打开alsa音频驱动,从文件头结构体取出采样精度,声道数,采样频率三个重 ...
- HTML5操作麦克风获取音频数据(WAV)的一些基础技能
基于HTML5的新特性,操作其实思路很简单. 首先通过navigator获取设备,然后通过设备监听语音数据,进行原始数据采集. 相关的案例比较多,最典型的就是链接:https://developer. ...
- Android 音视频深入 一 AudioRecord录音生成pcm转换为wav(附源码下载)
本篇项目地址,名字是AudioRecord录音(能暂停,将pch转换为wav),求starhttps://github.com/979451341/Audio-and-video-learning-m ...
- PC-1500的代码存入WAV文件
目录 第1章保存 1 1.1 操作 1 1.2 波形说明 4 1.3 波形整形 5 1.4 压缩 8 第2章载入 9 2.1 操作 9 2.2 音量 9 ...
- 音视频学习系列第(三)篇---wav文件的存储和解析
音视频系列 什么是wav wav是一种无损的音频文件格式,wav文件有两部分,第一部分是文件头,记录一些重要的参数信息,如音频的采样率,通道数,数据位宽,第二部分是数据部分,数据部分可以是PCM,也可 ...
- 将任意音频格式文件转换成16K采样率16bit的wav文件
此转换需要使用ffmpeg 假设有目录 d:\录音 目录有 张三.m4a, 李四.m4a xxx.m4a(其他任意格式音频触类旁通可以把 *.m4a改成*.*).批量转换成采样率16K,有符号,16b ...
- linux下alsa架构音频驱动播放wav格式文件
#include<stdio.h> #include<stdlib.h> #include <string.h> #include <alsa/asoundl ...
- Linux音频编程--使用ALSA库播放wav文件
在UBUNTU系统上使用alsa库完成了对外播放的wav文件的案例. 案例代码: /** *test.c * *注意:这个例子在Ubuntu 12.04.1环境下编译运行成功. * */ #inclu ...
- Windwos平台上ffmpeg解码音频并且保存到wav文件中
先附上代码,测试通过 #include <stdio.h> #include <math.h> #include "libavutil/avstring.h" ...
- Beginning SDL 2.0(6) 音频渲染及wav播放
前面几篇关于SDL的文章介绍的是以画面为主,这里介绍下SDL中针对音频播放提供的机制,以及如何应用. 对于音频而言,有几个概念需要事先了解下,采样率.声道数.量化位数,如果你不清楚的话,麻烦先了解下这 ...
随机推荐
- [转帖]【VIM】多行缩进空格与删除
向前或向后缩进一个TAB 按ctrl + v组合键进入Visual Line模式,可使用方向键选择多行: 按<或>,进行向前或向后缩进tab. 缩进n个TAB,按n+<或> 多 ...
- [转帖]minio 的 warp
3 benchmarking tool. Download Download Binary Releases for various platforms. Configuration Warp can ...
- [转帖]Jmeter连接InfluxDB2.0.4
Jmeter连接InfluxDB2.0.4 问题描述:在用Jmeter+InfluxDB构建监控时,因为docker构建的InfluxDB的版本是2.0.4,按照网上的教程进行后端监听器的填写,但是一 ...
- 人大金仓学习之二_ksh和kddm的学习
人大金仓学习之二_ksh和kddm的学习 摘要 承接上一篇文章 主要是这里总结一下ksh相关的文档. 这里学习了很多文档: https://help.kingbase.com.cn/v8/perfor ...
- 【转帖】如何使用route管理路由表
这里是引用 route快捷使用方法 我们一般管理路由有使用route命令 本身route使用大致有两种方法:但其实 在实际操作中,我们熟练掌握一种方法就可以了. route 有以下6种操作方法: 1) ...
- [转帖]Elasticsearch-sql 用SQL查询Elasticsearch
https://www.cnblogs.com/kangoroo/p/7273493.html https://www.cnblogs.com/kangoroo/p/7273493.html Elas ...
- React Hooks源码深度解析
作者:京东零售 郑炳懿 前言 React Hooks是React16.8 引入的一个新特性,它允许函数组件中使用state和其他 React 特性,而不必使用类组件.Hooks是一个非常重要的概念,因 ...
- JS中every的简单使用
every 方法 every()方法用于检测数组中的所有元素是否都满足指定条件. every()方法会遍历数组的每一项,如果有一项不满足条件,则返回false,剩余的项将不会再执行检测. 如果遍历完数 ...
- echarts饼图中央自定义文字
var option = { tooltip: { trigger: 'item' }, legend: { top: '5%', left: 'center' }, //中央自定义文字 title: ...
- TypeScript中泛型<T>详细讲解
1.泛型 在定义函数或者接口或者类的时候 不能预先确定要使用的数据类型 而是在使用函数.接口.或者类的时候才能够确定数据类型 这个时候我们就需要使用的是泛型 2.功能描述 我们需要实现一个方法,方法中 ...