2

float の配列を 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'
4

3 に答える 3

5

答えは、出力ファイルを開くところにありQIODevice::Textます。これはバイナリ ファイルであるため、フラグを省略しておく必要があります。text-flag が含まれている場合、0d各 の前に文字が挿入されます0a0aそのため、文字を含む各フロートはchar長く見えます。

この回答のすべてのクレジットは、次の回答に 当てはまります。フロートの長さは32ビットと40ビットの間で変化します

于 2013-04-02T16:20:19.570 に答える
1

IODevice::Text フラグを使用していなくても、同様の問題が発生しました。行を追加することがわかりました

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

バイナリモードであることを確認するために問題を解決しました。

于 2013-04-22T21:17:08.177 に答える
1

注: 私は 100% 正しいとは確信していません。私が間違っていることを知りたいのですが、これが私が考える方法です:

QDataStreamには独自のシリアル化形式があり、確認していませんが、おそらくそれに関連しています。ポイントは、それを使ってやろうとしていることを意図したものではありません.バイナリ形式だけを書いてください. クラスを利用することもできますが、メソッドのみを使用しwriteRawData()、バイトオーダーなどを自分で処理する必要があると思います。

于 2013-03-29T13:51:56.343 に答える