如何创建指向与 VST 音频缓冲区相同的指针数组的指针
How to create pointer to pointer array same as VST audio buffer?
在VST规范中,多声道音频数据的缓冲区被传递.....
MyClass::ProcessDoubleReplacing(double **inputs, double **outputs, int frames)
{
//and accessed like this...
outputs[channel][sample] = inputs[channel][sample]
}
我想创建一个类似的"2d 指针数组",但没有取得多大成功。 我可以创建一个简单的指针并遍历它读取/写入值......
double* samples;
samples[0] = aValue;
....但是我有一个崩溃节,试图实施一些让我......
samples[0][0] = aValue;
实现这一点的正确方法是什么?
double* samples;
samples[0] = aValue;
这真的很糟糕。:(请不要这样做!"样本"只是指向内存中某处的指针。它指向的内存根本没有分配,但您正在写入此内存...
您可以从堆或堆栈分配内存块。但是,堆栈有大小限制(在编译器设置中配置) - 因此对于较大的块(如音频数据),您通常会从堆中分配它。但是你必须小心,你不会从堆中泄漏内存 - 堆栈内存由变量的作用域自动管理,所以这更容易开始。在 C/C++ 中,你可以像这样从堆栈中分配内存:
double samples[512];
然后你可以做这样的事情:
samples[0] = aValue; // change value of 1st sample in sample buffer with 512 elements
或
double* pointerToSample = samples[255]; // point to 256ths sample in the sample buffer
pointerToSample[127] = aValue; // change value of 384ths sample (256+128) in our sample buffer with 512 elements
等等...但如果你只是这样做,
double* pointerToSample;
pointerToSample[127] = aValue;
您实际上是在写入未分配的内存!您的指针指向某处,但后面没有分配的内存。小心这个!如果样本变量已经超出范围,也永远不要访问 pointerToSample:否则不再分配内存指针到样本指向。
要从C++堆中分配内存,有关键字 new(分配内存)和删除(之后释放内存)。
即
double *samples = new double[512];
将为示例数据分配内存块。但是使用它后,您必须手动删除它 - 否则您将泄漏内存。所以只需做:
delete[] samples;
在你完成它之后。
最后但并非最不重要的是回答您的问题,如何创建一个二维数组来调用方法ProcessDoubleReplacing()
int main(int argc, char ** argv){
/* create 2 dimensional array */
int** samplesIn = new int*[44100];
int** samplesOut = new int*[44100];
for(int i = 0; i < 44100; ++i){ // 1s @ 44.1Khz
samplesIn[i] = new int[2]; // stereo
samplesOut[i] = new int[2]; // stereo
}
/* TODO: fill your input buffer with audio samples from somewhere i.e. file */
ProcessDoubleReplacing(samplesIn, samplesOut, 44100);
/* cleanup */
for(int i = 0; i < 44100; ++i) {
delete [] samplesIn[i];
delete [] samplesOut[i];
}
delete [] samplesIn;
delete [] samplesOut;
return 0;
}
>@Constantin的回答几乎是钉住了它,但我只是想补充一点,在您的实现中,您不应该在process()
回调中分配缓冲区。这样做可能会导致您的插件花费太多时间,因此系统可能会丢弃音频缓冲区,从而导致播放故障。
因此,这些缓冲区应该是主处理类(即AEffect
)的字段,并且您应该在构造函数中分配它们的大小。切勿在process()
方法中使用new
或delete
,否则您将自找麻烦!
这是关于实时音频编程的注意事项的精彩指南。
用C++写一些东西来提供类似于你展示的界面,我会使用 std::vector
来管理内存,如下所示:
vector<vector<double>> buffers (2,vector<double>(500));
这仅存储数据。对于指针数组,您需要一个指针数组。:)
vector<double*> pointers;
pointers.push_back(buffers[0].data());
pointers.push_back(buffers[1].data());
这是有效的,因为std::vector
保证所有元素都相邻且线性存储在内存中。因此,您也可以这样做:
double** p = pointers.data();
p[0][123] = 17;
p[1][222] = 29;
请务必注意,如果调整其中一些向量的大小,指针可能会无效,在这种情况下,您应该继续获取新指针。
请记住,data
成员函数是 C++11 功能。如果你不想使用它,你可以写
&some_vector[0] // instead of some_vector.data()
(除非向量为空)
您可能有兴趣直接通过引用传递缓冲区向量,而不是将 double** 传递给某个函数,但是,如果您希望接口与 C 兼容,这显然是行不通的。只是说。
编辑:关于为什么我选择std::vector
而不是new[]
和malloc
的说明:因为这在现代C++中是正确的做法!在这种情况下,搞砸的机会较低。您不会有任何内存泄漏,因为矢量负责管理内存。这在C++中尤其重要,因为您可能会有异常飞来飞去,因此在函数结束时使用delete[]
之前可能会提前退出函数。
- 将字符缓冲区强制转换为函数指针
- 将指针作为缓冲区传递到第一个字符串元素
- 将constexpr字节数组与缓冲区的一部分(指向数据的指针)进行比较
- char p[0]表示自动分配的缓冲区还是安全指针
- 指针符号在参数规范中表示什么,例如:(char16 *缓冲区,int32 大小)?C++
- OpenGL:使用指向静态数据的指针数组传递缓冲区数据
- 重置/包装 C/C++ 中的变量(环缓冲区指针)
- 将 char* 推送到矢量时出现问题,但在每次迭代后,它会将指向相同值缓冲区的指针添加到矢量中
- 返回指向矢量数据的指针,而不复制缓冲区和内存泄漏
- memcpy指向炭缓冲区的指针
- 来自 2 个指针的组合缓冲区,无需复制
- 来自指针向量的OpenGL阵列缓冲区
- C++:使用指针访问缓冲区与使用增量变量
- 具有两个不同缓冲区的指针算法
- 初始化的std ::阵列从指针优雅地变成缓冲区
- 使用新的位置来创建静态常量指针,指向静态内存缓冲区
- C++:使用std::ifstream读取二进制文件后删除缓冲区/指针时发生访问冲突
- visual 在指向缓冲区(字符串 " ")的空指针上使用 sizeof() C++ 以获得以字节为单位的大小?
- 如何将一个缓冲区指针的内容复制到另一个缓冲区指针
- 正在将缓冲区/指针设置为null