Пример #1
0
        private void AddRadioEffectIntercom(ClientAudio clientAudio)
        {
            var mixedAudio = clientAudio.PcmAudioShort;

            for (var i = 0; i < mixedAudio.Length; i++)
            {
                var audio = mixedAudio[i] / 32768f;

                audio = _highPassFilter.Transform(audio);

                if (float.IsNaN(audio))
                {
                    audio = _lowPassFilter.Transform(mixedAudio[i]);
                }
                else
                {
                    audio = _lowPassFilter.Transform(audio);
                }

                if (!float.IsNaN(audio))
                {
                    // clip
                    if (audio > 1.0f)
                    {
                        audio = 1.0f;
                    }
                    if (audio < -1.0f)
                    {
                        audio = -1.0f;
                    }

                    mixedAudio[i] = (short)(audio * 32767);
                }
            }
        }
Пример #2
0
        private void AdjustVolumeForLoss(ClientAudio clientAudio)
        {
            if (clientAudio.Modulation == (short)Modulation.MIDS || clientAudio.Modulation == (short)Modulation.SATCOM)
            {
                return;
            }

            var audio = clientAudio.PcmAudioShort;

            for (var i = 0; i < audio.Length; i++)
            {
                var speaker1Short = audio[i];

                //add in radio loss
                //if less than loss reduce volume
                if (clientAudio.RecevingPower > 0.85) // less than 20% or lower left
                {
                    //gives linear signal loss from 15% down to 0%
                    speaker1Short = (short)(speaker1Short * (1.0f - clientAudio.RecevingPower));
                }

                //0 is no loss so if more than 0 reduce volume
                if (clientAudio.LineOfSightLoss > 0)
                {
                    speaker1Short = (short)(speaker1Short * (1.0f - clientAudio.LineOfSightLoss));
                }

                audio[i] = speaker1Short;
            }
        }
        private void AdjustVolume(ClientAudio clientAudio)
        {
            var audio = clientAudio.PcmAudioShort;

            for (var i = 0; i < audio.Length; i++)
            {
                var speaker1Short = (short)(audio[i] * clientAudio.Volume);

                //calculate % loss
                var loss = 1 - clientAudio.RecevingPower;
                //add in radio loss
                //if less than loss reduce volume
                if (clientAudio.RecevingPower <= 0.1) // less than 10% or lower left
                {
                    //gives linear signal loss from 10% down to 0%
                    speaker1Short = (short)(speaker1Short * loss / 0.1);
                }

                //0 is no loss so if more than 0 reduce volume
                if (clientAudio.LineOfSightLoss > 0)
                {
                    speaker1Short = (short)(speaker1Short * (1.0f - clientAudio.LineOfSightLoss));
                }

                audio[i] = speaker1Short;
            }
        }
        public void AddClientAudioSamples(ClientAudio audio)
        {
            //sort out volume
            var timer = new Stopwatch();

            timer.Start();

            var decrytable = audio.Decryptable || (audio.Encryption == 0);

            if (decrytable)
            {
                //adjust for LOS + Distance + Volume
                AdjustVolume(audio);

                ////no radio effect for intercom
                if (audio.ReceivedRadio != 0)
                {
                    if (_settings.UserSettings[(int)SettingType.RadioEffects] != "OFF")
                    {
                        AddRadioEffect(audio);
                    }
                }
            }
            else
            {
                AddEncryptionFailureEffect(audio);

                if (_settings.UserSettings[(int)SettingType.RadioEffects] != "OFF")
                {
                    AddRadioEffect(audio);
                }
            }

            long now = Environment.TickCount;

            if ((now - LastUpdate) > 400) //400 ms since last update
            {
                // System.Diagnostics.Debug.WriteLine(audio.ClientGuid+"ADDED");
                //append ms of silence - this functions as our jitter buffer??
                var silencePad = (AudioManager.INPUT_SAMPLE_RATE / 1000) * SILENCE_PAD;

                var newAudio = new short[audio.PcmAudioShort.Length + silencePad];

                Buffer.BlockCopy(audio.PcmAudioShort, 0, newAudio, silencePad, audio.PcmAudioShort.Length);

                audio.PcmAudioShort = newAudio;
            }

            _lastReceivedOn = audio.ReceivedRadio;
            LastUpdate      = now;

            JitterBufferProviderInterface.AddSamples(new JitterBufferAudio
            {
                Audio        = SeperateAudio(ConversionHelpers.ShortArrayToByteArray(audio.PcmAudioShort), audio.ReceivedRadio),
                PacketNumber = audio.PacketNumber
            });

            timer.Stop();
        }
Пример #5
0
        private void AddEncryptionFailureEffect(ClientAudio clientAudio)
        {
            var mixedAudio = clientAudio.PcmAudioShort;

            for (var i = 0; i < mixedAudio.Length; i++)
            {
                mixedAudio[i] = RandomShort();
            }
        }
Пример #6
0
        private void AdjustVolume(ClientAudio clientAudio)
        {
            var audio = clientAudio.PcmAudioShort;

            for (var i = 0; i < audio.Length; i++)
            {
                var speaker1Short = (short)(audio[i] * clientAudio.Volume);

                audio[i] = speaker1Short;
            }
        }
Пример #7
0
        private void AddRadioEffect(ClientAudio clientAudio)
        {
            var mixedAudio = clientAudio.PcmAudioShort;

            for (var i = 0; i < mixedAudio.Length; i++)
            {
                var audio = (double)mixedAudio[i] / 32768f;

                if (_settings.GetClientSetting(SettingsKeys.RadioEffectsClipping).BoolValue)
                {
                    if (audio > RadioFilter.CLIPPING_MAX)
                    {
                        audio = RadioFilter.CLIPPING_MAX;
                    }
                    else if (audio < RadioFilter.CLIPPING_MIN)
                    {
                        audio = RadioFilter.CLIPPING_MIN;
                    }
                }

                //high and low pass filter
                for (int j = 0; j < _filters.Length; j++)
                {
                    var filter = _filters[j];
                    audio = filter.ProcessSample(audio);

                    if (double.IsNaN(audio))
                    {
                        audio = (double)mixedAudio[j] / 32768f;
                    }
                    else
                    {
                        // clip
                        if (audio > 1.0f)
                        {
                            audio = 1.0f;
                        }
                        if (audio < -1.0f)
                        {
                            audio = -1.0f;
                        }
                    }
                }

                mixedAudio[i] = (short)(audio * 32767);
            }
        }
        public void AddAudio(ClientAudio audio)
        {
            if (_firstPacketTime > GetTickCount64())
            {
                //      logger.Info("Start");
                _firstPacketTime = audio.ReceiveTime;
                _clientBuffers.Clear();
                _clientBuffers[audio.ClientGuid] = new List <byte>(1920 * 5); //asumes 5 sets worth of 20ms PCM audio
                _clientBuffers[audio.ClientGuid].AddRange(audio.PcmAudio);
            }
            else
            {
                //work out which buffer
                var diff = audio.ReceiveTime - _firstPacketTime;

                if (diff < 0 || diff > _bufferLength)
                {
                    //drop too early or to late
                    //TODO tune the too early? an old packet would knacker the queue
                    Logger.Warn("Dropping Packet - Diff: " + diff);
                }
                else
                {
                    if (!_clientBuffers.ContainsKey(audio.ClientGuid))
                    {
                        _clientBuffers[audio.ClientGuid] = new List <byte>();
                        _clientBuffers[audio.ClientGuid].AddRange(audio.PcmAudio);
                    }
                    else
                    {
                        //   logger.Info("adding");
                        _clientBuffers[audio.ClientGuid].AddRange(audio.PcmAudio);
                    }
                }
            }
        }
Пример #9
0
        public void AddClientAudioSamples(ClientAudio audio)
        {
            //sort out volume
//            var timer = new Stopwatch();
//            timer.Start();

            bool newTransmission = LikelyNewTransmission();

            int decodedLength = 0;

            var decoded = _decoder.Decode(audio.EncodedAudio,
                                          audio.EncodedAudio.Length, out decodedLength, newTransmission);

            if (decodedLength <= 0)
            {
                Logger.Info("Failed to decode audio from Packet for client");
                return;
            }

            // for some reason if this is removed then it lags?!
            //guess it makes a giant buffer and only uses a little?
            //Answer: makes a buffer of 4000 bytes - so throw away most of it
            var tmp = new byte[decodedLength];

            Buffer.BlockCopy(decoded, 0, tmp, 0, decodedLength);

            audio.PcmAudioShort = ConversionHelpers.ByteArrayToShortArray(tmp);

            var decrytable = audio.Decryptable || (audio.Encryption == 0);

            if (decrytable)
            {
                //adjust for LOS + Distance + Volume
                AdjustVolumeForLoss(audio);

                if (audio.ReceivedRadio == 0 ||
                    audio.Modulation == (short)RadioInformation.Modulation.MIDS)
                {
                    if (profileSettings.GetClientSettingBool(ProfileSettingsKeys.RadioEffects))
                    {
                        AddRadioEffectIntercom(audio);
                    }
                }
                else
                {
                    AddRadioEffect(audio);
                }

                //final adjust
                AdjustVolume(audio);
            }
            else
            {
                AddEncryptionFailureEffect(audio);

                AddRadioEffect(audio);

                //final adjust
                AdjustVolume(audio);
            }

            if (newTransmission)
            {
                // System.Diagnostics.Debug.WriteLine(audio.ClientGuid+"ADDED");
                //append ms of silence - this functions as our jitter buffer??
                var silencePad = (AudioManager.OUTPUT_SAMPLE_RATE / 1000) * SILENCE_PAD;

                var newAudio = new short[audio.PcmAudioShort.Length + silencePad];

                Buffer.BlockCopy(audio.PcmAudioShort, 0, newAudio, silencePad, audio.PcmAudioShort.Length);

                audio.PcmAudioShort = newAudio;
            }

            _lastReceivedOn = audio.ReceivedRadio;
            LastUpdate      = DateTime.Now.Ticks;

            JitterBufferProviderInterface.AddSamples(new JitterBufferAudio
            {
                Audio =
                    SeperateAudio(ConversionHelpers.ShortArrayToByteArray(audio.PcmAudioShort),
                                  audio.ReceivedRadio),
                PacketNumber = audio.PacketNumber
            });

            //timer.Stop();
        }
Пример #10
0
        private double AddRadioBackgroundNoiseEffect(double audio, ClientAudio clientAudio)
        {
            if (profileSettings.GetClientSettingBool(ProfileSettingsKeys.RadioBackgroundNoiseEffect))
            {
                if (clientAudio.Modulation == HQ || clientAudio.Modulation == AM)
                {
                    //mix in based on frequency
                    if (clientAudio.Frequency >= 200d * 1000000)
                    {
                        if (effectProvider.UHFNoise.Loaded)
                        {
                            var noise = effectProvider.UHFNoise.AudioEffectDouble;
                            //UHF Band?
                            audio += (noise[uhfNoisePosition]);
                            uhfNoisePosition++;

                            if (uhfNoisePosition == noise.Length)
                            {
                                uhfNoisePosition = 0;
                            }
                        }
                    }
                    else if (clientAudio.Frequency > 80d * 1000000)
                    {
                        if (effectProvider.VHFNoise.Loaded)
                        {
                            //VHF Band? - Very rough
                            var noise = effectProvider.VHFNoise.AudioEffectDouble;
                            audio += (double)(noise[vhfNoisePosition]);
                            vhfNoisePosition++;

                            if (vhfNoisePosition == noise.Length)
                            {
                                vhfNoisePosition = 0;
                            }
                        }
                    }
                    else
                    {
                        if (effectProvider.HFNoise.Loaded)
                        {
                            //HF!
                            var noise = effectProvider.HFNoise.AudioEffectDouble;
                            audio += (double)(noise[hfNoisePosition]);
                            hfNoisePosition++;

                            if (hfNoisePosition == noise.Length)
                            {
                                hfNoisePosition = 0;
                            }
                        }
                    }
                }
                else if (clientAudio.Modulation == FM)
                {
                    if (effectProvider.FMNoise.Loaded)
                    {
                        //FM picks up most of the 20-60 ish range + has a different effect
                        //HF!
                        var noise = effectProvider.FMNoise.AudioEffectDouble;
                        //UHF Band?
                        audio += (double)(noise[fmNoisePosition]);
                        fmNoisePosition++;

                        if (fmNoisePosition == noise.Length)
                        {
                            fmNoisePosition = 0;
                        }
                    }
                }
            }

            return(audio);
        }
Пример #11
0
        private void AddRadioEffect(ClientAudio clientAudio)
        {
            var mixedAudio = clientAudio.PcmAudioShort;

            for (var i = 0; i < mixedAudio.Length; i++)
            {
                var audio = (double)mixedAudio[i] / 32768f;

                if (profileSettings.GetClientSettingBool(ProfileSettingsKeys.RadioEffects))
                {
                    if (profileSettings.GetClientSettingBool(ProfileSettingsKeys.RadioEffectsClipping))
                    {
                        if (audio > RadioFilter.CLIPPING_MAX)
                        {
                            audio = RadioFilter.CLIPPING_MAX;
                        }
                        else if (audio < RadioFilter.CLIPPING_MIN)
                        {
                            audio = RadioFilter.CLIPPING_MIN;
                        }
                    }

                    //high and low pass filter
                    for (int j = 0; j < _filters.Length; j++)
                    {
                        var filter = _filters[j];
                        audio = filter.ProcessSample(audio);
                        if (double.IsNaN(audio))
                        {
                            audio = mixedAudio[j];
                        }

                        audio = audio * RadioFilter.BOOST;
                    }
                }

                if (clientAudio.Modulation == FM &&
                    effectProvider.NATOTone.Loaded &&
                    profileSettings.GetClientSettingBool(ProfileSettingsKeys.NATOTone))
                {
                    var natoTone = effectProvider.NATOTone.AudioEffectDouble;
                    audio += (double)(natoTone[natoPosition]);
                    natoPosition++;

                    if (natoPosition == natoTone.Length)
                    {
                        natoPosition = 0;
                    }
                }

                if (clientAudio.Modulation == HQ &&
                    effectProvider.HAVEQUICKTone.Loaded &&
                    profileSettings.GetClientSettingBool(ProfileSettingsKeys.HAVEQUICKTone))
                {
                    var hqTone = effectProvider.HAVEQUICKTone.AudioEffectDouble;

                    audio += (double)(hqTone[hqTonePosition]);
                    hqTonePosition++;

                    if (hqTonePosition == hqTone.Length)
                    {
                        var reset = _random.NextDouble();

                        if (reset > HQ_RESET_CHANCE)
                        {
                            hqTonePosition = 0;
                        }
                        else
                        {
                            //one back to try again
                            hqTonePosition += -1;
                        }
                    }
                }

                audio = AddRadioBackgroundNoiseEffect(audio, clientAudio);

                // clip
                if (audio > 1.0f)
                {
                    audio = 1.0f;
                }
                if (audio < -1.0f)
                {
                    audio = -1.0f;
                }

                mixedAudio[i] = (short)(audio * 32768f);
            }
        }
        private void AddRadioEffect(ClientAudio clientAudio)
        {
            var mixedAudio = clientAudio.PcmAudioShort;

            for (var i = 0; i < mixedAudio.Length; i++)
            {
                var audio = (double)mixedAudio[i] / 32768f;

                if (globalSettings.GetClientSettingBool(ProfileSettingsKeys.RadioEffectsClipping))
                {
                    if (audio > RadioFilter.CLIPPING_MAX)
                    {
                        audio = RadioFilter.CLIPPING_MAX;
                    }
                    else if (audio < RadioFilter.CLIPPING_MIN)
                    {
                        audio = RadioFilter.CLIPPING_MIN;
                    }
                }

                //high and low pass filter
                for (int j = 0; j < _filters.Length; j++)
                {
                    var filter = _filters[j];
                    audio = filter.ProcessSample(audio);

                    if (double.IsNaN(audio))
                    {
                        audio = (double)mixedAudio[j] / 32768f;
                    }
                    else
                    {
                        // clip
                        if (audio > 1.0f)
                        {
                            audio = 1.0f;
                        }
                        if (audio < -1.0f)
                        {
                            audio = -1.0f;
                        }
                    }
                }

                var shortAudio = (short)(audio * 32767);

                if (clientAudio.Modulation == FM &&
                    natoTone != null && globalSettings.GetClientSettingBool(ProfileSettingsKeys.NATOTone))
                {
                    shortAudio += natoTone[natoPosition];
                    natoPosition++;

                    if (natoPosition == natoTone.Length)
                    {
                        natoPosition = 0;
                    }
                }

                mixedAudio[i] = shortAudio;
            }
        }
Пример #13
0
        public byte[] AddClientAudioSamples(ClientAudio audio, bool skipEffects = false)
        {
            //sort out volume
            //            var timer = new Stopwatch();
            //            timer.Start();

            bool newTransmission = LikelyNewTransmission();

            var decoded = _decoder.Decode(audio.EncodedAudio,
                                          audio.EncodedAudio.Length, out var decodedLength, newTransmission);

            if (decodedLength <= 0)
            {
                Logger.Info("Failed to decode audio from Packet for client");
                return(null);
            }

            // for some reason if this is removed then it lags?!
            //guess it makes a giant buffer and only uses a little?
            //Answer: makes a buffer of 4000 bytes - so throw away most of it
            var tmp = new byte[decodedLength];

            Buffer.BlockCopy(decoded, 0, tmp, 0, decodedLength);

            audio.PcmAudioShort = ConversionHelpers.ByteArrayToShortArray(tmp);

            //only get settings every 3 seconds - and cache them - issues with performance
            long now = DateTime.Now.Ticks;

            if (TimeSpan.FromTicks(now - lastRefresh).TotalSeconds > 3) //3 seconds since last refresh
            {
                lastRefresh = now;

                natoToneEnabled     = profileSettings.GetClientSettingBool(ProfileSettingsKeys.NATOTone);
                hqToneEnabled       = profileSettings.GetClientSettingBool(ProfileSettingsKeys.HAVEQUICKTone);
                radioEffectsEnabled = profileSettings.GetClientSettingBool(ProfileSettingsKeys.RadioEffects);
                clippingEnabled     = profileSettings.GetClientSettingBool(ProfileSettingsKeys.RadioEffectsClipping);
                hqToneVolume        = profileSettings.GetClientSettingFloat(ProfileSettingsKeys.HQToneVolume);
                natoToneVolume      = profileSettings.GetClientSettingFloat(ProfileSettingsKeys.NATOToneVolume);

                fmVol  = profileSettings.GetClientSettingFloat(ProfileSettingsKeys.FMNoiseVolume);
                hfVol  = profileSettings.GetClientSettingFloat(ProfileSettingsKeys.HFNoiseVolume);
                uhfVol = profileSettings.GetClientSettingFloat(ProfileSettingsKeys.UHFNoiseVolume);
                vhfVol = profileSettings.GetClientSettingFloat(ProfileSettingsKeys.VHFNoiseVolume);
            }

            var decrytable = audio.Decryptable /* || (audio.Encryption == 0) <--- this test has already been performed by all callers and would require another call to check for STRICT_AUDIO_ENCRYPTION */;

            if (decrytable)
            {
                //adjust for LOS + Distance + Volume
                AdjustVolumeForLoss(audio);

                if (!skipEffects)
                {
                    if (audio.ReceivedRadio == 0 ||
                        audio.Modulation == (short)RadioInformation.Modulation.MIDS)
                    {
                        if (profileSettings.GetClientSettingBool(ProfileSettingsKeys.RadioEffects))
                        {
                            AddRadioEffectIntercom(audio);
                        }
                    }
                    else
                    {
                        AddRadioEffect(audio);
                    }
                }

                //final adjust
                AdjustVolume(audio);
            }
            else
            {
                AddEncryptionFailureEffect(audio);

                AddRadioEffect(audio);

                //final adjust
                AdjustVolume(audio);
            }

            if (newTransmission)
            {
                // System.Diagnostics.Debug.WriteLine(audio.ClientGuid+"ADDED");
                //append ms of silence - this functions as our jitter buffer??
                var silencePad = (AudioManager.OUTPUT_SAMPLE_RATE / 1000) * SILENCE_PAD;

                var newAudio = new short[audio.PcmAudioShort.Length + silencePad];

                Buffer.BlockCopy(audio.PcmAudioShort, 0, newAudio, silencePad, audio.PcmAudioShort.Length);

                audio.PcmAudioShort = newAudio;
            }

            _lastReceivedOn = audio.ReceivedRadio;
            LastUpdate      = DateTime.Now.Ticks;

            if (!passThrough)
            {
                JitterBufferProviderInterface.AddSamples(new JitterBufferAudio
                {
                    Audio =
                        SeperateAudio(ConversionHelpers.ShortArrayToByteArray(audio.PcmAudioShort),
                                      audio.ReceivedRadio),
                    PacketNumber = audio.PacketNumber
                });

                return(null);
            }
            else
            {
                //return MONO PCM 16 as bytes
                return(ConversionHelpers.ShortArrayToByteArray(audio.PcmAudioShort));
            }

            //timer.Stop();
        }