加载和保存 WAV 文件
Posted
技术标签:
【中文标题】加载和保存 WAV 文件【英文标题】:Loading and Saving WAV file 【发布时间】:2013-07-31 11:02:16 【问题描述】:我正在尝试将 WAVE 文件加载到数据结构中,然后将其作为原始副本保存回磁盘。加载和保存似乎工作正常,但复制的 WAVE 文件不会播放任何声音(尽管它确实打开没有错误)。我想知道这是否与字节序有关?
这是我保存 WAVE 文件的数据结构:
struct WaveFile
public:
static const uint16 NUM_CHARS = 4;
public:
WaveFile() : Data(nullptr)
~WaveFile() delete[] Data;
char ChunkID[NUM_CHARS];
uint32 ChunkSize;
char Format[NUM_CHARS];
char SubChunkID[NUM_CHARS];
uint32 SubChunkSize;
uint16 AudioFormat;
uint16 NumChannels;
uint32 SampleRate;
uint32 ByteRate;
uint16 BlockAlign;
uint16 BitsPerSample;
char SubChunk2ID[NUM_CHARS];
uint32 SubChunk2Size;
byte* Data;
;
这是我加载它的方式:
std::ifstream file(filename, std::ios::binary);
if (file.good())
file.read(waveFile.ChunkID, WaveFile::NUM_CHARS);
file.read(reinterpret_cast<char*>(&waveFile.ChunkSize), size_ui32);
file.read(waveFile.Format, WaveFile::NUM_CHARS);
file.read(waveFile.SubChunkID, WaveFile::NUM_CHARS);
file.read(reinterpret_cast<char*>(&waveFile.SubChunkSize), size_ui32);
file.read(reinterpret_cast<char*>(&waveFile.AudioFormat), size_ui16);
file.read(reinterpret_cast<char*>(&waveFile.NumChannels), size_ui16);
file.read(reinterpret_cast<char*>(&waveFile.SampleRate), size_ui32);
file.read(reinterpret_cast<char*>(&waveFile.ByteRate), size_ui32);
file.read(reinterpret_cast<char*>(&waveFile.BlockAlign), size_ui16);
file.read(reinterpret_cast<char*>(&waveFile.BitsPerSample), size_ui16);
file.read(waveFile.SubChunk2ID, WaveFile::NUM_CHARS);
file.read(reinterpret_cast<char*>(&waveFile.SubChunk2Size), size_ui32);
waveFile.Data = new byte[waveFile.SubChunk2Size];
file.read(reinterpret_cast<char*>(waveFile.Data), sizeof(waveFile.SubChunk2Size));
file.close();
这就是我将数据写回文件的方式:
std::ofstream file(outfile, std::ios::binary);
if (file.good())
file.flush();
file.write(waveFile.ChunkID, WaveFile::NUM_CHARS);
file.write(reinterpret_cast<const char*>(&waveFile.ChunkSize), size_ui32);
file.write(waveFile.Format, WaveFile::NUM_CHARS);
file.write(waveFile.SubChunkID, WaveFile::NUM_CHARS);
file.write(reinterpret_cast<const char*>(&waveFile.SubChunkSize), size_ui32);
file.write(reinterpret_cast<const char*>(&waveFile.AudioFormat), size_ui16);
file.write(reinterpret_cast<const char*>(&waveFile.NumChannels), size_ui16);
file.write(reinterpret_cast<const char*>(&waveFile.SampleRate), size_ui32);
file.write(reinterpret_cast<const char*>(&waveFile.ByteRate), size_ui32);
file.write(reinterpret_cast<const char*>(&waveFile.BlockAlign), size_ui16);
file.write(reinterpret_cast<const char*>(&waveFile.BitsPerSample), size_ui16);
file.write(waveFile.SubChunk2ID, WaveFile::NUM_CHARS);
file.write(reinterpret_cast<const char*>(&waveFile.SubChunk2Size), size_ui32);
file.write(reinterpret_cast<const char*>(waveFile.Data), waveFile.SubChunk2Size);
file.close();
副本的大小也与原件相同。如果有人想知道,uint16、uint32 和 byte 只是 unsigned short、unsigned int 和 unsigned char 的 typedef。 size_ui32 变量就是这样:
static const uint32 size_ui32 = sizeof(uint32);
static const uint32 size_ui16 = sizeof(uint16);
这不是它,似乎无法找出我哪里出错了。
为任何帮助干杯。
【问题讨论】:
【参考方案1】:这适用于大多数波形文件,但某些标题可能包含特定的用户数据。您可以使用结构 WAVEHEADER 的单写:
struct WAVEFILEHEADER
// don't change the order of attributes
char m_lpcChunkId[4];
int m_iChunkSize;
char m_lpcFormat[4];
char m_lpcSubChunkFmt[4];
int m_iSubChunkFmtSize;
short int m_siAudioFormat;
short int m_siNumChannels;
int m_iSampleRate;
int m_iByteRate;
short int m_siBlockAlign;
short int m_siBitsPerSample;
char m_lpcChunkData[4];
int m_iSubChunkDataSize;
// unsigned char * m_data;
;
WAVEFILEHEADER whdr;
FILE* fid = fopen("newaudio.wav","wb"); // important to use binary file
// some inicialization for whdr - RIFF etc.
// You can use only 1 write to save whole header:
fwrite(&whdr, 1, sizeof(WAVEFILEHEADER), fid);
// or you can read wav header
fread(&whdr, 1, sizeof(WAVEFILEHEADER), fid);
// check chunk size, few headers have aditional 2 bytes (by definition user data, but they was always 0x0000)
【讨论】:
【参考方案2】:发布此问题后,我刚刚发现了问题。
在读取数据时,我已经这样做了:
file.read(reinterpret_cast<char*>(waveFile.Data), sizeof(waveFile.SubChunk2Size));
应该是:
file.read(reinterpret_cast<char*>(waveFile.Data), waveFile.SubChunk2Size);
当我删除 sizeof() 时工作。傻我。
【讨论】:
以上是关于加载和保存 WAV 文件的主要内容,如果未能解决你的问题,请参考以下文章