Hi, we are currently having an issue that’s happening from quite some time already and we don’t know what are we doing wrong.
Everytime a VO event is being played there is an audio waveform visualizer that shows the moving waveform of that event. This feature worked fine but somehow the waveform visualizer now stops working when the user/player sets the volume from master or dialogues to 0 zero from the options menu. This worked fine before, even if the player set master or dialogue volume to zero.
The bus routing is working with a bus named VO (which contains the audio VO events) and it’s parent its a bus called WaveformVO which is the one the waveform data gets extracted. Also we created a custom DSP like the documentation reccomends.
While testing with Live Update, we can see that the WaveformVO Bus receives audio information, even when the VO Bus does not. All this while we reproduce the scenario that the volume is set to 0 when dialogues are being played.
Also, when the volume of dialogues is set to 0 while a dialogue is playing we get this console warning:
Error initializing dialogue waveform, trying again : ERR_STUDIO_NOT_LOADED
I don’t know if it helps but this is the script for the waveform visualizer:
using FMOD;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UI.Extensions;
public class DialogueWaveformView : MonoBehaviour
{
FMOD.Studio.EventInstance musicInstance;
FMOD.DSP fft;
//public UILineRenderer lineRenderer;
public Image[] waveImages;
private int divisionsCount = 10;
const int WindowSize = 1024;
[Range(0f,0.1f)]
public float heightMult = 0.01f;
[Range(0,1)]
public float heightOffset = 0.1f;
//public AnimationCurve decompressionMap = AnimationCurve.Linear(0f, -1, 1f, 1f);
[Range(0f, 1f)] public float valueDamp = 0.1f;
[Range(0f, 80f)] public float valueGateCutoff = 0.01f;
[Range(0f, WindowSize)] public float spectrumStart = 150f; //Fine tuning by voice range
[Range(0f, WindowSize)] public float spectrumEnd = 800f;
[Range(0f, 1f)]
public float noiseIntensity = 0.1f;
private float[] easedValues;
[SerializeField, InspectorReadOnly]
private bool initialized = false;
[SerializeField, InspectorReadOnly]
private bool updateWave = false;
private Coroutine initializeRoutine = null;
private IEnumerator Initialize()
{
divisionsCount = waveImages.Length;
easedValues = new float[divisionsCount];
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);
FMOD.RESULT result = FMOD.RESULT.OK;
ChannelGroup channelGroup;
AudioManager.instance.LockWaveformBus();
do
{
yield return null;
result = AudioManager.instance.GetWaveformBus(out channelGroup);
if (result != FMOD.RESULT.OK)
DebugEx.Warning("Error initializing dialogue waveform, trying again : " + result.ToString());
} while (result != FMOD.RESULT.OK);
channelGroup.addDSP(FMOD.CHANNELCONTROL_DSP_INDEX.TAIL, fft);
initialized = true;
initializeRoutine = null;
}
public void OnEndDialogue(Person person, string line)
{
updateWave = false;
//AudioManager.instance.UnlockVoiceBus();
}
public void OnStartDialogue(Person person, string line)
{
updateWave = true;
//AudioManager.instance.LockVoiceBus();
if (!initialized)
{
if(initializeRoutine == null)
initializeRoutine = StartCoroutine(Initialize());
}
}
private void OnEnable()
{
ResetWaveform();
}
private void ResetWaveform()
{
float value;
if(easedValues == null || easedValues.Length == 0)
easedValues = new float[waveImages.Length];
for (int i = 0; i < waveImages.Length; i++)
{
easedValues[i] = 0;
value = easedValues[i] + heightOffset;
waveImages[i].transform.localScale = new Vector3(1f, value, 1f);
}
}
void Update()
{
if (!initialized) return;
if (updateWave)
{
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));
var spectrum = fftData.spectrum;
if (fftData.numchannels > 0)
{
for (int i = 0; i < divisionsCount; ++i)
{
int j = (int)(Mathf.Lerp(spectrumStart, spectrumEnd, (float)i / divisionsCount)) * 2;
var v = (lin2dB(spectrum[0][j]) + 80);
//var s = (spectrum[0][j] * normalize - .5f) * 2f;
//v = Mathf.Abs(decompressionMap.Evaluate(v));
v = Mathf.Abs(v);
if (v < valueGateCutoff)
v = 0f;
v *= heightMult;
v = Mathf.Max(easedValues[i], v);
easedValues[i] = v;
}
}
}
float value;
var damp = Mathf.Pow(1f - valueDamp, Time.deltaTime * 60f);
for (int i = 0; i < divisionsCount; i++)
{
easedValues[i] += UnityEngine.Random.value * noiseIntensity;
easedValues[i] *= damp;
easedValues[i] = Mathf.Clamp(easedValues[i], 0f, 1f);
value = easedValues[i] + heightOffset;
waveImages[i].transform.localScale = new Vector3(1f, value, 1f);
}
}
float lin2dB(float linear)
{
return Mathf.Clamp(Mathf.Log10(linear) * 20.0f, 80.0f, 0.0f);
}
}
EDIT: Some more info that could help: The visualizer works again when having some volume, even if little. This issue only happens when the volume is set to zero either for dialogues or master slider from options menu in game.
I hope that someone can shed some light into this issue, thanks!