2013-03-29 47 views
1

我正在编写一个应用程序,该应用程序应该将一个浮点数组写入WAVE文件。我为此使用QDataStream,但是这导致了一个我不能解释的非常不可思议的输出。看起来QDataStream有时会选择32位浮点数,有时候会选择40位浮点数。这会弄乱整个输出文件,因为它必须遵守严格的格式。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' 

回答

5

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

此答案的所有信用去给出答案: Length of float changes between 32 and 40 bit

1

注:我不知道我是对的低于100% ,并希望听到我错了,但这是我的想法:

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

+0

谢谢,至少给出了一种没有for循环的方法;那很棒。但它仍然会产生相同的不一致性,有些花车比其他花车更长!这似乎意味着阵列中的浮点数是可变长度的(4或5个字节),这看起来非常不可能。 – Yellow

+0

并使用'QByteArray :: fromRawData()'似乎给出完全相同的问题... – Yellow

1

我即使我没有使用IODevice ::文本标记类似的问题。我发现,添加一行

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

解决了这个问题,以确保您在二进制模式。