// Native Audio // 5argon - Exceed7 Experiments // Problems/suggestions : 5argon@exceed7.com using System.Runtime.InteropServices; namespace E7.Native { public partial struct NativeSource { /// /// Used with to customize your play. /// Start creating it from . /// /// /// On some platforms like iOS, adjusting them after the play with /// is already too late because you will already hear the audio. (Even in consecutive lines of code) /// /// It has to be a `struct` since this will be sent to the native side, /// interop to a matching code in other language. /// [StructLayout(LayoutKind.Sequential)] public struct PlayOptions { /// /// Structs couldn't have custom default values and something like volume is better defaulted to 1 instead of 0. /// This prellocated `static` variable contains sensible default values that you can copy from as a starting point. /// /// /// Consists of : /// /// - Volume 1 (no attenuation) /// - Pan 0 (center) /// - Offset seconds 0 (starts from the beginning) /// - Source loop `false` /// public static readonly PlayOptions defaultOptions = new PlayOptions { volume = 1, pan = 0, offsetSeconds = 0, sourceLoop = false, }; // /// // /// Choose a target native source for this play. Choosing a source index that is already playing an audio will // /// cut the previous audio off. Valid index is zero-indexed based on how many you get at . // /// If you initialize 3 native sources, you can use 0, 1, or 2. // /// // /// - If -1 () The native source target will be round-robin selected for you. // /// - If any 0+ number, you specify which native source you like to use for this play. // /// - If the number is over how many sources the native side actually gave you at initialization, // /// it is converted to be like -1 automatically. // /// // /// All other options in this play options affects the target native source resulting from this. // /// // /// // /// // public int nativeSourceIndex; /// /// Set the volume of target native source before play. /// /// /// [iOS] Maps to `AL_GAIN`. It is a scalar amplitude multiplier, so the value can go over 1.0 for increasing volume but can be clipped. /// If you put 0.5f, it is attenuated by 6 dB. /// /// [Android] Maps to `SLVolumeItf` interface -> `SetVolumeLevel`. /// The floating volume parameter will be converted to millibel (20xlog10x100) so that putting 0.5f here results in 6dB attenuation. /// public float volume; /// /// Set the pan of target native source before play. /// -1 for full left, 0 for center, 1 for full right. /// /// This pan is based on "balance effect" and not a "constant energy pan". /// That is at the center you hear each side fully. (Constant energy pan has 3dB attenuation to both on center.) /// /// /// [iOS] 2D panning in iOS will be emulated in OpenAL's 3D audio engine by splitting your stereo sound into a separated mono sounds, /// then position each one on left and right ear of the listener. When panning, instead of adjusting gain we will just move the source /// further from the listener and the distance attenuation will do the work. (Gain is reserved to the setting volume command, /// so we have 2 stage of gain adjustment this way. /// /// [Android] Maps to `SLVolumeItf` interface -> `SetStereoPosition` /// public float pan; /// /// Start playing from other point in the audio by offsetting /// the target native source's playhead time SECONDS unit. /// /// Will do nothing if the offset is over the length of audio. /// public float offsetSeconds; /// /// Apply a looping state on the native source. /// /// /// The reason why it is "sourceLoop" instead of "loop" is to emphasize that if some newer sound /// decided to use that native source to play, that looping sound is immediately stopped since we do not mix /// and one native source can only handle one audio. /// /// To "protect" the looping sound, you likely have to plan your native source index carefully when /// choosing which source to play via /// /// Using the default round-robin sooner or later will stop your looping sound when it wraps back. /// public bool sourceLoop; } } }