大家好,我正在编写一个将麦克风输入记录到 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;
}
如果这里有任何看起来会导致错误数据附加到文件的内容,请告诉我。如果没有,我将三重检查输入数据(在回调中)。这个数据应该很好,因为如果我将它复制到更大的缓冲区(例如,两分钟)然后保存它,它就可以工作。