/// <summary>
        /// Immediately stop the entire transmission system
        /// </summary>
        private void StopTransmissionPipeline()
        {
            //Stop microphone
            if (_microphone != null && _microphone.IsRecording)
            {
                _microphone.StopCapture();
            }

            //Dispose preprocessor and encoder
            if (_preprocessor != null)
            {
                if (_microphone != null)
                {
                    _microphone.Unsubscribe(_preprocessor);
                }
                if (_encoder != null)
                {
                    _preprocessor.Unsubscribe(_encoder);
                }

                _preprocessor.Dispose();
                _preprocessor = null;
            }

            if (_encoder != null)
            {
                _encoder.Dispose();
                _encoder = null;
            }

            _encoderSubscribed = false;
        }
        /// <summary>
        /// (Re)Start the transmission pipeline, getting to a state where we *can* send voice (but aren't yet)
        /// </summary>
        private void RestartTransmissionPipeline(string reason)
        {
            Log.Debug("Restarting transmission pipeline: '{0}'", reason);

            StopTransmissionPipeline();

            //Clear the flag for requesting an explicit reset.
            //We're about to apply a reset so the request will be satisfied.
            _pendingResetRequest = false;

            //No point starting a transmission pipeline if the network is not a client
            if (_network == null || !_network.Mode.IsClientEnabled())
            {
                return;
            }

            //Create new mic capture system
            var format = _microphone.StartCapture(_micName);

            //If we created a mic (can be null if e.g. there is no mic)
            if (format != null)
            {
                //Close and re-open all channels, propogating this restart to the receiving end
                _roomChannels.Refresh();
                _playerChannels.Refresh();

                //Create preprocessor and subscribe it to microphone (webrtc preprocessor always wants audio to drive VAD+AEC)
                _preprocessor = CreatePreprocessor(format);
                _preprocessor.UpstreamLatency = _microphone.Latency;
                _preprocessor.Start();
                _microphone.Subscribe(_preprocessor);

                //Sub VAD listeners to preprocessor
                for (var i = 0; i < _activationListeners.Count; i++)
                {
                    _preprocessor.Subscribe(_activationListeners[i]);
                }

                //Sub audio listeners to the preprocessor output
                for (var i = 0; i < _audioListeners.Count; i++)
                {
                    var al = _audioListeners[i];
                    al.Reset();
                    _preprocessor.Subscribe(al);
                }

                //Create encoder (not yet subscribed to receive audio data, we'll do that later)
                Log.AssertAndThrowPossibleBug(_network != null, "5F33336B-15B5-4A85-9B54-54352C74768E", "Network object is unexpectedly null");
                _encoder = new EncoderPipeline(_preprocessor.OutputFormat, _codecSettingsLoader.CreateEncoder(), _network);
            }
            else
            {
                Log.Warn("Failed to start microphone capture; local voice transmission will be disabled.");
            }
        }
        /// <summary>
        /// Immediately stop the entire transmission system
        /// </summary>
        private void StopTransmissionPipeline()
        {
#if !NCRUNCH
            Profiler.BeginSample("CapturePipelineManager: StopTransmissionPipeline");
#endif

            //Stop microphone
            if (_microphone != null && _microphone.IsRecording)
            {
                _microphone.StopCapture();
            }

            //Dispose preprocessor and encoder
            if (_preprocessor != null)
            {
                if (_microphone != null)
                {
                    _microphone.Unsubscribe(_preprocessor);
                }
                if (_encoder != null)
                {
                    _preprocessor.Unsubscribe(_encoder);
                }

                _preprocessor.Dispose();
                _preprocessor = null;
            }

            if (_encoder != null)
            {
                _encoder.Dispose();
                _encoder = null;
            }

            _encoderSubscribed = false;

#if !NCRUNCH
            Profiler.EndSample();
#endif
        }
Beispiel #4
0
        /// <param name="micName"></param>
        /// <param name="source">Source to read frames from</param>
        private MicrophoneCapture([CanBeNull] string micName, AudioClip source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source", Log.PossibleBugMessage("capture source clip is null", "333E11A6-8026-41EB-9B34-EF9ADC54B651"));
            }

            _micName = micName;
            _clip    = source;
            var captureFormat = new WaveFormat(1, source.frequency);

            _maxReadBufferPower = (byte)Math.Ceiling(Math.Log(0.1f * source.frequency, 2));

            _preprocessing = new WebRtcPreprocessingPipeline(captureFormat);
            _preprocessing.Start();

            //Ensure we have enough buffer size to contain several input frames to the preprocessor
            _rawMicSamples = new BufferedSampleProvider(captureFormat, _preprocessing.InputFrameSize * 4);
            _rawMicFrames  = new SampleToFrameProvider(_rawMicSamples, (uint)_preprocessing.InputFrameSize);

            Log.Info("Began mic capture (SampleRate:{0} FrameSize:{1}, Buffer Limit:2^{2})", captureFormat.SampleRate, _preprocessing.InputFrameSize, _maxReadBufferPower);
        }
        /// <summary>
        /// (Re)Start the transmission pipeline, getting to a state where we *can* send voice (but aren't yet)
        /// </summary>
        private void RestartTransmissionPipeline(string reason)
        {
            Log.Debug("Restarting transmission pipeline: '{0}'", reason);

            StopTransmissionPipeline();

            //If capture has been specifically disabled, exit out of starting it
            if (_encounteredFatalException)
            {
                return;
            }

#if !NCRUNCH
            Profiler.BeginSample("CapturePipelineManager: RestartTransmissionPipeline");
#endif

            try
            {
                //Clear the flag for requesting an explicit reset.
                //We're about to apply a reset so the request will be satisfied.
                _pendingResetRequest = false;

                //No point starting a transmission pipeline if the network is not a client
                if (_network == null || !_network.Mode.IsClientEnabled())
                {
                    return;
                }

                //Create new mic capture system
                var format = _microphone.StartCapture(_micName);

                //If we created a mic (can be null if e.g. there is no mic)
                if (format != null)
                {
                    //Close and re-open all channels, propogating this restart to the receiving end
                    _roomChannels.Refresh();
                    _playerChannels.Refresh();

                    //Create preprocessor and subscribe it to microphone (webrtc preprocessor always wants audio to drive VAD+AEC)
                    _preprocessor = CreatePreprocessor(format);
                    _preprocessor.UpstreamLatency = _microphone.Latency;
                    _preprocessor.Start();
                    _microphone.Subscribe(_preprocessor);

                    //Sub VAD listeners to preprocessor
                    for (var i = 0; i < _activationListeners.Count; i++)
                    {
                        _preprocessor.Subscribe(_activationListeners[i]);
                    }

                    //Sub audio listeners to the preprocessor output
                    for (var i = 0; i < _audioListeners.Count; i++)
                    {
                        var al = _audioListeners[i];
                        al.Reset();
                        _preprocessor.Subscribe(al);
                    }

                    //Create encoder (not yet subscribed to receive audio data, we'll do that later)
                    Log.AssertAndThrowPossibleBug(_network != null, "5F33336B-15B5-4A85-9B54-54352C74768E", "Network object is unexpectedly null");
                    _encoder = new EncoderPipeline(_preprocessor.OutputFormat, _codecSettingsLoader.CreateEncoder(), _network);
                }
                else
                {
                    Log.Warn("Failed to start microphone capture; local voice transmission will be disabled.");
                    _cannotStartMic = true;
                }
            }
            catch (Exception ex)
            {
                //We don't know what happened, but something went wrong. As a precaution kill the transmission pipeline (it will be restarted if necessary)
                StopTransmissionPipeline();

                Log.Error("Unexpected exception encountered starting microphone capture; local voice transmission will be disabled: {0}", ex);
                _encounteredFatalException = true;
            }
            finally
            {
#if !NCRUNCH
                Profiler.EndSample();
#endif
            }
        }