Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qt QFile write WAV头仅写入4字节数据_Qt_Wav_Qfile - Fatal编程技术网

Qt QFile write WAV头仅写入4字节数据

Qt QFile write WAV头仅写入4字节数据,qt,wav,qfile,Qt,Wav,Qfile,我正在写一个WAV录音机,使用QFile作为主干。然而,当我填充Wav结构并尝试将其写入QFile时,它只写“RIFF”,我使用unix的od-cb1.Wav查看它。以下是示例代码: wavwriter.cpp Wav::Wav(const char *fname, QFile* parent) : QFile(fname, parent), m_fname(fname) { setFileName(fname); bool res = this->

我正在写一个WAV录音机,使用QFile作为主干。然而,当我填充Wav结构并尝试将其写入QFile时,它只写“RIFF”,我使用unix的
od-cb1.Wav
查看它。以下是示例代码:

wavwriter.cpp

   Wav::Wav(const char *fname, QFile* parent)
    : QFile(fname, parent),
      m_fname(fname)
{
    setFileName(fname);
    bool res = this->open(QIODevice::ReadWrite);
    if (res) {
        std::cout << "File opened for RW\n";
    }
}

Wav::~Wav()
{
}

void Wav::writeHeader(const WavHdr* hdr)
{
    write((char*)hdr);
    flush();
}

void Wav::appendData(const QByteArray &data)
{
    m_data.append(data);
}

QByteArray Wav::getWavData()
{
    return m_data;
}
WavHdr具有以下设置:

    struct WavHdr
{
    char riff[4];
    qint32 file_size;
    char wave[4];
    char fmt[4];
    char len[3];
    qint16 type;
    quint16 format;
    qint32 sample_rate;
    qint32 sr_bs_channs;
    quint8 bits_per_sample;
    char data[4];
    qint32 fsize;
};

这段代码似乎写入了所有44个字节:

char wav[44]={0};
memcpy(wav, hdr, 44);
write(QByteArray(wav), 44);
flush();
但是我必须检查是否所有的东西都填好了

  • 您不能将
    WavHdr
    直接转储到磁盘

    使用
    write
    方法的方式仅适用于以零结尾的字符串。它将在第一个零值字节停止写入。
    WavHdr
    不是以null结尾的字符串

    不能假设结构在内存中有任何特定的表示形式。编译器可以按照自己认为合适的方式自由安排该结构。它不仅可以任意填充和对齐成员,还可以重新排列它们。所以这是一个不可移植的反模式:它可能在某些编译器上工作,在其他编译器上则会被彻底破坏

  • 您的
    WavHdr
    错误

    请参阅以供参考。我在下面包含了一个正确的标题结构

  • 您可能希望使用
    QSaveFile

    保存文件时,您通常希望文件写入是原子的:要么成功写入并获得完整、有效的
    WAV
    文件,要么失败且磁盘上没有任何更改(例如,现有文件未被覆盖和损坏)。这就是
    QSaveFile
    的设计目的

  • 您可能希望wave类使用I/O设备,但不是这样

    只需一个
    QIODevice*
    实例即可完成I/O:然后您就可以轻松地将数据写入内存缓冲区、文件、网络套接字等。您的类用户应该可以自由选择要使用的特定设备

  • 相反,使用
    QDataStream
    以可移植的方式写入标头:

    struct WavHdr
    {
       constexpr static quint32 k_riff_id = 0x46464952;
       constexpr static quint32 k_wave_format = 0x45564157;
       constexpr static quint32 k_fmt_id = 0x20746d66;
       constexpr static quint32 k_data_id = 0x61746164;
       // RIFF
       quint32 chunk_id = k_riff_id;
       quint32 chunk_size;
       quint32 chunk_format = k_wave_format;
       // fmt
       quint32 fmt_id = k_fmt_id;
       quint32 fmt_size;
       quint16 audio_format;
       quint16 num_channels;
       quint32 sample_rate;
       quint32 byte_rate;
       quint16 block_align;
       quint16 bits_per_sample;
       // data
       quint32 data_id = k_data_id;
       quint32 data_size;
    };
    
    bool write(QIODevice * dev, const WavHdr & h) {
      QDataStream s{dev};
      s.setByteOrder(QDataStream::LittleEndian); // for RIFF
      s << h.chunk_id << h.chunk_size
        << h.chunk_format;
      s << h.fmt_id << h.fmt_size
        << h.audio_format
        << h.num_channels
        << h.sample_rate
        << h.byte_rate
        << h.block_align
        << h.bits_per_sample;
      s << h.data_id << h.data_size;
      return s.status() == QDataStream::Ok;
    }
    
    struct WavHdr
    {
    constexpr static quint32 k_riff_id=0x46464952;
    constexpr静态quint32 k_波形格式=0x45564157;
    constexpr static quint32 k_fmt_id=0x20746d66;
    constexpr static quint32 k_data_id=0x61746164;
    //里夫
    quint32 chunk\U id=k\U riff\U id;
    五分之32块大小;
    quint32 chunk\U格式=k\U wave\U格式;
    //fmt
    quint32 fmt_id=k_fmt_id;
    32个fmt_尺寸;
    16音频格式;
    16个数字通道;
    32个样本率;
    32字节/单位速率;
    quint16块_对齐;
    每个样本五次16位;
    //资料
    quint32 data_id=k_data_id;
    数据大小;
    };
    bool write(QIODevice*dev,const WavHdr&h){
    qdatastreams{dev};
    s、 setByteOrder(QDataStream::LittleEndian);//用于RIFF
    
    这是错误的。如果它碰巧起作用,那只是因为你很幸运,而不是因为你的代码是正确的。这是一种反模式。不要这样做。另外,
    flush()
    是不必要的。1st是错误的。你可以做
    写入(重新解释(hdr),sizeof(*hdr));
    因为文件是以二进制文件打开的。但是必须对结构进行打包才能正确执行,并且必须提供较小的尾数。@ilotXXI“打包”正确的结构并使其成为little endian是不可移植的。C/C++
    struct
    的设计目的不是提供任何一种可以信赖的二进制布局。你可以进行大量的破解,但这并不意味着它们是正确的或合理的。
    struct WavHdr
    {
       constexpr static quint32 k_riff_id = 0x46464952;
       constexpr static quint32 k_wave_format = 0x45564157;
       constexpr static quint32 k_fmt_id = 0x20746d66;
       constexpr static quint32 k_data_id = 0x61746164;
       // RIFF
       quint32 chunk_id = k_riff_id;
       quint32 chunk_size;
       quint32 chunk_format = k_wave_format;
       // fmt
       quint32 fmt_id = k_fmt_id;
       quint32 fmt_size;
       quint16 audio_format;
       quint16 num_channels;
       quint32 sample_rate;
       quint32 byte_rate;
       quint16 block_align;
       quint16 bits_per_sample;
       // data
       quint32 data_id = k_data_id;
       quint32 data_size;
    };
    
    bool write(QIODevice * dev, const WavHdr & h) {
      QDataStream s{dev};
      s.setByteOrder(QDataStream::LittleEndian); // for RIFF
      s << h.chunk_id << h.chunk_size
        << h.chunk_format;
      s << h.fmt_id << h.fmt_size
        << h.audio_format
        << h.num_channels
        << h.sample_rate
        << h.byte_rate
        << h.block_align
        << h.bits_per_sample;
      s << h.data_id << h.data_size;
      return s.status() == QDataStream::Ok;
    }