0
0

I’m fairly new to fmod and a bit rusty on my C++ so excuse me if I say anything ridiculous!

I’m trying to implement a system where I will apply 2 FIR filters that I specify myself to a mono audio track and output the two resulting outputs to the left and right stereo channel.

[code:1n29zpaz]
->FIR1——->OUTPUT LEFT
/
/
mono signal————
\
\
->FIR2——->OUTPUT RIGHT[/code:1n29zpaz]

I’ve been going through the custon dsp and dsp effect per speaker examples and they’ve been very helpful.

Is it best that I do this filtering in one custom dsp call where the inputs would be the audio track and the 2 impulse responses that I specify. Then I would have the 2 outputs from this. Although maybe this isn’t possible?

Or should I use 2 custom dsps, one for each channel? Each dsp would have 2 inputs (the mono track and the impulse response) and one output.

Or am I approaching this in completely the wrong way! Is this how I should bring in the impulse responses? Am I likely to run into problems because the number of input channels to the dsp won’t equal the number of output channels?

Finally…there doesn’t happen to be a convolution function tucked away somewhere that I haven’t been able to find?
I take it I have to implement this the long way with a for loop to sum each of the multiplications?

  • You must to post comments
0
0

Hi Claire, welcome to the FMOD forums!

I think what you’re trying to do is possible but it might take a bit of work because it’s non-standard usage.

[quote:156jvdeo]Am I likely to run into problems because the number of input channels to the dsp won’t equal the number of output channels? [/quote:156jvdeo]
Yes, all custom DSPs must have (num inchannels == num outchannels). This is not as restrictive as it sounds because you can control the mapping of sound to input channels using Channel::setSpeakerLevels. So if you play a mono sound you can route the whole sound into the left channel for example. You can then have the impulse response as another sound and route that to the right channel. Add both channels to a channel group, then you can add a DSP unit to the channel group. The DSP unit can then output normal stereo.

[quote:156jvdeo]there doesn’t happen to be a convolution function tucked away somewhere that I haven’t been able to find? [/quote:156jvdeo]
No, sorry the FMOD API doesn’t contain a convolution function.

-Pete

  • You must to post comments
0
0

Thanks for your reply.

[quote:2vt6hoz6]So if you play a mono sound you can route the whole sound into the left channel for example. You can then have the impulse response as another sound and route that to the right channel. Add both channels to a channel group, then you can add a DSP unit to the channel group. The DSP unit can then output normal stereo. [/quote:2vt6hoz6]

So in this case, where I have 2 impulse responses I want to apply (one to get the left stereo output and one to get the right stereo output), I would have to use 2 custom DSP callbacks to achieve what I want to do? Each would have as inputs the mono track as the left channel and one impulse response as the right channel and as an output one of the desired output channels I want. Then after the DSPs have been called I would look after routing the left and right outputs to where they should be.

I suppose I’m a little worried this would cause a small latency between the DSPs being applied to the left and right channel outputs but I’m probably being a bit over anxious! I would eventually like to have the impulse responses changing depending on some user input…but thats a while off I feel!

Anyway I’ll get coding and see what happens, thanks again.

  • You must to post comments
0
0

I’ve gotten a bit stuck with this. I’m starting off by just doing one filter, I figure if I can get that working then replicating it for a second FIR should be easy. I’ve also, for now, just directly copied the custom dsp callback from the custom dsp example provided with fmod. If I can get it to half the volume first then I’ll move on to the convolution.

Here’s what I have so far:

[code:1q7eltut] int main(int argc, char *argv[])
{
FMOD::System *system;
FMOD::Sound *sound , *hrir_l;
FMOD::Channel *channel =0;
FMOD::DSP *mydsp;
FMOD::ChannelGroup *groupL;
FMOD_RESULT result;
int key = 0;

/*Create a System object and initialize.*/
result = FMOD::System_Create(&system);  ERRCHECK(result);

result = system->init(32, FMOD_INIT_NORMAL, 0);  ERRCHECK(result);

result = system->createSound("mono_track.wav",   FMOD_LOOP_NORMAL, 0, &sound);  ERRCHECK(result);

result = system->createSound("filter1.wav",  FMOD_LOOP_OFF, 0, &hrir_l);  ERRCHECK(result);

printf("Press 'f' to activate, deactivate user filter\n");
printf("Press 'Esc' to quit\n");

//-----------------------------------------------------------------------------
// Send the 2 mono feeds to go to the left and right stereo channels

result = system->playSound(FMOD_CHANNEL_FREE, sound, false, &channel);  ERRCHECK(result);
float leftinputon[1]  = { 1.0};
result = channel->setSpeakerLevels(FMOD_SPEAKER_FRONT_LEFT, leftinputon, 1);  ERRCHECK(result);

result = system->playSound(FMOD_CHANNEL_FREE, hrir_l, false, &channel);  ERRCHECK(result);
float rightinputon[1]  = {1.0 };
result = channel->setSpeakerLevels(FMOD_SPEAKER_FRONT_RIGHT, rightinputon, 1);  ERRCHECK(result);
//-----------------------------------------------------------------------------

result = system->createChannelGroup("Group L", &groupL);  ERRCHECK(result);
result = channel->setChannelGroup(groupL);
// Create the DSP effects. 
{ 
    FMOD_DSP_DESCRIPTION  dspdesc; 

    memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); 

    strcpy(dspdesc.name, "My first DSP unit"); 
    dspdesc.channels     = 0; 
    dspdesc.read         = myDSPCallback; 
    dspdesc.userdata     = (void *)0x12345678; 

    result = system->createDSP(&dspdesc, &mydsp); 
    ERRCHECK(result); 
} 

mydsp->setBypass(true);
result = groupL->addDSP(mydsp, 0);

do{
    if (kbhit()){
        key = getch();
        switch (key){
            case 'f' : 
            case 'F' : {
                static bool active = false;
                mydsp->setBypass(active);
                active = !active;
                break;
            }
        }
    }
    system->update();
} while (key != 27);

// release resources
result = sound->release();  ERRCHECK(result);
result = hrir_l->release();  ERRCHECK(result);
result = groupL->release();  ERRCHECK(result);
result = mydsp->release();  ERRCHECK(result);
result = system->close();  ERRCHECK(result);
result = system->release();  ERRCHECK(result);

return 0;

}[/code:1q7eltut]

Anyway when I summon the dsp callback by hitting f there is no effect on the output audio… so what have I missed?
I put a printf statement outputting the number of input and output channels to the dsp in the callback and this stuff is printed out, so the callback is obviously being called but isnt doing anything!

So…I mustn’t be sending the data into the dsp properly I’m guessing?

  • You must to post comments
0
0

Apologies Claire, Channel::setSpeakerLevels is the wrong function. I should have said Channel::setSpeakerMix. Also in that block of code you’re overwriting the ‘channel’ handle and only one of your channels is getting added to the channel group:

Here is a modified version:
[code:ltfeonca]
result = system->createChannelGroup("Group L", &groupL); ERRCHECK(result);
//—————————————————————————–
// Send the 2 mono feeds to go to the left and right stereo channels

result = system->playSound(FMOD_CHANNEL_FREE, sound, false, &channel);  ERRCHECK(result);
ERRCHECK(result = channel->setChannelGroup(groupL));
ERRCHECK(result = channel->setSpeakerMix(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));

result = system->playSound(FMOD_CHANNEL_FREE, hrir_l, false, &channel);  ERRCHECK(result);
ERRCHECK(result = channel->setChannelGroup(groupL));
ERRCHECK(result = channel->setSpeakerMix(0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
//-----------------------------------------------------------------------------

[/code:ltfeonca]

[quote:ltfeonca]I suppose I’m a little worried this would cause a small latency between the DSPs being applied to the left and right channel outputs but I’m probably being a bit over anxious![/quote:ltfeonca]
In FMOD DSP units cannot add latency to the mix. It either completes the mix on time or it doesn’t (which is bad). The mix cannot complete until all DSP units have returned so if yours takes too long the soundcard will request some sound and the FMOD mixer wont be ready, this will cause glitchy sound. This is pretty unlikely, you can test how close to the limit you are by checking the ‘dsp’ value of System::getCPUUsage, make sure it doesn’t go over 100.

[quote:ltfeonca]Anyway when I summon the dsp callback by hitting f there is no effect on the output audio… so what have I missed? [/quote:ltfeonca]
Can you show me the code for your callback?

-Pete

  • You must to post comments
0
0

[quote:3gfkc0yg] Also in that block of code you’re overwriting the ‘channel’ handle and only one of your channels is getting added to the channel group: [/quote:3gfkc0yg]

Yea, I thought this was probably a bit iffy alright! Thanks for clearing that up for me.

I’ve modified the code to include your suggestions and still I’m not getting any effect from the dsp callback. I changed the code in the loop where the bypass is set on or off to get rid off any ambiguity there. So now entering ‘b’ turns on the filter and ‘a’ turns it off again.

[code:3gfkc0yg] mydsp->setBypass(true);
result = groupL->addDSP(mydsp, 0); ERRCHECK(result);

do{
    if (kbhit()){
        key = getch();
        switch (key){
            case 'a' : {
                static bool active = true;
                mydsp->setBypass(active);
                break;
           }
            case 'b' : {
                static bool active = false;
                mydsp->setBypass(active);
                break;
            }
        }
    }
    system->update();
    Sleep(10);
} while (key != 27);  //27 is ascii for ESC[/code:3gfkc0yg]

The code for the callback is copied directly from the custom dsp example provided with fmod. I’ve stuck a few printf statements in to check a few things and satisify myself that it is actually being called!

[code:3gfkc0yg] FMOD_RESULT F_CALLBACK myDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels)
{
unsigned int count, userdata;
int count2;
char name[256];
FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance;
printf("no of input channels is %d \n",inchannels);
printf("no of output channels is %d \n",outchannels);
printf("the length is %d \n",length);

thisdsp->getInfo(name, 0, 0, 0, 0);
thisdsp->getUserData((void **)&userdata);


for (count = 0; count < length; count++) { 
    for (count2 = 0; count2 < outchannels; count2++){
        outbuffer[(count * outchannels) + count2] = inbuffer[(count * inchannels) + count2] * 0.2f;
    }
} 
return FMOD_OK; 

} [/code:3gfkc0yg]

So based on these I’d expect that when I press ‘b’ there will be stuff printed out (which does happen) and the volume of the sound should decrease (which doesn’t). Pressing ‘a’ stops the printing as you would expect but the volume doesn’t change…

  • You must to post comments
0
0

Found the problem! I hadn’t specified the sounds should be in software mode when I created them.

I should have had:

[code:24veklnm]result = system->createSound("mono_track.wav", FMOD_SOFTWARE | FMOD_LOOP_NORMAL, 0, &sound);[/code:24veklnm]
instead of :
[code:24veklnm]result = system->createSound("mono_track.wav", FMOD_LOOP_NORMAL, 0, &sound);[/code:24veklnm]

Its always the little things like that that have you pulling your hair out!

  • You must to post comments
0
0

Glad to hear it is all working.

[quote:1cf9shot]Its always the little things like that that have you pulling your hair out![/quote:1cf9shot]
Too true. :)

  • You must to post comments
Showing 7 results
Your Answer

Please first to submit.