Beispiel #1
0
        public App()
            : base()
        {
            log = new ConsoleAL();
            mainWindow = new MainWindow();
            projectionWindow = new ProjectionWindow();
            game = new Game();
            displays = new List<ScoreDisplay>();
            projectorState = ProjectorState.STAND_BY;
            gameState = GameState.WAITING;
            liveMatch = mainWindow.liveMatch;
            selectedTab = mainWindow.GetSelectedTab();

            log.StartLog();

            SetupTimer();
            LoadDisplays();
            LoadFileHandler();
            WireHandlers();
            projectionWindow.Show();
            mainWindow.Show();
        }
Beispiel #2
0
        /// <summary>
        /// Sets up the hardware resources used by the controller.
        /// </summary>
        private ALController()
        {
            if (AL.NativeLibrary == IntPtr.Zero)
            {
                throw new DllNotFoundException(
                          "Couldn't initialize OpenAL because the native binaries couldn't be found.");
            }

            if (!Open())
            {
                throw new AudioHardwareException(
                          "OpenAL device could not be initialized, see console output for details.");
            }

            Efx = new EffectsExtension(Device);

            if (ALC.IsExtensionPresent(Device, "ALC_EXT_CAPTURE"))
            {
                Microphone.PopulateCaptureDevices();
            }

            // We have hardware here and it is ready

            _allSources = new uint[MaxNumberOfSources];
            AL.GenSources(_allSources);
            ALHelper.CheckError("Failed to generate sources.");

            // TODO: allow more effects
            if (Efx.IsAvailable)
            {
                Filter = Efx.GenFilter();
            }

            _availableSources = new Queue <uint>(_allSources);
            _sourcesInUse     = new HashSet <uint>();
        }
Beispiel #3
0
        /// <summary>
        /// Disposes the <see cref="ALController"/>.
        /// </summary>
        /// <param name="disposing">If true, the managed resources are to be disposed.</param>
        private void Dispose(bool disposing)
        {
            if (!_isDisposed)
            {
                if (disposing)
                {
                    Streamer.Dispose();

                    if (Filter != 0 && Efx.IsAvailable)
                    {
                        Efx.DeleteFilter(Filter);
                    }

                    SoundEffectInstancePool.DisposeInstances();

                    AL.DeleteSources(_allSources);
                    ALHelper.CheckError("Failed to delete source.");

                    Microphone.StopMicrophones();
                    DestroyContexts();
                }
                _isDisposed = true;
            }
        }
Beispiel #4
0
        public static bool CheckOpenALErrors(bool silent = false, [CallerMemberName] string callerInfoMember = null, [CallerFilePath] string callerInfoFile = null, [CallerLineNumber] int callerInfoLine = -1)
        {
            ALError error;
            bool    found = false;

            while ((error = AL.GetError()) != ALError.NoError)
            {
                if (!silent)
                {
                    Console.WriteLine(
                        "Internal OpenAL error, code {0} at {1} in {2}, line {3}.",
                        error,
                        callerInfoMember,
                        callerInfoFile,
                        callerInfoLine);
                }
                found = true;
                if (!silent && System.Diagnostics.Debugger.IsAttached)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }
            return(found);
        }
Beispiel #5
0
        public long StartAudioOut(ServiceCtx Context)
        {
            if (State == AudioOutState.Stopped)
            {
                State = AudioOutState.Started;

                try
                {
                    AudioCtx = new AudioContext(); //Create the audio context
                }
                catch (Exception)
                {
                    Logging.Warn("OpenAL Error! PS: Install OpenAL Core SDK!");
                    OpenALInstalled = false;
                }

                if (OpenALInstalled)
                {
                    AL.Listener(ALListenerf.Gain, (float)8.0);                  //Add more gain to it
                }
            }

            return(0);
        }
Beispiel #6
0
        private void Initialize(byte[] data, ALFormat format, int size, int frequency,
                                float volume, bool looping)
        {
            InitilizeSoundServices();

            bufferID = AL.GenBuffer();
            sourceID = AL.GenSource();

            try
            {
                // loads sound into buffer
                AL.BufferData(bufferID, format, data, size, frequency);

                // binds buffer to source
                AL.Source(sourceID, ALSourcei.Buffer, bufferID);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            Volume       = volume;
            this.looping = looping;
        }
Beispiel #7
0
        public static SoundClip LoadSound(string path)
        {
            SoundClip clip;

            string s = path.Substring(path.IndexOf('.'));

            switch (s)
            {
            case ".wav":
                clip = LoadWave(path);
                break;

            case ".ogg":
                clip = LoadOgg(path);
                break;

            default:
                throw new Exception("SoundFormat not recognised");
            }

            AL.BufferData(clip.buffer, GetSoundFormat(clip.format), clip.data, clip.data.Length, clip.format.sampleRate);

            return(clip);
        }
Beispiel #8
0
        public void Play()
        {
            var state = AL.GetSourceState(alSourceId);

            ALHelper.CheckError("Failed to get source state.");

            switch (state)
            {
            case ALSourceState.Playing: return;

            case ALSourceState.Paused:
                Resume();
                return;
            }

            Prepare();

            AL.SourcePlay(alSourceId);
            ALHelper.CheckError("Failed to play source.");

            Preparing = false;

            OggStreamer.Instance.AddStream(this);
        }
        void ClearBuffers(int input)
        {
            if (audio_context == null || audio_context == null)
            {
                return;
            }

            int[] freedbuffers;
            if (input == 0)
            {
                int BuffersProcessed;
                AL.GetSource(src, ALGetSourcei.BuffersProcessed, out BuffersProcessed);
                if (BuffersProcessed == 0)
                {
                    return;
                }
                freedbuffers = AL.SourceUnqueueBuffers(src, BuffersProcessed);
            }
            else
            {
                freedbuffers = AL.SourceUnqueueBuffers(src, input);
            }
            AL.DeleteBuffers(freedbuffers);
        }
        public override void Create(int numBuffers)
        {
            bufferIDs = new uint[numBuffers];
            completed = new bool[numBuffers];

            for (int i = 0; i < numBuffers; i++)
            {
                completed[i] = true;
            }
            NumBuffers = numBuffers;

            lock (contextLock) {
                if (context == IntPtr.Zero)
                {
                    CreateContext();
                }
                contextRefs++;

                MakeContextCurrent();
                AL.alDistanceModel(ALDistanceModel.None);
                CheckError("DistanceModel");
            }
            Console.WriteLine("al context:" + context);
        }
Beispiel #11
0
        protected override bool OnStart()
        {
            try
            {
                _al  = AL.GetApi();
                _alc = ALContext.GetApi();
            }
            catch (Exception ex)
            {
                XPlane.Trace.WriteLine($"[OpenAL Sample] Failed to initialize Open AL: " + ex);
                return(false);
            }

            _flightLoop = FlightLoop.Create(FlightLoopPhaseType.BeforeFlightModel, InitSound);
            _flightLoop.Schedule(-1, false);

            Menu.PluginsMenu
            .AddItem("OpenAL Sample (Private Context)", item =>
                     item.CreateSubMenu()
                     .AddItem("Play Sound", out _, PlaySound)
                     );

            return(true);
        }
Beispiel #12
0
        public override void Dispose()
        {
            if (SourceHandle == -1)
            {
                return;
            }

            // free queued buffers
            AL.SourceStop(SourceHandle);
            AL.GetSource(SourceHandle, ALGetSourcei.BuffersQueued, out int queued);
            if (queued > 0)
            {
                var buffers = new int[queued];
                AL.SourceUnqueueBuffers(SourceHandle, queued, buffers);
                foreach (int b in buffers)
                {
                    AL.DeleteBuffer(b);
                }
            }
            AL.DeleteSource(SourceHandle);
            SourceHandle = -1;

            base.Dispose();
        }
Beispiel #13
0
        public void Prepare()
        {
            if (Preparing)
            {
                return;
            }

            var state = AL.GetSourceState(alSourceId);

            lock (stopMutex)
            {
                switch (state)
                {
                case ALSourceState.Playing:
                case ALSourceState.Paused:
                    return;

                case ALSourceState.Stopped:
                    lock (prepareMutex)
                    {
                        Close();
                        Empty();
                    }
                    break;
                }

                if (!Ready)
                {
                    lock (prepareMutex)
                    {
                        Preparing = true;
                        Open(precache: true);
                    }
                }
            }
        }
 private OggPlayerCommandReturn Playback_Stop(bool Internal)
 {
     if (!(m_PlayerState == OggPlayerStatus.Playing) || (m_PlayerState == OggPlayerStatus.Paused) || (m_PlayerState == OggPlayerStatus.Buffering))
     {
         return(OggPlayerCommandReturn.InvalidCommandInThisPlayerState);
     }
     // Request stop
     m_StopRequested = true;
     // Wait a sensible time for the threads to enact this
     Thread.Sleep(50);
     // Stop player & clear buffers
     AL.SourceStop(m_Source);
     ClearBuffers();
     // Reset stuff
     ResetPlayerCondition();
     m_CurrentFile.SeekToTime(0);
     // Change state
     if (!Internal)
     {
         StateChange(OggPlayerStatus.Stopped, OggPlayerStateChanger.UserRequest);
     }
     // Done!
     return(OggPlayerCommandReturn.Success);
 }
Beispiel #15
0
        public void OnAction(Entity entity, List <Entity> entityList)
        {
            if ((entity.Mask & MASK) == MASK)
            {
                List <IComponent> components = entity.Components;

                IComponent audioComponent = components.Find(delegate(IComponent component)
                {
                    return(component.ComponentType == ComponentTypes.COMPONENT_AUDIO);
                });

                IComponent positionComponent = components.Find(delegate(IComponent component)
                {
                    return(component.ComponentType == ComponentTypes.COMPONENT_POSITION);
                });

                Position((ComponentPosition)positionComponent, (ComponentAudio)audioComponent);
                Vector3 listenerPosition  = new Vector3(0, 0, 0);
                Vector3 listenerDirection = new Vector3(0, 0, 0);
                Vector3 listenerUp        = Vector3.UnitY;
                AL.Listener(ALListener3f.Position, ref listenerPosition);
                AL.Listener(ALListenerfv.Orientation, ref listenerDirection, ref listenerUp);
            }
        }
Beispiel #16
0
        protected override void OnStop()
        {
            // Cleanup: nuke our context if we have it.  This is hacky and bad - we should really destroy
            // our buffers and sources.  I have _no_ idea if OpenAL will leak memory.
            if (ALC.GetCurrentContext() != default)
            {
                XPlane.Trace.WriteLine($"[OpenAL Sample] Deleting snd {_soundBuffer}");
                if (_soundSource != 0)
                {
                    AL.DeleteSource(_soundSource);
                    _soundSource = 0;
                }

                if (_soundBuffer != 0)
                {
                    AL.DeleteBuffer(_soundBuffer);
                    _soundBuffer = 0;
                }
            }

            if (_context != default)
            {
                XPlane.Trace.WriteLine($"[OpenAL Sample] Deleting my context 0x{(ulong)_context.Handle:X8}");
                ALC.MakeContextCurrent(default);
        public void Update()
        {
            HashSet <OALSoundBuffer> purgeMe = new HashSet <OALSoundBuffer> ();

            ALSourceState state;

            foreach (var soundBuffer in playingSourcesCollection)
            {
                state = AL.GetSourceState(soundBuffer.SourceId);

                if (state == ALSourceState.Stopped)
                {
                    AL.Source(soundBuffer.SourceId, ALSourcei.Buffer, 0);
                    purgeMe.Add(soundBuffer);
                    //Console.WriteLine ("to be recycled: " + soundBuffer.SourceId);
                }
            }

            foreach (var soundBuffer in purgeMe)
            {
                playingSourcesCollection.Remove(soundBuffer);
                RecycleSource(soundBuffer);
            }
        }
        private Exception _SoundInitException; // Here to bubble back up to the developer

        /// <summary>
        /// Sets up the hardware resources used by the controller.
        /// </summary>
        private OpenALSoundController()
        {
            if (!OpenSoundController())
            {
                return;
            }
            // We have hardware here and it is ready
            _bSoundAvailable = true;


            allSourcesArray = new int[MAX_NUMBER_OF_SOURCES];
            AL.GenSources(allSourcesArray);

            availableSourcesCollection = new List <int> ();
            inUseSourcesCollection     = new List <OALSoundBuffer> ();
            playingSourcesCollection   = new List <OALSoundBuffer> ();
            purgeMe = new List <OALSoundBuffer> ();


            for (int x = 0; x < MAX_NUMBER_OF_SOURCES; x++)
            {
                availableSourcesCollection.Add(allSourcesArray [x]);
            }
        }
Beispiel #19
0
 private void Button2_Click(object sender, EventArgs e)
 {
     AL.SourcePause(SoundSource);
     Playing = false;
 }
Beispiel #20
0
        private void Run()
        {
            try
            {
                App.DebugLog("Started streaming custom audio @ {0}Hz", m_sampleRate);

                // Get number of channels and sample rate
                var channels   = m_channels;
                var format     = (channels == 2) ? ALFormat.Stereo16 : ALFormat.Mono16;
                var sampleRate = m_sampleRate;

                // Start reading
                int nextBufferIndex = 0;
                var shortBuffer     = new short[SAMPLES_PER_BUFFER * channels];

                // Loop until the we stop
                while (true)
                {
                    // Get the queue state
                    int queued, processed;
                    lock (m_lock)
                    {
                        if (m_stopped)
                        {
                            break;
                        }

                        AL.GetSource(m_source, ALGetSourcei.BuffersQueued, out queued);
                        AL.GetSource(m_source, ALGetSourcei.BuffersProcessed, out processed);
                        App.CheckOpenALError(true);

                        // Dequeued processed buffers
                        if (processed > 0)
                        {
                            AL.SourceUnqueueBuffers((int)m_source, processed);
                            App.CheckOpenALError(true);
                            queued   -= processed;
                            processed = 0;
                        }
                    }

                    // Queue some samples
                    while (queued < m_buffers.Length)
                    {
                        // Generate the samples
                        m_audioSource.GenerateSamples(this, shortBuffer, 0, SAMPLES_PER_BUFFER);

                        // Pick an OpenAL buffer to put the samples in
                        var alBuffer = m_buffers[nextBufferIndex];
                        nextBufferIndex = (nextBufferIndex + 1) % m_buffers.Length;

                        lock (m_lock)
                        {
                            if (m_stopped)
                            {
                                break;
                            }

                            // Put the samples into the OpenAL buffer
                            AL.BufferData((int)alBuffer, format, shortBuffer, SAMPLES_PER_BUFFER * channels * sizeof(short), sampleRate);
                            App.CheckOpenALError(true);

                            // Add the buffer to the source's queue
                            AL.SourceQueueBuffer((int)m_source, (int)alBuffer);
                            App.CheckOpenALError(true);
                        }

                        queued++;
                    }

                    // Play the source if it's not playing already
                    lock (m_lock)
                    {
                        if (m_stopped)
                        {
                            break;
                        }

                        var state = AL.GetSourceState(m_source);
                        if (state != ALSourceState.Playing)
                        {
                            if (state != ALSourceState.Initial)
                            {
                                App.Log("Error: Buffer overrun detected. Resuming custom audio");
                            }
                            AL.SourcePlay(m_source);
                            App.CheckOpenALError(true);
                        }
                    }

                    // Sleep
                    Thread.Sleep(UPDATE_INTERVAL_MILLIS);
                }
                App.DebugLog("Stopped streaming custom audio");
            }
            catch (Exception e)
            {
                App.Log("Error streaming custom audio: Threw {0}: {1}", e.GetType().FullName, e.Message);
                App.Log(e.StackTrace);
            }
            finally
            {
                if (!m_stopped)
                {
                    // Wait for complete
                    while (true)
                    {
                        lock (m_lock)
                        {
                            if (m_stopped)
                            {
                                break;
                            }

                            var state = AL.GetSourceState(m_source);
                            if (state != ALSourceState.Playing)
                            {
                                break;
                            }
                        }
                        Thread.Sleep(UPDATE_INTERVAL_MILLIS);
                    }

                    // Stop
                    Stop();
                }
            }
        }
Beispiel #21
0
 private void InitDS()
 {
     SoundSource = AL.GenSource();
     SoundBuffer = AL.GenBuffer();
 }
Beispiel #22
0
 private void Button1_Click(object sender, EventArgs e)
 {
     AL.SourcePlay(SoundSource);
     Playing = true;
 }
Beispiel #23
0
 void ExitOpenAL()
 {
     AL.Destroy();
 }
Beispiel #24
0
        private void LoadBuffer(uint index)
        {
            if (!(Sounds[index].Type == 2))
            {
                System.IO.MemoryStream SoundStream  = new System.IO.MemoryStream();
                System.IO.BinaryWriter StreamWriter = new System.IO.BinaryWriter(SoundStream);
                Twinsanity.ADPCM       ADPCM_Device = new Twinsanity.ADPCM();
                SoundStream.Position = 44;
                if (Sounds[index].Type == 0)
                {
                    System.IO.MemoryStream ADPCM       = new System.IO.MemoryStream();
                    System.IO.MemoryStream PCM         = new System.IO.MemoryStream();
                    System.IO.BinaryWriter ADPCMWriter = new System.IO.BinaryWriter(ADPCM);
                    if (!Sounds[index].External)
                    {
                        MB.Position = Sounds[index].Offset + 48;
                        ADPCMWriter.Write(MBReader.ReadBytes((int)Sounds[index].Size));
                    }
                    else
                    {
                        ADPCMWriter.Write(Sounds[index].Stream.ToArray());
                    }
                    ADPCM.Position = 0;
                    ADPCM_Device.ADPCM2PCM(ADPCM, ref PCM);
                    SoundStream.Position = 0;
                    WriteHeader(ref SoundStream, Sounds[index].SampleRate, 1, (uint)PCM.Length);
                    StreamWriter.Write(PCM.ToArray());
                }
                else
                {
                    System.IO.MemoryStream ADPCM       = new System.IO.MemoryStream();
                    System.IO.MemoryStream ADPCM_R     = new System.IO.MemoryStream();
                    System.IO.MemoryStream ADPCM_L     = new System.IO.MemoryStream();
                    System.IO.MemoryStream PCM         = new System.IO.MemoryStream();
                    System.IO.MemoryStream PCM_R       = new System.IO.MemoryStream();
                    System.IO.MemoryStream PCM_L       = new System.IO.MemoryStream();
                    System.IO.BinaryWriter ADPCMWriter = new System.IO.BinaryWriter(ADPCM);
                    System.IO.BinaryWriter PCMWriter   = new System.IO.BinaryWriter(PCM);
                    if (!Sounds[index].External)
                    {
                        MB.Position = Sounds[index].Offset;
                        ADPCMWriter.Write(MBReader.ReadBytes((int)Sounds[index].Size));
                    }
                    else
                    {
                        ADPCMWriter.Write(Sounds[index].Stream.ToArray());
                    }
                    ADPCM.Position = 0;
                    ADPCM_Device.ADPCM_Demux(ADPCM, ref ADPCM_R, ref ADPCM_L, Interleave);
                    ADPCM_R.Position = 0;
                    PCM_R.Position   = 0;
                    ADPCM_L.Position = 0;
                    PCM_L.Position   = 0;
                    ADPCM_Device.ADPCM2PCM(ADPCM_R, ref PCM_R);
                    ADPCM_Device.ADPCM2PCM(ADPCM_L, ref PCM_L);
                    ADPCM_Device.PCM_Mux(ref PCM, PCM_R, PCM_L);
                    SoundStream.Position = 0;
                    WriteHeader(ref SoundStream, Sounds[index].SampleRate, 2, (uint)PCM.Length);
                    StreamWriter.Write(PCM.ToArray());
                }
                SoundStream.Position = 0;

                AL.BindBufferToSource(SoundSource, SoundBuffer);
                AL.BufferData(SoundBuffer, ALFormat.Stereo16, SoundStream.GetBuffer(), SoundStream.GetBuffer().Length, 44100);


                TrackBar1.Maximum = SoundStream.GetBuffer().Length - 1;
                Label10.Text      = "Loaded: yes";
            }
            else
            {
                Interaction.MsgBox("No data to play");
            }
        }
Beispiel #25
0
 public BufferPoolItem()
 {
     BufferID = AL.GenBuffer();
 }
Beispiel #26
0
 public void ApplyVolumeSettings(double volume)
 {
     AL.Source(_sourceID, ALSourcef.Gain, (float)volume);
 }
Beispiel #27
0
 private int GetSource(ALGetSourcei param)
 {
     AL.GetSource(_sourceID, param, out var value);
     return(value);
 }
Beispiel #28
0
        /// <summary>Updates the sound component. Should be called every frame.</summary>
        /// <param name="timeElapsed">The time in seconds that elapsed since the last call to this function.</param>
        protected override void UpdateInverseModel(double timeElapsed)
        {
            /*
             * Set up the listener.
             * */
            Vector3      listenerPosition    = Program.Renderer.Camera.AbsolutePosition;
            Orientation3 listenerOrientation = new Orientation3(Program.Renderer.Camera.AbsoluteSide, Program.Renderer.Camera.AbsoluteUp, Program.Renderer.Camera.AbsoluteDirection);
            Vector3      listenerVelocity;

            if (Program.Renderer.Camera.CurrentMode == CameraViewMode.Interior | Program.Renderer.Camera.CurrentMode == CameraViewMode.InteriorLookAhead | Program.Renderer.Camera.CurrentMode == CameraViewMode.Exterior)
            {
                CarBase car  = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar];
                Vector3 diff = car.FrontAxle.Follower.WorldPosition - car.RearAxle.Follower.WorldPosition;
                if (diff.IsNullVector())
                {
                    listenerVelocity = car.CurrentSpeed * Vector3.Forward;
                }
                else
                {
                    listenerVelocity = car.CurrentSpeed * Vector3.Normalize(diff);
                }
            }
            else
            {
                listenerVelocity = Vector3.Zero;
            }
            AL.Listener(ALListener3f.Position, 0.0f, 0.0f, 0.0f);
            AL.Listener(ALListener3f.Velocity, (float)listenerVelocity.X, (float)listenerVelocity.Y, (float)listenerVelocity.Z);
            var Orientation = new float[] { (float)listenerOrientation.Z.X, (float)listenerOrientation.Z.Y, (float)listenerOrientation.Z.Z, -(float)listenerOrientation.Y.X, -(float)listenerOrientation.Y.Y, -(float)listenerOrientation.Y.Z };

            AL.Listener(ALListenerfv.Orientation, ref Orientation);

            /*
             * Set up the atmospheric attributes.
             * */
            double elevation      = Program.Renderer.Camera.AbsolutePosition.Y + Program.CurrentRoute.Atmosphere.InitialElevation;
            double airTemperature = Program.CurrentRoute.Atmosphere.GetAirTemperature(elevation);
            double airPressure    = Program.CurrentRoute.Atmosphere.GetAirPressure(elevation, airTemperature);
            double speedOfSound   = Program.CurrentRoute.Atmosphere.GetSpeedOfSound(airPressure, airTemperature);

            try {
                AL.SpeedOfSound((float)speedOfSound);
            } catch { }

            /*
             * Collect all sounds that are to be played
             * and ensure that all others are stopped.
             * */
            List <SoundSourceAttenuation> toBePlayed = new List <SoundSourceAttenuation>();

            for (int i = 0; i < SourceCount; i++)
            {
                if (Sources[i].State == SoundSourceState.StopPending)
                {
                    /*
                     * The sound is still playing but is to be stopped.
                     * Stop the sound, then remove it from the list of
                     * sound sources.
                     * */
                    AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                    Sources[i].State            = SoundSourceState.Stopped;
                    Sources[i].OpenAlSourceName = 0;
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (Sources[i].State == SoundSourceState.Stopped)
                {
                    /*
                     * The sound was already stopped. Remove it from
                     * the list of sound sources.
                     * */
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (GlobalMute)
                {
                    /*
                     * The sound is playing or about to be played, but
                     * the global mute option is enabled. Stop the sound
                     * sound if necessary, then remove it from the list
                     * of sound sources if the sound is not looping.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                        Sources[i].State            = SoundSourceState.PlayPending;
                        Sources[i].OpenAlSourceName = 0;
                    }
                    if (!Sources[i].Looped)
                    {
                        Sources[i].State            = SoundSourceState.Stopped;
                        Sources[i].OpenAlSourceName = 0;
                        Sources[i] = Sources[SourceCount - 1];
                        SourceCount--;
                        i--;
                    }
                }
                else
                {
                    /*
                     * The sound is to be played or is already playing.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        int state;
                        AL.GetSource(Sources[i].OpenAlSourceName, ALGetSourcei.SourceState, out state);
                        if (state != (int)ALSourceState.Initial & state != (int)ALSourceState.Playing)
                        {
                            /*
                             * The sound is not playing any longer.
                             * Remove it from the list of sound sources.
                             * */
                            AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                            continue;
                        }
                    }

                    /*
                     * Calculate the gain, then add the sound
                     * to the list of sounds to be played.
                     * */
                    Vector3 position;
                    switch (Sources[i].Type)
                    {
                    case SoundType.TrainCar:
                        Vector3 direction;
                        var     Car = (AbstractCar)Sources[i].Parent;
                        Car.CreateWorldCoordinates(Sources[i].Position, out position, out direction);
                        break;

                    default:
                        position = Sources[i].Position;
                        break;
                    }
                    Vector3 positionDifference = position - listenerPosition;
                    double  distance           = positionDifference.Norm();
                    double  radius             = Sources[i].Radius;
                    if (Program.Renderer.Camera.CurrentMode == CameraViewMode.Interior | Program.Renderer.Camera.CurrentMode == CameraViewMode.InteriorLookAhead)
                    {
                        if (Sources[i].Parent != TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar])
                        {
                            radius *= 0.5;
                        }
                    }
                    double gain;
                    if (distance < 2.0 * radius)
                    {
                        gain = 1.0 - distance * distance * (4.0 * radius - distance) / (16.0 * radius * radius * radius);
                    }
                    else
                    {
                        gain = radius / distance;
                    }
                    gain *= Sources[i].Volume;
                    if (gain <= 0.0)
                    {
                        /*
                         * The gain is too low. Stop the sound if playing,
                         * but keep looping sounds pending.
                         * */
                        if (Sources[i].State == SoundSourceState.Playing)
                        {
                            AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.PlayPending;
                            Sources[i].OpenAlSourceName = 0;
                        }
                        if (!Sources[i].Looped)
                        {
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                        }
                    }
                    else
                    {
                        /*
                         * Add the source.
                         * */
                        toBePlayed.Add(new SoundSourceAttenuation(Sources[i], gain, distance));
                    }
                }
            }

            /*
             * Now that we have the list of sounds that are to be played,
             * sort them by their gain so that we can determine and
             * adjust the clamp factor.
             * */
            double clampFactor = Math.Exp(LogClampFactor);

            for (int i = 0; i < toBePlayed.Count; i++)
            {
                toBePlayed[i].Gain -= clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance;
            }
            toBePlayed.Sort();
            for (int i = 0; i < toBePlayed.Count; i++)
            {
                toBePlayed[i].Gain += clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance;
            }
            double desiredLogClampFactor;
            int    index = Interface.CurrentOptions.SoundNumber;

            if (toBePlayed.Count <= index)
            {
                desiredLogClampFactor = MinLogClampFactor;
            }
            else
            {
                double cutoffDistance = toBePlayed[index].Distance;
                if (cutoffDistance <= 0.0)
                {
                    desiredLogClampFactor = MaxLogClampFactor;
                }
                else
                {
                    double cutoffGain = toBePlayed[index].Gain;
                    desiredLogClampFactor = Math.Log(cutoffGain / (cutoffDistance * cutoffDistance));
                    if (desiredLogClampFactor < MinLogClampFactor)
                    {
                        desiredLogClampFactor = MinLogClampFactor;
                    }
                    else if (desiredLogClampFactor > MaxLogClampFactor)
                    {
                        desiredLogClampFactor = MaxLogClampFactor;
                    }
                }
            }
            const double rate = 3.0;

            if (LogClampFactor < desiredLogClampFactor)
            {
                LogClampFactor += timeElapsed * rate;
                if (LogClampFactor > desiredLogClampFactor)
                {
                    LogClampFactor = desiredLogClampFactor;
                }
            }
            else if (LogClampFactor > desiredLogClampFactor)
            {
                LogClampFactor -= timeElapsed * rate;
                if (LogClampFactor < desiredLogClampFactor)
                {
                    LogClampFactor = desiredLogClampFactor;
                }
            }

            /*
             * Play the sounds.
             * */
            clampFactor = Math.Exp(LogClampFactor);
            for (int i = index; i < toBePlayed.Count; i++)
            {
                toBePlayed[i].Gain = 0.0;
            }
            for (int i = 0; i < toBePlayed.Count; i++)
            {
                SoundSource source = toBePlayed[i].Source;
                double      gain   = toBePlayed[i].Gain - clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance;
                if (gain <= 0.0)
                {
                    /*
                     * Stop the sound.
                     * */
                    if (source.State == SoundSourceState.Playing)
                    {
                        AL.DeleteSources(1, ref source.OpenAlSourceName);
                        source.State            = SoundSourceState.PlayPending;
                        source.OpenAlSourceName = 0;
                    }
                    if (!source.Looped)
                    {
                        source.State            = SoundSourceState.Stopped;
                        source.OpenAlSourceName = 0;
                    }
                }
                else
                {
                    /*
                     * Ensure the buffer is loaded, then play the sound.
                     * */
                    if (source.State != SoundSourceState.Playing)
                    {
                        LoadBuffer(source.Buffer);
                        if (source.Buffer.Loaded)
                        {
                            AL.GenSources(1, out source.OpenAlSourceName);
                            AL.Source(source.OpenAlSourceName, ALSourcei.Buffer, source.Buffer.OpenAlBufferName);
                        }
                        else
                        {
                            /*
                             * We cannot play the sound because
                             * the buffer could not be loaded.
                             * */
                            source.State = SoundSourceState.Stopped;
                            continue;
                        }
                    }
                    Vector3 position;
                    Vector3 velocity;
                    switch (source.Type)
                    {
                    case SoundType.TrainCar:
                        Vector3 direction;
                        var     Car = (AbstractCar)Sources[i].Parent;
                        Car.CreateWorldCoordinates(source.Position, out position, out direction);
                        velocity = Car.CurrentSpeed * direction;
                        break;

                    default:
                        position = source.Position;
                        velocity = Vector3.Zero;
                        break;
                    }
                    position -= listenerPosition;
                    AL.Source(source.OpenAlSourceName, ALSource3f.Position, (float)position.X, (float)position.Y, (float)position.Z);
                    AL.Source(source.OpenAlSourceName, ALSource3f.Velocity, (float)velocity.X, (float)velocity.Y, (float)velocity.Z);
                    AL.Source(source.OpenAlSourceName, ALSourcef.Pitch, (float)source.Pitch);
                    AL.Source(source.OpenAlSourceName, ALSourcef.Gain, (float)gain);
                    if (source.State != SoundSourceState.Playing)
                    {
                        AL.Source(source.OpenAlSourceName, ALSourceb.Looping, source.Looped);
                        AL.SourcePlay(source.OpenAlSourceName);
                        source.State = SoundSourceState.Playing;
                    }
                }
            }
        }
Beispiel #29
0
        /// <summary>Updates the sound component. Should be called every frame.</summary>
        /// <param name="timeElapsed">The time in seconds that elapsed since the last call to this function.</param>
        protected override void UpdateLinearModel(double timeElapsed)
        {
            /*
             * Set up the listener
             * */
            Vector3      listenerPosition    = Program.Renderer.Camera.AbsolutePosition;
            Orientation3 listenerOrientation = new Orientation3(Program.Renderer.Camera.AbsoluteSide, Program.Renderer.Camera.AbsoluteUp, Program.Renderer.Camera.AbsoluteDirection);
            Vector3      listenerVelocity;

            if (Program.Renderer.Camera.CurrentMode == CameraViewMode.Interior | Program.Renderer.Camera.CurrentMode == CameraViewMode.InteriorLookAhead | Program.Renderer.Camera.CurrentMode == CameraViewMode.Exterior)
            {
                CarBase car  = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar];
                Vector3 diff = car.FrontAxle.Follower.WorldPosition - car.RearAxle.Follower.WorldPosition;
                listenerVelocity = car.CurrentSpeed * Vector3.Normalize(diff) + Program.Renderer.Camera.AlignmentSpeed.Position;
            }
            else
            {
                listenerVelocity = Program.Renderer.Camera.AlignmentSpeed.Position;
            }
            AL.Listener(ALListener3f.Position, 0.0f, 0.0f, 0.0f);
            AL.Listener(ALListener3f.Velocity, (float)listenerVelocity.X, (float)listenerVelocity.Y, (float)listenerVelocity.Z);
            var Orientation = new[] { (float)listenerOrientation.Z.X, (float)listenerOrientation.Z.Y, (float)listenerOrientation.Z.Z, -(float)listenerOrientation.Y.X, -(float)listenerOrientation.Y.Y, -(float)listenerOrientation.Y.Z };

            AL.Listener(ALListenerfv.Orientation, ref Orientation);

            /*
             * Set up the atmospheric attributes
             * */
            double elevation      = Program.Renderer.Camera.AbsolutePosition.Y + Program.CurrentRoute.Atmosphere.InitialElevation;
            double airTemperature = Program.CurrentRoute.Atmosphere.GetAirTemperature(elevation);
            double airPressure    = Program.CurrentRoute.Atmosphere.GetAirPressure(elevation, airTemperature);
            double speedOfSound   = Program.CurrentRoute.Atmosphere.GetSpeedOfSound(airPressure, airTemperature);

            try {
                AL.SpeedOfSound((float)speedOfSound);
            } catch { }

            /*
             * Update the sound sources
             * */
            int actuallyPlaying = 0;

            for (int i = 0; i < SourceCount; i++)
            {
                if (Sources[i].State == SoundSourceState.StopPending)
                {
                    /*
                     * The sound is still playing but is to be stopped.
                     * Stop the sound, then remove it from the list of
                     * sound sources.
                     * */
                    AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                    Sources[i].State            = SoundSourceState.Stopped;
                    Sources[i].OpenAlSourceName = 0;
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (Sources[i].State == SoundSourceState.Stopped)
                {
                    /*
                     * The sound was already stopped. Remove it from
                     * the list of sound sources.
                     * */
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (GlobalMute)
                {
                    /*
                     * The sound is playing or about to be played, but
                     * the global mute option is enabled. Stop the sound
                     * sound if necessary, then remove it from the list
                     * of sound sources if the sound is not looping.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                        Sources[i].State            = SoundSourceState.PlayPending;
                        Sources[i].OpenAlSourceName = 0;
                    }
                    if (!Sources[i].Looped)
                    {
                        Sources[i].State            = SoundSourceState.Stopped;
                        Sources[i].OpenAlSourceName = 0;
                        Sources[i] = Sources[SourceCount - 1];
                        SourceCount--;
                        i--;
                    }
                }
                else
                {
                    /*
                     * The sound is to be played or is already playing.
                     * Calculate the sound gain.
                     * */
                    Vector3 direction;
                    Vector3 position;
                    Vector3 velocity;

                    switch (Sources[i].Type)
                    {
                    case SoundType.TrainCar:
                        var Car = (AbstractCar)Sources[i].Parent;
                        Car.CreateWorldCoordinates(Sources[i].Position, out position, out direction);
                        velocity = Car.CurrentSpeed * direction;
                        break;

                    default:
                        position = Sources[i].Position;
                        velocity = Vector3.Zero;
                        break;
                    }
                    Vector3 positionDifference = position - listenerPosition;
                    double  gain;
                    if (GlobalMute)
                    {
                        gain = 0.0;
                    }
                    else
                    {
                        double distance    = positionDifference.Norm();
                        double innerRadius = Sources[i].Radius;
                        if (Program.Renderer.Camera.CurrentMode == CameraViewMode.Interior | Program.Renderer.Camera.CurrentMode == CameraViewMode.InteriorLookAhead)
                        {
                            if (Sources[i].Parent != TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar])
                            {
                                innerRadius *= 0.5;
                            }
                        }
                        double outerRadius = OuterRadiusFactor * innerRadius;
                        if (distance < outerRadius)
                        {
                            if (distance <= innerRadius)
                            {
                                gain = Sources[i].Volume;
                            }
                            else
                            {
                                gain  = (distance - outerRadius) / (innerRadius - outerRadius);
                                gain *= Sources[i].Volume;
                            }
                            gain = 3.0 * gain * gain - 2.0 * gain * gain * gain;
                        }
                        else
                        {
                            gain = 0.0;
                        }
                    }
                    if (gain <= GainThreshold)
                    {
                        /*
                         * If the gain is too low to be audible, stop the sound.
                         * If the sound is not looping, stop it if necessary,
                         * then remove it from the list of sound sources.
                         * */
                        if (Sources[i].State == SoundSourceState.Playing)
                        {
                            AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.PlayPending;
                            Sources[i].OpenAlSourceName = 0;
                        }
                        if (!Sources[i].Looped)
                        {
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                        }
                    }
                    else
                    {
                        /*
                         * Play the sound and update position, velocity, pitch and gain.
                         * For non-looping sounds, check if the sound is still playing.
                         * */
                        gain = (gain - GainThreshold) / (1.0 - GainThreshold);
                        if (Sources[i].State != SoundSourceState.Playing)
                        {
                            LoadBuffer(Sources[i].Buffer);
                            if (Sources[i].Buffer.Loaded)
                            {
                                AL.GenSources(1, out Sources[i].OpenAlSourceName);
                                AL.Source(Sources[i].OpenAlSourceName, ALSourcei.Buffer, Sources[i].Buffer.OpenAlBufferName);
                            }
                            else
                            {
                                /*
                                 * We cannot play the sound because
                                 * the buffer could not be loaded.
                                 * */
                                Sources[i].State = SoundSourceState.Stopped;
                                continue;
                            }
                        }
                        AL.Source(Sources[i].OpenAlSourceName, ALSource3f.Position, (float)positionDifference.X, (float)positionDifference.Y, (float)positionDifference.Z);
                        AL.Source(Sources[i].OpenAlSourceName, ALSource3f.Velocity, (float)velocity.X, (float)velocity.Y, (float)velocity.Z);
                        AL.Source(Sources[i].OpenAlSourceName, ALSourcef.Pitch, (float)Sources[i].Pitch);
                        AL.Source(Sources[i].OpenAlSourceName, ALSourcef.Gain, (float)gain);
                        if (Sources[i].State != SoundSourceState.Playing)
                        {
                            AL.Source(Sources[i].OpenAlSourceName, ALSourceb.Looping, Sources[i].Looped);
                            AL.SourcePlay(Sources[i].OpenAlSourceName);
                            Sources[i].State = SoundSourceState.Playing;
                        }
                        if (!Sources[i].Looped)
                        {
                            int state;
                            AL.GetSource(Sources[i].OpenAlSourceName, ALGetSourcei.SourceState, out state);
                            if (state != (int)ALSourceState.Initial & state != (int)ALSourceState.Playing)
                            {
                                /*
                                 * The sound is not playing any longer.
                                 * Remove it from the list of sound sources.
                                 * */
                                AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                                Sources[i].State            = SoundSourceState.Stopped;
                                Sources[i].OpenAlSourceName = 0;
                                Sources[i] = Sources[SourceCount - 1];
                                SourceCount--;
                                i--;
                            }
                            else
                            {
                                actuallyPlaying++;
                            }
                        }
                        else
                        {
                            actuallyPlaying++;
                        }
                    }
                }
            }

            /*
             * Adjust the outer radius factor / the clamp factor.
             * */
            if (actuallyPlaying >= Interface.CurrentOptions.SoundNumber - 2)
            {
                /*
                 * Too many sounds are playing.
                 * Reduce the outer radius factor.
                 * */
                OuterRadiusFactorSpeed -= timeElapsed;
                if (OuterRadiusFactorSpeed < -OuterRadiusFactorMaximumSpeed)
                {
                    OuterRadiusFactorSpeed = -OuterRadiusFactorMaximumSpeed;
                }
            }
            else if (actuallyPlaying <= Interface.CurrentOptions.SoundNumber - 6)
            {
                /*
                 * Only few sounds are playing.
                 * Increase the outer radius factor.
                 * */
                OuterRadiusFactorSpeed += timeElapsed;
                if (OuterRadiusFactorSpeed > OuterRadiusFactorMaximumSpeed)
                {
                    OuterRadiusFactorSpeed = OuterRadiusFactorMaximumSpeed;
                }
            }
            else
            {
                /*
                 * Neither too many nor too few sounds are playing.
                 * Stabilize the outer radius factor.
                 * */
                if (OuterRadiusFactorSpeed < 0.0)
                {
                    OuterRadiusFactorSpeed += timeElapsed;
                    if (OuterRadiusFactorSpeed > 0.0)
                    {
                        OuterRadiusFactorSpeed = 0.0;
                    }
                }
                else
                {
                    OuterRadiusFactorSpeed -= timeElapsed;
                    if (OuterRadiusFactorSpeed < 0.0)
                    {
                        OuterRadiusFactorSpeed = 0.0;
                    }
                }
            }
            OuterRadiusFactor += OuterRadiusFactorSpeed * timeElapsed;
            if (OuterRadiusFactor < OuterRadiusFactorMinimum)
            {
                OuterRadiusFactor      = OuterRadiusFactorMinimum;
                OuterRadiusFactorSpeed = 0.0;
            }
            else if (OuterRadiusFactor > OuterRadiusFactorMaximum)
            {
                OuterRadiusFactor      = OuterRadiusFactorMaximum;
                OuterRadiusFactorSpeed = 0.0;
            }
        }
Beispiel #30
0
        public unsafe void UnlockBuffer(int bytes)
        {
            int processed;

            AL.GetSource(this._Source, ALGetSourcei.BuffersProcessed, out processed);
            if (processed > 0)
            {
                var bufs = AL.SourceUnqueueBuffers(this._Source, processed);
                foreach (var buffer in bufs)
                {
                    if (buffer == 0)
                    {
                        continue;
                    }

                    var idx = Array.IndexOf(this._Buffers, buffer);
                    if (idx != -1)
                    {
                        this._SamplesSent     += this._BufferBytes[idx] >> (this.Host.Sound.shm.samplebits / 8 - 1);
                        this._SamplesSent     &= this.Host.Sound.shm.samples - 1;
                        this._BufferBytes[idx] = 0;
                    }
                    if (!this._FreeBuffers.Contains(buffer))
                    {
                        this._FreeBuffers.Enqueue(buffer);
                    }
                }
            }

            if (this._FreeBuffers.Count == 0)
            {
                this.Host.Console.DPrint("UnlockBuffer: No free buffers!\n");
                return;
            }

            var buf = this._FreeBuffers.Dequeue();

            if (buf != 0)
            {
                AL.BufferData(buf, this._BufferFormat, this.Host.Sound.shm.buffer, this.Host.Sound.shm.speed);

                AL.SourceQueueBuffer(this._Source, buf);

                var idx = Array.IndexOf(this._Buffers, buf);
                if (idx != -1)
                {
                    this._BufferBytes[idx] = bytes;
                }

                int state;
                AL.GetSource(this._Source, ALGetSourcei.SourceState, out state);
                if ((ALSourceState)state != ALSourceState.Playing)
                {
                    AL.SourcePlay(this._Source);

                    this.Host.Console.DPrint("Sound resumed from {0}, free {1} of {2} buffers\n",
                                             ((ALSourceState)state).ToString("F"),
                                             this._FreeBuffers.Count,
                                             this._Buffers.Length);
                }
            }
        }
Beispiel #31
0
 public void ClearBuffer()
 {
     AL.SourceStop(this._Source);
 }