【发布时间】:2019-06-14 06:29:42
【问题描述】:
我是 C# 的新手,在音频项目上可能需要一些帮助。
我的音频输入缓冲区在填满时调用一个方法。在我将这个缓冲区编组到本地 float[] 的方法中,将它传递给一个函数,在该函数中完成一些音频处理。处理完函数后,我会通过 Marshall.copy 将操纵的 float[] 传回音频输出缓冲区。它可以工作,但是很难足够快地完成音频处理,将结果传递回方法而不以丑陋的故障告终。如果我扩大音频缓冲区,它会变得更好,但我会在信号链中得到无法忍受的高延迟。
一个问题是GC。我的 DSP 例程正在执行一些 FFT,并且这些方法经常需要分配局部变量。我认为这大大减慢了我的进程。
所以我需要一种方法来分配一次(并重新访问)一些非托管内存,在整个运行时保持这个内存 fpr 并从方法中引用它。
我找到了例如:
IntPtr hglobal = Marshal.AllocHGlobal(8192);
Marshal.FreeHGlobal(hglobal);
所以我尝试用静态成员定义一个全局静态类“Globasl”并将该 IntPtr 分配给它。
Globals.mem1 = hglobal;
我现在可以通过任何其他方法访问它 例如
int[] f = new int[2];
f[0] = 111;
f[1] = 222;
Marshal.Copy(f, 0, Globals.mem1, 2);
现在我的问题来了: 如果我想用另一种方法从上面的示例中访问这个 int[],我该怎么做?
感谢您的快速帮助。 我好像有点不准确,对不起
我的音频设备驱动程序引发了一个我捕获的缓冲区填充事件(在伪代码中,因为我现在无法访问我的家庭桌面)。看起来像:
void buffer (....)
{
byte[] buf = new byte[asiobuffersize];
marshall.copy(asioinbuffers, 0, buf, asiobufferlenth);
buf= manipulate(buf);
marshall.copy(buf, 0, asiooutbuffer, asiobufferlenth);
}
操作函数正在做一些从字节到浮点数的转换,然后是一些数学 (FFT) 和反向转换到字节,看起来像例如
private byte[] manipulate(byte[] buf, Complex[] filter)
{
float bu = convertTofloat(buf); //conversion from byte to audio float here
Complex[] inbuf = new Complex[bu.Length];
Complex[] midbuf = new Complex[bu.Length];
Complex[] mid2buf = new Complex[bu.Length];
Complex[] outbuf = new Complex[bu.Length];
for ( n....)
{
inbuf[n]= bu[n]; //Copy to Complex
}
midbuf=FFT(inbuf); //Doing FFT transform
for (n....)
{
mid2buf[n]=midbuf[n]*filter[n]; // Multiply with filter
}
outbuf=iFFT(mid2buf) //inverse iFFT transform
byte bu = convertTobyte(float); //conversion from float back to audio byte
return bu;
}
在这里,我希望我的速度问题是。所以我认为如果操纵函数可以“获得”一块固定的非托管内存(一旦预先创建)固定所有这些变量(例如复杂)和预先分配的内存,问题就可以解决,所以我不能每次调用函数时创建新的。我首先想到了错误 FFT 或数学故障的原因,但它发生在几秒钟的“尖锐”时间距离内,因此它与削波等音频信号问题无关。我认为问题发生了,当 GC 正在做一些严肃的工作并且正好吃掉我这几毫秒的时间以及时填充输出缓冲区时。 可以接受。
【问题讨论】:
-
我在这里看不到方法。从其他方法访问某些内容是什么意思?
-
看不到你的很多代码我建议用
using封装你的处理,所以该对象只在它被使用的时间内有效,而垃圾收集器不需要照顾它 -
主要的问题是你在复制任何东西。如果没有看到更多的代码,很难给你一个合适的解决方案。简单地在你的静态类上分配一个静态数组应该让它在 appdomain 的生命周期内保持活跃,并且不应该需要“重新分配”。也就是说,在任何高吞吐量环境中批量复制缓冲区都会导致一些性能问题。我们需要查看更多代码。
-
短期本地 POCO 变量很少引入任何显着的性能影响。事实上,拥有大量短期变量是 GC 优化的场景。我建议不要在这种优化上浪费时间,而是寻找一种方法来修改代码以避免缓冲区复制。