Hi,
I would like to display the waveform (or envelope) of an fmod event before playing it, so that the user can see what sound it is beforehand.
Thanks to this Topic, I think I’m getting close: Trouble visualizing waveform from event without separate Sound object - Unity - FMOD Forums
Everything works fine except that Sound.ReadData() returns an ERR_UNSUPPORTED error.
Here is my code (most is copy pasted from the given topic, it’s just here for context):
public EventReference eventRef;
public void GetSound()
{
eventInstance = RuntimeManager.CreateInstance(eventRef);
//For now I'm starting it so that it loads, but I intend to either not start it or stop it right after as I don't want to play it now (I just need to readData)
eventInstance.start();
StartCoroutine(GetSoundFromInstance(eventInstance));
}
IEnumerator GetSoundFromInstance(EventInstance eventInstance)
{
if (eventInstance.hasHandle() && !sound.hasHandle())
{
//Wait for the sound to load
FMOD.Studio.PLAYBACK_STATE state;
FMOD.RESULT result;
do
{
result = eventInstance.getPlaybackState(out state);
if (result == FMOD.RESULT.OK)
{
if (state == FMOD.Studio.PLAYBACK_STATE.PLAYING)
{
if (eventInstance.getChannelGroup(out FMOD.ChannelGroup group) == FMOD.RESULT.OK)
{
sound = FindCurrentSound(group);
sound.getName(out string name, 256);
//This works fine for eg, as all others getSomething()
UnityEngine.Debug.Log($"Audio Name: {name}");
sound.getLength(out uint length, TIMEUNIT.RAWBYTES);
byte[] buffer = new byte[length];
//This seems correct as well
UnityEngine.Debug.Log($"Sound Length: {length}");
//================ISSUE IS HERE========================
FMOD.RESULT resultRead = sound.readData(buffer, out uint read);
if (resultRead != FMOD.RESULT.OK)
{
//This logs ERR_UNSUPPORTED
UnityEngine.Debug.Log($"Failed to retrieve data from sound: {resultRead }");
}
//Do things with buffer...
}
}
}
//This is always waited once, as the sound seem to take a frame to start playing
yield return null;
} while (result != RESULT.OK || state != FMOD.Studio.PLAYBACK_STATE.PLAYING);
}
}
//This is pasted from the above topic, seems to work fine
FMOD.Sound FindCurrentSound(FMOD.ChannelGroup channelGroup)
{
FMOD.Sound sound = new FMOD.Sound();
// Check if we are currently in the right channel group
if (channelGroup.getNumChannels(out int numChannels) == FMOD.RESULT.OK && numChannels > 0)
{
if (numChannels > 1)
{
UnityEngine.Debug.Log("More than 1 channel");
}
else
{
if (channelGroup.getChannel(0, out FMOD.Channel channel) == FMOD.RESULT.OK)
{
if (channel.getCurrentSound(out sound) == FMOD.RESULT.OK)
{
UnityEngine.Debug.Log("Found the correct Sound");
}
else
{
UnityEngine.Debug.Log("Could not retrieve sound");
sound = new FMOD.Sound();
}
}
}
}
// Check if the sound has been found
if (!sound.hasHandle())
{
// If not, continue the recusion
channelGroup.getName(out string name, 256);
UnityEngine.Debug.Log(name);
if (channelGroup.getNumGroups(out int numGroups) == FMOD.RESULT.OK && numGroups > 0)
{
if (numGroups > 1)
{
UnityEngine.Debug.Log("More than one Group");
}
else
{
if (channelGroup.getGroup(0, out FMOD.ChannelGroup child) == FMOD.RESULT.OK)
{
sound = FindCurrentSound(child);
}
}
}
}
// Else the sound has been found so return the sound
// This will either be a real sound or not depending if it was found in the recussion.
return sound;
}
I guess I’m missing a call to something but can’t figure what. Any idea?