写入.WAV – C时的两个问题

我目前正在用C语言编写一个带有openFrameworks的程序音乐引擎.我可以生成一首歌并从浮点数的标准化(在-1和1之间)缓冲区中播放它完全没问题,但是当我尝试将相同的浮点缓冲区写入32位时,我遇到了一些问题.WAV文件.

>当我在Finder的预览中播放文件时(我在OSX 10.9.2上),整个歌曲持续时间的播放被极度剪裁和扭曲.它似乎能够很好地读取格式,因为它显示正确的文件持续时间,比特率和采样率http://i.stack.imgur.com/fz2w8.png.奇怪的是,当我将同一个文件拖到Logic Pro X中时,它被读取正常,转换成功并播放回来没有失真.它还会生成一个波形显示,我可以看到两个通道(文件是立体声)的波形完全标准化(至少上半年……见下一期).
>虽然Logic Pro X能够比Finder的预览更成功地读取文件,但是在歌曲中途有一个很大的幅度跳跃并且波形开始剪辑(尽管远不及Finder播放中那么多).每次生成的歌曲(它们在结构上,节奏上和乐器上每次都不同)都会发生这种情况,我试图写入.WAV.你可以在这里看到一个例子http://i.stack.imgur.com/59y5w.jpg.

以下是我用来写入.WAV文件的代码:

template <typename T>
void write(std::ofstream& stream, const T& t) {
    stream.write((const char*)&t, sizeof(T));
}

template <typename SampleType>
void writeWAVData(const char* outFile, SampleType* buf, size_t bufSize, int sampleRate, short channels)
{
    std::ofstream stream(outFile, std::ios::binary);                // Open file stream at "outFile" location

    /* Header */
    stream.write("RIFF", 4);                                        // sGroupID (RIFF = Resource Interchange File Format)
    write<int>(stream, 36 + bufSize);                               // dwFileLength
    stream.write("WAVE", 4);                                        // sRiffType

    /* Format Chunk */
    stream.write("fmt ", 4);                                        // sGroupID (fmt = format)
    write<int>(stream, 16);                                         // Chunk size (of Format Chunk)
    write<short>(stream, 1);                                        // Format (1 = PCM)
    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 aka Block align
    write<short>(stream, 8 * sizeof(SampleType));                   // Bits per sample

    /* Data Chunk */
    stream.write("data", 4);                                        // sGroupID (data)
    stream.write((const char*)&bufSize, 4);                         // Chunk size (of Data, and thus of bufferSize)
    stream.write((const char*)buf, bufSize);                        // The samples DATA!!!
}

我使用以下行调用“writeWAVData”函数:

writeWAVData(path.c_str(), &buffer[0], sampleDuration * NUM_OF_CHANNELS * sizeof(buffer[0]), sampleRate, NUM_OF_CHANNELS);

哪里:

> path是包含文件路径的字符串.
> buffer是一个动态分配的浮点数组,它是我的样本缓冲区(我在这一步之前对样本进行规范化,当我对它们进行归类时,我可以看到它们完全在-1.0f和1.0f之间,没有任何剪辑).
> sampleRate是一个int的采样率.
> sampleDuration是样本中作为int的持续时间.
> NUM_OF_CHANNELS是定义为int的标头(在本例中为2).

任何建议,手腕上的拍打,完美的解决方案或严厉的批评都非常感谢!

解决方案:问题是我将“格式块”中的格式标记设置为1表示PCM.将其更改为3(对于FLOAT格式)后,.wav文件将完美播放.原始答案在这里https://stackoverflow.com/a/22227440/1711917.

最佳答案 我没有检查游标头,它看起来很好,但是在十六进制编辑器中查看文件并与
a reference进行比较是个好主意.我认为你的问题在于:

buffer is a dynamically allocated array of floats that is my buffer of samples (I am normalising the samples just before this step and when I cout them I can see that they are perfectly between -1.0f and 1.0f without any clipping).

您直接转储浮点数组,但WAV / PCM使用整数样本,通常为8或16位.在这里指定32位样本并将它们编码为浮点数而不是整数.

你有3个选择:

>使用char []或short []数据
>生成float []但在写入文件之前转换为char []或short []
>更改格式以支持浮点数据:format-tag 3 / FLOAT而不是1 / PCM,see here.

点赞