我有一个函数audioReceived (float * input, int bufferSize, int nChannels)
,我想在其中调用需要const float *const *inputBuffers
的库中的函数。
显然正在编译const float *const *inputBuffers = (const float* const*)input;
编译,但这是一个可怕的想法,崩溃程序,杀死小猫等。没有人需要修改原始float* input
,它是正在处理的传入音频数据。
我该怎么做正确的方法?
编辑:这是更多代码。 audioReceived
是:
void testApp::audioReceived (float * input, int bufferSize, int nChannels){
Vamp::RealTime rt = Vamp::RealTime::fromMilliseconds(ofGetSystemTime());
float const *const tmp[] = { input, 0 };
Vamp::Plugin::FeatureSet fs = myPlugin->process(tmp, rt);
}
库函数process
实际上是在基类中定义的:
/**
* Process a single block of input data.
*
* If the plugin's inputDomain is TimeDomain, inputBuffers will
* point to one array of floats per input channel, and each of
* these arrays will contain blockSize consecutive audio samples
* (the host will zero-pad as necessary). The timestamp in this
* case will be the real time in seconds of the start of the
* supplied block of samples.
*
* If the plugin's inputDomain is FrequencyDomain, inputBuffers
* will point to one array of floats per input channel, and each
* of these arrays will contain blockSize/2+1 consecutive pairs of
* real and imaginary component floats corresponding to bins
* 0..(blockSize/2) of the FFT output. That is, bin 0 (the first
* pair of floats) contains the DC output, up to bin blockSize/2
* which contains the Nyquist-frequency output. There will
* therefore be blockSize+2 floats per channel in total. The
* timestamp will be the real time in seconds of the centre of the
* FFT input window (i.e. the very first block passed to process
* might contain the FFT of half a block of zero samples and the
* first half-block of the actual data, with a timestamp of zero).
*
* Return any features that have become available after this
* process call. (These do not necessarily have to fall within
* the process block, except for OneSamplePerStep outputs.)
*/
virtual FeatureSet process(const float *const *inputBuffers,
RealTime timestamp) = 0;
并且在实际标题中:
FeatureSet process(const float *const *inputBuffers, Vamp::RealTime timestamp);
我认为EXC_BAD_ACCESS
可能源于想要零填充数组的库函数,而我没有给它一个。 (a)这听起来是否合理;(b)如果是,是时候提出不同的SO问题了吗?
感谢所有人的帮助到目前为止,它非常有启发性/澄清/教育/有趣。
答案 0 :(得分:2)
对于演员本身来说,&input
应该足够了。请注意,内部函数的参数是指向指针的指针。
修改强>
要根据原始问题的评论中的要求获取输入缓冲区的空终止列表,您可以使用:
float const * const buffers[] = {input, 0};
答案 1 :(得分:2)
语义在这里很重要。从参数名称,我可以猜测你要调用的函数接受多个缓冲区,因此它需要一个浮点指针数组(即一个数组数组)。由于您只有一个数组,因此需要创建一个包含原始指针的数组,并将其传递给该函数。
如果函数有一个单独的参数来传递数组的长度(即缓冲区的数量),那么使用一元&
运算符获取地址并传递长度为1应该足够了,否则你需要创建一个临时的空终止数组:
float const *const tmp[] = { input, 0 };
并将其传递给函数。
答案 2 :(得分:1)
float *
与
不同float **
所以将input
投射到inputBuffers
是行不通的。
通常,从非const到const的转换是隐式的,你不需要做任何特殊的事情。您不能轻易地从const转换为非const。当你考虑它时,这是合乎逻辑的。
答案 3 :(得分:0)
你需要传递一个float **
,即指向指针浮点数的指针。 const
只是告诉你该函数不会修改任何指向的值。
如果每个频道的频道数nChannels
可能有bufferSize
个浮点数,那么您可以设置必要的存储空间,例如。
float **data = new float *[nChannels];
for (int c = 0; c < nChannels; ++c) {
data[c] = new float[bufferSize];
}
之后data
的格式正确,以传递给此函数。 (函数知道这些东西有多大,因为你之前已经为插件构造函数提供了通道数和块大小。)
您的示例代码显示您有一个单指针float *
,这表明您可能以交错格式(即单个数组中的交替通道值)开始数据。如果是这种情况,您需要解交错到单独的通道才能传递到process
函数:
for (int i = 0; i < bufferSize; ++i) {
for (int c = 0; c < nChannels; ++c) {
data[c][i] = input[i * nChannels + c];
}
}
myPlugin->process(data, rt);
最后,不要忘记delete[]
成员指针以及之后的双指针。
for (int c = 0; c < nChannels; ++c) {
delete[] data[c];
}
delete[] data;
另一方面,如果你知道你只有一个数据通道 - 并且你在插件构造函数中提供了1作为通道数 - 那么你可以像其他人一样做额外的间接建议:
myPlugin->process(&input, rt);
(披露:我写的代码令提问者感到困惑)