2

我正在编写一个应用程序,该应用程序应该将浮点数组写入 WAVE 文件。我为此使用了 QDataStream,但这会导致我无法解释的非常不可能的输出。似乎 QDataStream 有时会选择 32 位浮点数,有时会选择 40 位浮点数。这会弄乱整个输出文件,因为它必须遵守严格的格式。

我的代码大致如下所示:

float* array;
unsigned int nSamples;

void saveWAV(const QString& fileName) const 
{
    QFile outFile(fileName);
    if (outFile.open(QIODevice::WriteOnly | QIODevice::Text)) 
    {
        QDataStream dataStream(&outFile);
        dataStream.setByteOrder(QDataStream::LittleEndian);
        dataStream.setFloatingPointPrecision(QDataStream::SinglePrecision);

        // ... do all the WAV file header stuff ...

        for(int ii = 0; ii < nSamples; ++ii) 
            dataStream << array[ii];
    }
}

我想不出为什么这段代码会产生这样的副作用。所以我做了一个最小的例子来了解发生了什么。我用这个替换了for循环:

float temp1 = 1.63006e-33f;
float temp2 = 1.55949e-32f;

dataStream << temp1;
dataStream << temp1;
dataStream << temp2;
dataStream << temp1;
dataStream << temp2;

然后我使用 Matlab 打开输出文件并查看写入文件的字节。那些是:

8b 6b 07 09      // this is indeed 1.63006e-33f (notice it's Little Endian)
8b 6b 07 09 
5b f2 a1 0d 0a    // I don't know what this is but it's a byte to long
8b 6b 07 09 
5b f2 a1 0d 0a

我非常随意地选择了这些值,它们恰好具有这种效果。一些值导出为 4 字节,而另一些值导出为 5 字节数字。有谁知道这可能是什么原因?

编辑: 当检查两个花车的大小时,它们看起来确实有 4char秒长,不过:

    qDebug() << sizeof(temp1); // prints '4'
    qDebug() << sizeof(temp2); // prints '4'
4

3 回答 3

5

答案在于打开输出文件:QIODevice::Text标志应该被忽略,因为它是一个二进制文件。如果包含 text-flag,0d则在每个0a. 因此,每个包含0a字符的浮点数似乎都char更长。

此答案的所有学分都归于以下给出的答案: 浮点长度在 32 和 40 位之间变化

于 2013-04-02T16:20:19.570 回答
1

注意:我不是 100% 确定我在下面,并且很想听到我错了,但我认为是这样的:

QDataStream有它自己的序列化格式,虽然我没有检查,但可能与此有关。关键是,它并不意味着你想用它做什么:只写任何二进制格式。您可以使用该类,但我相信您只需要使用writeRawData()方法,并自己处理字节顺序等。

于 2013-03-29T13:51:56.343 回答
1

即使我没有使用 IODevice::Text 标志,我也遇到了类似的问题。我发现添加一行

dataStream.device()->setTextModeEnabled(false);

解决了问题以确保您处于二进制模式。

于 2013-04-22T21:17:08.177 回答