nx_chord_grade.nx
buildroot/runtime/nx_chord_grade.nx
about
nx_chord_grade.nx -- INSTRUMENT-LEARN-GAME rung LG-4: CHORD-AWARE grading.
Fuses LG-3 polyphony (nx_polypitch) into the play-along grader so a song made
of CHORDS (not just single notes) is scored, with per-note partial credit --
e.g. you nailed 2 of the 3 notes in a chord. A single note is just a chord of
size 1, so this generalizes LG-2.
SONG layout (caller-owned *i64, CG_SLOT=9 words per slot):
[start, dur, n_target, m0, m1, m2, m3, m4, m5] (up to 6 target MIDI notes)
nx_chord_grade(song, n_slots, player, fs, tbl, verdicts) -> score_permille
per slot: detect the played note SET (nx_polypitch), count how many target
notes are present; verdict:
HIT = every target note present AND nothing extra
PARTIAL = some target notes present (but not a clean full match)
WRONG = notes played, none of them a target
MISS = nothing played
score = total target notes correctly played * 1000 / total target notes.
tbl = 128-entry note table from nx_note_table.
license_tier: ORIGINAL
module: nishi-core.audio.chord_grade
depends: nishi-core.audio.polypitch, nishi-core.audio.note
capability: AUDIO_LEARN_GAME_POLY
dependencies 2 imports · 1 importers
imports: nx_syscalls_x86_64.nxnx_polypitch.nx
imported by: nx_chord_grade_gate.nx
structs
| none |
consts
| 27 | const CG_SLOT: i64 = 9 |
| 28 | const CG_HIT: i64 = 0 |
| 29 | const CG_PARTIAL: i64 = 1 |
| 30 | const CG_WRONG: i64 = 2 |
| 31 | const CG_MISS: i64 = 3 |
| 33 | const CG_SKIP: i64 = 256 // skip the chord's attack transient |
| 34 | const CG_N: i64 = 1024 // analysis frame |
| 35 | const CG_MLO: i64 = 40 // E2 |
| 36 | const CG_MHI: i64 = 76 // E5 |
functions
| 38 | func _cg_contains(arr: *i64, n: i64, v: i64) -> i64 called by 1: nx_chord_grade |
| 47 | func nx_chord_grade(song: *i64, n_slots: i64, player: *u8, fs: i64, |