示例#1
0
        public async void WillBackupIfRequested()
        {
            var backupPath = this.target.Path + ".bak";
            var dryRun     = new DryRun(false, this.dryRunLogger);

            var before = await this.fileUtilities.CalculateChecksum(this.target.Path, HashAlgorithmName.SHA256);

            await this.AssertMetadata(BeforeFixSamples, FirmwareVersion);

            var actual = await this.fixer.ProcessFileAsync(this.target.Path, dryRun, true);

            Assert.Equal(FixStatus.Fixed, actual.Status);
            Assert.Contains($"Old total samples was", actual.Message);

            // modified file
            await this.AssertMetadata(AfterFixSamples, FirmwareVersion, PatchedTag);

            // backup
            using (var stream = (FileStream)this.fileSystem.File.OpenRead(backupPath))
            {
                var actualSamples  = (ulong)Flac.ReadTotalSamples(stream);
                var actualFirmware = (FirmwareRecord) await ReadFirmwareAsync(stream);

                Assert.Equal(BeforeFixSamples, actualSamples);
                Assert.Equal(FirmwareVersion, actualFirmware.Version);

                actualFirmware.Tags.Should().BeEquivalentTo(Array.Empty <string>());
            }

            var after = await this.fileUtilities.CalculateChecksum(backupPath, HashAlgorithmName.SHA256);

            // the backup file has the same hash as the original
            Assert.Equal(before, after);
        }
示例#2
0
 public void ReadBitDepthTest(FixtureModel model)
 {
     if (model.Process.ContainsKey(FixtureModel.FlacHeaderExtractor))
     {
         Fin <byte> bitDepth = Flac.ReadBitDepth(model.ToTargetInformation(this.RealFileSystem).FileStream);
         Assert.True(bitDepth.IsSucc);
         ((byte)bitDepth).Should().Be(model.Record.BitDepth);
     }
 }
示例#3
0
 public void ReadNumChannelsTest(FixtureModel model)
 {
     if (model.Process.ContainsKey(FixtureModel.FlacHeaderExtractor))
     {
         Fin <byte> channels = Flac.ReadNumChannels(model.ToTargetInformation(this.RealFileSystem).FileStream);
         Assert.True(channels.IsSucc);
         ((byte)channels).Should().Be((byte)model.Record.Channels);
     }
 }
示例#4
0
 public void ReadSampleRateTest(FixtureModel model)
 {
     if (model.Process.ContainsKey(FixtureModel.FlacHeaderExtractor))
     {
         Fin <uint> sampleRate = Flac.ReadSampleRate(model.ToTargetInformation(this.RealFileSystem).FileStream);
         Assert.True(sampleRate.IsSucc);
         ((uint)sampleRate).Should().Be(model.Record.SampleRateHertz);
     }
 }
示例#5
0
 public void ReadTotalSamplesTest(FixtureModel model)
 {
     if (model.Process.ContainsKey(FixtureModel.FlacHeaderExtractor))
     {
         Fin <ulong> totalSamples = Flac.ReadTotalSamples(model.ToTargetInformation(this.RealFileSystem).FileStream);
         Assert.True(totalSamples.IsSucc);
         ((ulong)totalSamples).Should().Be(model.Record.TotalSamples);
     }
 }
示例#6
0
        private async Task AssertMetadata(ulong samples, decimal firmwareVersion, params string[] tags)
        {
            using var stream = (FileStream) this.fileSystem.File.OpenRead(this.target.Path);
            var actualSamples  = (ulong)Flac.ReadTotalSamples(stream);
            var actualFirmware = (FirmwareRecord) await ReadFirmwareAsync(stream);

            Assert.Equal(samples, actualSamples);
            Assert.Equal(firmwareVersion, actualFirmware.Version);

            actualFirmware.Tags.Should().BeEquivalentTo(tags);
        }
示例#7
0
        public static async ValueTask <Fin <FirmwareRecord> > ReadFirmwareAsync(FileStream stream)
        {
            var vorbisChunk = Flac.ScanForChunk(stream, Flac.VorbisCommentBlockNumber);

            if (vorbisChunk.IsFail)
            {
                return((Error)vorbisChunk);
            }

            var vorbisSpan = await RangeHelper.ReadRangeAsync(stream, (RangeHelper.Range) vorbisChunk);

            // find the frontier labs vorbis vendor comment
            return(FindInBufferFirmware(vorbisSpan, ((RangeHelper.Range)vorbisChunk).Start));
        }
示例#8
0
        public ValueTask <Recording> ProcessFileAsync(TargetInformation information, Recording recording)
        {
            var samples    = Flac.ReadTotalSamples(information.FileStream);
            var sampleRate = Flac.ReadSampleRate(information.FileStream);
            var channels   = Flac.ReadNumChannels(information.FileStream);
            var bitDepth   = Flac.ReadBitDepth(information.FileStream);

            Rational?duration = samples.IsFail || sampleRate.IsFail || (uint)sampleRate == 0 ? null : (new Rational((ulong)samples) / new Rational((uint)sampleRate));
            uint?    bitRate  = sampleRate.IsFail || bitDepth.IsFail || channels.IsFail ? null : (uint)sampleRate * (uint)bitDepth * (uint)channels;

            recording = recording with
            {
                DurationSeconds = recording.DurationSeconds ?? duration,
                SampleRateHertz = recording.SampleRateHertz ?? (sampleRate.IsFail ? null : (uint)sampleRate),
                TotalSamples    = recording.TotalSamples ?? (samples.IsFail ? null : (ulong)samples),
                Channels        = recording.Channels ?? (channels.IsFail ? null : (byte)channels),
                BitDepth        = recording.BitDepth ?? (bitDepth.IsFail ? null : (byte)bitDepth),
                BitsPerSecond   = recording.BitsPerSecond ?? bitRate,
            };

            return(ValueTask.FromResult(recording));
        }
示例#9
0
        public void HasMetadataBlockTest(FixtureModel model)
        {
            bool hasMetadata = Flac.HasMetadataBlock(model.ToTargetInformation(this.RealFileSystem).FileStream).IfFail(false);

            ((bool)hasMetadata).Should().Be(model.IsFlac && model.ValidMetadata != ValidMetadata.No);
        }
示例#10
0
        public void IsFlacFileTest(FixtureModel model)
        {
            bool isFlac = Flac.IsFlacFile(model.ToTargetInformation(this.RealFileSystem).FileStream).IfFail(false);

            isFlac.Should().Be(model.IsFlac);
        }
        public ValueTask <Recording> ProcessFileAsync(TargetInformation information, Recording recording)
        {
            var tryComments = Flac.ExtractComments(information.FileStream);

            if (tryComments.IsSucc)
            {
                Dictionary <string, string> comments = (Dictionary <string, string>)tryComments;

                Dictionary <string, double> location = (Dictionary <string, double>) this.ParseComment(FrontierLabs.LocationCommentKey, comments);
                Dictionary <string, object> sdCid    = (Dictionary <string, object>) this.ParseComment(FrontierLabs.SdCidCommentKey, comments);

                List <Microphone> microphones = new List <Microphone>();
                int micNumber = 1;

                // Extract all microphone information
                while (comments.ContainsKey(FrontierLabs.MicrophoneTypeCommentKey + micNumber))
                {
                    // FL uses channel A, B to refer to microphones 1 and 2 respectively
                    // Converts to channel name using ASCII value offset of 64
                    string channelName = ((char)(micNumber + 64)).ToString();

                    Microphone microphone = new Microphone() with
                    {
                        Type        = (string)this.ParseComment(FrontierLabs.MicrophoneTypeCommentKey + micNumber, comments),
                        UID         = (string)this.ParseComment(FrontierLabs.MicrophoneUIDCommentKey + micNumber, comments),
                        BuildDate   = (LocalDate?)this.ParseComment(FrontierLabs.MicrophoneBuildDateCommentKey + micNumber, comments),
                        Gain        = (double?)this.ParseComment(FrontierLabs.MicrophoneGainCommentKey + micNumber, comments),
                        Channel     = micNumber,
                        ChannelName = channelName,
                    };

                    if (microphone.Type != null)
                    {
                        microphones.Add(microphone);
                    }

                    micNumber++;
                }

                // Extract battery related values
                // Two batter values are extracted from the same comment as a tuple
                var    batteryValues = ((double?, double?)?) this.ParseComment(FrontierLabs.BatteryLevelCommentKey, comments);
                double?batteryLevel = null, voltage = null;

                if (batteryValues != null)
                {
                    batteryLevel = batteryValues?.Item1;

                    batteryLevel = batteryLevel == null ? null : batteryLevel / 100;

                    voltage = batteryValues?.Item2;
                }

                // Update recording information with parsed comments
                recording = recording with
                {
                    Sensor = (recording.Sensor ?? new Sensor()) with
                    {
                        Firmware     = recording.Sensor?.Firmware ?? (string)this.ParseComment(FrontierLabs.FirmwareCommentKey, comments),
                        BatteryLevel = recording.Sensor?.BatteryLevel ?? batteryLevel,
                        Voltage      = recording.Sensor?.Voltage ?? voltage,
                        LastTimeSync = recording.Sensor?.LastTimeSync ?? (OffsetDateTime?)this.ParseComment(FrontierLabs.LastSyncCommentKey, comments),
                        SerialNumber = recording.Sensor?.SerialNumber ?? (string)this.ParseComment(FrontierLabs.SensorIdCommentKey, comments),
                        Microphones  = recording.Sensor?.Microphones ?? new Microphone[microphones.Length()],
                    },