/* define our own since we want to use private bool[] for c[] bits */ internal new eCorrectionResult Deconvolution() { int failures = ConvolutionalCoder.Decode(SCHData, ref SCHDataDecoded); if (failures == 0) { return(eCorrectionResult.Correct); } else if (failures < 10) { return(eCorrectionResult.Fixed); } else { return(eCorrectionResult.Failed); } }
/* define our own since we want to use private bool[] for c[] bits */ internal new eCorrectionResult Deconvolution(bool[] burstBufferC) { int failures = ConvolutionalCoder.Decode(burstBufferC, ref BurstBufferU); if (failures == 0) { return(eCorrectionResult.Correct); } else if (failures < 10) { return(eCorrectionResult.Fixed); } else { return(eCorrectionResult.Failed); } }
public override eSuccessState ParseData(GSMParameters param, bool[] decodedBurst, int sequence) { eSuccessState success = eSuccessState.Unknown; if (IsDummy(decodedBurst)) { State = eBurstState.Idle; DummyBursts++; //CloseFiles(); /* don't treat TCHs as a reliable source for end-of-connection detection */ //DummyBurstReceived(param); if (DumpRawData) { StatusMessage = "Dummy Burst"; } return(eSuccessState.Succeeded); } EncryptionType = AssociatedSACCH.EncryptionType; ChannelEncrypted = AssociatedSACCH.ChannelEncrypted; StoreBurstContext(param, decodedBurst, TCHSeq); /* GSM 05.03 Ch 2.1 */ /* when we got 8 TCH bursts */ if (++TCHSeq == 8) { TCHSeq = 0; /* try to decrypt buffer if this is enabled, but do not try to crack the key */ if (!HandleEncryption(param, false)) { State = eBurstState.CryptedTraffic; /* encrypted but no decryptor available, silently return */ return(eSuccessState.Unknown); } /* deinterleave the 8 TCH bursts. the result is a 456 bit block. i[] to c[] */ Deinterleave(); /* * GSM-05.03 4.2.5 * was this burst stolen for a FACCH? hl(B) (in e[]) is set for the last 4 bursts */ if (IsHL(decodedBurst)) { /* pass encryption information to FACCH */ FACCH.A5Algorithm = A5Algorithm; FACCH.A5CipherKey = A5CipherKey; FACCH.ChannelEncrypted = ChannelEncrypted; /* pass c[] to FACCH handler */ success = FACCH.ParseFACCHData(param, BurstBufferC); StatusMessage = FACCH.StatusMessage; ErrorMessage = FACCH.ErrorMessage; FACCH.StatusMessage = null; FACCH.ErrorMessage = null; } else { /* TCH speech/data (data not supported yet) */ /* split up the class 1... */ Array.Copy(BurstBufferC, Class1DataConv, Class1DataConv.Length); /* ... and class 2 bits */ Array.Copy(BurstBufferC, 378, GSMFrameBufferD, 182, 78); /* use an own convolutional coder buffer for these 188 bits */ if (ConvolutionalCoder.Decode(Class1DataConv, ref Class1Data) == 0) { bool[] parityBits = new bool[53]; for (int pos = 0; pos < 91; pos++) { GSMFrameBufferD[2 * pos] = Class1Data[pos]; GSMFrameBufferD[2 * pos + 1] = Class1Data[184 - pos]; } /* calculate parity */ Array.Copy(GSMFrameBufferD, 0, parityBits, 0, 50); Array.Copy(Class1Data, 91, parityBits, 50, 3); bool[] crc = CRC.Calc(parityBits, 0, 53, CRC.PolynomialTCHFR); if (CRC.Matches(crc)) { DataBursts++; success = eSuccessState.Succeeded; if (ChannelEncrypted) { State = eBurstState.DecryptedTraffic; } else { State = eBurstState.PlainTraffic; } #if false #region Microsoft WAV49 GSM Format if (WAV49First) { BitMapping.Unmap(GSMFrameBufferD, 0, WAV49FrameBool, 0, BitMapping.g610BitOrder); } else { /* directly unmap into boolean WAV49 frame buffer */ BitMapping.Unmap(GSMFrameBufferD, 0, WAV49FrameBool, 260, BitMapping.g610BitOrder); /* convert that WAV49 frame to byte[] */ ByteUtil.BitsToBytes(WAV49FrameBool, WAV49FrameByte); try { if (OutFile == null) { string name = ("GSM_" + Name + "_" + param.FN + ".wav").Replace("/", "_"); OutFile = new FileStream(name, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); WriteHeader(OutFile); } /* and write it */ WriteBuffer(OutFile, WAV49FrameByte); WriteHeader(OutFile); StatusMessage = "GSM 06.10 Voice data (" + OutFile.Name + ")"; } catch (Exception e) { StatusMessage = "GSM 06.10 Voice data (Writing file failed, " + e.GetType() + ")"; } } WAV49First = !WAV49First; #endregion #endif if (ChannelMode != 33) { #region write audio dump in RTP A/V Format /* GSM frame magic */ RTPFrameBool[0] = true; RTPFrameBool[1] = true; RTPFrameBool[2] = false; RTPFrameBool[3] = true; /* directly unmap into boolean RTP frame buffer */ BitMapping.Unmap(GSMFrameBufferD, 0, RTPFrameBool, 4, BitMapping.g610BitOrder); /* convert that RTP frame to byte[] */ ByteUtil.BitsToBytes(RTPFrameBool, RTPFrameByte); StatusMessage = ""; if (ChannelEncrypted) { StatusMessage += "======= encrypted =======" + Environment.NewLine; } try { if (OutFile == null) { string name = ("GSM_" + Name + "_" + param.FN).Replace("/", "_"); OutFile = new FileStream(name + ".gsm", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); //OutFileRaw = new FileStream(name + ".raw", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); StatusMessage += "Created file: '" + name + "'" + Environment.NewLine; } /* and write it */ OutFile.Write(RTPFrameByte, 0, RTPFrameByte.Length); OutFile.Flush(); /* * Array.Copy(GSMFrameBufferD, 0, RTPFrameBool, 4, GSMFrameBufferD.Length); * RTPFrameBool[0] = false; * RTPFrameBool[1] = false; * RTPFrameBool[2] = false; * RTPFrameBool[3] = false; * ByteUtil.BitsToBytes(RTPFrameBool, RTPFrameByte); * OutFileRaw.Write(RTPFrameByte, 0, RTPFrameByte.Length); */ StatusMessage += "GSM 06.10 Voice data (" + OutFile.Name + ")"; } catch (Exception e) { StatusMessage += "GSM 06.10 Voice data (Writing file failed, " + e.GetType() + ")"; } #endregion } else { #region write audio dump in AMR Format (assume 12.2kbit/s) UnmapDToW(); UnmapWToS(); /* convert that AMR frame to byte[] */ ByteUtil.BitsToBytes(BurstBufferSpeechBits, RTPFrameByte); StatusMessage = ""; if (ChannelEncrypted) { StatusMessage += "======= encrypted =======" + Environment.NewLine; } try { if (OutFile == null) { byte[] fileHeader = new byte[] { 0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A }; string name = ("GSM_" + Name + "_" + param.FN).Replace("/", "_"); OutFile = new FileStream(name + ".amr", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); OutFile.Write(fileHeader, 0, fileHeader.Length); } /* and write it */ OutFile.WriteByte(0x3C); OutFile.Write(RTPFrameByte, 0, 31); OutFile.Flush(); StatusMessage += "GSM 06.90 Voice data (" + OutFile.Name + ")"; } catch (Exception e) { StatusMessage += "GSM 06.90 Voice data (Writing file failed, " + e.GetType() + ")"; } #endregion } } else { State = eBurstState.Failed; CryptedFrames++; ErrorMessage = "(TCH/F Class Ia: CRC Error)"; } } else { State = eBurstState.Failed; CryptedFrames++; ErrorMessage = "(TCH/F Class I: Error in ConvolutionalCoder)"; } } /* trick: * first use the last 8 bursts until one block was successfully decoded. * then use the last 4 bursts as we normally would do. * this will help in finding the correct alignment within the 4 frames. */ if (success == eSuccessState.Succeeded) { BurstShiftCount = 4; } else { BurstShiftCount = 7; } /* save the last n bursts for the next block */ for (int pos = 0; pos < BurstShiftCount; pos++) { BurstData src = BurstBlock[(8 - BurstShiftCount) + pos]; BurstData dst = BurstBlock[pos]; dst.FN = src.FN; dst.Count = src.Count; Array.Copy(src.BurstBufferI, 0, dst.BurstBufferI, 0, dst.BurstBufferI.Length); Array.Copy(src.BurstBufferE, 0, dst.BurstBufferE, 0, dst.BurstBufferE.Length); } /* and continue at position n (so we will read another 8-n bursts) */ TCHSeq = BurstShiftCount; /* only when in sync, return error flag */ if (BurstShiftCount == 4) { return(success); } } return(eSuccessState.Unknown); }