0

マイク入力を WAV ファイルに記録するアプリケーションを作成しています。以前は、指定されたサイズのバッファを埋めるためにこれを書いていましたが、うまくいきました。さて、任意の長さに録音できるようにしたいと思います。これが私がやろうとしていることです:

  • 32 個の小さなオーディオ バッファをセットアップする (循環バッファリング)
  • ofstream で WAV ファイルを開始 -- PCM の長さを 0 に設定してヘッダーを書き込みます
  • 入力にバッファを追加する
  • バッファが完了すると、そのデータが WAV ファイルに追加され、ヘッダーが更新されます。バッファをリサイクルする
  • ユーザーが「停止」を押したら、残りのバッファをファイルに書き込んで閉じます

ファイルが正しい長さ(ヘッダーとファイルサイズが正しい)になるという点で、それは一種の機能です。ただし、データは地獄のように不安定です。私が言ったことの類似性を理解することができます - そしてタイミングは正しいです - しかし、この反復的な歪みのブロックがあります. 基本的に、データの半分だけがファイルに取り込まれているように聞こえます。

コードが使用するいくつかの変数を次に示します (ヘッダー内)。

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

ファイルを準備するコードは次のとおりです。

// 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);

}

バッファを受け取るコードは次のとおりです。これは、受信データが正しいことを前提としています。正しいはずですが、正しくない可能性も排除していません。

// 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;

}

ファイルに不正なデータが追加される可能性があると思われるものがあれば、お知らせください。そうでない場合は、(コールバックで) 入力データをトリプル チェックします。このデータは、より大きなバッファー (たとえば 2 分) にコピーしてから保存すると機能するため、適切なはずです。

4

4 に答える 4

2

どうやって

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

// (...)
    mPcmBufferPosition = 0;

}

動作します(ところで、sizeofint16_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使用する理由がわかりません。&

于 2011-02-11T19:16:14.773 に答える
1

最も可能性の高い理由は、バッファ自体からではなく、ポインタのアドレスからバッファに書き込んでいることです。最後のmFile.writeの「&」を削除します。(バッファが近くに割り当てられていて、そのチャンクを取得した場合は、適切なデータが含まれている可能性がありますが、書き込みがバッファとオーバーラップする可能性があるのは幸運です)

一般に、このような状況に陥った場合は、レコーディングコードとは別に、このコードをテストする方法を考えてみてください。値が0..255のバッファーを設定してから、 「チャンクサイズ」を16に設定し、16回の個別の書き込み操作で0..255の連続シーケンスを書き出すかどうかを確認します。これにより、バッファリングコードが機能しているかどうかをすばやく確認できます。

于 2011-02-11T19:20:37.350 に答える
0

私はあなたのコードをデバッグしませんが、あなたがチェックしてエラーがどこにあるかを決定するために試みることができるもののチェックリストをあなたに与えることを試みます:

  • 指示対象レコーダーまたはプレーヤーを常に手元に置いてください。これは、Windows Sound Recorder、Audacity、またはAdobeAuditionのような単純なものにすることができます。ファイルを正しく録音および再生できる、確実なレコーダー/プレーヤーを用意します。
  • アプリでファイルを記録し、リファレンスプレーヤーで再生してみてください。働く?
  • 参照レコーダーでファイルを録音し、プレーヤーで再生してみてください。働く?
  • レコーダーのWAVファイルにSOUNDデータを書き込むときは、1つの追加ファイルに書き込みます。そのファイルをプレーヤーでRAWモードで開きます(ここではWindowsサウンドレコーダーでは不十分です)。正しく再生されますか?
  • プレーヤーでファイルを再生し、サウンドカードに書き込むときは、出力をRAWファイルに書き込んで、データが正しく再生されているかどうか、またはサウンドカーに問題があるかどうかを確認します。正しく再生されますか?

これをすべて試してみると、どこで問題が発生したかをより正確に把握できます。

于 2011-02-11T19:22:17.840 に答える
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;

    }

}

皆さんのアドバイスとレポートを試してみます。

于 2011-02-11T20:04:36.273 に答える