c++ - 使用 ofstream 写入二进制数据时出现问题

标签 c++ audio binary wav ofstream

大家好,我正在编写一个将麦克风输入记录到 WAV 文件的应用程序。以前,我写过这个来填充指定大小的缓冲区并且工作正常。现在,我希望能够记录到任意长度。这是我正在尝试做的事情:

  • 设置32个小音频缓冲区(循环缓冲)
  • 使用 ofstream 启动一个 WAV 文件——写入 header ,PCM 长度设置为 0
  • 为输入添加一个缓冲区
  • 当缓冲区完成时,将其数据附加到 WAV 文件并更新标题;回收缓冲区
  • 当用户点击“停止”时,将剩余的缓冲区写入文件并关闭

它的工作原理是文件的长度正确(标题和文件大小都是正确的)。然而,数据非常不稳定。我可以辨认出我所说的内容——而且时间是正确的——但是有这种重复的失真 block 。基本上听起来只有一半的数据进入了文件。

这是代码使用的一些变量(在标题中)

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

}

如果此处有任何内容看起来会导致错误数据附加到文件中,请告诉我。如果没有,我将三次检查输入数据(在回调中)。此数据应该很好,因为如果我将它复制到更大的缓冲区(例如,两分钟)然后保存它,它就可以工作。

最佳答案

我只是想知道,怎么办

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是一个指针,不知道为什么要在write中使用&

关于c++ - 使用 ofstream 写入二进制数据时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4972810/

相关文章:

php - 如何用php将文件内容转换为字节数组

c# - FtpWeb 请求错误 : 550 Size not allowed in ASCII mode

c++ - 删除指向数组 C++ 的数组指针时出错

iphone - 音频播放中特定时间回调

python - 反转二进制文件中 float32 字节顺序的快速方法

javascript - 当鼠标不在 HTML 元素上时,将 Rythm.js 播放的音乐静音

audio - 使用 AFSK 将数字数据调制成音频

c++ - 为什么std::forward_list::: remove和std::erase <std::forward_list>具有不同的值类型?

c++ - 在 Visual Studio 下使用 pair 作为 hash_map 的键

c++ - 在 boost async_receive_from 上定义超时