public static void Update() { if (system == null) { return; } // Update sound if (channel != null) { FMOD.MODE mode = FMOD.MODE.DEFAULT; channel.getMode(ref mode); if ((mode & FMOD.MODE._3D) == FMOD.MODE._3D) { FMOD.VECTOR pos; pos.x = 0.0f; pos.y = 0.0f; pos.z = 0.0f; FMOD.VECTOR vel; vel.x = 0.0f; vel.y = 0.0f; vel.z = 0.0f; channel.get3DAttributes(ref pos, ref vel); float distance = (float)Math.Sqrt((double)(pos.x * pos.x + pos.y * pos.y)); float minDist = 0.0f, maxDist = 1000.0f; channel.get3DMinMaxDistance(ref minDist, ref maxDist); float distRatio = distance / maxDist; if (ignorefod == false) { // Set direct and reverb occlusion float direct = 1.0f - GetDistanceRatioValue(CONTROLTYPE.DIRECT, distRatio); float reverb = 1.0f - GetDistanceRatioValue(CONTROLTYPE.REVERB, distRatio); channel.set3DOcclusion(direct, reverb); // Set lowpass FMOD.DSP head = null; channel.getDSPHead(ref head); if (head != null) { int inputs = 0; head.getNumInputs(ref inputs); for (int i = 0; i < inputs; i++) { FMOD.DSP dsp = null; FMOD.DSPConnection dspcon = null; head.getInput(i, ref dsp, ref dspcon); if (dsp == null) { continue; } FMOD.DSP_TYPE type = FMOD.DSP_TYPE.UNKNOWN; dsp.getType(ref type); if (type == FMOD.DSP_TYPE.LOWPASS_SIMPLE) { float hrtf = 1.0f; FMOD.VECTOR dir; dir.x = pos.x; dir.y = pos.y; dir.z = 0.0f; float length = (float)Math.Sqrt((double)(dir.x * dir.x + dir.y * dir.y)); if (length > 0.0001f) { length = 1.0f / length; dir.x *= length; dir.y *= length; float _angle = (float)Math.Acos((double)dir.y); hrtf = 1.0f - HRTFDATA.Scale * Math.Min(1.0f, Math.Max(0.0f, (_angle - HRTFDATA.MinAngle) / (HRTFDATA.MaxAngle - HRTFDATA.MinAngle))); } float lowpass = 21990.0f * GetDistanceRatioValue(CONTROLTYPE.LOWPASS, distRatio) * hrtf + 10.0f; dsp.setParameter((int)FMOD.DSP_LOWPASS_SIMPLE.CUTOFF, lowpass); break; } } } // Set pan level float panlevel = GetDistanceRatioValue(CONTROLTYPE.PANLEVEL, distRatio); channel.set3DPanLevel(panlevel); } else { channel.set3DPanLevel(0.0f); } } } system.update(); }
private void Form1_Load(object sender, System.EventArgs e) { uint version = 0; FMOD.RESULT result; FMOD.DSPConnection dspconnectiontemp = null; /* * Create a System object and initialize. */ result = FMOD.Factory.System_Create(ref system); ERRCHECK(result); result = system.getVersion(ref version); ERRCHECK(result); if (version < FMOD.VERSION.number) { MessageBox.Show("Error! You are using an old version of FMOD " + version.ToString("X") + ". This program requires " + FMOD.VERSION.number.ToString("X") + "."); Application.Exit(); } result = system.init(32, FMOD.INITFLAGS.NORMAL, (IntPtr)null); ERRCHECK(result); result = system.createSound("../../../../../examples/media/drumloop.wav", FMOD.MODE.SOFTWARE | FMOD.MODE.LOOP_NORMAL, ref sound); ERRCHECK(result); result = system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel); ERRCHECK(result); /* * Create the DSP effects. */ result = system.createDSPByType(FMOD.DSP_TYPE.LOWPASS, ref dsplowpass); ERRCHECK(result); result = system.createDSPByType(FMOD.DSP_TYPE.CHORUS, ref dspchorus); ERRCHECK(result); /* * Connect up the DSP network */ /* * When a sound is played, a subnetwork is set up in the DSP network which looks like this. * Wavetable is the drumloop sound, and it feeds its data from right to left. * * [DSPHEAD]<------------[DSPCHANNELMIXER] */ result = system.getDSPHead(ref dsphead); ERRCHECK(result); result = dsphead.getInput(0, ref dspchannelmixer, ref dspconnectiontemp); ERRCHECK(result); /* * Now disconnect channeldsp head from wavetable to look like this. * * [DSPHEAD] [DSPCHANNELMIXER] */ result = dsphead.disconnectFrom(dspchannelmixer); ERRCHECK(result); /* * Now connect the 2 effects to channeldsp head. * * [DSPLOWPASS] * / * [DSPHEAD] [DSPCHANNELMIXER] \ \ [DSPCHORUS] */ result = dsphead.addInput(dsplowpass, ref dsplowpassconnection); ERRCHECK(result); result = dsphead.addInput(dspchorus, ref dspchorusconnection); ERRCHECK(result); /* * Now connect the wavetable to the 2 effects * * [DSPLOWPASS] * / \ * [DSPHEAD] [DSPCHANNELMIXER] \ / \ [DSPCHORUS] */ result = dsplowpass.addInput(dspchannelmixer, ref dspconnectiontemp); ERRCHECK(result); result = dspchorus.addInput(dspchannelmixer, ref dspconnectiontemp); ERRCHECK(result); /* * Now the drumloop will be twice as loud, because it is being split into 2, then recombined at the end. * What we really want is to only feed the dspchannelmixer->dsplowpass through the left speaker, and * dspchannelmixer->dspchorus to the right speaker. * We can do that simply by setting the pan, or speaker levels of the connections. * * [DSPLOWPASS] * /1,0 \ * [DSPHEAD] [DSPCHANNELMIXER] \0,1 / * [DSPCHORUS] */ { float[] leftinputon = { 1.0f, 0.0f }; float[] rightinputon = { 0.0f, 1.0f }; float[] inputsoff = { 0.0f, 0.0f }; result = dsplowpassconnection.setLevels(FMOD.SPEAKER.FRONT_LEFT, leftinputon, 2); ERRCHECK(result); result = dsplowpassconnection.setLevels(FMOD.SPEAKER.FRONT_RIGHT, inputsoff, 2); ERRCHECK(result); result = dsplowpassconnection.setLevels(FMOD.SPEAKER.FRONT_LEFT, inputsoff, 2); ERRCHECK(result); result = dsplowpassconnection.setLevels(FMOD.SPEAKER.FRONT_RIGHT, rightinputon, 2); ERRCHECK(result); } result = dsplowpass.setBypass(true); result = dspchorus.setBypass(true); result = dsplowpass.setActive(true); result = dspchorus.setActive(true); }