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; }
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()); }
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; }
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; } }
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"); } }
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(); }
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(); }
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"); } }