音频-从零开始创建一个wave 文件,并且写入硬盘(版本1)

我最初的目的就是将来自声卡的数据保存到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)

C++ 文件的读写(fin && fout)_一只努力翻身的咸鱼的博客-CSDN博客_fout

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值