折腾这么久,终于可以正常从硬盘读取wave文件了
上代码
// read_write_wave.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<fstream>
#include<iomanip>
#include <string.h>
using namespace std;
struct WAV_Chunk_RIFF
{
char ChunkID[4]; //理论上内容应该是:'RIFF' (0x52494646)
uint32_t ChunkSize; // 36 + Subchunk2Size Size是整个文件的长度减去ID和Size的长度
char Format[4]; //理论上内容应该是:'WAVE'(0x57415645)
WAV_Chunk_RIFF()//结构体也可以有构造函数,在里面可以对成员变量 赋值
{
strcpy(ChunkID, "RIFF");
ChunkSize = 0;
strcpy(Format, "W1VE");
}
};
struct WAV_Chunk_FMT
{
char ChunkID[4]; //理论上内容应该是:'fmt ' (0x666D7420)
uint32_t ChunkSize; /* Size表示该区块数据的长度(不包含ID和Size的长度) 16表示没有附加信息块*/
uint16_t AudioFormat; /* PCM = 1 音频格式*/
uint16_t NumChannels; /* Mono = 1, Stereo = 2, etc. */
uint32_t SampleRate; /* 8000, 44100, etc. */
uint32_t ByteRate; /* = SampleRate * NumChannels * BitsPerSample/8 每秒数据字节数 */
uint16_t BlockAlign; /* = NumChannels * BitsPerSample/8 数据块对齐 */
uint16_t BitsPerSample; /* 8bits, 16bits, etc. 采样位数 */
WAV_Chunk_FMT()
{
strcpy(ChunkID, "fmt");
ChunkSize = 16;
AudioFormat = 1;
NumChannels = 2;
SampleRate = 44100;
ByteRate = 0;
BlockAlign = 0;
BitsPerSample = 0;
}
};
struct WAV_Chunk_data
{
char ChunkID[4]; /* "data" */
uint32_t ChunkSize; /* data size */
char* Chunkdata;
WAV_Chunk_data()
{
strcpy(ChunkID, "data");
ChunkSize = 0;
Chunkdata = (char*)"1234";
}
};
struct WAV_fotmat
{
WAV_Chunk_RIFF riff;
WAV_Chunk_FMT fmt;
WAV_Chunk_data data;
};
//声明一个函数:将wave文件从硬盘读取,并拆解
string read_wave_file();
//声明一个函数:将数据以WAVE格式写入硬盘
string write_wave_file();
//一个全局的变量,用于表示一个WAV文件在内存中的样子
WAV_fotmat g_WAV_File;
int main()
{
string gsz_rerurn =read_wave_file();
std::cout<<"函数:read_wave_file的返回值----" << gsz_rerurn << "\n" << std::endl;
gsz_rerurn = write_wave_file();
std::cout << "Hello World!\n";
}
//将wave文件从硬盘读取,并拆解
string read_wave_file()
{
//第零步:从硬盘读取文件
FILE* fp;
fp = fopen("e:\\test3.wav", "rb");
if (!fp)
{
return "error_fopen";
}
else
{
std::cout << "成功从硬盘找到并打开 wav文件\n";
}
//第一步:对RIFF区块的读取
fread(g_WAV_File.riff.ChunkID, sizeof(char), 4, fp); // 读取'RIFF'
if (('R' != g_WAV_File.riff.ChunkID[0]) || ('I' != g_WAV_File.riff.ChunkID[1]) || ('F' != g_WAV_File.riff.ChunkID[2]) || ('F' != g_WAV_File.riff.ChunkID[3]))//零 这两个字符串相等。
{
return "error_RIFF_id";
}
//
fread(&g_WAV_File.riff.ChunkSize, sizeof(unsigned long), 1, fp); // 读取文件大小(整个文件的长度减去ID和Size的长度)
//
fread(g_WAV_File.riff.Format, sizeof(char), 4, fp); // 读取'RIFF'
if (('W'!=g_WAV_File.riff.Format[0])||('A' != g_WAV_File.riff.Format[1]) || ('V' != g_WAV_File.riff.Format[2]) || ('E' != g_WAV_File.riff.Format[3]))
{
return "error_WAVE";
}
//第二步:FORMAT区块
fread(g_WAV_File.fmt.ChunkID, sizeof(char), 4, fp); // 读取4字节 "fmt ";
fread(&g_WAV_File.fmt.ChunkSize, sizeof(unsigned long), 1, fp);//Size表示该区块数据的长度(不包含ID和Size的长度)
//若Format Chunk的size大小为18,则该模块的最后两个字节为附加信息
std::cout << "函数:read_wave_file--format_length----" << g_WAV_File.fmt.ChunkSize << "\n" << std::endl;
if (18 == g_WAV_File.fmt.ChunkSize)
{
std::cout << "函数:read_wave_file--该WAVE文件里面有附加信息块----" << "\n" << std::endl;
std::cout << "本程序,不支持 对附加信息读取!!!" << "\n" << std::endl;
}
else
{
std::cout << "函数:read_wave_file--该WAVE文件里面没有附加信息块----" << "\n" << std::endl;
}
fread(&g_WAV_File.fmt.AudioFormat, sizeof(short), 1, fp); // 读取文件tag 音频格式 PCM信号采样 = 1
std::cout << "函数:read_wave_file--音频格式----" << g_WAV_File.fmt.AudioFormat << "\n" << std::endl;
fread(&g_WAV_File.fmt.NumChannels, sizeof(short), 1, fp); // 读取通道数目
std::cout << "函数:read_wave_file--通道数目----" << g_WAV_File.fmt.NumChannels << "\n" << std::endl;
fread(&g_WAV_File.fmt.SampleRate, sizeof(unsigned long), 1, fp); // 读取采样率大小
std::cout << "函数:read_wave_file--采样率大小----" << g_WAV_File.fmt.SampleRate << "\n" << std::endl;
fread(&g_WAV_File.fmt.ByteRate, sizeof(unsigned long), 1, fp);//每秒数据字节数 SampleRate * NumChannels * BitsPerSample / 8
std::cout << "函数:read_wave_file--每秒数据字节数----" << g_WAV_File.fmt.ByteRate << "\n" << std::endl;
fread(&g_WAV_File.fmt.BlockAlign, sizeof(short), 1, fp); //每个采样所需的字节数 = NumChannels * BitsPerSample / 8
std::cout << "函数:read_wave_file--每个采样所需的字节数----" << g_WAV_File.fmt.BlockAlign << "\n" << std::endl;
fread(&g_WAV_File.fmt.BitsPerSample, sizeof(short), 1, fp); // 每个采样存储的bit数,8:8bit,16:16bit,32:32bit
std::cout << "函数:read_wave_file--每个采样存储的bit数----" << g_WAV_File.fmt.BitsPerSample << "\n" << std::endl;
//第三步: DATA区块
fread(g_WAV_File.data.ChunkID, sizeof(char), 4, fp); // 读入'data'
if (('d' != g_WAV_File.data.ChunkID[0]) || ('a' != g_WAV_File.data.ChunkID[1]) || ('t' != g_WAV_File.data.ChunkID[2]) || ('a' != g_WAV_File.data.ChunkID[3]))
{
return "error_data";
}
//震动数据的字节数目
fread(&g_WAV_File.data.ChunkSize, sizeof(unsigned long), 1, fp); // 读取数据大小
std::cout << "函数:read_wave_file--数据大小----" << g_WAV_File.data.ChunkSize << "\n" << std::endl;
//震动数据本身
g_WAV_File.data.Chunkdata = new char[g_WAV_File.data.ChunkSize];// 读取数据
fread(g_WAV_File.data.Chunkdata, sizeof(char), g_WAV_File.data.ChunkSize, fp);
//for (int i = 0; i < 100; i++)
//{
// uint16_t left=0;
// fread(&left, sizeof(char),2, fp);
// //数据的存储位置。
// //项目大小(以字节为单位)。
// //要读取的项的最大数量。
// //指向 FILE 结构的指针。
// std::cout << "16位--双字节数据--"<< dec << left << "\n" << std::endl;
//}
//如果16位双通道,那么数据应该是L低字节,L高字节,R低字节,R高字节,
return "read_wave_file_OK";
}
//将数据以WAVE格式写入硬盘
string write_wave_file()
{
ofstream fout("Wave__11.wav", ios::binary);
int a = sizeof(g_WAV_File.riff);
fout.write((char*)(&g_WAV_File.riff), a);
int b = sizeof(g_WAV_File.fmt);
fout.write((char*)(&g_WAV_File.fmt), b);
int c= sizeof(g_WAV_File.data.ChunkID);
fout.write((char*)(&g_WAV_File.data.ChunkID),c);
int d = sizeof(g_WAV_File.data.ChunkSize);
fout.write((char*)(&g_WAV_File.data.ChunkSize), d);
fout.write((char*)(g_WAV_File.data.Chunkdata), g_WAV_File.data.ChunkSize);
return "write_wave_file_OK";
}
***