Beispiel #1
0
        public OpenALDevice()
        {
            string envDevice = Environment.GetEnvironmentVariable("FNA_AUDIO_DEVICE_NAME");

            if (String.IsNullOrEmpty(envDevice))
            {
                /* Be sure ALC won't explode if the variable doesn't exist.
                 * But, fail if the device name is wrong. The user needs to know
                 * if their environment variable was incorrect.
                 * -flibit
                 */
                envDevice = String.Empty;
            }
            alDevice = ALC10.alcOpenDevice(envDevice);
            if (CheckALCError() || alDevice == IntPtr.Zero)
            {
                throw new InvalidOperationException("Could not open audio device!");
            }

            int[] attribute = new int[0];
            alContext = ALC10.alcCreateContext(alDevice, attribute);
            if (CheckALCError() || alContext == IntPtr.Zero)
            {
                Dispose();
                throw new InvalidOperationException("Could not create OpenAL context");
            }

            ALC10.alcMakeContextCurrent(alContext);
            if (CheckALCError())
            {
                Dispose();
                throw new InvalidOperationException("Could not make OpenAL context current");
            }

            float[] ori = new float[]
            {
                0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f
            };
            AL10.alListenerfv(AL10.AL_ORIENTATION, ori);
            AL10.alListener3f(AL10.AL_POSITION, 0.0f, 0.0f, 0.0f);
            AL10.alListener3f(AL10.AL_VELOCITY, 0.0f, 0.0f, 0.0f);
            AL10.alListenerf(AL10.AL_GAIN, 1.0f);

            EFX.alGenFilters(1, out INTERNAL_alFilter);

            // FIXME: Remove for FNA 16.11! -flibit
            if (!AL10.alIsExtensionPresent("AL_SOFT_gain_clamp_ex"))
            {
                FNALoggerEXT.LogWarn("AL_SOFT_gain_clamp_ex not found!");
                FNALoggerEXT.LogWarn("Update your OpenAL Soft library!");
            }
        }
Beispiel #2
0
            public static void Create()
            {
                IntPtr ctx;

                try
                {
                    FAudio.FAudioCreate(
                        out ctx,
                        0,
                        FAudio.FAUDIO_DEFAULT_PROCESSOR
                        );
                }
                catch (Exception e)
                {
                    /* FAudio is missing, bail! */
                    FNALoggerEXT.LogWarn("FAudio failed to load: " + e.ToString());
                    return;
                }

                uint devices;

                FAudio.FAudio_GetDeviceCount(
                    ctx,
                    out devices
                    );
                if (devices == 0)
                {
                    /* No sound cards, bail! */
                    FAudio.FAudio_Release(ctx);
                    return;
                }

                FAudioContext context = new FAudioContext(ctx, devices);

                if (context.Handle == IntPtr.Zero)
                {
                    /* Soundcard failed to configure, bail! */
                    context.Dispose();
                    return;
                }

                Context = context;
            }
        public static void Initialize()
        {
            // We should only have one of these!
            if (ALDevice != null)
            {
                FNALoggerEXT.LogWarn("ALDevice already exists, overwriting!");
            }

            bool disableSound = Environment.GetEnvironmentVariable(
                "FNA_AUDIO_DISABLE_SOUND"
                ) == "1";

            if (disableSound)
            {
                ALDevice = new NullALDevice();
            }
            else
            {
                ALDevice = FNAPlatform.CreateALDevice();
            }

            // Populate device info
            if (ALDevice != null)
            {
                ALDevice.SetMasterVolume(MasterVolume);
                ALDevice.SetDopplerScale(DopplerScale);
                ALDevice.SetSpeedOfSound(SpeedOfSound);

                Renderers      = ALDevice.GetDevices();
                Microphone.All = ALDevice.GetCaptureDevices();

                InstancePool        = new List <SoundEffectInstance>();
                DynamicInstancePool = new List <DynamicSoundEffectInstance>();
                ActiveMics          = new List <Microphone>();
                AppDomain.CurrentDomain.ProcessExit += Dispose;
            }
            else
            {
                Renderers      = new ReadOnlyCollection <RendererDetail>(new List <RendererDetail>());
                Microphone.All = new ReadOnlyCollection <Microphone>(new List <Microphone>());
            }
        }
Beispiel #4
0
        protected T ReadAsset <T>(string assetName, Action <IDisposable> recordDisposableObject)
        {
            if (string.IsNullOrEmpty(assetName))
            {
                throw new ArgumentNullException("assetName");
            }
            if (disposed)
            {
                throw new ObjectDisposedException("ContentManager");
            }

            object result            = null;
            Stream stream            = null;
            string modifiedAssetName = String.Empty;             // Will be used if we have to guess a filename

            try
            {
                stream = OpenStream(assetName);
            }
            catch (Exception e)
            {
                // Okay, so we couldn't open it. Maybe it needs a different extension?
                // FIXME: This only works for files on the disk, what about custom streams? -flibit
                modifiedAssetName = MonoGame.Utilities.FileHelpers.NormalizeFilePathSeparators(
                    Path.Combine(RootDirectoryFullPath, assetName)
                    );
                if (typeof(T) == typeof(Texture2D) || typeof(T) == typeof(Texture))
                {
                    modifiedAssetName = Texture2DReader.Normalize(modifiedAssetName);
                }
                else if ((typeof(T) == typeof(SoundEffect)))
                {
                    modifiedAssetName = SoundEffectReader.Normalize(modifiedAssetName);
                }
                else if ((typeof(T) == typeof(Effect)))
                {
                    modifiedAssetName = EffectReader.Normalize(modifiedAssetName);
                }
                else if ((typeof(T) == typeof(Song)))
                {
                    modifiedAssetName = SongReader.Normalize(modifiedAssetName);
                }
                else if ((typeof(T) == typeof(Video)))
                {
                    modifiedAssetName = VideoReader.Normalize(modifiedAssetName);
                }
                else
                {
                    // No raw format available, disregard!
                    modifiedAssetName = null;
                }

                // Did we get anything...?
                if (String.IsNullOrEmpty(modifiedAssetName))
                {
                    // Nope, nothing we're aware of!
                    throw new ContentLoadException(
                              "Could not load asset " + assetName + "! Error: " + e.Message,
                              e
                              );
                }

                stream = TitleContainer.OpenStream(modifiedAssetName);
            }

            // Check for XNB header
            stream.Read(xnbHeader, 0, xnbHeader.Length);
            if (xnbHeader[0] == 'X' &&
                xnbHeader[1] == 'N' &&
                xnbHeader[2] == 'B' &&
                targetPlatformIdentifiers.Contains((char)xnbHeader[3]))
            {
                using (BinaryReader xnbReader = new BinaryReader(stream))
                    using (ContentReader reader = GetContentReaderFromXnb(assetName, ref stream, xnbReader, (char)xnbHeader[3], recordDisposableObject))
                    {
                        result = reader.ReadAsset <T>();
                        GraphicsResource resource = result as GraphicsResource;
                        if (resource != null)
                        {
                            resource.Name = assetName;
                        }
                    }
            }
            else
            {
                // It's not an XNB file. Try to load as a raw asset instead.

                // FIXME: Assuming seekable streams! -flibit
                stream.Seek(0, SeekOrigin.Begin);

                if (typeof(T) == typeof(Texture2D) || typeof(T) == typeof(Texture))
                {
                    Texture2D texture;
                    if (xnbHeader[0] == 'D' &&
                        xnbHeader[1] == 'D' &&
                        xnbHeader[2] == 'S' &&
                        xnbHeader[3] == ' ')
                    {
                        texture = Texture2D.DDSFromStreamEXT(
                            GetGraphicsDevice(),
                            stream
                            );
                    }
                    else
                    {
                        texture = Texture2D.FromStream(
                            GetGraphicsDevice(),
                            stream
                            );
                    }
                    texture.Name = assetName;
                    result       = texture;
                }
                else if ((typeof(T) == typeof(SoundEffect)))
                {
                    result = SoundEffect.FromStream(stream);
                }
                else if ((typeof(T) == typeof(Effect)))
                {
                    byte[] data = new byte[stream.Length];
                    stream.Read(data, 0, (int)stream.Length);
                    result = new Effect(GetGraphicsDevice(), data);
                }
                else if ((typeof(T) == typeof(Song)))
                {
                    // FIXME: Not using the stream! -flibit
                    result = new Song(modifiedAssetName);
                }
                else if ((typeof(T) == typeof(Video)))
                {
                    // FIXME: Not using the stream! -flibit
                    result = new Video(modifiedAssetName, GetGraphicsDevice());
                    FNALoggerEXT.LogWarn(
                        "Video " +
                        modifiedAssetName +
                        " does not have an XNB file! Hacking Duration property!"
                        );
                }
                else
                {
                    stream.Close();
                    throw new ContentLoadException("Could not load " + assetName + " asset!");
                }

                /* Because Raw Assets skip the ContentReader step, they need to have their
                 * disposables recorded here. Doing it outside of this catch will
                 * result in disposables being logged twice.
                 */
                IDisposable disposableResult = result as IDisposable;
                if (disposableResult != null)
                {
                    if (recordDisposableObject != null)
                    {
                        recordDisposableObject(disposableResult);
                    }
                    else
                    {
                        disposableAssets.Add(disposableResult);
                    }
                }

                /* Because we're not using a BinaryReader for raw assets, we
                 * need to close the stream ourselves.
                 * -flibit
                 */
                stream.Close();
            }

            return((T)result);
        }
Beispiel #5
0
        internal void Play(bool isManaged)
        {
            // No-op if we're already playing.
            if (State != SoundState.Stopped)
            {
                if (State == SoundState.Paused)
                {
                    // ... but be sure pause/resume still works
                    Resume();
                }
                return;
            }

            if (INTERNAL_alSource != null)
            {
                // The sound has stopped, but hasn't cleaned up yet...
                AudioDevice.ALDevice.StopAndDisposeSource(INTERNAL_alSource);
                INTERNAL_alSource = null;
            }
            while (queuedBuffers.Count > 0)
            {
                availableBuffers.Enqueue(queuedBuffers.Dequeue());
                PendingBufferCount -= 1;
            }

            if (AudioDevice.ALDevice == null)
            {
                throw new NoAudioHardwareException();
            }

            INTERNAL_alSource = AudioDevice.ALDevice.GenSource();
            if (INTERNAL_alSource == null)
            {
                FNALoggerEXT.LogWarn("AL SOURCE WAS NOT AVAILABLE, SKIPPING.");
                return;
            }

            // Queue the buffers to this source
            while (buffersToQueue.Count > 0)
            {
                IALBuffer nextBuf = buffersToQueue.Dequeue();
                queuedBuffers.Enqueue(nextBuf);
                AudioDevice.ALDevice.QueueSourceBuffer(INTERNAL_alSource, nextBuf);
            }

            // Apply Pan/Position
            if (INTERNAL_positionalAudio)
            {
                INTERNAL_positionalAudio = false;
                AudioDevice.ALDevice.SetSourcePosition(
                    INTERNAL_alSource,
                    position
                    );
            }
            else
            {
                Pan = Pan;
            }

            // Reassign Properties, in case the AL properties need to be applied.
            Volume = Volume;
            Pitch  = Pitch;

            // ... but wait! What if we need moar buffers?
            for (
                int i = MINIMUM_BUFFER_CHECK - PendingBufferCount;
                (i > 0) && BufferNeeded != null;
                i -= 1
                )
            {
                BufferNeeded(this, null);
            }

            // Finally.
            AudioDevice.ALDevice.PlaySource(INTERNAL_alSource);
            if (isManaged)
            {
                AudioDevice.DynamicInstancePool.Add(this);
            }
        }
Beispiel #6
0
        public virtual void Play()
        {
            if (State != SoundState.Stopped)
            {
                return;
            }

            if (INTERNAL_alSource != null)
            {
                // The sound has stopped, but hasn't cleaned up yet...
                AudioDevice.ALDevice.StopAndDisposeSource(INTERNAL_alSource);
                INTERNAL_alSource = null;
            }

            IALBuffer srcBuf;

            if (INTERNAL_positionalAudio && INTERNAL_parentEffect.INTERNAL_monoBuffer != null)
            {
                srcBuf = INTERNAL_parentEffect.INTERNAL_monoBuffer;
            }
            else
            {
                srcBuf = INTERNAL_parentEffect.INTERNAL_buffer;
            }
            INTERNAL_alSource = AudioDevice.ALDevice.GenSource(
                srcBuf,
                INTERNAL_isXACTSource
                );
            if (INTERNAL_alSource == null)
            {
                FNALoggerEXT.LogWarn("AL SOURCE WAS NOT AVAILABLE, SKIPPING.");
                return;
            }

            // Apply Pan/Position
            if (INTERNAL_positionalAudio)
            {
                AudioDevice.ALDevice.SetSourcePosition(
                    INTERNAL_alSource,
                    position
                    );
            }
            else
            {
                Pan = Pan;
            }

            // Reassign Properties, in case the AL properties need to be applied.
            Volume   = Volume;
            IsLooped = IsLooped;
            Pitch    = Pitch;

            // Apply EFX
            if (INTERNAL_alReverb != null)
            {
                AudioDevice.ALDevice.SetSourceReverb(
                    INTERNAL_alSource,
                    INTERNAL_alReverb
                    );
            }

            AudioDevice.ALDevice.PlaySource(INTERNAL_alSource);
        }