nx_actor_role_audio_grader_test.nx source
↩ module page · 115 lines · 4717 B
1// nx_actor_role_audio_grader_test.nx -- smoke for nx_actor_role_audio_grader.
2
3import "nx_syscalls.nx"
4import "nx_tier.nx"
5import "nx_actor.nx"
6import "nx_message.nx"
7import "nx_actor_role_audio_grader.nx"
8
9func main() -> i64 {
10 let now: nx_size = 1000000
11
12 // 1: enum validity
13 if nx_ag_phase_is_valid(NX_AG_PHASE_INIT) != 1 { return 1 }
14 if nx_ag_phase_is_valid(NX_AG_PHASE_DONE) != 1 { return 2 }
15 if nx_ag_phase_is_valid(-1) != 0 { return 3 }
16 if nx_ag_phase_is_valid(4) != 0 { return 4 }
17 if NX_AG_PHASE_N != 4 { return 5 }
18
19 if nx_ag_v_is_valid(NX_AG_V_STEPPED) != 1 { return 6 }
20 if nx_ag_v_is_valid(NX_AG_V_NULL) != 1 { return 7 }
21
22 // 2: build synthetic 8-bin spectrum (balanced moderate stddev) +
23 // 16-frame rms with variance (good dynamic range) + 4 sources
24 let bins_buf: *u8 = sys_mmap(8 * 8)
25 let bins: *i64 = bins_buf as *i64
26 bins[0] = 6000
27 bins[1] = 8000
28 bins[2] = 9000
29 bins[3] = 10000
30 bins[4] = 9500
31 bins[5] = 8500
32 bins[6] = 7000
33 bins[7] = 5500
34
35 let rms_buf: *u8 = sys_mmap(16 * 8)
36 let rms: *i64 = rms_buf as *i64
37 var i: nx_int = 0
38 while i < 16 {
39 rms[i] = 2000 + ((i * 200) as i64) // gentle ramp 2000..5000
40 i = i + 1
41 }
42
43 // 3: construct ctx
44 let ctx: *NxAudioGraderCtx = nx_ag_actor_new(bins, 8, rms, 16, 4)
45 if (ctx as i64) == 0 { return 8 }
46 if ctx.n_bins != 8 { return 9 }
47 if ctx.n_frames != 16 { return 10 }
48 if ctx.n_sources != 4 { return 11 }
49 if ctx.current_phase != NX_AG_PHASE_INIT { return 12 }
50 if ctx.overall_score_q14 != 0 { return 13 }
51
52 // 4: invalid construction
53 if nx_ag_actor_new(bins, 0, rms, 16, 4) != (0 as *NxAudioGraderCtx) { return 14 }
54 if nx_ag_actor_new(bins, 8, rms, 0, 4) != (0 as *NxAudioGraderCtx) { return 15 }
55 if nx_ag_actor_new(bins, 8, rms, 16, -1) != (0 as *NxAudioGraderCtx) { return 16 }
56
57 let null_bins: *i64 = (0 as i64) as *i64
58 if nx_ag_actor_new(null_bins, 8, rms, 16, 4) != (0 as *NxAudioGraderCtx) { return 17 }
59
60 // 5: scheduler + bus
61 let sched: *NxActorScheduler = nx_ac_sched_new(4, 1000000, 4, now)
62 nx_ac_spawn(sched, 6001, 4, 70, 0, now)
63 let bus: *NxMessageBus = nx_ms_bus_new(4, 4, 8)
64 nx_ms_register(bus, 6001)
65 nx_ms_register(bus, 6002)
66 nx_ms_subscribe(bus, 6002, NX_MS_KIND_AUDIO_FRAME)
67
68 // 6: phase progression -- INIT -> GRADE -> EMIT -> DONE (3 steps total)
69 if nx_ag_actor_step(ctx, sched, bus, 6001, now + 100) != NX_AG_V_STEPPED { return 18 }
70 if ctx.current_phase != NX_AG_PHASE_GRADE { return 19 }
71
72 if nx_ag_actor_step(ctx, sched, bus, 6001, now + 200) != NX_AG_V_STEPPED { return 20 }
73 if ctx.current_phase != NX_AG_PHASE_EMIT { return 21 }
74 // After GRADE, overall_score_q14 should be non-zero positive (we built a healthy scene)
75 if nx_ag_actor_score_q14(ctx) <= 0 { return 22 }
76
77 // Individual axes should be in [0, NX_AQ_Q] (Q14 = 16384)
78 if nx_ag_actor_axis_q14(ctx, NX_AQ_AXIS_FREQ_BALANCE) < 0 { return 23 }
79 if nx_ag_actor_axis_q14(ctx, NX_AQ_AXIS_DYNAMIC_RANGE) < 0 { return 24 }
80 if nx_ag_actor_axis_q14(ctx, NX_AQ_AXIS_SOURCE_DIVERSITY) <= 0 { return 25 }
81 // axis out of range returns 0
82 if nx_ag_actor_axis_q14(ctx, -1) != 0 { return 26 }
83 if nx_ag_actor_axis_q14(ctx, NX_AQ_AXIS_COUNT) != 0 { return 27 }
84
85 // 7: EMIT pushes message + completes
86 if nx_ag_actor_step(ctx, sched, bus, 6001, now + 300) != NX_AG_V_COMPLETED { return 28 }
87 if ctx.current_phase != NX_AG_PHASE_DONE { return 29 }
88 if nx_ag_actor_is_done(ctx) != 1 { return 30 }
89
90 // Listener mailbox received AUDIO_FRAME
91 if nx_ms_pending(bus, 6002) != 1 { return 31 }
92 let m: *NxMessage = nx_ms_receive(bus, 6002)
93 if m.kind != NX_MS_KIND_AUDIO_FRAME { return 32 }
94 if m.sender_actor_id != 6001 { return 33 }
95 // payload = overall score
96 if (m.payload_handle as nx_int) != nx_ag_actor_score_q14(ctx) { return 34 }
97
98 // 8: scheduler marks COMPLETED
99 let a: *NxActor = nx_ac_find(sched, 6001)
100 if a.state != NX_AC_STATE_COMPLETED { return 35 }
101
102 // 9: idempotent stepping past DONE
103 if nx_ag_actor_step(ctx, sched, bus, 6001, now + 400) != NX_AG_V_COMPLETED { return 36 }
104 if nx_ms_pending(bus, 6002) != 0 { return 37 }
105
106 // 10: null guards
107 let null_ctx: *NxAudioGraderCtx = (0 as i64) as *NxAudioGraderCtx
108 if nx_ag_actor_step(null_ctx, sched, bus, 6001, now) != NX_AG_V_NULL { return 38 }
109 if nx_ag_actor_phase(null_ctx) != NX_AG_PHASE_DONE { return 39 }
110 if nx_ag_actor_score_q14(null_ctx) != 0 { return 40 }
111 if nx_ag_actor_is_done(null_ctx) != 0 { return 41 }
112 if nx_ag_actor_axis_q14(null_ctx, NX_AQ_AXIS_FREQ_BALANCE) != 0 { return 42 }
113
114 return 0
115}