public void AnalyzeSignal_KnownSignal_ReturnsExpectedValues()
        {
            var audioStream = new MemoryStream();

            var audioGenerator    = new AudioGenerator(audioStream);
            var fskAudioGenerator = new FskAudioGenerator(audioGenerator);

            fskAudioGenerator.GenerateAudio(_binaryFskAnalyzerSettings.BaudRate,
                                            _binaryFskAnalyzerSettings.SpaceFrequency, _binaryFskAnalyzerSettings.MarkFrequency,
                                            _bitManipulator.StringToBits(Resources.LoremIpsumTestString));

            var audioAnalyzer     = new AudioAnalyzer(audioStream, audioGenerator);
            var binaryFskAnalyzer = (IBinaryFskAnalyzer) new BinaryFskAnalyzer(audioAnalyzer, new ZeroCrossingsFrequencyDetector(), _binaryFskAnalyzerSettings);
            var results           = binaryFskAnalyzer.AnalyzeSignal();

            var result = binaryFskAnalyzer.AnalyzeSignal();
            var bits   = new List <bool>();

            foreach (var frame in result.AnalysisFrames)
            {
                if (frame.Bit.HasValue == true)
                {
                    bits.Add(frame.Bit.Value);
                }
            }

            var ascii = BitManipulator.BitsToString(bits);

            Assert.AreEqual(Resources.LoremIpsumTestString, ascii);
        }
示例#2
0
        public AnalysisResult AnalyzeSignal(string testString = null)
        {
            var baudRateIncrementMicroseconds = 1.0 / _settings.BaudRate * Math.Pow(10, 6);
            var windowPositionEndMicroseconds = _audioAnalyzer.FileLengthInMicroseconds;

            var frequencyDifferences    = new List <int>();
            int numberOfZeroFrequencies = 0;

            var analysisFrames = new List <AnalysisFrame>();
            var i = 0;

            for (var currentWindowPositionMicroseconds = 0.0; currentWindowPositionMicroseconds < windowPositionEndMicroseconds; currentWindowPositionMicroseconds += baudRateIncrementMicroseconds)
            {
                // Debug.WriteLine($"Current pos: {currentWindowPositionMicroseconds:N1}, increment: {baudRateIncrementMicroseconds:N1}, end: {windowPositionEndMicroseconds :N1}");

                i++;

                var samplingResult = _audioAnalyzer.GetSamples(currentWindowPositionMicroseconds, currentWindowPositionMicroseconds + baudRateIncrementMicroseconds);

                // TODO: How to set this threshold?
                var targetNumberOfSamples = _audioAnalyzer.SampleRate / Math.Pow(10, 6) * baudRateIncrementMicroseconds;
                var sampleThreshold       = 0.9;
                if (samplingResult.Samples.Count() < (targetNumberOfSamples * sampleThreshold))
                {
                    continue;
                }

                var frequency           = _frequencyDetector.DetectFrequency(samplingResult.Samples);
                var frequencyDifference = FrequencyDifference(frequency, _settings.SpaceFrequency, _settings.MarkFrequency);
                var markOrSpace         = MarkOrSpace(frequency, _settings.SpaceFrequency, _settings.MarkFrequency);

                if (frequency <= 0)
                {
                    numberOfZeroFrequencies++;
                }

                if (frequencyDifference > _settings.FrequencyDeviationTolerance)
                {
                    Debug.WriteLine($"WARN: @ {currentWindowPositionMicroseconds / Math.Pow(10, 6):N3} seconds (Baud rate {_settings.BaudRate}) [{i}] outside of tolerance (frequency {frequency} Hz, difference {frequencyDifference} Hz, tolerance {_settings.FrequencyDeviationTolerance} Hz)");

                    frequencyDifferences.Add(frequencyDifference);
                }

                // Debug.WriteLine($"[{currentWindowStart:N3} us to {currentWindowStart + currentWindowLength:N3} us ({(currentWindowStart + currentWindowLength) - currentWindowStart:N3} us)] {frequency:N0} Hz average (+/- {frequencyDifference:N0} Hz) [Want {_settings.MarkFrequency:N0} Hz / {_settings.SpaceFrequency:N0} Hz] -> bit {bits.Count}: {markOrSpace}");

                analysisFrames.Add(
                    new AnalysisFrame
                {
                    Bit           = (frequency > 0 && frequencyDifference <= _settings.FrequencyDeviationTolerance) ? (markOrSpace == 0 ? false : true) : (bool?)null,
                    Frequency     = frequency,
                    DecodeFailure = frequency > _settings.FrequencyDeviationTolerance ? true : false,
                    DifferenceFromExpectedFrequencies = frequencyDifference,
                    TimeOffsetMicroseconds            = currentWindowPositionMicroseconds
                }
                    );
            }

            var analysisResult = new AnalysisResult
            {
                AnalysisFrames = analysisFrames,
                NumberOfFrequencyDifferences = frequencyDifferences.Count(),
                NumberOfZeroFrequencies      = numberOfZeroFrequencies,
                MinimumFrequencyDifference   = frequencyDifferences.Count() > 0 ? frequencyDifferences.Min() : 0,
                MaximumFrequencyDifference   = frequencyDifferences.Count() > 0 ? frequencyDifferences.Max() : 0,
                AverageFrequencyDifference   = frequencyDifferences.Count() > 0 ? frequencyDifferences.Average() : 0
            };

            bool?  match           = null;
            string resultingString = null;

            if (testString != null)
            {
                var bits = new List <bool>();
                analysisFrames.Where(x => x.Bit.HasValue == true).Select(x => x).ForEach(x => bits.Add(x.Bit.Value));

                resultingString = BitManipulator.BitsToString(bits);
                match           = false;
                if (resultingString == testString)
                {
                    match = true;
                }
            }

            // Debug.WriteLine($"Boost freq.: {_audioAnalyzer.BoostFrequencyAmount} Hz, avg. freq. diff.: {averageFrequencyDifference}, # missed freqs.: {missedFrequencies}");

            AnalysisComplete((int)_settings.BaudRate, _audioAnalyzer.BoostFrequencyAmount, analysisResult, resultingString, match);

            return(analysisResult);
        }