Hello !
I tried to do a cube reacting to the beat of a given sound.
This works quite well, however each time I close my game, I get a warning from FMOD saying :
[FMOD] SystemI::close : mDSPLevelsPool not cleaned up properly!. 64 bytes remaining.
(The bytes remaining are not always the same, depending on the moment I close my game I think.)
using System;
using System.Collections;
using UnityEngine;
using System.Runtime.InteropServices;
class SoundSpectrumBeat : MonoBehaviour
{
public Material normalMaterial;
public Material activeMaterial;
private bool isActive = false;
[Tooltip("Path to the file containing the beat reference.")]
public string beatReferencePath = "/Audio/Beats/musique-Glockenspiel.mid";
public float activationThreshold = -45.0f;
public float disactivationThreshold = -50.0f;
[Tooltip("The volume percentage (between 0 and 1).")]
public float volume = 1.0f;
[Tooltip("The delay to start the music (in seconds).")]
public float delay = 0.0f;
private bool started = false;
public Action onBeatHit = null;
FMOD.DSP fft;
const int WindowSize = 1024;
static private int availableId = 0;
private int id = availableId++;
private FMOD.ChannelGroup channelGroup;
private FMOD.ChannelGroup volumeAdjustedChannelGroup;
private FMOD.Sound sound;
void Start()
{
if(disactivationThreshold > activationThreshold) {
Debug.LogError("Disactivation threshold should be lower than activation threshold.");
}
GetComponent<Renderer>().material = normalMaterial;
FMODUnity.RuntimeManager.CoreSystem.createDSPByType(FMOD.DSP_TYPE.FFT, out fft);
fft.setParameterInt((int)FMOD.DSP_FFT.WINDOWTYPE, (int)FMOD.DSP_FFT_WINDOW.HANNING);
fft.setParameterInt((int)FMOD.DSP_FFT.WINDOWSIZE, WindowSize * 2);
Debug.Log(id);
// FMOD.ChannelGroup channelGroup;
FMODUnity.RuntimeManager.CoreSystem.createChannelGroup("SoundSpectrumBeat"+id.ToString(), out channelGroup);
channelGroup.addDSP(FMOD.CHANNELCONTROL_DSP_INDEX.TAIL, fft);
FMODUnity.RuntimeManager.CoreSystem.createChannelGroup("SoundSpectrumBeatMuted"+id.ToString(), out volumeAdjustedChannelGroup);
volumeAdjustedChannelGroup.addGroup(channelGroup);
volumeAdjustedChannelGroup.setVolume(volume);
FMOD.ChannelGroup masterGroup;
FMODUnity.RuntimeManager.CoreSystem.getMasterChannelGroup(out masterGroup);
masterGroup.addGroup(volumeAdjustedChannelGroup);
FMOD.RESULT res;
res = FMODUnity.RuntimeManager.CoreSystem.createStream(Application.dataPath+beatReferencePath, FMOD.MODE.DEFAULT, out sound);
// res = FMODUnity.RuntimeManager.CoreSystem.createStream(Application.dataPath+"/Audio/FMod/project/Assets/musique-Glockenspiel.wav", FMOD.MODE.DEFAULT, out sound);
if(res != FMOD.RESULT.OK) {
Debug.LogWarning(Application.dataPath);
Debug.LogError("Failed to open specified sound file (Reason: "+res+")");
}
StartCoroutine(StartDelayed(sound, channelGroup));
}
IEnumerator StartDelayed(FMOD.Sound sound, FMOD.ChannelGroup channelGroup) {
yield return new WaitForSecondsRealtime(delay);
FMOD.Channel channel;
FMODUnity.RuntimeManager.CoreSystem.playSound(sound, channelGroup, false, out channel);
channel.setPriority(0);
started = true;
}
const float WIDTH = 10.0f;
const float HEIGHT = 0.1f;
void Update()
{
if(!started) {
return;
}
IntPtr unmanagedData;
uint length;
fft.getParameterData((int)FMOD.DSP_FFT.SPECTRUMDATA, out unmanagedData, out length);
// FMOD.DSP_PARAMETER_FFT fftData = (FMOD.DSP_PARAMETER_FFT)Marshal.PtrToStructure(unmanagedData, typeof(FMOD.DSP_PARAMETER_FFT));
FMOD.DSP_PARAMETER_FFT fftData = Marshal.PtrToStructure<FMOD.DSP_PARAMETER_FFT>(unmanagedData);
float[][] spectrum = fftData.spectrum;
if (fftData.numchannels > 0)
{
bool shouldActivate = false;
float maxLevel = -10000f;
for (int i = 0; i < WindowSize; ++i)
{
float level = lin2dB(spectrum[0][i]);
maxLevel = Mathf.Max(level, maxLevel);
}
if(isActive) {
if(maxLevel < disactivationThreshold) {
isActive = false;
GetComponent<Renderer>().material = normalMaterial;
}
}
else {
if(maxLevel > activationThreshold) {
isActive = true;
GetComponent<Renderer>().material = activeMaterial;
if(onBeatHit != null) {
onBeatHit();
}
}
}
}
Marshal.FreeHGlobal(unmanagedData);
}
float lin2dB(float linear)
{
return Mathf.Clamp(Mathf.Log10(linear) * 20.0f, -80.0f, 0.0f);
}
private void OnDestroy() {
Debug.Log("Destruction");
channelGroup.removeDSP(fft);
channelGroup.release();
volumeAdjustedChannelGroup.release();
fft.release();
sound.release();
}
}
Can you, please, help me spot the point where I could cause a memory lack or a memory management problem ?
I’m a newbie in using FMOD and C#, I search in the docs for those details but didn’t found anything.
Thanks !
PS: I based this script on the one I found on this thread.