Ejemplo n.º 1
0
        void OnAudioFilterRead(float [] data, int numChannels)
        {
                        #if GAT_DEBUG
            if (_FiltersHandler.NbOfFilteredChannels != numChannels)
            {
                Debug.LogError("This player was setup for " + GATInfo.NbOfChannels + " channels output, current is " + numChannels + ". Disabling player.");
                _shouldDisable = true;
                return;
            }
                        #endif
            BufferedSample sample;
            bool           shouldRemove;
            int            i;
            int            dataLength;
            bool           noData = false;

            dataLength = data.Length;
            //*********************************************************************************************
            //First, we check if any samples in the scheduled queue need to be moved to the playing queue

            shouldRemove = false;
            sample       = _scheduledSamples.head.next;       // caching the first item of the linked queue: thread safe iteration

            if (sample != null)
            {
                double nextBufferDSPTime = AudioSettings.dspTime + GATInfo.AudioBufferDuration;

                while (sample != null)
                {
                    if (nextBufferDSPTime > sample.scheduledDspTime)                      //flag samples which need to be moved
                    {
                        sample.shouldBeRemoved = true;
                        shouldRemove           = true;
                        sample.OffsetInBuffer  = ( int )((sample.scheduledDspTime - AudioSettings.dspTime) * GATInfo.OutputSampleRate);
                    }
                    sample = sample.next;
                }

                if (shouldRemove)                  //move to playing queue
                {
                    lock ( _scheduledSamples )     // make sure no sample is added from the main thread whilst removing
                    {
                        _scheduledSamples.TrimAndKeepDiscarded(_discardedSamples);
                    }

                    _playingSamples.Enqueue(_discardedSamples);                       // no need to lock on the playing queue: it is only accessed by the audio thread
                }
            }

            //*************************************************************************
            //Second, we check the PlayImmediate queue

            lock ( _samplesToEnqueue )            //make sure no play immediate sample gets added by the main thread whilst we concatenate the 2 queues
            {
                if (_samplesToEnqueue.head.next != null)
                {
                    _playingSamples.Enqueue(_samplesToEnqueue);
                    _samplesToEnqueue.Clear();
                }
            }
            //***********************************************************
            //Third, we mix the samples of the Playing queue

            sample = _playingSamples.head.next;

            if (onPlayerWillMix != null)
            {
                onPlayerWillMix();
            }

            //Even if there is no samples to play, filters might add to the mix:
            if (sample == null)
            {
                noData = true;

                //Check tracks
                for (i = 0; i < _tracks.Count; i++)
                {
                    if (ReferenceEquals(_tracks[i], null) == false)
                    {
                        if (_tracks[i].FXAndMixTo(data))
                        {
                            noData = false;
                        }
                    }
                }

                //Check Master Filters
                if (_FiltersHandler.HasFilters)
                {
                    if (_FiltersHandler.ApplyFilters(data, 0, dataLength, noData))
                    {
                        noData = false;
                    }
                }

                //Broadcast stream
                _audioThreadStreamProxy.BroadcastStream(data, 0, noData);

                //Stop there.
                if (onPlayerDidMix != null)
                {
                    onPlayerDidMix();
                }

                return;
            }

            shouldRemove = false;

            while (sample != null)
            {
                if (sample.MixNow(data) == true)
                {
                    shouldRemove = true;
                }
                sample = sample.next;
            }

            //****************************************************
            //Then, we remove samples which ended and clip the mix if needed
            if (shouldRemove)
            {
                _playingSamples.TrimAndReleaseDiscarded();
            }

            //****************************************************
            //Now, we check and mix tracks
            for (i = 0; i < _tracks.Count; i++)
            {
                if (ReferenceEquals(_tracks[i], null) == false)
                {
                    _tracks[i].FXAndMixTo(data);
                }
            }

            //Filter the mix, includes a default gain filter which will clip if set so
            if (_FiltersHandler.HasFilters)
            {
                _FiltersHandler.ApplyFilters(data, 0, dataLength, false);
            }

            //****************************************************
            //Finally, we fire the last callback

            _audioThreadStreamProxy.BroadcastStream(data, 0, false);

            if (onPlayerDidMix != null)
            {
                onPlayerDidMix();
            }

            if (_releasePlaying)
            {
                _playingSamples.ReleaseAllAndPool(this);
                _releasePlaying = false;
                float deltaGain = 1f / (data.Length / numChannels);
                float gain      = 1f;
                for (i = 0; i < data.Length; i += numChannels)
                {
                    data[i]     *= gain;
                    data[i + 1] *= gain;
                    gain        -= deltaGain;
                }
            }
        }
Ejemplo n.º 2
0
        // Called by GATPlayer.
        // Applies effects, and pan-mixes
        // to the audio buffer.
        public bool FXAndMixTo(float[] audioBuffer)
        {
            if (!_active)
            {
                return(false);
            }

            int  i;
            bool isEmptyData = false;

            if (_hasData == false)              //no sample overwrote the buffer, let's clear it
            {
                if (_bufferIsDirty)
                {
                    _trackBuffer.Clear();
                    _bufferIsDirty = false;
                }

                isEmptyData = true;
            }

            if (_contributor != null)
            {
                isEmptyData = !(_contributor.MixToTrack(_trackBuffer, _trackNb));
            }

            if (_filtersHandler.HasFilters)
            {
                if (_filtersHandler.ApplyFilters(_trackBuffer.ParentArray, _trackBuffer.MemOffset, GATInfo.AudioBufferSizePerChannel, isEmptyData))
                {
                    isEmptyData = false;
                }
            }

            if (isEmptyData)
            {
                _audioThreadStreamProxy.BroadcastStream(_trackBuffer.ParentArray, _trackBuffer.MemOffset, isEmptyData);
                return(false);
            }

            if (_shouldToggleMute)
            {
                if (_nextMute)
                {
                    _trackBuffer.FadeOut(GATInfo.AudioBufferSizePerChannel);
                }
                else
                {
                    _trackBuffer.FadeIn(GATInfo.AudioBufferSizePerChannel);
                    _mute = false;
                }

                _shouldToggleMute = false;
            }

            _bufferIsDirty = true;

            _audioThreadStreamProxy.BroadcastStream(_trackBuffer.ParentArray, _trackBuffer.MemOffset, false);

            if (_mute)
            {
                return(false);
            }

            GATDynamicChannelGain channelGain;

            for (i = 0; i < _panInfo.channelGains.Count; i++)
            {
                channelGain = _panInfo.channelGains[i];
                if (channelGain.ShouldInterpolate)
                {
                    _trackBuffer.SmoothedGainMixToInterlaced(audioBuffer, 0, 0, GATInfo.AudioBufferSizePerChannel, channelGain);
                    continue;
                }

                if (channelGain.Gain != 0f)
                {
                    _trackBuffer.GainMixToInterlaced(audioBuffer, 0, 0, GATInfo.AudioBufferSizePerChannel, channelGain);
                }
            }

            if (_nextMute)              //only set mute here to allow for mixing of faded data : elegant stop
            {
                _mute = true;
            }

            return(!isEmptyData);
        }