2011-02-11 31 views
0

ちょっと、私はマイク入力をWAVファイルに記録するアプリケーションを作成しています。これまでは、指定したサイズのバッファを埋めるためにこれを書いていましたが、うまくいきました。今、私は任意の長さに録音できるようにしたいと思います。ここで私は何をしようとしているのです:ofstreamでバイナリデータを書き込む際の問題

    32個の小さなオーディオのバッファ(循環バッファリング)を設定
  • はofstreamのでWAVファイルを起動
  • - 追加0
  • に設定PCMの長さのヘッダーを書きます入力バッファー
  • バッファーが完了したら、そのデータをWAVファイルに追加してヘッダーを更新します。ユーザーがファイルに残りのバッファを書き、「停止」と近い

それは一種のファイルは、ヘッダとファイルサイズ(正しい長さに出てきていることで動作しているヒットするとバッファ

  • をリサイクル正しい)。しかし、そのデータは地獄のように不安定です。私は、私が言ったこととタイミングが正しいことのようなものを作り出すことができますが、この反復的な歪みのブロックがあります。基本的には、データの半分しかファイルに入っていないようです。

    // Start recording audio 
    void CaptureApp::startRecording() 
    { 
    
        // Set flag 
        mRecording = true; 
    
        // Set size values 
        mPcmBufferPosition = 0; 
        mPcmTotalSize = 0; 
    
        // Open file for streaming 
        mFile.open("c:\my.wav", ios::binary|ios::trunc); 
    
    } 
    

    ここでバッファを受け取るコードは次のとおり

    ここで(ヘッダ内の)コードが使用ここ

    // File writing 
    ofstream mFile; 
    WAVFILEHEADER mFileHeader; 
    int16_t * mPcmBuffer; 
    int32_t mPcmBufferPosition; 
    int32_t mPcmBufferSize; 
    uint32_t mPcmTotalSize; 
    bool mRecording; 
    

    ファイルを準備するコードであり、いくつかの変数です。これは、受信データが正しいことを前提としています - になりますが、そうではないと判断していません。

    // Append file buffer to output WAV 
    void CaptureApp::writeData() 
    { 
    
        // Update header with new PCM length 
        mPcmBufferPosition *= sizeof(int16_t); 
        mPcmTotalSize += mPcmBufferPosition; 
        mFileHeader.bytes = mPcmTotalSize + sizeof(WAVFILEHEADER); 
        mFileHeader.pcmbytes = mPcmTotalSize; 
        mFile.seekp(0); 
        mFile.write(reinterpret_cast<char *>(&mFileHeader), sizeof(mFileHeader)); 
    
        // Append PCM data 
        if (mPcmBufferPosition > 0) 
        { 
         mFile.seekp(mPcmTotalSize - mPcmBufferPosition + sizeof(WAVFILEHEADER)); 
         mFile.write(reinterpret_cast<char *>(&mPcmBuffer), mPcmBufferPosition); 
        } 
    
        // Reset file buffer position 
        mPcmBufferPosition = 0; 
    
    } 
    

    そして、これは、ファイルを閉じコードです:

    // Stop recording 
    void CaptureApp::stopRecording() 
    { 
    
        // Save remaining data 
        if (mPcmBufferSize > 0) 
         writeData(); 
    
        // Close file 
        if (mFile.is_open()) 
        { 
         mFile.flush(); 
         mFile.close(); 
        } 
    
        // Turn off recording flag 
        mRecording = false; 
    
    } 
    

    それがファイルに追加取得不良データにつながるように見えるここに何があるのならば、私に知らせてください。そうでない場合は、入力データ(コールバック内)を3回確認します。このデータでなければなりません。なぜなら、それを大きなバッファ(例えば2分)にコピーしてから保存すると機能するからです。

  • +0

    この[mPcmBufferPosition * = sizeof(int16_t); ]はタイプミスのように見えます。それは+ =であるはずですか? –

    答えて

    2

    私がどれだけ

    void CaptureApp::writeData() 
    { 
        mPcmBufferPosition *= sizeof(int16_t); // mPcmBufferPosition = 0, so 0*2 = 0; 
    
    // (...) 
        mPcmBufferPosition = 0; 
    
    } 
    

    は作品(ところで。はsizeof int16_tは常に2である)、疑問に思って。 mPcmBufferPositionを別の場所に設定していますか?

    void CaptureApp::writeData() 
    { 
    
        // Update header with new PCM length 
        long pos = mFile.tellp(); 
        mPcmBufferBytesToWrite *= 2; 
        mPcmTotalSize += mPcmBufferBytesToWrite; 
        mFileHeader.bytes = mPcmTotalSize + sizeof(WAVFILEHEADER); 
        mFileHeader.pcmbytes = mPcmTotalSize; 
    
        mFile.seekp(0); 
        mFile.write(reinterpret_cast<char *>(&mFileHeader), sizeof(mFileHeader)); 
        mFile.seekp(pos); 
    
        // Append PCM data 
        if (mPcmBufferBytesToWrite > 0)  
         mFile.write(reinterpret_cast<char *>(mPcmBuffer), mPcmBufferBytesToWrite); 
    } 
    

    またmPcmBufferはポインタであるので、あなたが書き込みで&を使用する理由がわかりません。

    +0

    mPcmBufferはconst int16_t(ファイルバッファが大きな固定長のとき)であって、ポインタではありませんでした。私はストリーミングを開始すると明らかにそれを逃した。 – BTR

    1

    最も可能性が高いのは、ポインタ自体のバッファではなく、ポインタのアドレスからバッファに書き込むことです。最終的なmFile.writeに "&"と記入してください。(あなたのバッファが近くに割り当てられていて、そのチャンクを取得した場合は、その中にいくつかの良いデータがあるかもしれませんが、あなたのバッファがあなたのバッファに重なり合うのはちょうど運がいい)

    一般に、この種の状況では、記録コードとは別にこのコードをテストする方法を考えてみることができます。値が0..255のバッファを設定し、 "チャンクサイズ"を16に設定し、 16個の別々の書き込み操作に渡って0..255の連続したシーケンスを書き出す場合です。それはすぐにあなたのバッファリングコードが動作しているかどうかを確認します。

    +0

    これは答えですが、最初のポスターの方が数分早いです。ええ、これは、あまりにも少ない睡眠で長すぎるために同じコードを見ているケースで終わった。しかし、誰もがWAVにオーディオをストリーミングする方法を知りたい場合に備えて、私はそれを投稿してうれしいです。 :) – BTR

    +0

    また、私はコードを少し簡略化しました。 sizeof(int16_t)ここで私のコードでは実際にsizeof(T)です。 – BTR

    0

    私はあなたのコードをデバッグすることはありませんが、あなたがチェックし、エラーだ場所を判断しようとすることができるもののことチェックリスト与えることをしようとします:

    • は常に持っている参照先レコーダーやプレーヤー便利に。これは、Windowsサウンドレコーダー、Audacity、またはAdobe Auditionなどの簡単なものにすることができます。レコーダー/プレーヤーにあなたが正しくファイルを記録して再生させるようにしてください。
    • あなたのアプリにファイルを記録し、参照プレーヤーで再生してみてください。ワーキング?
    • リファレンスレコーダーでファイルを記録して、プレーヤーと再生してみます。ワーキング?
    • レコーダーのWAVファイルにSOUNDデータを書き込むときに、1つの余分なファイルに書き込みます。そのファイルをRAWモードでプレーヤーで開きます(Windowsサウンドレコーダーでは十分ではありません)。それは正しく再生されますか?
    • あなたのプレーヤーでファイルを再生し、サウンドカードに書き込み、RAWファイルに出力を書き込んで、データを正しく再生しているか、サウンドカーが問題になっているかどうかを確認します。それは正しく再生されますか?

    これをすべて試してみると、どこが間違っているのかがはっきり分かります。

    0

    シュート、申し訳ありません - 深夜の仕事があり、今日は少し離れています。私はあなたに実際のコールバックを示すのを忘れてしまった。これです:

    // Called when buffer is full 
    void CaptureApp::onData(float * data, int32_t & size) 
    { 
    
        // Check recording flag and buffer size 
        if (mRecording && size <= BUFFER_LENGTH) 
        { 
    
         // Save the PCM data to file and reset the array if we 
         // don't have room for this buffer 
         if (mPcmBufferPosition + size >= mPcmBufferSize) 
          writeData(); 
    
         // Copy PCM data to file buffer 
         copy(mAudioInput.getData(), mAudioInput.getData() + size, mPcmBuffer + mPcmBufferPosition); 
    
         // Update PCM position 
         mPcmBufferPosition += size; 
    
        } 
    
    } 
    

    y'allsのアドバイスとレポートを試します。

    関連する問題