我目前正在使用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
是动态分配的float
s数组,它是我的样本缓冲区(我在此步骤之前对样本进行规范化,当我cout
时,我可以看到它们完全在-1.0f
和1.0f
之间,没有任何剪辑。sampleRate
的采样率为int
。sampleDuration
是样本中的持续时间int
。NUM_OF_CHANNELS
是定义的标头int
(在这种情况下为2
)。任何建议,手腕上的拍打,完美的解决方案或严厉的批评都非常感谢!
解决方案:问题是我将“格式块”中的格式标记设置为1表示PCM。将其更改为3(对于FLOAT格式)后,.wav文件将完美播放。原始答案https://stackoverflow.com/a/22227440/1711917。
答案 0 :(得分:2)
我没有检查游标标题,看起来很好,但最好在十六进制编辑器中查看文件并与a reference进行比较。我认为你的问题在于:
缓冲区是一个动态分配的浮点数组,它是我的样本缓冲区(我在这一步之前对样本进行规范化,当我对它们进行规范时,我可以看到它们完全在-1.0f和1.0f之间,没有任何剪裁)
您直接转储float
数组,但WAV / PCM使用整数样本,通常为8或16位。在这里指定32位样本并将它们编码为浮点数而不是整数。
您有3个选项:
char[]
或short[]
数据float[]
但在写入文件前转换为char[]
或short[]