当创建并读写wav文件时,要以二进制打开
#include <windows.h> #include <mmsystem.h> #include <iostream> #include<fstream> #include<math.h> #include <vector> #define WAVE_HEAD_LENGTH 44//wav头文件长度 #define m_samplefreq 22050 //每秒采样数-采样速率(22050Hz) #define m_channels 1 //通道数量,1为单通道,2为双通道 #define m_channelbits 8 #define MATH_PI 3.1415 using namespace std; //.wav文件的文件头结构 typedef struct { char chRIFF[4]; //头部那个RIFF; DWORD dwRIFFLen; //存的是后面所有文件的大小; char chWAVE[4]; char chFMT[4]; DWORD dwFMTLen; //存的是fmt保存的大小,包含这之后,data前面几个,共16个; PCMWAVEFORMAT pwf; char chDATA[4]; DWORD dwDATALen; //数据的长度; //UINT8* pBufer; }WaveHeader; //采样率、频率、音量、数据空间、采样点数 void MakeWaveData(int rate, int freq, int amp, char* p, int len) { int flag = 0; if (m_channelbits == 16) //16位 { if (m_channels == 1) { for (int i = 0; i < len; i++) { INT16 v = INT16(amp/100*32768 * sin(2 * MATH_PI * freq * i / rate)); *(p + flag) = v & 0xFF;//低8位 *(p + flag + 1) = (v >> 8) & 0xFF;//16bit量化 高8位 flag += 2; } } else { for (int i = 0; i < len; i++) { INT16 vl = INT16(amp / 100 * 32768 * sin(2 * MATH_PI * freq * i / rate)) ; INT16 vr = INT16(amp / 100 * 32768 * sin((2 * MATH_PI * freq * (i+5) )/ rate)) ; *(p + flag) = (vl & 0xFF); *(p + flag + 1) = ((vl >> 8) & 0xFF); *(p + flag + 2) = (vr & 0xFF); *(p + flag + 3) = ((vr >> 8) & 0xFF); flag += 4; } } } else { if (m_channels == 1) { for (int i = 0; i < len; i++) { *(p + i) = char(sin(i * (MATH_PI * 2) / rate * freq) * amp * 128 / 100 + 128); } } else { for (int i = 0; i < len; i++) { *(p + flag)= char(sin(i * (MATH_PI * 2) / rate * freq) * amp * 128 / 100+128); *(p + flag + 1)= char(sin((i+5) * (MATH_PI * 2) / rate * freq) * amp * 128 / 100+128); flag += 2; } } } } //频率、音量、持续时间、wav文件保存路径(包含文件名+后缀 int Create(vector<int> freqVec, int volume, int durations, std::string wavPath) { WaveHeader *pHeader = new WaveHeader; DWORD totalLen = (m_samplefreq * m_channels * m_channelbits / 8) * durations + 44;//文件总长度=(采样率 * 通道数 * 比特数 / 8) * 持续时间(s) pHeader->chRIFF[0] = 'R'; pHeader->chRIFF[1] = 'I'; pHeader->chRIFF[2] = 'F'; pHeader->chRIFF[3] = 'F'; pHeader->dwRIFFLen = totalLen - 8;//文件的总长度-8bits pHeader->chWAVE[0] = 'W'; pHeader->chWAVE[1] = 'A'; pHeader->chWAVE[2] = 'V'; pHeader->chWAVE[3] = 'E'; pHeader->chFMT[0] = 'f'; pHeader->chFMT[1] = 'm'; pHeader->chFMT[2] = 't'; pHeader->chFMT[3] = ' '; pHeader->dwFMTLen = 0x0010;//一般情况下Size为16,如果为18则最后多了2个字节的附加信息 pHeader->pwf.wf.wFormatTag = 0x0001;//波形声音的格式-编码方式 pHeader->pwf.wf.nChannels = m_channels; //通道数量,1为单通道,2为双通道 pHeader->pwf.wf.nSamplesPerSec = m_samplefreq; //采样速率 =44.1KHz pHeader->pwf.wf.nAvgBytesPerSec = m_samplefreq * m_channels * m_channelbits / 8;//平均数据传输率,每秒所需字节数、缓冲区大小 pHeader->pwf.wf.nBlockAlign = m_channels * m_channelbits / 8;//以字节为单位设置块对齐,一个采样的字节数 pHeader->pwf.wBitsPerSample = m_channelbits;//每次采样样本的大小;16位,即设置PCM的方式为16位立体声(双通道) pHeader->chDATA[0] = 'd'; pHeader->chDATA[1] = 'a'; pHeader->chDATA[2] = 't'; pHeader->chDATA[3] = 'a'; pHeader->dwDATALen = totalLen - WAVE_HEAD_LENGTH;//数据的长度,=文件总长度-头长度(44bit) char *pWaveBuffer = new char[totalLen]; //音频数据 memcpy(pWaveBuffer, pHeader, WAVE_HEAD_LENGTH); int freNum = freqVec.size(); int singleLen = m_samplefreq*durations/freNum; char* tempBuffer = pWaveBuffer + WAVE_HEAD_LENGTH; for ( int iFre = 0; iFre < freNum; ++iFre ) { if ( iFre > 0 ) { tempBuffer += singleLen; } //TODO:最后一个参数 MakeWaveData(pHeader->pwf.wf.nSamplesPerSec, freqVec[iFre], volume, tempBuffer, singleLen);//采样点数 } ofstream ocout; ocout.open(wavPath, ios::out | ios::binary);//以二进制形式打开文件 if (ocout) ocout.write(pWaveBuffer, totalLen); else return 0; ocout.close(); delete(pHeader); return 1; } int main() { vector<int> freqVec; freqVec.push_back(262); freqVec.push_back(294); freqVec.push_back(330); freqVec.push_back(349); freqVec.push_back(392); freqVec.push_back(440); freqVec.push_back(494); freqVec.push_back(524); std::string wavPath = "D:\\lhcWave.wav"; if (Create(freqVec, 20, freqVec.size()/2, wavPath)) cout << "创建成功!" << endl; else cout << "创建失败!" << endl; //system( "pause" ); return 0; }