How do I use NVorbis to load an ogg into a Unity Audioclip?

647 Views Asked by At

I am trying to use NVorbis to load the contents of an .ogg file into a buffer so that I can use AudioClip.SetData to render the contents into a Unity Audioclip, but the examples given on the NVorbis github are vague about how to actually achieve this. Reading the code definition of vorbis.ReadSamples() suggests to me that using the values given in the simplest example ((readBuffer, 0, readBuffer.Length), where readBuffer is the float[] buffer you want to use) ought to make the method behave rather like File.ReadAllBytes(), which is what I want, but this doesn't seem to be the case and I don't understand what the default example is doing instead. That is, I don't understand what "// do stuff with the buffer" is supposed to entail in a context where I don't want to manipulate the data at all except to make it compatible with a Unity AudioClip (which if it is PCM data it should already be).

My code is as follows:

    public static AudioClip LoadOgg(string filePath)
    {
        AudioClip clip;
        using (var vorbis = new NVorbis.VorbisReader(filePath))
        {
            int channels = vorbis.Channels;
            int sampleRate = vorbis.SampleRate;

            float[] audioData = new float[channels * sampleRate / 5];

            int cnt;
            while ((cnt = vorbis.ReadSamples(audioData, 0, audioData.Length)) > 0) 
            { 
            }
            clip = AudioClip.Create(SSSLoadingHelper.IsolateFileName(filePath), (int)(audioData.Length / channels), channels, sampleRate, false);
            clip.SetData(audioData, 0);
            return clip;
        }
    }

Additional context:

  • This project is a code injection mod that targets a game using Unity 5 and .Net 3.5. Consequently I am using NVorbis 0.8.4, because version 0.9.0 dropped support for .Net 3.5, and do not have access to Unity features newer than Unity 5. This also means that while I am also using NAudio for non-ogg audio types, I do not have access to NAudio.Vorbis, as none of its extant versions support NVorbis 0.8.4.
  • I am not using www for this purpose because its insistence on asynchronous loading of an IEnumerator and attachment to a GameObject make it incompatible with what aspects of the existing code I can safely change and with the intended design of the mod.
  • It will never be necessary for this method or any other in the project that loads audio to do anything more complex than transfer the data into an AudioClip object.
  • SSSLoadingHelper.IsolateFilePath() is a method that extracts the filename (sans extension) from the filePath string given and returns it as a string. It is confirmed working elsewhere in the code and not relevant to this question.
1

There are 1 best solutions below

0
On

Not tested on v0.8.4 but suppose that VorbisReader.ReadSamples behaves the same as latest (v0.10.4) and you really want to load all samples on memory, the buffer size is incorrect (and no need of reading loop, I guess).

float[] audioData = new float[channels * sampleRate * vorbis.TotalSamples];

This may lead huge memory allocations for long sound files like background music.

The example intends to apply some action for each 200ms slice. See also TestApp for a better understanding.