Hi Brett,
I’ve been trying your solution using the custom dsp example.
I don’t understand everything in the example yet.
I made the following code:
#include "fmod.hpp"
#include "common.h"
int const bufferlength = 1024;
int read{ bufferlength - 1 }, write{ 0 };
float transferbuffer[bufferlength];
bool bypass;
FMOD_RESULT F_CALLBACK myDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels)
{
FMOD_RESULT result;
char name[256];
void* userdata;
FMOD::DSP *raw_outdsp = (FMOD::DSP *)dsp_state->instance;
result = raw_outdsp->getInfo(name, 0, 0, 0, 0);
ERRCHECK(result);
result = raw_outdsp->getUserData(&userdata);
ERRCHECK(result);
for (unsigned int samp = 0; samp < length; samp++)
{
{
if (bypass == false ) transferbuffer[write] = inbuffer[samp ];
else transferbuffer[write] = 0.0;
if (write < bufferlength) write++;
else write =0;
//Common_Draw(" %f", transferbuffer);
}
}
return FMOD_OK;
}
FMOD_RESULT F_CALLBACK inDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels)
{
FMOD_RESULT result;
char name[256];
void* userdata;
FMOD::DSP *raw_indsp = (FMOD::DSP *)dsp_state->instance;
result = raw_indsp->getInfo(name, 0, 0, 0, 0);
ERRCHECK(result);
result = raw_indsp->getUserData(&userdata);
ERRCHECK(result);
for (unsigned int samp = 0; samp < length; samp++)
{
outbuffer[samp] = transferbuffer[read];
if ((read < bufferlength)) read++;
else read = 0;
}
return FMOD_OK;
}
int FMOD_Main()
{
FMOD::System *system;
FMOD::System *systemSoundCard;
FMOD::Sound *sound;
FMOD::Channel *channel;
FMOD::DSP *outdsp;
FMOD::DSP *indsp;
FMOD::ChannelGroup *mastergroup;
FMOD::ChannelGroup *mastergroupSoundCard;
FMOD_RESULT result;
unsigned int version;
void *extradriverdata = 0;
Common_Init(&extradriverdata);
result = FMOD::System_Create(&system);
ERRCHECK(result);
int recordingSources;
system->getRecordNumDrivers(0,&recordingSources);
result = FMOD::System_Create(&systemSoundCard);
ERRCHECK(result);
result = system->getVersion(&version);
ERRCHECK(result);
if (version < FMOD_VERSION)
{
Common_Fatal("FMOD lib version %08x doesn't match header version %08x", version, FMOD_VERSION);
}
result = system->setOutput(FMOD_OUTPUTTYPE_NOSOUND_NRT);
ERRCHECK(result);
int samplerate;
result = system->getSoftwareFormat(& samplerate,0,0);
ERRCHECK(result);
result = systemSoundCard->setSoftwareFormat(samplerate, FMOD_SPEAKERMODE_MONO, 0);
ERRCHECK(result);
result = system->init(32, FMOD_INIT_NORMAL, extradriverdata);
ERRCHECK(result);
result = systemSoundCard->init(32, FMOD_INIT_NORMAL, extradriverdata);
ERRCHECK(result);
result = system->createSound(Common_MediaPath("drumloop.wav"), FMOD_LOOP_NORMAL, 0, &sound);
ERRCHECK(result);
result = system->playSound(sound, 0, false, &channel);
ERRCHECK(result);
/*
Create the Raw output DSP effect.
*/
{
FMOD_DSP_DESCRIPTION dspdesc;
memset(&dspdesc, 0, sizeof(dspdesc));
strncpy(dspdesc.name, "My first DSP unit", sizeof(dspdesc.name));
dspdesc.version = 0x00010000;
dspdesc.numinputbuffers = 1;
dspdesc.numoutputbuffers = 1;
dspdesc.read = myDSPCallback;
dspdesc.userdata = (void *)0x12345678;
result = system->createDSP(&dspdesc, &outdsp);
ERRCHECK(result);
}
/*
Create the Raw input DSP effect.
*/
{
FMOD_DSP_DESCRIPTION dspdescin;
memset(&dspdescin, 0, sizeof(dspdescin));
strncpy(dspdescin.name, "Output DSP", sizeof(dspdescin.name));
dspdescin.version = 0x00010000;
dspdescin.numinputbuffers = 1;
dspdescin.numoutputbuffers = 1;
dspdescin.read = inDSPCallback;
dspdescin.userdata = (void *)0x12345678;
result = systemSoundCard->createDSP(&dspdescin, &indsp);
ERRCHECK(result);
}
/*
Attach the DSP, inactive by default.
*/
result = outdsp->setBypass(true);
ERRCHECK(result);
result = outdsp->setBypass(false);
ERRCHECK(result);
result = system->getMasterChannelGroup(&mastergroup);
ERRCHECK(result);
result = mastergroup->addDSP(0, outdsp);
ERRCHECK(result);
result = systemSoundCard->getMasterChannelGroup(&mastergroupSoundCard);
ERRCHECK(result);
result = mastergroupSoundCard->addDSP(0, indsp);
ERRCHECK(result);
/*
Main loop.
*/
do
{
// bool bypass;
Common_Update();
systemSoundCard->update();
if (Common_BtnPress(BTN_ACTION1))
{
bypass = !bypass;
}
result = system->update();
ERRCHECK(result);
Common_Draw("==================================================");
Common_Draw("Custom DSP Example.");
Common_Draw("Copyright (c) Firelight Technologies 2004-2015.");
Common_Draw("==================================================");
Common_Draw("");
Common_Draw("Press %s to toggle filter bypass", Common_BtnStr(BTN_ACTION1));
Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT));
Common_Draw("");
Common_Draw("Filter is %s", bypass ? "inactive" : "active");
Common_Draw("Number of recording sources is %i", recordingSources);
Common_Sleep(50);
} while (!Common_BtnPress(BTN_QUIT));
/*
Shut down
*/
result = sound->release();
ERRCHECK(result);
result = mastergroup->removeDSP(outdsp);
ERRCHECK(result);
result = outdsp->release();
ERRCHECK(result);
result = system->close();
ERRCHECK(result);
result = system->release();
ERRCHECK(result);
Common_Close();
return 0;
}
There is some slowed down distorted sound.
Is it a problem that the two systems may be out of sync, causing the intermediate buffer to skip or repeat samples, caused by different speeds in reading and writing ?
What am I doing wrong ? Or can you redirect me to other questions and or examples to get a better understanding of developing DSP’s and solving this problem ?
Best regards,
Tom