public ClientAudioProvider()
        {
            _filters    = new OnlineFilter[2];
            _filters[0] =
                OnlineFilter.CreateBandpass(ImpulseResponse.Finite, AudioManager.INPUT_SAMPLE_RATE, 560, 3900);
            _filters[1] =
                OnlineFilter.CreateBandpass(ImpulseResponse.Finite, AudioManager.INPUT_SAMPLE_RATE, 100, 4500);

            JitterBufferProviderInterface =
                new JitterBufferProviderInterface(new WaveFormat(AudioManager.INPUT_SAMPLE_RATE, 2));

            SampleProvider = new Pcm16BitToSampleProvider(JitterBufferProviderInterface);

            _decoder = OpusDecoder.Create(AudioManager.INPUT_SAMPLE_RATE, 1);
            _decoder.ForwardErrorCorrection = false;

            _highPassFilter = BiQuadFilter.HighPassFilter(AudioManager.INPUT_SAMPLE_RATE, 520, 0.97f);
            _lowPassFilter  = BiQuadFilter.LowPassFilter(AudioManager.INPUT_SAMPLE_RATE, 4130, 2.0f);

            var effect = new CachedAudioEffect(CachedAudioEffect.AudioEffectTypes.NATO_TONE);

            if (effect.AudioEffectBytes.Length > 0)
            {
                natoTone = ConversionHelpers.ByteArrayToShortArray(effect.AudioEffectBytes);

                var vol = Settings.GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.NATOToneVolume)
                          .FloatValue;

                for (int i = 0; i < natoTone.Length; i++)
                {
                    natoTone[i] = (short)(natoTone[i] * vol);
                }
            }
        }
        public CachedLoopingAudioProvider(IWaveProvider source, WaveFormat waveFormat, CachedAudioEffect.AudioEffectTypes effectType)
        {
            this.WaveFormat = waveFormat;
            var effect = new CachedAudioEffect(effectType);

            _audioEffectShort = ConversionHelpers.ByteArrayToShortArray(effect.AudioEffectBytes);

            this.source = source;
        }
예제 #3
0
        public void ConversionTestShortByteArray()
        {
            short[] shorts = new short[] { 1, short.MaxValue, short.MinValue, 0 };

            var bytes = ConversionHelpers.ShortArrayToByteArray(shorts);

            var result = ConversionHelpers.ByteArrayToShortArray(bytes);

            var query = shorts.Where((b, i) => b == result[i]);

            Assert.AreEqual(shorts.Length, query.Count());
        }
예제 #4
0
        public void ConversionTestByteShortArray()
        {
            byte[] bytes = new byte[] { 255, 253, 102, 0, 5, 0, 0, 0 };

            var shorts = ConversionHelpers.ByteArrayToShortArray(bytes);

            var result = ConversionHelpers.ShortArrayToByteArray(shorts);

            var query = bytes.Where((b, i) => b == result[i]);

            Assert.AreEqual(bytes.Length, query.Count());
        }
        private void CreateAudioEffectDouble(CachedAudioEffect effect)
        {
            if (effect.Loaded)
            {
                var effectShort  = ConversionHelpers.ByteArrayToShortArray(effect.AudioEffectBytes);
                var effectDouble = new double[effectShort.Length];

                for (int i = 0; i < effectShort.Length; i++)
                {
                    effectDouble[i] = ((effectShort[i] / 32768f));
                }
                effect.AudioEffectDouble = effectDouble;
            }
        }
        public CachedLoopingAudioProvider(IWaveProvider source, WaveFormat waveFormat, CachedAudioEffect.AudioEffectTypes effectType)
        {
            this.WaveFormat = waveFormat;
            var effect = new CachedAudioEffect(effectType);

            _audioEffectShort = ConversionHelpers.ByteArrayToShortArray(effect.AudioEffectBytes);

            var vol = Settings.GlobalSettingsStore.Instance.GetClientSetting(GlobalSettingsKeys.NATOToneVolume)
                      .FloatValue;

            for (int i = 0; i < _audioEffectShort.Length; i++)
            {
                _audioEffectShort[i] = (short)(_audioEffectShort[i] * vol);
            }

            this.source = source;
        }
예제 #7
0
        private void ChangeVolumeOfEffect(CachedAudioEffect effect, GlobalSettingsKeys key)
        {
            if (effect.Loaded)
            {
                var effectShort  = ConversionHelpers.ByteArrayToShortArray(effect.AudioEffectBytes);
                var effectDouble = new double[effectShort.Length];

                var vol = Settings.GlobalSettingsStore.Instance.GetClientSetting(key)
                          .FloatValue;

                for (int i = 0; i < effectShort.Length; i++)
                {
                    effectDouble[i] = ((effectShort[i] / 32768f) * vol);
                }
                effect.AudioEffectDouble = effectDouble;
            }
        }
예제 #8
0
        public void AddClientAudioSamples(ClientAudio audio)
        {
            var newTransmission = LikelyNewTransmission();

            if (newTransmission)
            {
                Logger.Debug($"{LogClientId}| Likely New Transmission");
            }

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

            if (decodedLength > 0)
            {
                // 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);

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

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

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

                    audio.PcmAudioShort = newAudio;
                }

                LastUpdate = DateTime.Now.Ticks;

                var pcmAudio = ConversionHelpers.ShortArrayToByteArray(audio.PcmAudioShort);
                _speechAudioProvider.AddSamples(pcmAudio, 0, pcmAudio.Length);
            }
            else
            {
                Logger.Debug($"{LogClientId}| Failed to decode audio from Packet for client");
            }
        }
        private void UdpAudioDecode()
        {
            try
            {
                while (!_stop)
                {
                    try
                    {
                        var encodedOpusAudio = new byte[0];
                        _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token);

                        var time = GetTickCount64(); //should add at the receive instead?

                        if ((encodedOpusAudio != null) && (encodedOpusAudio.Length > 36))
                        {
                            //  process
                            // check if we should play audio

                            var myClient = IsClientMetaDataValid(_guid);

                            if ((myClient != null) && _clientStateSingleton.DcsPlayerRadioInfo.IsCurrent())
                            {
                                //Decode bytes
                                var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio);

                                // check the radio
                                RadioReceivingState receivingState = null;
                                var receivingRadio =
                                    _clientStateSingleton.DcsPlayerRadioInfo.CanHearTransmission(
                                        udpVoicePacket.Frequency,
                                        (RadioInformation.Modulation)udpVoicePacket.Modulation,
                                        udpVoicePacket.UnitId, out receivingState);

                                //Check that we're not transmitting on this radio

                                double receivingPowerLossPercent = 0;
                                float  lineOfSightLoss           = 0;

                                if ((receivingRadio != null) && (receivingState != null)
                                    &&
                                    ((receivingRadio.modulation == RadioInformation.Modulation.INTERCOM)
                                     // INTERCOM Modulation is 2 so if its two dont bother checking LOS and Range
                                     ||
                                     (
                                         HasLineOfSight(udpVoicePacket, out lineOfSightLoss)
                                         &&
                                         InRange(udpVoicePacket, out receivingPowerLossPercent)
                                         &&
                                         !ShouldBlockRxAsTransmitting(receivingState.ReceivedOn)
                                     )
                                    )
                                    )
                                {
                                    //  RadioReceivingState[receivingState.ReceivedOn] = receivingState;

                                    //DECODE audio
                                    int len1;
                                    var decoded = _decoder.Decode(udpVoicePacket.AudioPart1Bytes,
                                                                  udpVoicePacket.AudioPart1Bytes.Length, out len1);


                                    if (len1 > 0)
                                    {
                                        // for some reason if this is removed then it lags?!
                                        //guess it makes a giant buffer and only uses a little?
                                        var tmp = new byte[len1];
                                        Buffer.BlockCopy(decoded, 0, tmp, 0, len1);

                                        //ALL GOOD!
                                        //create marker for bytes
                                        var audio = new ClientAudio
                                        {
                                            ClientGuid    = udpVoicePacket.Guid,
                                            PcmAudioShort = ConversionHelpers.ByteArrayToShortArray(tmp),
                                            //Convert to Shorts!
                                            ReceiveTime   = GetTickCount64(),
                                            Frequency     = udpVoicePacket.Frequency,
                                            Modulation    = udpVoicePacket.Modulation,
                                            Volume        = receivingRadio.volume,
                                            ReceivedRadio = receivingState.ReceivedOn,
                                            UnitId        = udpVoicePacket.UnitId,
                                            Encryption    = udpVoicePacket.Encryption,
                                            Decryptable   =
                                                (udpVoicePacket.Encryption == receivingRadio.encKey) &&
                                                receivingRadio.enc,
                                            // mark if we can decrypt it
                                            RadioReceivingState = receivingState,
                                            RecevingPower       =
                                                receivingPowerLossPercent,     //loss of 1.0 or greater is total loss
                                            LineOfSightLoss = lineOfSightLoss, // Loss of 1.0 or greater is total loss
                                            PacketNumber    = udpVoicePacket.PacketNumber
                                        };


                                        //handle effects
                                        var radioState = RadioReceivingState[audio.ReceivedRadio];

                                        if ((radioState == null) || radioState.PlayedEndOfTransmission ||
                                            !radioState.IsReceiving)
                                        {
                                            var decrytable = audio.Decryptable || (audio.Encryption == 0);

                                            //mark that we have decrpyted encrypted audio for sound effects
                                            if (decrytable && (audio.Encryption > 0))
                                            {
                                                _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio,
                                                                                          true,
                                                                                          audio.Volume);
                                            }
                                            else
                                            {
                                                _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio,
                                                                                          false,
                                                                                          audio.Volume);
                                            }
                                        }

                                        RadioReceivingState[audio.ReceivedRadio] = new RadioReceivingState
                                        {
                                            IsSecondary             = receivingState.IsSecondary,
                                            LastReceviedAt          = DateTime.Now.Ticks,
                                            PlayedEndOfTransmission = false,
                                            ReceivedOn = receivingState.ReceivedOn
                                        };

                                        _audioManager.AddClientAudio(audio);
                                    }
                                    else
                                    {
                                        Logger.Info("Failed to decode audio from Packet");
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Info("Failed to decode audio from Packet");
                    }
                }
            }
            catch (OperationCanceledException)
            {
                Logger.Info("Stopped DeJitter Buffer");
            }
        }
예제 #10
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();
        }
예제 #11
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();
        }
예제 #12
0
        private void UdpAudioDecode()
        {
            try
            {
                while (!_stop)
                {
                    try
                    {
                        var encodedOpusAudio = new byte[0];
                        _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token);

                        var time = GetTickCount64(); //should add at the receive instead?

                        if (encodedOpusAudio != null && encodedOpusAudio.Length > 36)
                        {
                            //  process
                            // check if we should play audio

                            var myClient = IsClientMetaDataValid(_guid);

                            if (myClient != null && RadioDCSSyncServer.DcsPlayerRadioInfo.IsCurrent())
                            {
                                //Decode bytes
                                var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio);

                                // check the radio
                                RadioReceivingState receivingState = null;
                                var receivingRadio =
                                    RadioDCSSyncServer.DcsPlayerRadioInfo.CanHearTransmission(udpVoicePacket.Frequency,
                                                                                              udpVoicePacket.Modulation,
                                                                                              udpVoicePacket.UnitId, out receivingState);

                                //Check that we're not transmitting on this radio

                                double receivingPower  = 0;
                                float  lineOfSightLoss = 0;

                                if (receivingRadio != null && receivingState != null
                                    &&
                                    (receivingRadio.modulation == 2
                                     // INTERCOM Modulation is 2 so if its two dont bother checking LOS and Range
                                     ||
                                     (
                                         HasLineOfSight(udpVoicePacket, out lineOfSightLoss)
                                         &&
                                         InRange(udpVoicePacket, out receivingPower)
                                         &&
                                         !ShouldBlockRxAsTransmitting(receivingState.ReceivedOn)
                                     )
                                    )
                                    )
                                {
                                    //  RadioReceivingState[receivingState.ReceivedOn] = receivingState;

                                    //DECODE audio
                                    int len1;
                                    var decoded = _decoder.Decode(udpVoicePacket.AudioPart1Bytes,
                                                                  udpVoicePacket.AudioPart1Bytes.Length, out len1);

                                    int len2;
                                    var decoded2 = _decoder.Decode(udpVoicePacket.AudioPart2Bytes,
                                                                   udpVoicePacket.AudioPart2Bytes.Length, out len2);

                                    if (len1 > 0 && len2 > 0)
                                    {
                                        // for some reason if this is removed then it lags?!
                                        //guess it makes a giant buffer and only uses a little?
                                        var tmp = new byte[len1 + len2];
                                        Buffer.BlockCopy(decoded, 0, tmp, 0, len1);
                                        Buffer.BlockCopy(decoded2, 0, tmp, len1, len2);

                                        //ALL GOOD!
                                        //create marker for bytes
                                        var audio = new ClientAudio
                                        {
                                            ClientGuid    = udpVoicePacket.Guid,
                                            PcmAudioShort = ConversionHelpers.ByteArrayToShortArray(tmp),
                                            //Convert to Shorts!
                                            ReceiveTime   = GetTickCount64(),
                                            Frequency     = udpVoicePacket.Frequency,
                                            Modulation    = udpVoicePacket.Modulation,
                                            Volume        = receivingRadio.volume,
                                            ReceivedRadio = receivingState.ReceivedOn,
                                            UnitId        = udpVoicePacket.UnitId,
                                            Encryption    = udpVoicePacket.Encryption,
                                            Decryptable   =
                                                udpVoicePacket.Encryption == receivingRadio.encKey && receivingRadio.enc,
                                            // mark if we can decrypt it
                                            RadioReceivingState = receivingState,
                                            RecevingPower       = receivingPower,
                                            LineOfSightLoss     = lineOfSightLoss // Loss of 1.0 or greater is total loss
                                        };

                                        //add to JitterBuffer!
                                        lock (_lock)
                                        {
                                            _jitterBuffer.AddAudio(audio);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Info("Failed Decoding");
                    }
                }
            }
            catch (OperationCanceledException)
            {
                Logger.Info("Stopped DeJitter Buffer");
            }
        }