// trigger_seam — converts Trigger fade lengths between the engine domain (TriggerParams:
// SOURCE FRAMES, anchored to the source-timeline read pointer) and the overlay domain
// (AmpEnvelope: FRACTIONS in [0,1] of the played span, so the drawn shape stays invariant
// across sample-rate changes). Owns the one shared pack/unpack formula so both directions
// stay consistent; reasampler_editor calls these from packEnvelope/unpackEnvelope.
//
// playLengthFrames = round(lengthFraction * (frameCount - startFrame))

#pragma once

#include <cstdint>

namespace reasampler::instrument::map {

// postStart = max(0, frameCount - startFrame); playLength = round(lengthFraction * postStart).
// `startFrame` is the effective start point (0 when absent). Returns 0 when postStart == 0
// or lengthFraction <= 0.
std::int64_t triggerPlayLength(double lengthFraction,
                               std::int64_t frameCount,
                               std::int64_t startFrame);

// PACK direction (draw path): frames -> fraction of play span. Not clamped here — the
// caller clamps to [0,1] when filling AmpEnvelope (envelope_edit owns that logic).
double framesToFadeFraction(std::int64_t fadeFrames, std::int64_t playLength);

// UNPACK direction (commit path): fraction -> nearest source frame.
std::int64_t fadeFractionToFrames(double fadeFraction, std::int64_t playLength);

}  // namespace reasampler::instrument::map
