void SendMicrophoneData()
        {
            if (_microphoneStream == null)
            {
                return;
            }

            // Store the client ID / stream ID so remote clients can find the corresponding AudioOutputStream
            model.clientID = _microphoneStream.ClientID();
            model.streamID = _microphoneStream.StreamID();

            // Check if AudioInputStream is valid.
            if (model.clientID < 0 || model.streamID < 0)
            {
                return;
            }


            // Clear the previous microphone frame data
            Array.Clear(_microphoneFrameData, 0, _microphoneFrameData.Length);

            // Send audio data in _microphoneFrameSize chunks until we're out of microphone data to send
            bool didGetAudioData = false;

            while (GetMicrophoneAudioData(_microphoneFrameData))
            {
                // If we have an _audioPreprocessor, preprocess the microphone data to remove noise and echo
                if (_audioPreprocessor != null)
                {
                    _audioPreprocessor.ProcessRecordSamples(_microphoneFrameData);
                }

                // Note that even when muted audio still needs to run through the audio processor to make sure echo cancellation works properly when mute is turned back off.
                if (_mute)
                {
                    Array.Clear(_microphoneFrameData, 0, _microphoneFrameData.Length);
                }

                // Send out microphone data
                _microphoneStream.SendRawAudioData(_microphoneFrameData);

                didGetAudioData = true;
            }

            // Normcore queues audio packets locally so they can go out in a single packet. This sends them off.
            if (didGetAudioData)
            {
                _microphoneStream.SendQueuedMessages();
            }

            // If we got audio data, update the current microphone level.
            // Note: I moved this here so that we do our volume level calculations on microphone audio that has run through the AudioPreprocessor.
            if (didGetAudioData)
            {
                int firstFrame = _microphoneFrameData.Length - 256;
                if (firstFrame < 0)
                {
                    firstFrame = 0;
                }
                int firstSample = firstFrame * _microphoneChannels;
                _microphoneDbLevel = StaticFunctions.CalculateAverageDbForAudioBuffer(_microphoneFrameData, firstSample);
            }
        }