写入Wave标头和添加数据,而不关闭流

时间:2014-07-02 19:30:00

标签: c++ iostream wav

正如主题所说,这是代码:

    template <typename SampleType>
void writeWAVHeader
(
char const* outFile,
SampleType* buf,
int sizeMult,
size_t bufSize,
int sampleRate,
short channels,
int Flush
)
{ 
    if (sizeMult != 0)
        bufSize = bufSize*sizeMult;

        std::ofstream stream(outFile, std::ios::in | std::ios::binary | std::ios::app);
    stream.seekp(0);
    stream.write("RIFF", 4);
    write<int>(stream, 36 + bufSize);
    stream.write("WAVE", 4);
    stream.write("fmt ", 4);
    write<int>(stream, 16);
    writeFormat<SampleType>(stream);                                // Format
    write<short>(stream, channels);                                 // Channels
    write<int>(stream, sampleRate);                                 // Sample Rate
    write<int>(stream, sampleRate * channels * sizeof(SampleType)); // Byterate
    write<short>(stream, channels * sizeof(SampleType));            // Frame size
    write<short>(stream, 8 * sizeof(SampleType));                   // Bits per sample
    stream.write("data", 4);
    stream.write((const char*)&bufSize, 4);
    stream.seekp(stream.end);
    if(sizeMult != 0)
        bufSize = bufSize/sizeMult;
    stream.write((const char*)buf, bufSize);
    stream.flush();
    if (Flush >= 100)
    stream.close();
}

你可以看到我一直在尝试的注释掉的东西。

在我看来,这应该很容易。

我用这些参数打开文件,寻找开头,写标题,然后寻找到最后,因为我附加到wave并重写标题,但它不起作用。它只是一直重写整个事物。

代码是它工作时的样子。我必须关闭并重新打开,对我来说,在这种情况下没有任何意义。

更新

我更改了代码,但这并没有按预期工作,我感到困惑。

我seekp(0)=文件的开头。

写下标题。

寻找文件的末尾,。

添加新的音频数据。

2 个答案:

答案 0 :(得分:3)

问题的第一部分在于使用std::ios::app标志。如cppreference

所示
  

app在每次写入之前寻求到流的结尾

因此,如果您使用此选项,则无论seekp(0)次呼叫如何,都会在文件末尾附加标题和数据。因此,您应该打开您的信息流:

std::ofstream stream(outFile, std::ios::in | std::ios::binary);

问题的另一部分是使用seekp。当使用单个参数seekp调用时,将常量std::ios::end(在某种类型转换之后)解释为文件中的绝对位置(相对于文件的开头),而不是使用对应于文件的结尾。

所以你应该换行:

stream.seekp(stream.end)

为:

steam.seekp(0, stream.end);

答案 1 :(得分:1)

这是一个符合预期的工作代码。 它可能有问题,但如果没有人说什么,那么这很可能就是我的问题的答案。

template <>
void writeFormat<float>(std::ofstream& stream) {
    write<short>(stream, 3);
}


template <typename SampleType>
void writeWAVHeader
(
char const* outFile,
SampleType* buf,
int sizeMult,
size_t bufSize,
int sampleRate,
short channels,
int Flush
)
{ 
    if (sizeMult != 0)
        bufSize = bufSize*sizeMult;


    std::ofstream stream(outFile, std::ios::in | std::ios::binary);

    stream.write("RIFF", 4);
    write<int>(stream, 36 + bufSize);
    stream.write("WAVE", 4);
    stream.write("fmt ", 4);
    write<int>(stream, 16);
    writeFormat<SampleType>(stream);                                // Format
    write<short>(stream, channels);                                 // Channels
    write<int>(stream, sampleRate);                                 // Sample Rate
    write<int>(stream, sampleRate * channels * sizeof(SampleType)); // Byterate
    write<short>(stream, channels * sizeof(SampleType));            // Frame size
    write<short>(stream, 8 * sizeof(SampleType));                   // Bits per sample
    stream.write("data", 4);
    stream.write((const char*)&bufSize, 4);
    stream.seekp(0,stream.end);
    if(sizeMult != 0)
        bufSize = bufSize/sizeMult;
    stream.write((const char*)buf, bufSize);
    stream.flush();
    if (Flush >= 100) //Prevent close on each run.
        {
        stream.close();

    }

}