public void StopEncoding() { lock (lockObj) { _textToSpeech?.Dispose(); _textToSpeech = null; _wasapiCapture?.StopRecording(); _wasapiCapture?.Dispose(); _wasapiCapture = null; _resampler?.Dispose(true); _resampler = null; _waveOut?.Stop(); _waveOut?.Dispose(); _waveOut = null; _micWaveOut?.Stop(); _micWaveOut?.Dispose(); _micWaveOut = null; _volumeSampleProvider = null; _clientAudioMixer?.RemoveAllMixerInputs(); _clientAudioMixer = null; _clientsBufferedAudio.Clear(); _encoder?.Dispose(); _encoder = null; if (_udpVoiceHandler != null) { _udpVoiceHandler.RequestStop(); _udpVoiceHandler = null; } _speex?.Dispose(); _speex = null; SpeakerMax = -100; MicMax = -100; _effectsOutputBuffer = null; foreach (var guid in _subs) { MessageHub.Instance.UnSubscribe(guid); } _subs.Clear(); } }
private void WasapiCaptureOnDataAvailable(object sender, WaveInEventArgs e) { if (_resampler == null) { //create and use in the same thread or COM issues _resampler = new EventDrivenResampler(windowsN, _wasapiCapture.WaveFormat, new WaveFormat(AudioManager.INPUT_SAMPLE_RATE, 16, 1)); } if (e.BytesRecorded > 0) { //Logger.Info($"Time: {_stopwatch.ElapsedMilliseconds} - Bytes: {e.BytesRecorded}"); short[] resampledPCM16Bit = _resampler.Resample(e.Buffer, e.BytesRecorded); // Logger.Info($"Time: {_stopwatch.ElapsedMilliseconds} - Bytes: {resampledPCM16Bit.Length}"); //fill sound buffer for (var i = 0; i < resampledPCM16Bit.Length; i++) { _micInputQueue.Enqueue(resampledPCM16Bit[i]); } //read out the queue while (_micInputQueue.Count >= AudioManager.SEGMENT_FRAMES) { short[] pcmShort = new short[AudioManager.SEGMENT_FRAMES]; for (var i = 0; i < AudioManager.SEGMENT_FRAMES; i++) { pcmShort[i] = _micInputQueue.Dequeue(); } try { //volume boost pre for (var i = 0; i < pcmShort.Length; i++) { // n.b. no clipping test going on here pcmShort[i] = (short)(pcmShort[i] * MicBoost); } //process with Speex _speex.Process(new ArraySegment <short>(pcmShort)); float max = 0; for (var i = 0; i < pcmShort.Length; i++) { //determine peak if (pcmShort[i] > max) { max = pcmShort[i]; } } //convert to dB MicMax = (float)VolumeConversionHelper.ConvertFloatToDB(max / 32768F); var pcmBytes = new byte[pcmShort.Length * 2]; Buffer.BlockCopy(pcmShort, 0, pcmBytes, 0, pcmBytes.Length); //encode as opus bytes int len; var buff = _encoder.Encode(pcmBytes, pcmBytes.Length, out len); if ((_udpVoiceHandler != null) && (buff != null) && (len > 0)) { //create copy with small buffer var encoded = new byte[len]; Buffer.BlockCopy(buff, 0, encoded, 0, len); // Console.WriteLine("Sending: " + e.BytesRecorded); if (_udpVoiceHandler.Send(encoded, len)) { //send audio so play over local too _micWaveOutBuffer?.AddSamples(pcmBytes, 0, pcmBytes.Length); } } else { Logger.Error($"Invalid Bytes for Encoding - {pcmShort.Length} should be {SEGMENT_FRAMES} "); } _errorCount = 0; } catch (Exception ex) { _errorCount++; if (_errorCount < 10) { Logger.Error(ex, "Error encoding Opus! " + ex.Message); } else if (_errorCount == 10) { Logger.Error(ex, "Final Log of Error encoding Opus! " + ex.Message); } } } } }