Playing FMOD.Sound from Audioclip has no volume

Hello! I’ve used FMOD previous for monogame, and I’m porting the project over to Unity. I’m using a .wav file as an instrument in the game. It’s the same file that I used and worked in the monogame project.
Load Type : Decompress on Load
Preload Audio Data : True (would prefer not, but for testing).
Compression format: PCM

I made sure to initialize fmod first;
FMODUnity.RuntimeManager.CoreSystem.init(32, FMOD.INITFLAGS.NORMAL, (IntPtr)0);

I’ve converted an audioclip to FMOD.Sound using this code. This probably where I mess up. It’s a bit low level for me too be honest!

            unityClip.GetData(samples, 0);

            byte[] byteArray = new byte[samples.Length * sizeof(float)];
            System.Buffer.BlockCopy(samples, 0, byteArray, 0, byteArray.Length);

            uint lenbytes = (uint)(unityClip.samples * unityClip.channels * sizeof(float));

            CREATESOUNDEXINFO soundinfo = new CREATESOUNDEXINFO();
            soundinfo.cbsize = Marshal.SizeOf(typeof(CREATESOUNDEXINFO));
            soundinfo.length = lenbytes;
            //soundinfo.format = SOUND_FORMAT.BITSTREAM;
            soundinfo.format = SOUND_FORMAT.PCMFLOAT;
            soundinfo.defaultfrequency = unityClip.frequency;
            soundinfo.numchannels = unityClip.channels;

            RESULT result;
            FMOD.Sound sound;
            
            //doesn't work
            //result = RuntimeManager.CoreSystem.createSound(byteArray, FMOD.MODE.OPENMEMORY | FMOD.MODE.CREATESAMPLE, ref soundinfo, out sound);
            
            //I'm not sure where to actually pass the float array
            result = RuntimeManager.CoreSystem.createSound(unityClip.name, FMOD.MODE.OPENUSER | FMOD.MODE.CREATESAMPLE, ref soundinfo, out sound);

            if (result != FMOD.RESULT.OK)
                Debug.LogError($"error creating sound {result}" );
            else
                Debug.Log($"converted sound {result} : sound");

I then try to play this sound as followed;

    {
        sound = FmodSound.LoadSound(instrumentPlayer.audioClip);
        RuntimeManager.CoreSystem.createChannelGroup(" test", out channelGroup);
        channelGroup.setVolumeRamp(false);
        channelGroup.setVolume(1);
    }

    // Update is called once per frame
    void Update()
    {
        Keyboard keyboard = playerInput.GetDevice<Keyboard>();
        if (keyboard == null) return;

        if (keyboard.dKey.wasPressedThisFrame)
        {

            RuntimeManager.CoreSystem.playSound( sound, channelGroup, false, out FMOD.Channel fmodChannel);
            fmodChannel.setVolume(1);
            fmodChannel.setVolumeRamp(false);
            //instrumentPlayer.instrument.Play(Note.C3);
        }
}

I can see a channel is created, but the volume remains at -80.
image

I’m sure I’m just forgetting a very basic thing, help is appreciated!

Hi,

What version of the FMOD integration are you using?
image

Are you manually calling this? This is called as part of the integration. It is possible to modify the flags passed to the core system if you wish on line: RuntimeManger.cs 376. ’

I would suggest having a look at our API example user_created_sound.cpp which is included with our engine download: "C:\Program Files (x86)\FMOD SoundSystem\FMOD Studio API Windows\api\core\examples\vs2019\examples.sln" which outlines how to pass PCM data to a sound to be played via a callback.

Hope this helps!

That’s the same version I’m using!

As a temporary work around both of these are working;

path = Path.Combine(Application.streamingAssetsPath, eventName);
path = Path.Combine("Assets/Audio/" + eventName);
FMOD.RESULT result = FMODUnity.RuntimeManager.CoreSystem.createSound(path, FMOD.MODE.DEFAULT, out fmodSound);

So I know I’ve set up FMOD correctly and that the audio file is fine.
That narrowed it down to incorrectly converting the audioclip to FMOD.Sound.

The problem is specific to the Audioclip, so I don’t think looking at the .cpp will help!

1 Like

Good to hear it is fixed. Thanks for sharing the solution.

I’m trying to run the game on my android phone now and I end up with a weird path;

[FMOD] FOpenFile::open : fopen failed to open ‘jar:file:///data/app/~~Qttb5drYckL9p7dm74fIpA==/com.UnityTechnologies.com.unity.template.urpblank-Mvv2mCfXgWWAu5Q9UXwb3g==/base.apk!/assets/nyan_c-001.wav’, errno = 2

This is why I initially tried to create the sound from an audioclip, since I can rely on this working on every platform.
Anyone has any clue on how to do that, or which path I should insert for it to work on Android?

Alright I’m not gonna be able to figure this out alone, I made a sample project. I actually can’t manage to get any sound at all in this new project, even when using Streaming Assets. So I’m completely clueless

Some small progress, I found that the sound’s volume and speed are both 0, even if I set them manually.
No idea what this means, but it might be a hint.

	public static FMOD.Sound LoadSound(AudioClip unityClip)
    {
        float[] samples = new float[unityClip.samples * unityClip.channels];
        unityClip.GetData(samples, 0);

        uint lenbytes = (uint)(unityClip.samples * unityClip.channels * sizeof(float));

        CREATESOUNDEXINFO soundinfo = new CREATESOUNDEXINFO();
        soundinfo.cbsize = Marshal.SizeOf(typeof(CREATESOUNDEXINFO));
        soundinfo.length = lenbytes;
        soundinfo.format = SOUND_FORMAT.PCMFLOAT;
        soundinfo.defaultfrequency = unityClip.frequency;
        soundinfo.numchannels = unityClip.channels;

        RESULT result;
        FMOD.Sound sound;
        result = RuntimeManager.CoreSystem.createSound("abc", FMOD.MODE.OPENUSER, ref soundinfo, out sound);

        IntPtr ptr1, ptr2;
        uint len1, len2;
        result = sound.@lock(0, lenbytes, out ptr1, out ptr2, out len1, out len2);
        Marshal.Copy(samples, 0, ptr1, (int)(len1 / sizeof(float)));
        if (len2 > 0)
        {
            Marshal.Copy(samples, (int)(len1 / sizeof(float)), ptr2, (int)(len2 / sizeof(float)));
        }
        result = sound.unlock(ptr1, ptr2, len1, len2);

        sound.setMusicSpeed(1f);
        sound.setMusicChannelVolume(0, 1f);

        sound.getLength(out uint length, FMOD.TIMEUNIT.MS);
        sound.getMusicChannelVolume(0, out float soundVolume);
        sound.getMusicSpeed(out float musicspeed);

        UnityEngine.Debug.Log($"RESULT => {result}, length {length} , speed {musicspeed} , volume {soundVolume}" );

        return sound;
    }

You need to create a Unity web request to read a file from an APK. I am finding this works fine for reading a file from the StreamingAssets directory on Android:

    // Call with StartCoroutine(PlayFromAPK("filename.wav"))
    private IEnumerator PlayFromAPK(string filename)
    {
        UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequest.Get(Application.streamingAssetsPath + "/" + filename);

        yield return www.SendWebRequest();
        byte[] loadWebResult = www.downloadHandler.data;

        CREATESOUNDEXINFO soundinfo = new CREATESOUNDEXINFO();
        soundinfo.cbsize = Marshal.SizeOf(typeof(CREATESOUNDEXINFO));
        soundinfo.length = (uint)loadWebResult.Length;

        ERRCHECK(FMODUnity.RuntimeManager.CoreSystem.createSound(loadWebResult, MODE.OPENMEMORY, ref soundinfo, out Sound sound));
        ERRCHECK(FMODUnity.RuntimeManager.CoreSystem.playSound(sound, new ChannelGroup(), false, out Channel channel));
    }

    public static void ERRCHECK(FMOD.RESULT result)
    {
        if (result != FMOD.RESULT.OK)
        {
            UnityEngine.Debug.Log(result);
        }
    }

Can you please give that a shot and let me know if you are still having trouble loading the file?

That did the trick, you’re a legend!
It’s using the same API as converting the audioclip, so I’m really surprised that it works, but at this point I don’t care about the “why” anymore haha.

1 Like

The problem is essentially that APKs are zip archives, and UnityWebRequest is the most convenient API for reading files from a zip archive, leading to an unintuitive scenario- reading files on Android requires a “web request”.
In any case, glad it’s working for you now. Please let us know if you run into any other issues.