code wiki / (root) / nx_actor_role_audio_grader_test.nx

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}