最近为了调试,写了一个 WAVE 的生成器,能够生成指定采样率,指定格式的 WAVE文件,这样可以在输出端直接查看输出是否是指定的数据。特别注意的是,WAVE 中,使用 int16 (有符号十六进制)来表示当前的信号,更具体来说,负数使用补码来表示。代码如下:
// WaveGenerator.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#pragma pack(push, 1)
struct Chunk1 { // 'R', 'I', 'F', 'F'
char chunk_id[4];
uint32_t chunk_size;
char format[4]; // 'W', 'A', 'V', 'E'
};
struct Chunk2 {
char chunk_id[4];
uint32_t chunk_size;
int16_t wFormatTag;
int16_t nChannels;
int32_t nSamplesPerSec;
int32_t nAvgBytesPerSec;
int16_t nBlockAlign; // => num_channels * bits_per_sample / 8
int16_t wBitsPerSample;
};
struct Chunk3 {
char chunk_id[4];
uint32_t chunk_size;
};
#pragma pack(pop) // 恢复到之前的对齐设置
#define AUDIODURATION 5 // 音频时长,以秒为单位
#define SAMPLEBITS 16 // 采样位
#define SAMPLERATE 96000 // 采样率
#define CHANNELNUM 2 // Channel 数量
int main()
{
Chunk1 chunk1;
chunk1.chunk_id[0] = 'R'; chunk1.chunk_id[1] = 'I'; chunk1.chunk_id[2] = 'F'; chunk1.chunk_id[3] = 'F';
// 数据长度= Chunk123 总长 + RAW 数据长度(双声道,SAMPLEBITS Bits)
chunk1.chunk_size = sizeof(Chunk1)-8 + sizeof(Chunk2) + sizeof(Chunk3)+ AUDIODURATION* CHANNELNUM *(SAMPLEBITS/8)* SAMPLERATE;
chunk1.format[0] = 'W'; chunk1.format[1] = 'A'; chunk1.format[2] = 'V'; chunk1.format[3] = 'E';
Chunk2 chunk2;
chunk2.chunk_id[0] = 'f'; chunk2.chunk_id[1] = 'm'; chunk2.chunk_id[2] = 't'; chunk2.chunk_id[3] = ' ';
chunk2.chunk_size = sizeof(Chunk2)-8;
chunk2.wFormatTag = 0x0001; //PCM 格式
chunk2.nChannels = CHANNELNUM;
chunk2.nSamplesPerSec = SAMPLERATE;
chunk2.nAvgBytesPerSec = CHANNELNUM * SAMPLERATE * (SAMPLEBITS / 8);
chunk2.nBlockAlign = CHANNELNUM * (SAMPLEBITS / 8);
chunk2.wBitsPerSample = SAMPLEBITS;
Chunk3 chunk3;
chunk3.chunk_id[0] = 'd'; chunk3.chunk_id[1] = 'a'; chunk3.chunk_id[2] = 't'; chunk3.chunk_id[3] = 'a';
chunk3.chunk_size = AUDIODURATION * CHANNELNUM * SAMPLERATE * (SAMPLEBITS / 8);
// 打开文件用于写入,以二进制模式
FILE* file = fopen("C:\\WaveGenerator\\Debug\\example.wav", "wb");
fwrite(&chunk1, sizeof(chunk1), 1, file);
fwrite(&chunk2, sizeof(chunk2), 1, file);
fwrite(&chunk3, sizeof(chunk3), 1, file);
short int s=0,e=0;
for (int i = 0; i < AUDIODURATION* SAMPLERATE; i++) {
//s = sin(i * 2 * 3.1415 / (SAMPLERATE/1000)) * (65535 / 2);
// 左声道
s++;
fwrite(&s, sizeof(s), 1, file);
// 右声道
e = 0;
fwrite(&e, sizeof(e), 1, file);
}
fclose(file);
//getchar();
}