Newer
Older
TIASShot / TIASshot / Cameras / GainCalc.cs
namespace TIASshot {
    /// <summary>
    /// ゲイン更新比率の計算ロジック(ピュアロジック層).
    /// ハードウェアに依存しない純粋な計算のみを担う.
    /// </summary>
    internal static class GainCalc {
        /// <summary>
        /// ゲイン値の更新比率を計算する.
        /// value が 255.0f のときは updateRate によらず係数を 1.0 として比率を求める.
        /// </summary>
        /// <param name="value">現在の計測値</param>
        /// <param name="target">目標値</param>
        /// <param name="updateRate">更新レート(0 より大きい値を想定)</param>
        /// <returns>更新比率</returns>
        internal static float CalcRatio(float value, float target, float updateRate) {
            float ratio = target / value;
            ratio = (ratio - 1.0f) * (value == 255.0f ? 1.0f : updateRate) + 1.0f;
            return ratio;
        }

        /// <summary>
        /// 現在のゲイン値に更新比率を掛けた新しいゲイン設定値を求める.
        /// ハードウェアが受け付ける範囲 [rangeMin, rangeMax] に収めて返す.
        /// </summary>
        /// <param name="currentValue">現在のゲイン設定値</param>
        /// <param name="ratio">更新比率(<see cref="CalcRatio"/> の戻り値)</param>
        /// <param name="rangeMin">設定可能な最小値</param>
        /// <param name="rangeMax">設定可能な最大値</param>
        /// <returns>範囲内に収めた新しいゲイン設定値</returns>
        internal static int CalcGainValue(int currentValue, float ratio, int rangeMin, int rangeMax) {
            // 計測値・目標値がともに 0 のとき比率は NaN になり更新量を決められないため現在値を維持する
            if (float.IsNaN(ratio)) return currentValue;

            // float→int キャストは範囲外・非有限値(Infinity)で未定義値になるため,
            // キャスト前に double のまま範囲判定する
            double value = 0.5 + (double)(currentValue * ratio);
            if (value < rangeMin) return rangeMin;
            if (value > rangeMax) return rangeMax;
            return (int)value;
        }
    }
}