Se vogliamo ottenere l’esatto livello RMS di un’istanza, dobbiamo lavorare nel codice con FMOD.DSP
, FMOD.DSP_METERING_INFO
e FMOD.ChannelGroup
.
Scarica il progetto Unity & FMOD su questo tutorial.
Dichiariamo gli structs sopra citati insieme all’EventInstance di FMOD e al percorso dell’evento:
FMOD.Studio.EventInstance instance;
[FMODUnity.EventRef]
public string fmodEvent;
FMOD.DSP dsp = new FMOD.DSP();
FMOD.DSP_METERING_INFO meterInfo = new FMOD.DSP_METERING_INFO();
FMOD.ChannelGroup channelGroup;
bool loaded;
La variabile booleana loaded
ci aiuta a verificare in seguito se l’istanza è stata caricata. Nel metodo Start() di Unity avviamo l’istanza:
void Start()
{
instance = FMODUnity.RuntimeManager.CreateInstance(fmodEvent);
instance.start();
StartCoroutine(GetChannelGroup());
}
Eseguiamo la coroutine GetChannelGroup() per ottenere il ChannelGroup dell’istanza:
IEnumerator GetChannelGroup()
{
if (instance.isValid())
{
while (instance.getChannelGroup(out channelGroup) != FMOD.RESULT.OK)
{
yield return new WaitForEndOfFrame();
loaded = false;
}
channelGroup.getDSP(0, out dsp);
dsp.setMeteringEnabled(false, true);
loaded = true;
}
else
{
Debug.Log("L'istanza non esiste!");
yield return null;
}
}
Non è possibile ricevere il ChannelGroup fino a quando l’istanza dell’evento non è stata caricata correttamente. Di conseguenza, mettiamo in loop getChannelGroup()
fino ad ottenere il valore di ritorno FMOD.RESULT.OK
. Con channelGroup.getDSP()
otteniamo l’indirizzo di una variabile per ricevere un pointer all’unità DSP richiesta. Con setMeteringEnabled() si attiva la misurazione (metering) dell’output.
Il passo successivo consiste nel creare una funzione che restituisce il livello RMS come variabile float:
float GetRMS()
{
float rms = 0f;
dsp.getMeteringInfo(IntPtr.Zero, out meterInfo);
for (int i = 0; i < meterInfo.numchannels; i++)
{
rms += meterInfo.rmslevel[i] * meterInfo.rmslevel[i];
}
rms = Mathf.Sqrt(rms / (float)meterInfo.numchannels);
float dB = rms > 0 ? 20.0f * Mathf.Log10(rms * Mathf.Sqrt(2.0f)) : -80.0f;
if (dB > 10.0f) dB = 10.0f;
return dB;
}
Tramite GetRMS() possiamo accedere al livello RMS. Nel progetto Unity ho visualizzato nuovamente il valore semplicemente con del testo su una canvas: