Can't load OGG or MP3 with Song.FromUri because the file is supposedly locked

I’m running this on Windows. I’m trying to load an .OGG file (or alternatively an .MP3 file) using Song.FromUri(name, new Uri(fileName, UriKind.Relative)). It’s failing with this exception:

An unhandled exception of type 'System.IO.IOException' occurred in System.Private.CoreLib.dll: 'The process cannot access the file 'C:\[...]\Content\Audio\BGM\regular-game.ogg' because it is being used by another process.'
   at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
   at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.IO.File.Open(String path, FileMode mode, FileAccess access, FileShare share)
   at NVorbis.VorbisReader..ctor(String fileName)
   at Microsoft.Xna.Framework.Audio.OggStream.Open(Boolean precache)
   at Microsoft.Xna.Framework.Audio.OggStream.Prepare()
   at Microsoft.Xna.Framework.Media.Song.PlatformInitialize(String fileName)
   at Microsoft.Xna.Framework.Media.Song..ctor(String fileName)
   at Microsoft.Xna.Framework.Media.Song.FromUri(String name, Uri uri)

Things I tried so far to make sure the file really isn’t used:

  • Delete the file (it deletes with no issues)
  • Restart the computer
  • Re-encode the OGG as an MP3
  • Restart again after encoding as MP3
  • Close my IDE and run dotnet run from the CLI
  • Use Process Monitor (procmon) to make sure it’s not locked
  • Use Performance Monitor (Windows built-in) to make sure it’s not locked

I can play other sounds fine (SoundEffect / SoundEffectInstance) but those are .WAV files, so I don’t see the relevance, other than to suggest that MonoGame audio works fine in other cases.

I really hope I can get an answer to this.

Meanwhile, for anyone else who stumbles onto this thread, I solved it by using NAudio and NAudio.Vorbis. You can see the sample code in their repo README.md here. (It’s trivial to play audio from an OGG file.)

My previous post was incorrect; OGG and MP3 playback both suffer from the same issue (changing the volume in-game changes it in Windows Mixer).

I eventually solved this with a convoluted solution:

  • Encode background audio as MP3 files
  • At runtime, decode them back into .wav files and play them as-is

For this to run on Linux, I ended up using NLayer.NAudio. There’s some source-code here that uses Mp3FrameDecompressor for this purpose.