decode

fun decode(packet: ByteArray, config: DeviceConfig, state: DecodeState, contactOut: (BooleanArray) -> Unit? = null, hardware: DeviceHardware = DeviceHardware.legacyDefault(config.model), digitalInput: Boolean = false, out: (EegFrame) -> Unit): Boolean

Decode one stream packet into typed EegFrames, advancing state. hardware decides the footer layout (accelerometer / gyroscope blocks present or not); it defaults to the V2 board of the config's model, which is every device without a readable Model Number. Returns true on success, false if the packet was malformed. See decodeRaw for the positional output.

EegFrame.sampleIndex is exact for every value of the device's 32-bit counter: it never passes through the positional FloatArray, whose Float index column is exact only up to 2^24 (2.3 h at 2 kHz, 18.6 h at 250 Hz).

digitalInput says the stream was started with the stream option of that name (firmware 3.8.1+): every packet then ends with [ceil(n/8) bytes: bit i%8 of byte i/8 = the input at the packet's sample i][u8 n], after the sampleSize byte that ends the packet without it (n = the packet's samples, sample 0 the uncompressed one). The block is stripped before decoding, so the rest decodes exactly as without it, and the bits land on EegFrame.digitalInput: bit k on the k-th sample the packet carried, none on gap-fill dummies. A packet too short for its own block returns false and decodes nothing. Leave it false for a stream that did not ask for the option: its packets carry no block.

A config with no active channel returns false: its packets cannot say how many samples they span.