I’ve tried to figured out a scratch in c++, but it doesn’t work. I got FMOD_ERR_INVALID_PARAM
while calling GetParameterDataCallback
.
First, I add CreateCallback
and ReleaseCallback
while the Unity sample does not have. I believe it’s necessary in c++ because I need to manage the memory manually.
Second, I add one GetParameterDataCallback
to get the plugindata like the dsp_custom.cpp
example. It is probably where the program failed. I call the GetParameterDataCallback
in the do-while render loop but get FMOD_ERR_INVALID_PARAM
. The process also doesn’t enter the GetParameterDataCallback
function in my debug process. However, I am not aware of which param is wrong.
I am using latest version: 2.01.08.
Here is the c++ scratch I am using now. This sample intends to capture the raw mono pcm data after dsp processing and writes them as a file. I hope it can be useful for others after the problem is solved.
#include <fstream>
#include "fmod.hpp"
#include "common.h"
typedef struct {
float *buffer;
int length_samples;
} mono_pcm;
// This dsp does nothing on audio but copy raw data into data buffer
FMOD_RESULT F_CALLBACK
CaptureDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels,
int *outchannels) {
mono_pcm *data = (mono_pcm *) dsp_state->plugindata;
for (size_t i = 0; i < length; ++i) {
outbuffer[i] = inbuffer[i];
data->buffer[i] = outbuffer[i];
}
return FMOD_OK;
}
FMOD_RESULT F_CALLBACK CaptureDSPCreateCallback(FMOD_DSP_STATE *dsp_state) {
unsigned int blocksize;
FMOD_RESULT result;
result = dsp_state->functions->getblocksize(dsp_state, &blocksize);
// allocate mem for mono_pcm struct
mono_pcm *data = (mono_pcm *) calloc(sizeof(mono_pcm), 1);
if (!data) return FMOD_ERR_MEMORY;
// allocate mem for buffer in mono_pcm
dsp_state->plugindata = data;
data->length_samples = blocksize;
data->buffer = (float *) malloc(blocksize * sizeof(float));
if (!data->buffer) return FMOD_ERR_MEMORY;
return FMOD_OK;
}
FMOD_RESULT F_CALLBACK CaptureDSPReleaseCallback(FMOD_DSP_STATE *dsp_state) {
if (dsp_state->plugindata) {
mono_pcm *data = (mono_pcm *) dsp_state->plugindata;
if (data->buffer) free(data->buffer);
free(data);
}
return FMOD_OK;
}
// This api should give access to mono_pcm struct
FMOD_RESULT F_CALLBACK
captureDSPGetParameterDataCallback(FMOD_DSP_STATE *dsp_state, int index, void **data, unsigned int *length, char *) {
printf("Entered captureDSPGetParameterDataCallback!\n");
if (index == 0) {
unsigned int blocksize;
FMOD_RESULT result;
mono_pcm *mydata = (mono_pcm *) dsp_state->plugindata;
result = dsp_state->functions->getblocksize(dsp_state, &blocksize);
ERRCHECK(result);
*data = (void *) mydata;
return FMOD_OK;
}
return FMOD_ERR_INVALID_PARAM;
}
int main() {
FMOD::System *system;
FMOD::Sound *sound1;
FMOD::Channel *channel = 0;
FMOD::DSP *channelhead, *shiftedVocalFader, *captureDSP;
FMOD::ChannelGroup *masterGroup;
FMOD_RESULT result;
FMOD::System_Create(&system);
system->init(32, FMOD_INIT_NORMAL, 0);
// open sound
system->createSound("media/drumloop.wav", FMOD_DEFAULT, 0, &sound1);
system->playSound(sound1, 0, false, &channel);
// prepare capture dsp
FMOD_DSP_DESCRIPTION dspdesc;
memset(&dspdesc, 0, sizeof(dspdesc));
strncpy(dspdesc.name, "Capture DSP", sizeof(dspdesc.name));
dspdesc.numinputbuffers = 1;
dspdesc.numoutputbuffers = 1;
dspdesc.read = CaptureDSPCallback;
dspdesc.create = CaptureDSPCreateCallback;
dspdesc.release = CaptureDSPReleaseCallback;
dspdesc.getparameterdata = captureDSPGetParameterDataCallback;
result = system->createDSP(&dspdesc, &captureDSP);
ERRCHECK(result);
// add dsp
channel->getDSP(FMOD_CHANNELCONTROL_DSP_HEAD, &channelhead);
system->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &shiftedVocalFader);
shiftedVocalFader->setActive(true);
shiftedVocalFader->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 1.8f);
system->getMasterChannelGroup(&masterGroup);
result = masterGroup->addDSP(0, captureDSP); // add capture
ERRCHECK(result);
masterGroup->addDSP(0, shiftedVocalFader);
bool isplaying = true;
mono_pcm *captureData;
std::ofstream outf("out/captured.pcm", std::ios::binary);
unsigned int length;
char valuestr[512];
do {
result = system->update();
ERRCHECK(result);
channel->isPlaying(&isplaying);
// cannot get the mono_pcm into captureData: FMOD_ERR_INVALID_PARAM
result = captureDSP->getParameterData(0, (void **) &captureData, &length, valuestr, 0);
ERRCHECK(result);
// failed to write pcm file because captureData == NULL
outf.write((char *) captureData->buffer, captureData->length_samples * sizeof(float));
} while (isplaying);
outf.close();
result = sound1->release();
ERRCHECK(result);
result = masterGroup->removeDSP(captureDSP);
ERRCHECK(result);
result = captureDSP->release();
ERRCHECK(result);
result = system->close();
ERRCHECK(result);
result = system->release();
ERRCHECK(result);
}