读wav文件

#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;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值