读取.wav文件 - 不读取标头
Reading .wav files - Not reading header?
我正在尝试从.wav文件中读取标头信息,并且正在读取文件的以下属性:
type
size
Format Tag
Format Length
Channels
Sample Rate
Average Bytes Second
Block Align
Bits Per Sample
Data size
现在,一切都可以完美读取,直到读取采样率,然后,输出要么是"0"值,要么只是 NULL。
这是代码:(我已经打开了文本文件,并将指针传递给了成员函数)
bool Wav::readHeader(FILE *dataIn)
{
char type2[4];
fread(this->type, sizeof(char), 4, dataIn);
fread(&this->size, sizeof(int), 1, dataIn);
fread(this->type, sizeof(char), 4, dataIn);
fread(this->type, sizeof(char), 4, dataIn);
fread(&this->format_length, sizeof(short), 1, dataIn);
fread(&this->format_tag, sizeof(short), 1, dataIn);
fread(&this->channels, sizeof(short), 1, dataIn);
fread(&this->sample_rate, sizeof(unsigned int), 1, dataIn);
fread(&this->avg_bytes_sec, sizeof(unsigned short), 1, dataIn);
fread(&this->block_align, sizeof(short), 1, dataIn);
fread(&this->bits_per_sample, sizeof(short), 1, dataIn);
return true;
}
类成员定义为:
char type[4];
int size;
unsigned short format_tag;
unsigned short format_length;
unsigned short channels;
unsigned int sample_rate;
unsigned short avg_bytes_sec;
unsigned short block_align;
unsigned short bits_per_sample;
unsigned int data_size;
有人有任何解决方案或建议吗?
(附言如果这个问题不对,请道歉。我试图尽我所能写它!
如果你有代表 (PCM) WAVE 标头的紧密打包结构,它将如下所示:
struct Riff
{
char chunkId[4]; // "RIFF" (assuming char is 8 bits)
int chunkSize; // (assuming int is 32 bits)
char format[4]; // "WAVE"
};
struct Format
{
char chunkId[4]; // "fmt "
int chunkSize;
short format; // assuming short is 16 bits
short numChannels;
int sampleRate;
int byteRate;
short align;
short bitsPerSample;
};
struct Data
{
char chunkId[4]; // "data"
int chunkSize; // length of data
char* data;
};
struct Wave // Actual structure of a PCM WAVE file
{
Riff riffHeader;
Format formatHeader;
Data dataHeader;
};
从本质上讲,您的问题是format_length
(在我的结构中Format::chunkSize
)和avg_bytes_sec
(在我的结构中Format::byteRate
)在您的代码中各是 2 个字节,但它们每个应该是 4。您也没有读取数据子块的标头,但我认为这是故意的?
要阅读,您可以执行以下操作:
void readWave(std::ifstream& file, Wave& wave)
{
// First read the RIFF header
file.read(wave.riffHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.riffHeader.chunkSize), 4);
file.read(wave.riffHeader.format, 4);
// Now read the FORMAT header
file.read(wave.formatHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.chunkSize), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.format), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.numChannels), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.sampleRate), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.byteRate), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.align), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.bitsPerSample), 2);
// Now read the DATA header
file.read(wave.dataHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.dataHeader.chunkSize), 4);
// The actual data goes in wave.dataHeader.data, so you can allocate it
// and then read direclty into it now
}
Michael的链接是我需要读/写WAVE文件时总是使用的链接(我不得不这样做几次)。我建议你仔细阅读。
如果你的 WAVE 文件中在"数据"区块之前有额外的区块,这段代码应该能够跳过它们:
void readWave(std::ifstream& file, Wave& wave)
{
// First read the RIFF header
file.read(wave.riffHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.riffHeader.chunkSize), 4);
file.read(wave.riffHeader.format, 4);
// Now read the FORMAT header
file.read(wave.formatHeader.chunkId, 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.chunkSize), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.format), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.numChannels), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.sampleRate), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.byteRate), 4);
file.read(reinterpret_cast<char*>(&wave.formatHeader.align), 2);
file.read(reinterpret_cast<char*>(&wave.formatHeader.bitsPerSample), 2);
// WAVE files are just a special type of RIFF file, so it's possible
// there are other chunks, like "fact" chunks. We'll skip over these
// extra chunks until we find a "data" chunk
char chunkId[4] = {0};
int chunkSize = 0;
while (file.read(chunkId, 4) &&
(chunkId[0] != 'd' ||
chunkId[1] != 'a' ||
chunkId[2] != 't' ||
chunkId[3] != 'a'))
{
file.read(reinterpret_cast<char*>(&chunkSize), 4); // Read the chunk's size
file.seekg(chunkSize, std::ios_base::cur); // Skip the chunk
}
// We've found the DATA chunk and header
wave.dataHeader.chunkId[0] = chunkId[0];
wave.dataHeader.chunkId[1] = chunkId[1];
wave.dataHeader.chunkId[2] = chunkId[2];
wave.dataHeader.chunkId[3] = chunkId[3];
file.read(reinterpret_cast<char*>(&wave.dataHeader.chunkSize), 4);
// The actual data goes in wave.dataHeader.data, so you can allocate it
// and then read direclty into it now
}
相关文章:
- 理解boost::asio-async_read在无需读取内容时的行为
- 使用新行和不使用新行读取文件
- 读取文件并输入到矢量中
- 用c++从输入文件中读取另一行
- 读取文件的最后一行并输入到链接列表时出错
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 无法找到/读取配置文件.conf-FileIOException
- 如何使用Luacneneneba API正确读取字符串和表参数
- C++将文本文件中的数据读取到结构数组中
- ifstream(c ++)的替代方案,同时尝试在Android中读取.wav文件
- 正在读取Wav文件,输出错误
- 读取.wav文件 - 不读取标头
- 使用Hopfield神经网络读取WAV文件的数据部分以进行语音识别
- 使用libsndfile库读取C++中的WAV文件
- 在c中读取.wav文件并从中提取频率
- 在c++中读取.wav数据时的意外输出
- 在C/ c++中读取和处理WAV文件数据
- 读取16位wav文件并将其归一化,如Matlab所做的
- 读取.wav文件并在C++中应用FFT
- Istream:每个样本读取和wav格式位