cancel
Showing results for 
Search instead for 
Did you mean: 

FMOD low level API: spatializer doesn't work

lightsome
Honored Guest
Hi guys,

        I have spent last months with testing OSP in FMOD low-level API in c#. I can't use it from FMOD studio because I'm blind and it isn't usable for me. I traversed through many forums but I'm still struggling. Please help me.

Problem description
I can hear no spatialization and no reverb room effects and the sound sounds a bit muffled.

        My code

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

using FMOD;

namespace FmodOculusTest
{
    internal enum OspGlobalsParamIndex
    {
        ReflectionEngineEnabled, // bool
        ReverbEnabled,            // bool
        GlobalScale,              // float
        BypasAll,                // bypass
        RoomWidth,                // float
        RoomHeight,               // float
        RoomLength,               // float
        RefLeft,                  // float
        RefRight,                 // float
        RefUP,                    // float
        RefDown,                  // float
        RefNear,                  // float
        RefFar,                   // float
        ReverbRangeMin,          // float
        ReverbRangeMax,          // float

        OspGlobalsPINDEXNumParameters
    };

    internal enum OspParamIndex
    {
        SoundPosition,           // FMOD_DSP_PARAMETER_3DATTRIBUTES - both absolute and relative to camera
        ReflectionsEnabled,      // bool
        AttenuationEnabled,      // bool
        SourceVolumetricRadius, // float
        SourceRangeMin,         // float
        SourceRangeMax,         // float
        OspNumParameters
    };

    internal enum OspParamIndexAmbisonic
    {
        SoundPosition,         // FMOD_DSP_PARAMETER_3DATTRIBUTES - both absolute and relative to camera
        VirtualSpeakerMode,   // bool - OculusAmbi vs. Virtual Speakers

        OspAmbisonicNumParameters
    };

    internal class OvrTest
    {
        private uint _hrtfHandle;
        private Channel _channel;
        private ChannelGroup _masterGroup;
        private DSP _sharedReverb;
        private Sound _sound;
        private DSP _spatializerDSP;
        private ChannelGroup _spatializerGroup;
        private FMOD.System _system;

        public OvrTest()
        {
            // initialization
            ECheck(Factory.System_Create(out _system), "Creating context");
            ECheck(_system.init(1024, INITFLAGS.NORMAL, IntPtr.Zero), "FMOD initialization");

            // načtení pluginu Oculus Spatializer
            ECheck(_system.loadPlugin("OculusSpatializerFMOD.dll", out _hrtfHandle), "Loading plugin");

            // Creating DSP
            ECheck(_system.createDSPByPlugin(_hrtfHandle, out _spatializerDSP), "Creating DSP " + nameof(_spatializerDSP));
            ECheck(_system.createDSPByPlugin(_hrtfHandle + 2, out _sharedReverb), "Creating DSP " + nameof(_sharedReverb));

            // Optaining master channel group and creating group for spatialization
            ECheck(_system.getMasterChannelGroup(out _masterGroup), "Optaining master channel group");
            ECheck(_system.createChannelGroup("spatializer", out _spatializerGroup), "Creating channel group " + nameof(_spatializerGroup));

            // Adding DSP into channel group
            ECheck(_spatializerGroup.addDSP(CHANNELCONTROL_DSP_INDEX.HEAD, _spatializerDSP), "Adding DSP into channel group");
            ECheck(_masterGroup.addDSP(CHANNELCONTROL_DSP_INDEX.HEAD, _sharedReverb), "Adding DSP into channel group");

            // Shared reverb parameters
            ECheck(_sharedReverb.setParameterBool((int)OspGlobalsParamIndex.ReflectionEngineEnabled, true), "Enabling reverberation");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.RoomWidth, 10f), "Setting room width");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.RoomLength, 20f), "Setting room length");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.RoomHeight, 4f), "Setting room height");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.RefLeft, 1f), "Setting left wall reflection");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.RefRight, 1f), "Setting right wall reflection");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.RefUP, 1f), "Setting ceiling reflection");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.RefDown, 1f), "Setting floor reflection");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.RefNear, 1f), "Setting near reflection");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.RefFar, 1f), "Setting far reflection");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.ReverbRangeMin, 1f), "Setting ReverbRangeMin");
            ECheck(_sharedReverb.setParameterFloat((int)OspGlobalsParamIndex.ReverbRangeMax, 6f), "Setting ReverbRangeMax");

            ECheck(_sharedReverb.setParameterBool((int)OspGlobalsParamIndex.ReverbEnabled, true), "Enbaling reverberation");
            ECheck(_sharedReverb.setParameterBool((int)OspGlobalsParamIndex.BypasAll, false), "Switching bypas parameter off");
        }

        public void Play()
        {
            // Playing sound
            string fileName = "sound.wav";
            ECheck(_system.createSound(fileName, MODE.DEFAULT, out _sound), "Loading sound");
            ECheck(_system.playSound(_sound, _spatializerGroup, true, out _channel), "Playing sound");

            // Setting parameters
            ECheck(_spatializerDSP.setParameterBool((int)OspParamIndex.AttenuationEnabled, true), "Enabling attenuation");
            ECheck(_spatializerDSP.setParameterFloat((int)OspParamIndex.SourceVolumetricRadius, 11f), "Setting volumetric radius");

            // Setting sound position
            DSP_PARAMETER_3DATTRIBUTES attributes = new DSP_PARAMETER_3DATTRIBUTES()
            {
                absolute = new ATTRIBUTES_3D()
                {
                    velocity = new VECTOR() { x = 8f, y = 5f, z = 2f },
                    position = new VECTOR() { x = -14f, y = 0f, z = 0f }
                },

                relative = new ATTRIBUTES_3D()
                {
                    velocity = new VECTOR() { x = 2f, y = 4f, z = 7f },
                    position = new VECTOR() { x = -14f, y = 0f, z = 0f }
                }
            };

            // Putting structure into parameter
            int attributesSize = Marshal.SizeOf(typeof(ATTRIBUTES_3D));
            IntPtr attributesPtr = Marshal.AllocHGlobal(attributesSize);
            Marshal.StructureToPtr(attributes, attributesPtr, false);
            ECheck(_spatializerDSP.setParameterData(0, GetBytes(attributesPtr,
                                                                             attributesSize)), "Putting structure into parameter");
            Marshal.FreeHGlobal(attributesPtr);

            _channel.setPaused(false);
        }

        public void Release()
        {
            _system.release();
        }

        private static byte[] GetBytes(IntPtr ptr, int length)
        {
            if (ptr != IntPtr.Zero)
            {
                byte[] byteArray = new byte[length];
                Marshal.Copy(ptr, byteArray, 0, length);
                return byteArray;
            }
            // Return an empty array if the pointer is null.
            return new byte[1];
        }

        //mt

        //mtd

        private void ECheck(RESULT r, string activity)
        {
            if (r != RESULT.OK)
            {
                Say($"Chyba: {activity}.");
                Application.Exit();
            }
        }

        private void Say(string text)
                    => MessageBox.Show(text);

        //mtd
    }//cls
} //nsp
0 REPLIES 0