gpt4 book ai didi

c++ - 实时音频,快速循环中的临时缓冲区,不同的方法

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:17:26 25 4
gpt4 key购买 nike

我的应用程序必须处理实时音频,为此我必须创建一个临时缓冲区来保存处理过的音频,直到它到达驱动程序为止。我用多线程来做到这一点,所以我基本上是这样做的:

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() 时,都会创建一个新的 float 缓冲区,然后在 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 缓冲区,并在程序退出时删除它:

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;

请注意,上面的代码只是一个示例,我的实际代码使用了多个线程并使用了立体声音频。只使用一个线程将其变成“多线程”是没有意义的,因此请不要对此发表评论。

问题:

  1. vector 分配和解除分配的速度有多快?
  2. 在非常快速的循环中连续创建然后删除内存缓冲区有多安全?
  3. 您认为哪种方法更安全?

最佳答案

  1. 足够快。 vector 为元素分配的内存是连续的。
  2. 这在通用硬件上并不是真正的安全问题,因为您不希望内存用完。如果您正在实现驱动程序或此代码需要在嵌入式系统中运行,则可能会有所不同。
  3. 最安全的方法是 vector 方法,前提是您的操作正确(ProcessChunk 不会调整 vector 的大小)。

    方法一可以,但还是手动管理内存。如果您不记得删除[] 怎么办?

    使用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];
}
}

关于c++ - 实时音频,快速循环中的临时缓冲区,不同的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31450268/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com