Answered
0
0

I’m trying to use FMOD in my UWP app to draw a real time wave of the playing mp3 file.
My code is:

FMOD.Factory.System_Create(out FMODSys);
        FMODSys.init(1, FMOD.INITFLAGS.NORMAL, IntPtr.Zero); 
FMODSys.createStream(SelectedTrack.StorageFile.Path, FMOD.MODE.DEFAULT, out FMODSound);
FMODSys.playSound(FMODSound, null, false, out FMODChannel);

        FMOD.DSP_DESCRIPTION desc = new FMOD.DSP_DESCRIPTION();
        desc.numinputbuffers = 1;
        desc.numoutputbuffers = 1;
        desc.read = DSPWaveRead;
        FMODSys.createDSP(ref desc, out FMODDspWave);
        FMODDspWave.setBypass(false);
        FMODChannel.addDSP(0, FMODDspWave);
        FMODChannel.setVolume(Gain);

private unsafe RESULT DSPWaveRead(ref DSP_STATE dsp_state, 
IntPtr inbuffer, IntPtr outbuffer, uint length, int inchannels, ref int outchannels)
    {
        float* bufferOUT = (float*)outbuffer;
        float* bufferIN = (float*)inbuffer;

        for (uint samp = 0; samp < length; samp++)
        {
            for (int chan = 0; chan < outchannels; chan++)
            {
                float val = bufferIN[(samp * inchannels) + chan] / Gain;
                HGraph.AddFloatToArray(val, chan);
                bufferOUT[(samp * outchannels) + chan] = bufferIN[(samp * inchannels) + chan];
            }
        }
        return FMOD.RESULT.ERR_DSP_DONTPROCESS;
    }

File is playing well without attaching custom DSP, but when I attach the DSP with the code above I have a “access violation in fmod_X64”, even if I do nothing in the DSPWaveRead callback.
I’m using the c# wrapper from windows version of FMOD because there isn’t one provided in the UWP version.
Any suggestion?

  • You must to post comments
Best Answer
0
0

You need to look at the lifetime of all your managed objects. The C# memory management doesn’t know about references to an object that is being held by native code. It can garbage collect them and as a result the native code will be calling invalid objects pointers.

A big gotcha in this area is auto-creating delegate objects that don’t have the correct lifetime.

desc.read = DSPWaveRead;

is actually

desc.read = new DSP_READCALLBACK(DSPWaveRead);

and the lifetime of the DSP_READCALLBACK object is not correctly managed.

  • Enrico

    Yep. Defining the DSP_READCALLBACK works well as expected. I was following the c++ sample and didn’t think about createing the callback.
    Thank you.

  • You must to post comments
0
0

You should return FMOD_OK in your callback if you’re making sound, not dont process.

You need to make sure your FMOD_DSP_DESCRIPTION struct is all zeroes as well. Are there uninitialized members? Have you used a debugger to find out at what line of code exactly it crashes?

  • You must to post comments
0
0

Thx for the answer. Yes, FMOD.RESULT.ERR_DSP_DONTPROCESS was just for testing purpose trying to find what was wrong. Yes, maybe there is something not initialized. Error is coming from the fmod_x64.dll, not from the code above. But there isn’t the fmod_x64.pdb in the code, so I cannot debug the whole thing deeper. Can I find xmod pdb files somewhere?

  • Brett Paterson

    Did you checked everything was cleared? That’s the first thing you should be doing
    We don’t typically give out pdbs, it doesn’t really tell you anything, because you’d just be reporting what it said back to us anyway. If you want, give me the address / asm/crash dump information from the crash exception dialog which would be the same information from our point of view.

  • You must to post comments
0
0

Hello Brett,
sorry for the non-prompt response, but it takes me some days to deeply investigate the issue. I’m new to FMOD, so I didn’t want to seem not accurate.
The DSP is initializing well, with everyting cleared and everyting not cleared. After hours of test I found out that placing the read callback outside the creation method of the DSP leads to access violatiion exception.
If I place the callback inside the method (with anonymous action) access vioaltion is not raised.

desc.read = (ref DSP_STATE dsp_state, IntPtr inbuffer, IntPtr outbuffer,
                uint length, int inchannels, ref int outchannels) =>
            {
                float* bufferIN = (float*)inbuffer;
                float* bufferOUT = (float*)outbuffer;
                var bBytes = new byte[length];

                for (int i = 0; i < length; i++)
                {
                    for (int c = 0; c < outchannels; c++)
                    {
                        bufferOUT[i * outchannels + c] = bufferIN[i * inchannels + c];
                    }
                }                   
                Marshal.Copy(inbuffer, bBytes, 0, (int)length);
                FMODDsp.setUserData(outbuffer);
                return FMOD.RESULT.OK;
            };

But then, if I call something (property or method) outside the anonymous callback from inside the callback, I get the access violation. So, if I want to store data in a byte array to use later for drawing process is impossible. I tried to add data to the dsp userData, but it’s the same, because dsp is defined outside the method.
Am I missing something or is it not a correct behaviour?
I’m solving the issue writing all the FMOD codes in a c++ usercontrol.

  • Brett Paterson

    Hi Enrico,
    Thanks for that investigation. I’ll defer to someone in the office who has more knowledge about C# as this seems to be the crux of the issue, hopefully we can get an answer for you tomorrow.

  • You must to post comments
Showing 4 results
Your Answer

Please first to submit.