diff --git a/Tagging/Sig.cs b/Tagging/Sig.cs index e273b1c..ddead55 100644 --- a/Tagging/Sig.cs +++ b/Tagging/Sig.cs @@ -136,9 +136,17 @@ public static void Read(byte[] data, out int sampleRate, out int sampleCount, ou writableBands[i] = new(); while(mem.Position < mem.Length) { - var bandIndex = reader.ReadInt32() - 0x60030040; - if(bandIndex < 0 || bandIndex > 3) - throw new InvalidOperationException(); + var fat = false; + var bandIndex = 0; + var header = reader.ReadInt32(); + + if(header == 0x60023e80) { + fat = true; + } else { + bandIndex = header - 0x60030040; + if(bandIndex < 0 || bandIndex > 3) + throw new InvalidOperationException(); + } var len = reader.ReadInt32(); var end = mem.Position + len; @@ -146,15 +154,27 @@ public static void Read(byte[] data, out int sampleRate, out int sampleCount, ou while(mem.Position < end) { if(end - mem.Position >= 5) { - var x = reader.ReadByte(); - if(x == 255) { + if(fat) { stripe = reader.ReadInt32(); - x = reader.ReadByte(); + } else { + var x = reader.ReadByte(); + if(x == 255) { + stripe = reader.ReadInt32(); + x = reader.ReadByte(); + } + stripe += x; + } + + var word1 = reader.ReadUInt16(); + var word2 = reader.ReadUInt16(); + + if(fat) { + mem.Position += 4; + (word1, word2) = (word2, word1); } - stripe += x; - var magn = reader.ReadUInt16(); - var bin = reader.ReadUInt16() / 64; + var magn = word1; + var bin = word2 / 64; if(bin == 0 || magn == 0) throw new InvalidOperationException(); @@ -228,6 +248,7 @@ static int GetSampleRateCode(int sampleRate) { } static int SampleRateFromCode(int code) { + code &= 0xf; return code switch { 1 => 8000, 3 => 16000, diff --git a/Test/PeakDensityResearch.cs b/Test/PeakDensityResearch.cs index bbe20eb..5611958 100644 --- a/Test/PeakDensityResearch.cs +++ b/Test/PeakDensityResearch.cs @@ -18,8 +18,22 @@ public PeakDensityResearch(ITestOutputHelper output) { } [Fact] - public void Run() { - LoadPeakMap(out var bandedPeakRates); + public void Normal() { + Run("gabin-full-sigx-10.1.3.bin"); + } + + [Fact] + public void Fat() { + // Generated using libsigx.so from Android app v7.11 + // SigType.SINGLE_FILE, SigOptions.FAT + // 'Fat' signature, presumably, contains raw peaks + // - before bin interpolation + // - before rate limit + Run("gabin-60s-sigx-5.1.0-fat.bin"); + } + + void Run(string fileName) { + LoadPeakMap(fileName, out var bandedPeakRates); for(var i = 0; i < bandedPeakRates.Count; i++) Output.WriteLine($"Band {i} peak rate {bandedPeakRates[i]:0.#} peak/sec"); @@ -70,8 +84,8 @@ public void Run() { Output.WriteLine($"{bin}\t{stripe}"); } - void LoadPeakMap(out IReadOnlyList bandedRates) { - var path = Path.Combine(TestHelper.DATA_DIR, "gabin-full-sigx-10.1.3.bin"); + void LoadPeakMap(string fileName, out IReadOnlyList bandedRates) { + var path = Path.Combine(TestHelper.DATA_DIR, fileName); Sig.Read( File.ReadAllBytes(path), diff --git a/TestData/gabin-60s-sigx-5.1.0-fat.bin b/TestData/gabin-60s-sigx-5.1.0-fat.bin new file mode 100644 index 0000000..48b1c9b Binary files /dev/null and b/TestData/gabin-60s-sigx-5.1.0-fat.bin differ