实时音频,快速循环中的临时缓冲区,不同的方法
Real-time audio, temporary buffers in fast loop, different methods
我的应用程序必须处理实时音频,为此我必须创建一个临时缓冲区来保存处理过的音频,直到它到达驱动程序。我在多线程中这样做所以我基本上是这样做的:
float *ProcessChunk(int sf)
{
float tmp = new float[sf]; // Remember to delete[]
for (int s=0; s<sf; ++s)
tmp[s] = myProcessor->Tick(); // an external class that does the audio processing and returns the result per sample
}
void AudioCallbackFunction(void *outputBuffer, int sampleFrames)
{
float *out = (float*)outputBuffer;
auto t1 = async(launch::async, &ProcessChunk, sampleFrames);
float *b = t1.get();
for (int s=0; s<sampleFrames; ++s)
{
*out++ = b[s];
}
delete[] b;
}
在上面的例子中,这是完美的工作,每次ProcessChunk()
被调用,一个新的浮点缓冲区被创建,然后在AudioCallbackFunction()
中被删除。
另一种方法是使用vector:
vector<float> ProcessChunk(int sf)
{
vector<float> tmp;
for (int s=0; s<sf; ++s)
tmp[s] = myProcessor->Tick();
return tmp;
}
void AudioCallbackFunction(void *outputBuffer, int sampleFrames)
{
float *out = (float*)outputBuffer;
auto t1 = async(launch::async, &ProcessChunk, sampleFrames);
vector<float> b = t1.get(); // get another copy of the vector?
for (int s=0; s<sampleFrames; ++s)
{
*out++ = b[s];
}
}
另一种替代方法是在程序启动时只创建一次浮点缓冲区,并在程序退出时删除它:
float *tmp;
// Once i know the exact value of sampleFrames
tmp = new float[sampleFrames];
float *ProcessChunk(int sf)
{
for (int s=0; s<sf; ++s)
tmp[s] = myProcessor->Tick();
}
void AudioCallbackFunction(void *outputBuffer, int sampleFrames)
{
float *out = (float*)outputBuffer;
auto t1 = async(launch::async, &ProcessChunk, sampleFrames);
float *b = t1.get();
for (int s=0; s<sampleFrames; ++s)
{
*out++ = b[s];
}
}
// in main() when the program quits
delete[] tmp;
请注意,上面的代码只是一个例子,我的实际代码使用多个线程,并使用立体声音频。只使用一个线程将使它成为"多线程"没有意义,所以请不要评论这个。
问题:
- 向量分配和释放有多快?
- 在一个非常快的循环中连续创建然后删除内存缓冲区是多么安全?
- 您认为哪种方法更安全?
- 不够快。vector为元素分配的内存是连续的。 在通用硬件上,这不是一个真正的安全问题,因为你不希望内存耗尽。如果您正在实现一个驱动程序或此代码需要在嵌入式系统中运行,则可能会有所不同。
最安全的方法是矢量之一,假设你做得正确(
ProcessChunk
不调整矢量大小)。方法1很好,但是您仍然需要手动管理内存。如果你没有记得删除[]呢?
使用
global
缓冲区需要额外注意线程安全。多少取决于你的实际代码。
可以将vector和惟一缓冲区组合:
vector<float> permbuffer;
void ProcessChunk(vector<float>& perm, int sf)
{
//perm size will eventually converge.
perm.resize(sf);
for (int s=0; s<sf; ++s)
perm[s] = myProcessor->Tick();
return; //good practice would be to return effectively read
}
void AudioCallbackFunction(void *outputBuffer, int sampleFrames)
{
float *out = (float*)outputBuffer;
//ditch async for thread to use references
std::thread t(ProcessChunk, std::ref(permbuffer), sampleFrames);
t.wait();
for (int s=0; s<sampleFrames; ++s)
{
*out++ = permbuffer[s];
}
}
相关文章:
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- 为什么 Glib::VariantBase::store 方法破坏了给定缓冲区的开始
- C++ - 有什么方法可以将输入插入缓冲区/停止 cin.忽略需要输入?
- OpenGL 顶点缓冲区类重定义和模板方法错误
- 将随机数放入缓冲区以写入文件的有效方法是什么?
- 将数组与传入的字节*缓冲区进行比较的最快方法
- memcmp - 是否有更快的方法来按位比较两个缓冲区
- 操作方法:将 boost::endian 缓冲区类型转换回本机格式
- 从二进制缓冲区初始化变量的正确方法是什么
- 从 char* 缓冲区读取int32_t的惯用 cpp14 方法是什么?
- 在环形缓冲区中向后循环的好方法是什么
- 是否有更好的方法来处理缓冲区和阅读中的不完整数据
- 在amd64体系结构上的C++中,将图像缓冲区blit到另一个缓冲区的xy偏移中的最快方法
- 从与对象大小不一致的连续固定大小缓冲区解析对象的有效方法
- 在堆栈和堆上使用较低级别的方法获取缓冲区的长度
- 在 c++ 中使用消息结构读取/填充数据缓冲区的正确方法是什么?
- 连接多个缓冲区的有效方法
- 在C++中使用 fread 时实现固定大小缓冲区的最佳方法是什么?
- VisualC++DLL将2-3兆字节复制到C#缓冲区的最快方法是什么
- 在字符串附加函数中,null终止无符号字符缓冲区的有效方法