Xna Framework Audio OpenALSoundController

The title of this post is the exception that may occurs on some devices when the app starts.
It appears using Monogame v3.7.1

This is a bug in Monogame framework, already fixed since 29 September 2018.
Unfortunately, I run in this issue using the milestone 3.7.1 :-(

Both my dev and test devices doesn't throw this exception, so I was informed of this from Android Vitals page on Google Play Console.

Fixing this issue appears very simple, just downloaded and installed the 3.8.0 development version of Monogame and the Exception vanished... but.. but!!

When published a new Beta release of Cartoonator o Google Play Console, the pre-launch report tells me that a Huawei P8 Lite device fails to start, raising the following exception:

Fatal AndroidRuntime Exception detected.

FATAL EXCEPTION: main
Process: com.alimede.android.cartoonator, PID: 19837
android.runtime.JavaProxyThrowable: System.DivideByZeroException: Attempted to divide by zero.
  at (wrapper managed-to-native) System.Object.__icall_wrapper___emul_op_idiv(int,int)
  at Microsoft.Xna.Framework.Audio.OALSoundBuffer.BindDataBuffer (System.Byte[] dataBuffer, MonoGame.OpenAL.ALFormat format, System.Int32 size, System.Int32 sampleRate, System.Int32 sampleAlignment) [0x000d4] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Microsoft.Xna.Framework.Audio.SoundEffect.PlatformInitializePcm (System.Byte[] buffer, System.Int32 offset, System.Int32 count, System.Int32 sampleBits, System.Int32 sampleRate, Microsoft.Xna.Framework.Audio.AudioChannels channels, System.Int32 loopStart, System.Int32 loopLength) [0x00032] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Microsoft.Xna.Framework.Audio.SoundEffect..ctor (System.Byte[] header, System.Byte[] buffer, System.Int32 bufferSize, System.Int32 durationMs, System.Int32 loopStart, System.Int32 loopLength) [0x0005c] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Microsoft.Xna.Framework.Content.SoundEffectReader.Read (Microsoft.Xna.Framework.Content.ContentReader input, Microsoft.Xna.Framework.Audio.SoundEffect existingInstance) [0x00045] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Microsoft.Xna.Framework.Content.ContentTypeReader`1[T].Read (Microsoft.Xna.Framework.Content.ContentReader input, System.Object existingInstance) [0x00003] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Microsoft.Xna.Framework.Content.ContentReader.InnerReadObject[T] (T existingInstance) [0x0002d] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Microsoft.Xna.Framework.Content.ContentReader.ReadObject[T] () [0x00000] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Microsoft.Xna.Framework.Content.ContentReader.ReadAsset[T] () [0x00006] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Microsoft.Xna.Framework.Content.ContentManager.ReadAsset[T] (System.String assetName, System.Action`1[T] recordDisposableObject) [0x00045] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Microsoft.Xna.Framework.Content.ContentManager.Load[T] (System.String assetName) [0x0005a] in <e0cb617a22cc4d71bc8dedbbff3b0458>:0 
  at Cartoonator.Contents.LoadData (Microsoft.Xna.Framework.Content.ContentManager content_manager) [0x00088] in <1605888cae67493d8432ad7b5ae0caeb>:0 
  at Cartoonator.CartoonatorGame.LoadContent () [0x00011] in <1605888cae67493d8432ad7b5ae0caeb>:0 
  at .......

CartoonatorGame.LoadContent() is a method that loads all gfx and sounds into Texture2D and SoundEffect objects respectively.

hmm... this feels me that the Monogame v3.8.0 still not load correctly the Audio Layer on some devices, and when you try to load a SoundEffect the app may crash due to some uninitialized code.

 

I solved this in two steps: at first, inside the LoadContent() method, grouping into a try-catch statement the load of all sound effects: if a SoundEffect fails to load, his property remains to null and the app initialization go over.

public virtual void LoadData(ContentManager content_manager)
{
	try
	{
		// loading sound effects:
		this.Sound_Alarm = content_manager.Load<SoundEffect>("sound_alarm");
		this.Sound_Broom = content_manager.Load<SoundEffect>("sound_broom");
        //... omissis ...
		this.Sound_Saxophone = content_manager.Load<SoundEffect>("sound_saxophone");
	}
	catch (Exception)
	{
		// if i can't load sounds (eg: device audio not fully supported by Monogame)
		// it's a shame, but I have to continue loading other resources:
	}

	// loading gfx files:
    //...

}//LoadData

Then, I created a static Sound class, that provides a method to play sounds, only if the sound is not null:

public static class Sound
{

	/// <summary>
	/// Play a SoundEffect, if defined.
	/// </summary>
	/// <param name="sound_effect">SoundEffect to play</param>
	public static void Play(SoundEffect sound_effect)
	{
		try
		{
			if (sound_effect != null)
				sound_effect.Play();
		}
		catch (Exception)
		{
			// unmanaged exception, I'm doing this only to not crash the app here..
		}

	}//Play

}//class

Using this piece of code, compiled using Monogame v3.8.0, the app will starts on more devices, at least it appears mute when the sound layer is not fully compatible with Monogame.

...rather than nothing...

Comments

No Comments

Write comment

* These fields are required