feat(waveform): generalize high-res compute to every track (Direction B)
Per-track high-res datum keyed by EntryKey in the renamed track-waveforms vault; computed at upload for all tracks, regenerable per-track via CMS, with a re-runnable backfill. Mix read path repointed so it keeps working.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
using DeepDrftContent.Processors;
|
||||
|
||||
namespace DeepDrftTests;
|
||||
|
||||
/// <summary>
|
||||
/// Behavioral tests for the duration-derived high-res bucket-count derivation. The contract: capture at
|
||||
/// a constant time resolution (≈333 samples/sec) so a 333 ms max-zoom window holds enough samples on any
|
||||
/// track length, clamped to a sane floor (short/degenerate tracks) and an upper cap (extreme outliers).
|
||||
/// Applies to every track (Mix, Session, Cut) under the per-track model — phase-12 §5.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class WaveformResolutionTests
|
||||
{
|
||||
[Test]
|
||||
public void BucketCountForDuration_TypicalTrack_CapturesAtTargetDensity()
|
||||
{
|
||||
// 3 minutes × 333/s = 59,940 — a typical short track, comfortably inside [floor, cap].
|
||||
var buckets = WaveformResolution.BucketCountForDuration(180.0);
|
||||
|
||||
Assert.That(buckets, Is.EqualTo((int)Math.Ceiling(180.0 * WaveformResolution.SamplesPerSecond)));
|
||||
Assert.That(buckets, Is.EqualTo(59_940));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BucketCountForDuration_SixtyMinuteTrack_ProducesAboutOnePointTwoMillion()
|
||||
{
|
||||
// 60 min × 333/s = 1,198,800 ≈ 1.2M samples (≈1.2 MB datum), still under the cap.
|
||||
var buckets = WaveformResolution.BucketCountForDuration(3600.0);
|
||||
|
||||
Assert.That(buckets, Is.EqualTo(1_198_800));
|
||||
Assert.That(buckets, Is.LessThan(WaveformResolution.MaxBucketCount));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BucketCountForDuration_OverHundredMinutes_ClampsToCap()
|
||||
{
|
||||
// 120 min × 333/s = 2,397,600 > cap → clamps to the cap.
|
||||
var buckets = WaveformResolution.BucketCountForDuration(7200.0);
|
||||
|
||||
Assert.That(buckets, Is.EqualTo(WaveformResolution.MaxBucketCount));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BucketCountForDuration_NearZeroDuration_HitsFloor()
|
||||
{
|
||||
// 0.1 s × 333/s = 34 buckets, far below the floor → clamps up to the floor.
|
||||
var buckets = WaveformResolution.BucketCountForDuration(0.1);
|
||||
|
||||
Assert.That(buckets, Is.EqualTo(WaveformResolution.MinBucketCount));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BucketCountForDuration_ZeroDuration_HitsFloor()
|
||||
{
|
||||
Assert.That(WaveformResolution.BucketCountForDuration(0.0), Is.EqualTo(WaveformResolution.MinBucketCount));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BucketCountForDuration_NegativeOrNaN_HitsFloor()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(WaveformResolution.BucketCountForDuration(-5.0), Is.EqualTo(WaveformResolution.MinBucketCount));
|
||||
Assert.That(WaveformResolution.BucketCountForDuration(double.NaN), Is.EqualTo(WaveformResolution.MinBucketCount));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BucketCountForDuration_DurationAtFloorBoundary_ReturnsFloorThenGrows()
|
||||
{
|
||||
// floor / 333 = 6.15 s is the duration where the derived count meets the floor exactly.
|
||||
const double floorBoundarySeconds = (double)WaveformResolution.MinBucketCount / WaveformResolution.SamplesPerSecond;
|
||||
|
||||
// Just below the boundary clamps to the floor; just above derives above the floor.
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(WaveformResolution.BucketCountForDuration(floorBoundarySeconds - 0.1), Is.EqualTo(WaveformResolution.MinBucketCount));
|
||||
Assert.That(WaveformResolution.BucketCountForDuration(floorBoundarySeconds + 1.0), Is.GreaterThan(WaveformResolution.MinBucketCount));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BucketCountForDuration_DurationAtCapBoundary_ReturnsCap()
|
||||
{
|
||||
// cap / 333 = 6006.006 s is the duration where the derived count meets the cap exactly.
|
||||
const double capBoundarySeconds = (double)WaveformResolution.MaxBucketCount / WaveformResolution.SamplesPerSecond;
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(WaveformResolution.BucketCountForDuration(capBoundarySeconds + 1.0), Is.EqualTo(WaveformResolution.MaxBucketCount));
|
||||
Assert.That(WaveformResolution.BucketCountForDuration(capBoundarySeconds - 10.0), Is.LessThan(WaveformResolution.MaxBucketCount));
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user