# `hooks/use-rpn` _(no submodules)_ ## Purpose `useRPN(selector)` wraps the universal RPN reducer and exposes the consolidated `RPNChange` as React state. RPN ("Registered Parameter Number") covers the well-known parameters such as pitch-bend range, fine/coarse tuning, channel pressure sensitivity, and modulation depth. Like NRPN it arrives over the wire as a four-CC dance — CC 101 (param MSB), CC 100 (param LSB), CC 6 (data MSB), CC 38 (data LSB) — and the hook folds that into one React event per dance. ## Features - Folds CC 101/100/6/38 into one `RPNChange` per dance. - Per-port reducer — fresh state on port identity change. - Returns `null` until the first completed dance. ## Usage: Basic ```tsx import { useRPN } from "@suaveplan/react-midi"; function PitchBendRange() { const change = useRPN("first"); // RPN (0,0) is "Pitch Bend Sensitivity". if (!change) return

(no RPN yet)

; return (

RPN ({change.paramHigh}.{change.paramLow}) → {change.value}

); } ``` ## Usage: Advanced ```tsx function useChannelTuning() { const change = useRPN("first"); // RPN (0,1) = fine-tuning; RPN (0,2) = coarse-tuning. return change?.paramHigh === 0 ? change : null; } ``` ## API Reference - `useRPN(selector: string | "first"): RPNChange | null` ## Implementation Notes The hook mirrors `useNRPN` exactly, replacing only the reducer class and the parameter-MSB CC numbers (101 instead of 99). The reducer's data-MSB/LSB CCs (6 and 38) are shared with NRPN — devices follow the convention of sending a fresh paramHigh selector to switch between the two address spaces, which the reducer handles via its "new paramHigh resets partial state" rule. Consumers that need to listen to *both* NRPN and RPN streams from the same port simply compose the two hooks side by side; the underlying input adapter fans the parsed messages out to both subscriptions without double-binding the Web MIDI `onmidimessage` slot.