首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当我写入.wav文件时,输出音轨中没有声音

当我写入.wav文件时,输出音轨中没有声音
EN

Stack Overflow用户
提问于 2022-03-07 15:11:01
回答 1查看 59关注 0票数 0

我在C++中很新,我试图解析.wav文件,以便在其上添加一些音频效果。因此,首先我尝试读取和解析输入.wav文件,然后将其写入输出.wav文件。输出文件在资源管理器中具有相同的大小,在音频播放器中具有一定的持续时间,但是在播放时声音是不存在的。它有什么问题?

这是我的密码。

代码语言:javascript
复制
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

struct WavHeader
{
    char                chunkId[4];     // RIFF, FMT, DATA, e.t.c.
    unsigned long       ChunkSize;      // Chunk Size  
};

struct RiffHeader : WavHeader
{
    char                format[4];      // WAVE Header      
};

struct FmtHeader : WavHeader
{                            
    unsigned short      AudioFormat;    // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM 
    unsigned short      NumOfChan;      // Number of channels 1=Mono 2=Sterio                   
    unsigned long       SamplesPerSec;  // Sampling Frequency in Hz                             
    unsigned long       bytesPerSec;    // bytes per second 
    unsigned short      blockAlign;     // 2=16-bit mono, 4=16-bit stereo 
    unsigned short      bitsPerSample;  // Number of bits per sample
};

struct DataHeader : WavHeader
{
};

struct Wav
{
    RiffHeader RiffHeader;
    FmtHeader FmtHeader;
    DataHeader DataHeader;
    vector<char> Data;
};

/// <summary>
/// Read/write .wav files.
/// </summary>
class WavFileManager
{
public:
    /// <summary>
    /// Read whole .wav file.
    /// </summary>
    /// <param name="path">Path to file.</param>
    Wav ReadAll(const string& path)
    {
        ifstream file(path);

        if (!file)
        {
            throw runtime_error("Can't open file: " + path);
        }

        Wav* wavFile = new Wav();

        wavFile->RiffHeader = ReadHeader<RiffHeader>(file);

        if (wavFile->RiffHeader.format != "WAVE\0")
        {
            // throw runtime_error("Wrong format. File: " + path);
        }

        wavFile->FmtHeader = ReadHeader<FmtHeader>(file);

        if (!TrySkipChunksBefore(file, "data"))
        {
            throw runtime_error("Can't find wav data. File: " + path);
        }

        wavFile->DataHeader = ReadHeader<DataHeader>(file);


        vector<char>& data = wavFile->Data;
        data.reserve(wavFile->DataHeader.ChunkSize);
        for (int i = 0; i < wavFile->DataHeader.ChunkSize; i++)
        {
            char buffer;
            file.read((char*)&buffer, sizeof(char));
            data.push_back(buffer);
        }
        reverse(data.begin(), data.end());


        file.close();
        return *wavFile;
    }

    /// <summary>
    /// Read header of .wav file.
    /// </summary>
    /// <param name="file">File stream.</param>
    /// <returns>Header of type T.</returns>
    template<typename T>
    T ReadHeader(ifstream& file)
    {
        T header;
        int headerSize = sizeof(T);
        file.read((char*)&header, headerSize);
        return header;
    }

    /// <summary>
    /// Read data chunk of .wav file.
    /// </summary>
    /// <param name="file">File stream.</param>
    /// <param name="size">Chunk size.</param>
    /// <returns>Array of bytes.</returns>
    char* ReadChunk(ifstream& file, unsigned long size)
    {
        char* chunk = new char[size];
        file.read(chunk, size);
        return chunk;
    }

    /// <summary>
    /// Check if .wav header has following chunkId.
    /// </summary>
    /// <param name="header">.wav header.</param>
    /// <param name="chunkId">Id to compare.</param>
    bool HasChunkID(const WavHeader& header, const char chunkId[4])
    {
        return ((header.chunkId[0] == chunkId[0]) &&
            (header.chunkId[1] == chunkId[1]) &&
            (header.chunkId[2] == chunkId[2]) &&
            (header.chunkId[3] == chunkId[3]));
    }

    /// <summary>
    /// Skip all chunks before reqired chunk.
    /// </summary>
    /// <param name="file">File stream.</param>
    /// <param name="chunkId">Id of required chunk.</param>
    bool TrySkipChunksBefore(ifstream& file, const char chunkId[4])
    {
        while (!file.eof())
        {
            streampos pos = file.tellg();
            WavHeader header = ReadHeader<WavHeader>(file);
            char* chunk = ReadChunk(file, header.ChunkSize);
            if (HasChunkID(header, chunkId))
            {
                file.clear();
                file.seekg(pos);
                return true;
            }
            delete[] chunk;
        }
        return false;
    }

    /// <summary>
    /// Write all data into file.
    /// </summary>
    /// <param name="data">Wav to write.</param>
    /// <param name="path">Path to output file.</param>
    void WriteAll(Wav data, const string& path)
    {
        ofstream file(path, ios::binary);
        file.write((char*)&data.RiffHeader, sizeof(RiffHeader));
        file.write((char*)&data.FmtHeader, sizeof(FmtHeader));
        file.write((char*)&data.DataHeader, sizeof(DataHeader));
        reverse(data.Data.begin(), data.Data.end());
        for (int i = 0; i < data.Data.size(); i++)
        {
            file.write((char*)&data.Data[i], sizeof(char));
        }
        file.close();
    }
};

int main()
try
{
    auto* mgr = new WavFileManager();
    auto wav = mgr->ReadAll ("input.wav");
    mgr->WriteAll(wav, "output.wav");
}
catch (runtime_error& e)
{
    cerr << "Error! " << e.what() << '\n';
}
EN

回答 1

Stack Overflow用户

发布于 2022-03-09 09:33:39

解决问题很容易。

代码语言:javascript
复制
ifstream file(path, ios::binary);

而不是

代码语言:javascript
复制
ifstream file(path);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71383152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档