前面写了一个,今天更新一下
主要更新内容如下:
1)增加注释,简化程序
2)实现音频数据自身频率的变化。实现类似扫频的效果
***
// CreateWaveWriteDisk.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
}
};
//这个是data块里面 :ID和SIZE 两个参数的赋值
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()
{
int gsz_time_s= 10;//设定音频时间 ,单位是S。
uint16_t gsz_numChannels=2;//设定通道数目为2
uint32_t gsz_sampleRate=44100;//设定采样频率为44.1K。
uint16_t gsz_bitsPerSample=16;//设定每通道每次采样得到的数据AD转化位数
uint16_t gsz_blockAlign= (gsz_numChannels* gsz_bitsPerSample)/8; // = NumChannels * BitsPerSample / 8= 2*16/8=4
uint32_t gsz_byteRate= gsz_sampleRate* gsz_blockAlign; //数据传送速率(每秒字节)=采样频率×每个样本字节数=176,400字节
int gsz_size_Riff = 4 + 4 + 4;// RIFF区块的大小=ID+SIZE+Type=12
int gsz_size_FORMAT = 4 + 4 + 2 + 2 + 4 + 4 + 2 + 2;// FORMAT区块=ID+SIZE+AudioFormat+NumChannels+SampleRate+ByteRate+BlockAlign+BitsPerSample=24
int gsz_size_data_ID = 4;//DATA区块的ID是四个字节
int gsz_size_data_szie = 4;DATA区块的SIZE也是四个字节Size表示音频数据的长度
//所以整个WAVE文件的大小就是:12+24+8+176,400*10=1 764 044
uint32_t gsz_total_wave_size = gsz_size_Riff+ gsz_size_FORMAT+ gsz_size_data_ID+ gsz_size_data_szie+ gsz_time_s* gsz_byteRate;
printf("整个wave文件的大小是:%u\n", gsz_total_wave_size);
ofstream fout("Wave.wav", ios::binary);
RIFF riff(gsz_time_s * gsz_byteRate);//此处填写的整个测试时间内,震动数据的占用的字节数目
FMT fmt(gsz_numChannels, gsz_sampleRate, gsz_bitsPerSample);//2个声道,信号采样率44.1K。 每个数据用16个b,两个字节存储。
DATA_HEADER dataHeader(gsz_time_s * gsz_byteRate);
fout.write((char*)(&riff), sizeof(riff));
fout.write((char*)(&fmt), sizeof(fmt));
fout.write((char*)(&dataHeader), sizeof(dataHeader));
for (int i = 0; i < 44100* gsz_time_s; i++) //采样率是44100,此处循环了441000 是10倍的44.1K。那就是10S的音频数据了
{
int gsz_shang = i / 4410;
printf("商等于:%d\n", gsz_shang);
double Sin = sin(2 * PI * (200+gsz_shang*150) * 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));
}//生成远程的震动数目 因为无符号16位
fout.close();
return 0;
}