#ifndef _WAVE_FILE_H_
#define _WAVE_FILE_H_
#include <stdint.h>
#include <string>
#include <fstream>
#include <memory>
struct WaveHeader_S
{
char riff[4]; //资源交换文件标志(RIFF)
uint32_t file_length; //文件总大小 - size(riff) - sizeof(file_length)
char wave[4]; //wav文件标志(WAVE)
char fmt[4]; //波形格式标志(fmt)
uint32_t fmt_length; //过滤字节 16 或 18,表示到数据标志(data)还有几个字节
uint16_t format; //格式种类,1-PCM编码
uint16_t channels; //通道数,1-单声道,2-立体声
uint32_t sample_rate; //采样率
uint32_t bytes_p_second; //波形数据传输速率(每秒平均字节数),计算公式:声道数×采样频率×每样本的数据位数 / 8
uint16_t blocks_align; //数据的调整数(按字节计算) <1 or 2>
uint16_t sample_length; //样本的数据位数,采样分辨率(采样精度),常见:8, 12 or 16 bit,位数越高,表示的动态范围越大,音频质量也更高
};
class WaveFile
{
public:
WaveFile(const std::string &filePath);
~WaveFile();
public:
bool is_ok() const;
uint32_t get_sample_length() const;
uint32_t get_channels() const;
uint32_t get_sample_rate() const;
uint32_t get_frame_size() const;
char *get_data() const;
uint32_t get_data_len() const;
private:
bool read_header();
void dump_header();
bool read_data();
std::string formatCoverToStr(int format);
private:
std::ifstream m_file;
WaveHeader_S m_waveHeader;
uint32_t m_dataLen;
std::unique_ptr<char[]> m_data;
bool m_waveIsOk;
};
#endif
#include "WaveFile.h"
#include <stdio.h>
#include <string.h>
#define WAV_FMT_PCM 0x0001
#define WAV_FMT_IEEE_FLOAT 0x0003
#define WAV_FMT_DOLBY_AC3_SPDIF 0x0092
#define WAV_FMT_EXTENSIBLE 0xfffe
WaveFile::WaveFile(const std::string &filePath)
: m_file(filePath, std::ios::binary)
, m_dataLen(0)
, m_data(nullptr)
, m_waveIsOk(false)
{
memset(&m_waveHeader, 0x0, sizeof(WaveHeader_S));
if (m_file.is_open())
{
if (read_header())
{
if (read_data())
{
m_waveIsOk = true;
}
}
}
else
{
printf("open %s failed \n", filePath.c_str());
}
}
WaveFile::~WaveFile()
{
if (m_file.is_open())
{
m_file.close();
}
}
bool WaveFile::read_header()
{
m_file.read(reinterpret_cast<char*>(&m_waveHeader), sizeof(WaveHeader_S));
if (m_file.gcount() != sizeof(WaveHeader_S))
{
printf("read wav header failed \n");
return false;
}
dump_header();
char data_flag[8] = {0};
if (m_waveHeader.fmt_length == 16)
{
m_file.read(data_flag, 4);
if (m_file.gcount() != 4)
{
printf("read data flag failed \n");
return false;
}
printf("data_flag: %c%c%c%c\n", data_flag[0], data_flag[1], data_flag[2], data_flag[3]);
}
else if (m_waveHeader.fmt_length == 18)
{
m_file.read(data_flag, 6);
if (m_file.gcount() != 6)
{
printf("read data flag failed \n");
return false;
}
printf("data_flag: %c%c%c%c\n", data_flag[2], data_flag[3], data_flag[4], data_flag[5]);
}
else
{
return false;
}
m_file.read(reinterpret_cast<char*>(&m_dataLen), sizeof(m_dataLen));
if (m_file.gcount() != sizeof(m_dataLen))
{
printf("read data len failed \n");
return false;
}
printf("data len: %d\n\n", m_dataLen);
return true;
}
void WaveFile::dump_header()
{
printf("riff: %c%c%c%c\n", m_waveHeader.riff[0], m_waveHeader.riff[1], m_waveHeader.riff[2], m_waveHeader.riff[3]);
printf("file_length: %d\n", m_waveHeader.file_length);
printf("wave: %c%c%c%c\n", m_waveHeader.wave[0], m_waveHeader.wave[1], m_waveHeader.wave[2], m_waveHeader.wave[3]);
printf("fmt: %c%c%c%c\n", m_waveHeader.fmt[0], m_waveHeader.fmt[1], m_waveHeader.fmt[2], m_waveHeader.fmt[3]);
printf("fmt_length: %d\n", m_waveHeader.fmt_length);
printf("format: %s\n", formatCoverToStr(m_waveHeader.format).c_str());
printf("channels: %d\n", m_waveHeader.channels);
printf("sample_rate: %d\n", m_waveHeader.sample_rate);
printf("bytes_p_second: %d\n", m_waveHeader.bytes_p_second);
printf("blocks_align: %d\n", m_waveHeader.blocks_align);
printf("sample_length: %d\n", m_waveHeader.sample_length);
}
bool WaveFile::read_data()
{
if (m_dataLen <= 0)
{
printf("data len error \n");
return false;
}
m_data = std::unique_ptr<char[]>(new char[m_dataLen]);
m_file.read(m_data.get(), m_dataLen);
if (m_file.gcount() != m_dataLen)
{
printf("read data failed, m_dataLen:%d, read len: %ld \n", m_dataLen, m_file.gcount());
return false;
}
return true;
}
std::string WaveFile::formatCoverToStr(int format)
{
switch (format) {
case WAV_FMT_PCM:
return "PCM";
break;
case WAV_FMT_IEEE_FLOAT:
return "IEEE FLOAT";
break;
case WAV_FMT_DOLBY_AC3_SPDIF:
return "DOLBY AC3 SPDIF";
break;
case WAV_FMT_EXTENSIBLE:
return "EXTENSIBLE";
break;
default:
return "";
break;
}
}
bool WaveFile::is_ok() const
{
return m_waveIsOk;
}
uint32_t WaveFile::get_sample_length() const
{
return m_waveHeader.sample_length;
}
uint32_t WaveFile::get_channels() const
{
return m_waveHeader.channels;
}
uint32_t WaveFile::get_sample_rate() const
{
return m_waveHeader.sample_rate;
}
/*
帧长度 = 样本长度 * 声道数 / 8, 单位:字节
*/
uint32_t WaveFile::get_frame_size() const
{
return m_waveHeader.sample_length * m_waveHeader.channels / 8;
}
char *WaveFile::get_data() const
{
return m_data.get();
}
uint32_t WaveFile::get_data_len() const
{
return m_dataLen;
}