QDataStream有时使用32位浮点数,有时使用40位浮点数

时间:2013-03-29 13:30:49

标签: c++ wav qt4.8

我正在编写一个应用程序,它应该将一个浮点数组写入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字节数字。有谁知道这可能是什么原因?

修改 在检查两个浮点数的大小时,它们看起来确实是4 char长,但是:

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

3 个答案:

答案 0 :(得分:5)

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

此答案的所有学分都会转到以下答案: Length of float changes between 32 and 40 bit

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

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

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