anchor.diff:      open SoundMetrics.Aris.AcousticSettings.AcousticMath
       open SoundMetrics.Data
       open SoundMetrics.Data.Range
  +    open SoundMetrics.Aris.AcousticSettings
   
       let deriveAutoSamplePeriod projection = failwith "nyi"
   
  
positive.code: 
      let private deriveAutoFrequency systemContext
                                      (projection : LegacyAcousticProjection)
                                      : Frequency = // Return proper type for AcousticSettings frequency
  
          let window = deriveWindow systemContext projection
  
          if window.Max > SonarConfig.systemTypeRangeMap.[systemContext.SystemType].UsableRange.LFCrossoverRange then
              Frequency.Low
          else
              Frequency.High
  
negative.code:         { projection with Frequency = frequency }
  
  
      /// Local version of Range.constrainTo that logs when a value is constrained.
      let constrainWithLog<'T when 'T : equality and 'T : comparison>
                      (range : Range<'T>)
                      name
                      (originalValue : 'T) : 'T =
  
          let constrainedValue = originalValue |> Range.constrainTo range
          if constrainedValue <> originalValue then
              Log.Information(
                  "LegacyAcousticProjection: constrained {name}; was {originalValue}; now {constrainedValue}",
                  name, originalValue, constrainedValue)
  
          constrainedValue
  
  
      //-------------------------------------------------------------------------
      // Top-level implementation of the functions necessary for mapping the project.
  
      let constrainProjection (systemContext: SystemContext) (projection: LegacyAcousticProjection) =
  
          let frameRate =
              match projection.FrameRate with
              | MaximumFrameRate -> projection.FrameRate
              | CustomFrameRate fps ->
                  CustomFrameRate (
                      ("FrameRate", fps) ||> constrainWithLog SonarConfig.FrameRateRange)
  
          let sampleCount =
              { projection.SampleCount
                  with SampleCount = ("SampleCount", projection.SampleCount.SampleCount)
                          ||> constrainWithLog SonarConfig.SampleCountRange }
  
          let sampleStartDelay =
              ("SampleStartDelay", projection.SampleStartDelay) ||> constrainWithLog SonarConfig.SampleStartDelayRange
  
          let detail =
              match projection.Detail with
              | AutoSamplePeriod ->  projection.Detail
              | CustomSamplePeriod sp ->
                  CustomSamplePeriod (
                      ("SamplePeriod", sp) ||> constrainWithLog SonarConfig.SamplePeriodRange)
  
          let pulseWidth =
              match projection.PulseWidth with
              | CustomPulseWidth pw ->
                  CustomPulseWidth (
                      ("PulseWidth", pw) ||> constrainWithLog SonarConfig.PulseWidthRange)
              | AutoPulseWidth
              | Narrow
              | Medium
              | Wide -> projection.PulseWidth
  
          let receiverGain =
              ("ReceiverGain", projection.ReceiverGain) ||> constrainWithLog SonarConfig.ReceiverGainRange
  
          {
              projection with
                  FrameRate = frameRate
                  SampleCount = sampleCount
                  SampleStartDelay = sampleStartDelay
                  Detail = detail
                  PulseWidth = pulseWidth
                  ReceiverGain = receiverGain
          }
  
      let applyChange systemContext projection change : LegacyAcousticProjection =
  
  