嘿所有,我正在编写一个将麦克风输入录制到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;
}
如果此处有任何内容会导致错误数据附加到文件中,请告知我们。如果没有,我将三重检查输入数据(在回调中)。这个数据应该是好的,因为如果我将它复制到更大的缓冲区(例如,两分钟)然后保存它就可以了。
答案 0 :(得分: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
是一个指针,所以不知道你为什么在写中使用&
。
答案 1 :(得分:1)
最可能的原因是你从指针的地址写入缓冲区,而不是缓冲区本身。放弃“&amp;”在最后的mFile.write中。 (如果你的缓冲区是在附近分配的,那么它可能会有一些很好的数据,你碰巧抓住了它的一大块,但这只是运气,你的写作需要重叠你的缓冲区)
一般情况下,如果您发现自己处于这种情况,您可以尝试考虑如何独立于录制代码测试此代码:设置一个值为0..255的缓冲区,并且然后将“块大小”设置为16,看它是否在16个独立的写操作中写出了连续的0..255序列。这将很快验证您的缓冲代码是否正常工作。
答案 2 :(得分:0)
我不会调试您的代码,但会尝试为您提供可以尝试检查的内容的清单,并确定错误的位置:
尝试所有这些,你会更好地了解哪里出了问题。
答案 3 :(得分: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;
}
}
将尝试你们的建议和报告。