C++ 如何创建与VST音频缓冲区相同的指针数组?

C++ 如何创建与VST音频缓冲区相同的指针数组?,c++,arrays,pointers,audio,vst,C++,Arrays,Pointers,Audio,Vst,在VST规范中,多声道音频数据的缓冲区被传递 MyClass::ProcessDoubleReplacing(double **inputs, double **outputs, int frames) { //and accessed like this... outputs[channel][sample] = inputs[channel][sample] } 我想创建一个类似的“2d指针数组”,但没有太大的成功。我可以创建一个简单的指针,并在其中迭代读取/写入值 dou

在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];
vector<vector<double>> buffers (2,vector<double>(500));
然后你可以做一些事情,比如:

samples[0] = aValue; // change value of 1st sample in sample buffer with 512 elements

等等。。。 但如果你这么做

double* pointerToSample;
pointerToSample[127] = aValue;
您正在实现对未分配内存的写入!您的指针指向某个地方,但后面没有分配的内存。 注意!如果samples变量已经超出范围,也不要访问pointerToSample:否则将不再分配指向的内存指针

从C++中的堆中分配内存,关键字是new(分配内存)和动态删除(以后释放内存)。 i、 e

将为您的示例数据分配一块内存。但在使用它之后,您必须手动删除它-否则您将泄漏内存。因此,只需执行以下操作:

delete[] samples;
在你完成它之后

最后但并非最不重要的一点是回答您的问题:如何创建一个二维数组来调用ProcessDoubleReplacing()方法

int main(int argc,char**argv){
/*创建二维数组*/
int**samplesIn=新int*[44100];
int**samplesOut=新int*[44100];
对于(inti=0;i<44100;++i){//1s@44.1Khz
samplesIn[i]=new int[2];//立体声
samplesOut[i]=new int[2];//立体声
}
/*TODO:用某处的音频样本(例如文件)填充输入缓冲区*/
ProcessDoubleReplacement(采样输入,采样输出,44100);
/*清理*/
对于(int i=0;i<44100;++i){
删除[i]中的[]样本;
删除[]样本[i];
}
删除[]样本;
删除[]样本;
返回0;
}

<>代码> < p>如果你想在C++中写一些类似于你所显示的接口的东西,我会用<代码> STD::vector < /C>来管理这样的内存:

double samples[512];
vector<vector<double>> buffers (2,vector<double>(500));
需要注意的是,如果调整其中一些向量的大小,指针可能会无效,在这种情况下,您应该继续获取新指针

请记住,
data
成员函数是C++11的一个特性。如果您不想使用它,可以编写

&some_vector[0] // instead of some_vector.data()
(除非向量为空)

与向某个函数传递double**不同,您可能希望通过引用直接传递buffers向量,但是,如果您希望接口与C兼容,这显然是行不通的


Edit:关于我为什么选择
std::vector
而不是
new[]因为在现代C++中,这是正确的事情,在这种情况下出错的几率较低。因为向量管理内存,所以不会有任何内存泄漏。这在C++中尤其重要,因为你可能会有异常的飞行,这样函数在U之前就可以退出。函数末尾的一个
delete[]

@Constantin的回答非常准确,但我只想补充一点,在您的实现中,您不应该在
进程()中分配缓冲区
回调。这样做可能会导致插件花费太多时间,因此系统可能会丢弃音频缓冲区,导致播放故障

因此,这些缓冲区应该是您的主处理类的字段(即
aeeffect
),您应该在构造函数中分配它们的大小。切勿在
process()
方法中使用
new
delete
,否则您会自找麻烦


关于实时音频编程的注意事项。

如果您只需要语法示例[0][0]要工作,你不需要指针。你也可以使用向量向量。谢谢,这看起来很完美,因为它能够使用向量管理和指针的直接访问速度。这段代码非常危险,它在过程中做了大量额外的工作()回调非常关键。“君士坦丁的答案对于C++音频工作来说是更好的。我意识到你在提倡C++的最佳实践,但是在这种情况下,需要额外的优化,否则插件会掉下音频缓冲区,引起播放的闪烁。”NikReiman,我不同意你一点。也许你误解了S。omething。我当然不想提倡在时间关键的阶段创建大量临时向量。想想我在这里写的“设置”代码。@NikReiman:另外,向量与新[]事情与您提出的关于何时分配内存的问题是非常正交的。@sellibitze在这种情况下,也许我对您的帖子的理解过于直白。对不起!不知道为什么您认为有人建议在调用进程函数时分配内存。
vector<double*> pointers;
pointers.push_back(buffers[0].data());
pointers.push_back(buffers[1].data());
double** p = pointers.data();
p[0][123] = 17;
p[1][222] = 29;
&some_vector[0] // instead of some_vector.data()