2013-03-29 76 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); 

解決了這個問題,以確保您在二進制模式。