nx_timeline.nx source
↩ module page · 56 lines · 2215 B
1// nx_timeline.nx -- editor timeline assembler (R4b): turn a clip list + per-gap
2// transition windows into a single output frame SCHEDULE. Crossfade-overlap
3// model (standard NLE): between clip k and k+1, the last W frames of k overlap-
4// blend with the first W frames of k+1, so total = sum(len) - sum(window).
5// W=0 = hard cut. This is the stitch logic ("put recordings together with
6// smooth transitions"); it composes nx_transition for the actual pixels.
7//
8// Output: one record per output frame, 6 i64:
9// [mode, srcA, frmA, srcB, frmB, progress_q14]
10// mode 0 = straight (show clip srcA frame frmA)
11// mode 1 = blend (crossfade srcA/frmA with srcB/frmB at progress_q14)
12// Pure integer scheduling -- no pixels -> exactly gateable.
13//
14// genealogy_id: nle_crossfade_overlap_edit + edit_decision_list
15// lineage_id: clip_schedule + overlap_transition_window
16// license_tier: ORIGINAL
17import "nx_syscalls.nx"
18
19const NX_TL_REC: i64 = 6
20
21func nx_timeline_plan(lens: *i64, nclips: i64, wins: *i64, q: i64, recs: *i64, maxr: i64) -> i64 {
22 var n: i64 = 0
23 var k: i64 = 0
24 while k < nclips {
25 let lk: i64 = lens[k]
26 var win_in: i64 = 0
27 if k > 0 { win_in = wins[k - 1] }
28 var win_out: i64 = 0
29 if k < nclips - 1 { win_out = wins[k] }
30 // straight frames of clip k: [win_in, lk - win_out)
31 var f: i64 = win_in
32 while f < lk - win_out {
33 if n < maxr {
34 recs[n * 6 + 0] = 0; recs[n * 6 + 1] = k; recs[n * 6 + 2] = f
35 recs[n * 6 + 3] = 0; recs[n * 6 + 4] = 0; recs[n * 6 + 5] = 0
36 n = n + 1
37 }
38 f = f + 1
39 }
40 // transition out of clip k into k+1
41 if win_out > 0 {
42 var t: i64 = 0
43 while t < win_out {
44 let prog: i64 = (t + 1) * q / (win_out + 1)
45 if n < maxr {
46 recs[n * 6 + 0] = 1; recs[n * 6 + 1] = k; recs[n * 6 + 2] = lk - win_out + t
47 recs[n * 6 + 3] = k + 1; recs[n * 6 + 4] = t; recs[n * 6 + 5] = prog
48 n = n + 1
49 }
50 t = t + 1
51 }
52 }
53 k = k + 1
54 }
55 return n
56}