VC++ 保存数据为音频文件(WAV)学习
? ? 根據(jù)到目前我的認識,凡是保存為某種格式的文件的程序,都是用C++做的。下面來學(xué)習(xí)一下保存為wav文件;
1. 音頻簡介
經(jīng)常見到這樣的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等.
44100HZ 16bit stereo: 每秒鐘有 44100 次采樣, 采樣數(shù)據(jù)用 16 位(2字節(jié))記錄, 雙聲道(立體聲);
22050HZ 8bit ?mono: 每秒鐘有 22050 次采樣, 采樣數(shù)據(jù)用 8 位(1字節(jié))記錄, 單聲道;
采樣率是指:聲音信號在“模→數(shù)”轉(zhuǎn)換過程中單位時間內(nèi)采樣的次數(shù)。采樣值是指每一次采樣周期內(nèi)聲音模擬信號的積分值。
對于單聲道聲音文件,采樣數(shù)據(jù)為八位的短整數(shù)(short int 00H-FFH);
而對于雙聲道立體聲聲音文件,每次采樣數(shù)據(jù)為一個16位的整數(shù)(int),高八位(左聲道)和低八位(右聲道)分別代表兩個聲道。
人對頻率的識別范圍是 20HZ - 20000HZ, 如果每秒鐘能對聲音做 20000 個采樣, 回放時就足可以滿足人耳的需求. 所以 22050 的采樣頻率是常用的, 44100已是CD音質(zhì), 超過48000的采樣對人耳已經(jīng)沒有意義。這和電影的每秒 24 幀圖片的道理差不多。
2 wav 文件格式
WAV文件遵循RIFF規(guī)則,其內(nèi)容以區(qū)塊(chunk)為最小單位進行存儲。
WAV文件一般由3個區(qū)塊組成:RIFF chunk、Format chunk和Data chunk。另外,文件中還可能包含一些可選的區(qū)塊,如:Fact chunk、Cue points chunk、Playlist chunk、Associated data list chunk等。
3 VC++保存數(shù)據(jù)為音頻文件
首先要定義波形數(shù)據(jù)格式,
typedef struct{WORD ?wFormatTag;?
?? ? ?WORD nChannels;?
?? ? ?DWORD nSamplesPerSec;?
?? ? ?DWORD nAvgBytesPerSec;
?? ? ?WORD ?nBlockAlign;?
?? ? ?WORD wBitsPerSample;?
?? ? ?WORD ?cbSize; } WAVEFORMATEX;
wFormatTag:波形數(shù)據(jù)的格式,定義在MMREG.H文件中
nChannels:波形數(shù)據(jù)的通道數(shù):單聲道或立體聲
nSamplesPerSec:采樣率,對于PCM格式的波形數(shù)據(jù),采樣率有8.0 kHz,11.025kHz,22.05 kHz,44.1 kHz等
nAvgBytesPerSec:數(shù)據(jù)率,對于PCM格式的波形數(shù)據(jù),數(shù)據(jù)率等于采樣率乘以每樣點字節(jié)數(shù)
nBlockAlign:每個樣點字節(jié)數(shù)
wBitsPerSample:采樣精度,對于PCM格式的波形數(shù)據(jù),采樣精度為8或16
cbSize:附加格式信息的數(shù)據(jù)塊大小
然后要定義設(shè)備頭結(jié)構(gòu)
WAVEHDR定義了指向波形數(shù)據(jù)緩沖區(qū)的設(shè)備頭。
typedef struct { LPSTR lpData;?
?? ?DWORD dwBufferLength;?
?? ?DWORD dwBytesRecorded;?
?? ?DWORD dwUser;?
?? ?DWORD dwFlags;?
?? ?DWORD dwLoops;?
?? ?struct wavehdr_tag * lpNext;?
?? ?DWORD reserved; } WAVEHDR;?
lpData:波形數(shù)據(jù)的緩沖區(qū)地址
dwBufferLength:波形數(shù)據(jù)的緩沖區(qū)地址的長度
dwBytesRecorded:當(dāng)設(shè)備用于錄音時,標(biāo)志已經(jīng)錄入的數(shù)據(jù)長度
dwUser:用戶數(shù)據(jù)
dwFlags:波形數(shù)據(jù)的緩沖區(qū)的屬性
dwLoops:播放循環(huán)的次數(shù),僅用于播放控制中
lpNext和reserved均為保留值
定義這些結(jié)構(gòu)體是為了保存數(shù)據(jù)用的;
基本保存代碼如下;
CFile m_file;
CFileException fileException;
CString m_csFileName= "F:\\audio.wav";//保存路徑
m_file.Open(m_csFileName,CFile::modeCreate|CFile::modeReadWrite, &fileException);
DWORD m_WaveHeaderSize = 38;
DWORD m_WaveFormatSize = 18;
m_file.SeekToBegin();
m_file.Write("RIFF",4);
unsigned int Sec=(sizeof pSaveBuffer + m_WaveHeaderSize);
m_file.Write(&Sec,sizeof(Sec));
m_file.Write("WAVE",4);
m_file.Write("fmt ",4);
m_file.Write(&m_WaveFormatSize,sizeof(m_WaveFormatSize));
m_file.Write(&waveform.wFormatTag,sizeof(waveform.wFormatTag));
m_file.Write(&waveform.nChannels,sizeof(waveform.nChannels));
m_file.Write(&waveform.nSamplesPerSec,sizeof(waveform.nSamplesPerSec));
m_file.Write(&waveform.nAvgBytesPerSec,sizeof(waveform.nAvgBytesPerSec));
m_file.Write(&waveform.nBlockAlign,sizeof(waveform.nBlockAlign));
m_file.Write(&waveform.wBitsPerSample,sizeof(waveform.wBitsPerSample));
m_file.Write(&waveform.cbSize,sizeof(waveform.cbSize));
m_file.Write("data",4);
m_file.Write(&dwDataLength,sizeof(dwDataLength));
m_file.Write(pSaveBuffer,dwDataLength);
m_file.Seek(dwDataLength,CFile::begin);
m_file.Close();
總結(jié)
以上是生活随笔為你收集整理的VC++ 保存数据为音频文件(WAV)学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用PowerDesigner设计物理模
- 下一篇: 离散余弦变换和C语言实现-win32版本