我最初的目的就是将来自声卡的数据保存到wave文件,所以这个Demo似乎更有价值。
***
// wave_read_001.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <cmath>
#include<cstdint>
#include<fstream>
#include<iomanip>
using namespace std;
uint32_t endianSwap(uint32_t n) //大小端转换
{
uint32_t changed = 0;
for (int i = 0; i < 4; i++)
{
changed <<= 8;
changed |= (n << ((3 - i) * 8)) >> 24;
}
return changed;
}
struct RIFF
{
char chunkID[4];
uint32_t chunkSize;
char format[4];
RIFF(uint32_t n)//结构体里面竟然可以有构造函数, 这个构造函数竟然可以有参数。 晕,基本功不扎实啊。。
{
chunkID[0] = 'R';
chunkID[1] = 'I';
chunkID[2] = 'F';
chunkID[3] = 'F';
uint32_t ChunkSize = n + 36;//36 + Subchunk2Size Size是整个文件的长度减去ID和Size的长度
chunkSize = ChunkSize;
format[0] = 'W';
format[1] = 'A';
format[2] = 'V';
format[3] = 'E';
}
};
struct FMT
{
char subchunk1ID[4];
uint32_t subchunk1Size;//16
uint16_t audioFormat;//1
uint16_t numChannels;
uint32_t sampleRate;
uint32_t byteRate;//数据传送速率(每秒字节=采样频率×每个样本字节数
uint16_t blockAlign;// = NumChannels * BitsPerSample / 8= 2*16/8=4
uint16_t bitsPerSample;
FMT(uint32_t NumChannels, uint32_t SampleRate, uint32_t BitsPerSample) :
subchunk1Size(16), audioFormat(1), numChannels(NumChannels),
sampleRate(SampleRate), blockAlign(4), bitsPerSample(BitsPerSample) //尼玛,好复杂的语法。就是为了给结构体的变量赋值
{
subchunk1ID[0] = 'f';
subchunk1ID[1] = 'm';
subchunk1ID[2] = 't';
subchunk1ID[3] = ' ';
byteRate = SampleRate * NumChannels * BitsPerSample >> 3;//44100*2*16=1,411,200
}
};
struct DATA_HEADER
{
char subchunk2ID[4];
uint32_t subchunk2Size;
DATA_HEADER(uint32_t n) : subchunk2Size(n)
{
subchunk2ID[0] = 'd';
subchunk2ID[1] = 'a';
subchunk2ID[2] = 't';
subchunk2ID[3] = 'a';
}
};
struct DATA_BLOCK
{
uint16_t left;
uint16_t right;
DATA_BLOCK(uint16_t Left, uint16_t Right) :
left(Left), right(Right)
{
}
};
const double PI = acos(-1.0);
int main()
{
ofstream fout("Wave.wav", ios::binary);
RIFF riff(1764000);//此处填写的是1764000.那么整个文件大小应该 是1764000+36+8=176,4044
// RIFF 块 +FMT块+Data块的ID +Data块的SIZE =12+24+8=44
//那么data块的data数据=176,4044-44=1764000
//data块的整体大小=1764000
FMT fmt(2, 44100, 16);//2个声道,信号采样率44.1K。 每个数据用16个b,两个字节存储。
DATA_HEADER dataHeader(1764000);
fout.write((char*)(&riff), sizeof(riff));
fout.write((char*)(&fmt), sizeof(fmt));
fout.write((char*)(&dataHeader), sizeof(dataHeader));
for (int i = 0; i < 441000; i++) //采样率是44100,此处循环了441000 是10倍的44.1K。那就是10S的音频数据了
{
double Sin = sin( 2 * PI * 1000 * i / 44100);//2*圆周率*频率*采样点
int16_t Data = (int16_t)(Sin * 32767);//振幅 最大=位数的最大
uint16_t* data = (uint16_t*)&Data;
DATA_BLOCK block(*data, *data);
fout.write((char*)(&block), sizeof(block));
}//数据计算
//1764000-4-4=1,763,992
//每次采样产生数据=左声道数据+右声道数据=16位+16位=32位=4个字节
//那么1S的数量量=44100*4=176,400
//10S的数据量=176,4000
fout.close();
return 0;
}
***************
matalb 仿真一下波形
符合预取!
后记:
1)
2)两套文件读写API
fread函数详解和fwrite函数详解
(fread函数详解和fwrite函数详解_dangzhangjing97的博客-CSDN博客_fread fwrite)
C++ 文件的读写(fin && fout)