我目前正在用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.