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); } } }
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(); }
private void AddEncryptionFailureEffect(ClientAudio clientAudio) { var mixedAudio = clientAudio.PcmAudioShort; for (var i = 0; i < mixedAudio.Length; i++) { mixedAudio[i] = RandomShort(); } }
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; } }
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); } } } }
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(); }
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); }
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; } }
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(); }