From ea2b7879e9a8357aed4a91458e95acac9b18dd0c Mon Sep 17 00:00:00 2001 From: Christian Schwinne Date: Mon, 3 Nov 2025 21:50:58 +0100 Subject: [PATCH 1/9] Define visualizer support object and binary data types Updated the visualizer support object structure and binary type details. --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ad741b4..07408a6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + # The Resonate Protocol _This is raw, unfiltered and experimental._ @@ -546,30 +547,64 @@ This section describes messages specific to clients with the `visualizer` role, The `visualizer_support` object in [`client/hello`](#client--server-clienthello) has this structure: -- `visualizer_support`: object - - Desired FFT details (to be determined) - - `buffer_capacity`: integer - max size in bytes of visualization data messages in the buffer that are yet to be displayed +- `visualizer_support`: object containing the desired FFT details: + + +```json +{ + "visualizer_support": { + "types": [2,3,4], + "buffer_capacity": 2048, + "spectrum": { + "n_disp_bins": 16, + "scale": "log", + "f_min": 20, + "f_max": 20000, + "rate_max": 60 + } + } +} +``` +, where: +`types`: The Visualization Data Types supported/requested by the client. Server may ignore any types it doesn't support. See type definition in binary definition table below. +`n_disp_bins`: Number of display bins (i.e. bars on a graphical equalizer) +`scale`: One of `mel`, `log` (logarithmic), or `lin` (linear). Controls the mapping from FFT to display bins. +`f_min`: The minimum frequency where the lowest display band should start (reasonable default 20-40 Hz) +`f_max`: The maximum frequency where the highest display band should end (reasonable default ~16-22 kHz) +`rate_max`: The maximum number of spectrum updates per second. (this is somewhat constrained by n_fft - this is just a maximum so that e.g. clients with a max. display refresh rate of 60 Hz don't receive e.g. 300 messages/second) ### Server → Client: `stream/start` visualizer object The `visualizer` object in [`stream/start`](#server--client-streamstart) has this structure: - `visualizer`: object - - FFT details (to be determined) + - FFT details of actually streamed data (see above) ### Server → Client: `stream/update` visualizer object The `visualizer` object in [`stream/update`](#server--client-streamupdate) has this structure with delta updates: - `visualizer`: object - - FFT details (to be determined) + - FFT details of actually streamed data (see above) ### Server → Client: Visualization Data (Binary) Binary messages should be rejected if there is no active stream. - Byte 0: message type `8` (uint8) -- Bytes 1-8: timestamp (big-endian int64) - server clock time in microseconds when the visualization should be displayed by the device -- Rest of bytes: visualization data +- Bytes 1-8: timestamp (big-endian int64) - server clock time in microseconds when the visualization should be displayed by the device, corresponding to the audio timeline. Clients must translate this server timestamp to their local clock using the offset computed from clock synchronization. +- Rest of bytes: Visualizer binary data, uses a tag-value encoding. The following types are currently defined: + +| Type byte | Type name | Data type + length (bytes) | Unit | +|---|---|---|---| +|`0`| Reserved | - (0) +|`1`| Beat detected at this timestamp | - (0) +|`2`| Amplitude/Loudness | `uint16` (2) | % of peak?, logarithmically adj. to human hearing +|`3`| Frequency with highest amplitude | `uint16` (2) | Hz +|`4`| Spectrum / FFT | `byte` + `uint16[n]` (1 + 2*n) | First data byte number of display bins `n`, followed by `n`display bins from low to high freq., each an `uint16` + +Multiple data types may be appended in a single message, if they have the same timestamp. +For example, the message `08 <8 timestamp bytes> 02 7F FF 03 04 00` both specifies the amplitude (~50% of peak) and the peak frequency (1024 Hz). + + -The timestamp indicates when this visualization data should be displayed, corresponding to the audio timeline. Clients must translate this server timestamp to their local clock using the offset computed from clock synchronization. From a2b9081e0850b6483a06ce26ca0bdd69e4140332 Mon Sep 17 00:00:00 2001 From: Christian Schwinne Date: Mon, 3 Nov 2025 21:54:42 +0100 Subject: [PATCH 2/9] rm stray newline --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 07408a6..d648c0c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - # The Resonate Protocol _This is raw, unfiltered and experimental._ From 6b04ee0d4f1e4a07b135c9486c40b3c7a298dbe2 Mon Sep 17 00:00:00 2001 From: Christian Schwinne Date: Sun, 23 Nov 2025 19:31:51 +0100 Subject: [PATCH 3/9] Separate binary message for beat String types (tentative) fixed binary format, no tag bytes --- README.md | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 759aff5..56c9653 100644 --- a/README.md +++ b/README.md @@ -630,8 +630,9 @@ The `visualizer_support` object in [`client/hello`](#client--server-clienthello) ```json { "visualizer_support": { - "types": [2,3,4], + "types": ["loudness","spectrum","beat"], "buffer_capacity": 2048, + "batch_max": 32, "spectrum": { "n_disp_bins": 16, "scale": "log", @@ -643,7 +644,9 @@ The `visualizer_support` object in [`client/hello`](#client--server-clienthello) } ``` , where: -`types`: The Visualization Data Types supported/requested by the client. Server may ignore any types it doesn't support. See type definition in binary definition table below. +`types`: The Visualization Data Types supported/requested by the client. Server may ignore any types it doesn't support. See type definition in binary definition table below. Currently defined: `beat`, `loudness`, `f_peak`, and `spectrum`. +`buffer_capacity`: The maximum size in bytes of visualization messages that the client is able to buffer. +`batch_max`: The maximum number of logical messages with separate timestamps the server may batch into WebSockets binary message. `n_disp_bins`: Number of display bins (i.e. bars on a graphical equalizer) `scale`: One of `mel`, `log` (logarithmic), or `lin` (linear). Controls the mapping from FFT to display bins. `f_min`: The minimum frequency where the lowest display band should start (reasonable default 20-40 Hz) @@ -669,19 +672,24 @@ The `visualizer` object in [`stream/update`](#server--client-streamupdate) has t Binary messages should be rejected if there is no active stream. - Byte 0: message type `8` (uint8) -- Bytes 1-8: timestamp (big-endian int64) - server clock time in microseconds when the visualization should be displayed by the device, corresponding to the audio timeline. Clients must translate this server timestamp to their local clock using the offset computed from clock synchronization. -- Rest of bytes: Visualizer binary data, uses a tag-value encoding. The following types are currently defined: +- Byte 1: number of frames batched as part of this message. Each frame includes the timestamp and data bytes. Frames sent in one message must be in chronological order, with the earliest timestamp occuring first. +- Bytes 2-9: timestamp (big-endian int64) - server clock time in microseconds when the visualization should be displayed by the device, corresponding to the audio timeline. Clients must translate this server timestamp to their local clock using the offset computed from clock synchronization. +- Rest of bytes: Visualizer binary data in a fixed format - the order is given by the server in the `stream/start` type array. -| Type byte | Type name | Data type + length (bytes) | Unit | -|---|---|---|---| -|`0`| Reserved | - (0) -|`1`| Beat detected at this timestamp | - (0) -|`2`| Amplitude/Loudness | `uint16` (2) | % of peak?, logarithmically adj. to human hearing -|`3`| Frequency with highest amplitude | `uint16` (2) | Hz -|`4`| Spectrum / FFT | `byte` + `uint16[n]` (1 + 2*n) | First data byte number of display bins `n`, followed by `n`display bins from low to high freq., each an `uint16` -Multiple data types may be appended in a single message, if they have the same timestamp. -For example, the message `08 <8 timestamp bytes> 02 7F FF 03 04 00` both specifies the amplitude (~50% of peak) and the peak frequency (1024 Hz). +| Type name | Data type + length (bytes) | Unit | +|---|---|---| +| `loudness` | `uint16` (2) | % of full scale, logarithmically adj. to human hearing +| `f_peak` (Frequency with highest amplitude) | `uint16` (2) | Hz +| `spectrum` (FFT) | `uint16[n]` (2*n) | `n` display bins from low to high freq., each an `uint16`. (`n` = `n_disp_bins` in `stream/start`) +For example, for types `["loudness", "f_peak"]` the message `08 01 <8 timestamp bytes> 7F FF 04 00` both specifies the loudness (~50% of peak) and the peak frequency (1024 Hz). +### Server → Client: Visualization Data - Beats (Binary) +For the `beat` visualizer type, a separate binary message type is used. + +- Byte 0: message type `9` (uint8) +- Byte 1: number of frames batched as part of this message. Each frame is simply the timestamp where a beat occurs. Frames sent in one message must be in chronological order, with the earliest timestamp occuring first. +- Byte 2-9: timestamp (big-endian int64) - server clock time in microseconds when the beat occurs +- (Byte 10...): next beat timestamp (big-endian int64)... \ No newline at end of file From 5c0b94828bc52166b6b478245cd8ab5ffd715eec Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 16 Feb 2026 10:36:44 +0100 Subject: [PATCH 4/9] docs: restructure visualizer section to match spec style --- README.md | 75 ++++++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 56c9653..0131186 100644 --- a/README.md +++ b/README.md @@ -624,72 +624,67 @@ This section describes messages specific to clients with the `visualizer` role, The `visualizer_support` object in [`client/hello`](#client--server-clienthello) has this structure: -- `visualizer_support`: object containing the desired FFT details: - - -```json -{ - "visualizer_support": { - "types": ["loudness","spectrum","beat"], - "buffer_capacity": 2048, - "batch_max": 32, - "spectrum": { - "n_disp_bins": 16, - "scale": "log", - "f_min": 20, - "f_max": 20000, - "rate_max": 60 - } - } -} -``` -, where: -`types`: The Visualization Data Types supported/requested by the client. Server may ignore any types it doesn't support. See type definition in binary definition table below. Currently defined: `beat`, `loudness`, `f_peak`, and `spectrum`. -`buffer_capacity`: The maximum size in bytes of visualization messages that the client is able to buffer. -`batch_max`: The maximum number of logical messages with separate timestamps the server may batch into WebSockets binary message. -`n_disp_bins`: Number of display bins (i.e. bars on a graphical equalizer) -`scale`: One of `mel`, `log` (logarithmic), or `lin` (linear). Controls the mapping from FFT to display bins. -`f_min`: The minimum frequency where the lowest display band should start (reasonable default 20-40 Hz) -`f_max`: The maximum frequency where the highest display band should end (reasonable default ~16-22 kHz) -`rate_max`: The maximum number of spectrum updates per second. (this is somewhat constrained by n_fft - this is just a maximum so that e.g. clients with a max. display refresh rate of 60 Hz don't receive e.g. 300 messages/second) +- `visualizer_support`: object + - `types`: string[] - visualization data types requested by the client. Server may ignore types it doesn't support. Currently defined: 'beat', 'loudness', 'f_peak', 'spectrum' + - `buffer_capacity`: integer - max size in bytes of visualization messages that the client is able to buffer + - `batch_max`: integer - max number of logical messages with separate timestamps the server may batch into a single WebSocket binary message + - `spectrum?`: object - spectrum configuration, required if `types` includes 'spectrum' + - `n_disp_bins`: integer - number of display bins (i.e. bars on a graphical equalizer) + - `scale`: 'mel' | 'log' | 'lin' - mapping from FFT frequencies to display bins. 'mel' for mel scale, 'log' for logarithmic, 'lin' for linear + - `f_min`: integer - minimum frequency in Hz where the lowest display band starts (reasonable default: 20-40 Hz) + - `f_max`: integer - maximum frequency in Hz where the highest display band ends (reasonable default: 16000-22000 Hz) + - `rate_max`: integer - maximum spectrum updates per second. Clients should set this to their display refresh rate to avoid receiving excessive messages ### Server → Client: `stream/start` visualizer object The `visualizer` object in [`stream/start`](#server--client-streamstart) has this structure: - `visualizer`: object - - FFT details of actually streamed data (see above) + - `types`: string[] - visualization data types the server will stream + - `spectrum?`: object - spectrum configuration, only if `types` includes 'spectrum' + - `n_disp_bins`: integer - number of display bins + - `scale`: 'mel' | 'log' | 'lin' - mapping from FFT frequencies to display bins + - `f_min`: integer - minimum frequency in Hz + - `f_max`: integer - maximum frequency in Hz + - `rate_max`: integer - spectrum updates per second ### Server → Client: `stream/update` visualizer object The `visualizer` object in [`stream/update`](#server--client-streamupdate) has this structure with delta updates: - `visualizer`: object - - FFT details of actually streamed data (see above) + - `types?`: string[] - visualization data types the server will stream + - `spectrum?`: object - spectrum configuration updates + - `n_disp_bins?`: integer - number of display bins + - `scale?`: 'mel' | 'log' | 'lin' - mapping from FFT frequencies to display bins + - `f_min?`: integer - minimum frequency in Hz + - `f_max?`: integer - maximum frequency in Hz + - `rate_max?`: integer - spectrum updates per second ### Server → Client: Visualization Data (Binary) Binary messages should be rejected if there is no active stream. - Byte 0: message type `8` (uint8) -- Byte 1: number of frames batched as part of this message. Each frame includes the timestamp and data bytes. Frames sent in one message must be in chronological order, with the earliest timestamp occuring first. -- Bytes 2-9: timestamp (big-endian int64) - server clock time in microseconds when the visualization should be displayed by the device, corresponding to the audio timeline. Clients must translate this server timestamp to their local clock using the offset computed from clock synchronization. -- Rest of bytes: Visualizer binary data in a fixed format - the order is given by the server in the `stream/start` type array. +- Byte 1: number of frames batched in this message (uint8) +- Remaining bytes: frames in chronological order, earliest first +Each frame is: +- 8 bytes: timestamp (big-endian int64) - server clock time in microseconds when this data should be displayed. Clients must translate this server timestamp to their local clock using the offset computed from clock synchronization +- Data bytes: visualization data in the order given by the `types` array in [`stream/start`](#server--client-streamstart-visualizer-object). The data length per frame is fixed for the duration of a stream | Type name | Data type + length (bytes) | Unit | |---|---|---| -| `loudness` | `uint16` (2) | % of full scale, logarithmically adj. to human hearing -| `f_peak` (Frequency with highest amplitude) | `uint16` (2) | Hz -| `spectrum` (FFT) | `uint16[n]` (2*n) | `n` display bins from low to high freq., each an `uint16`. (`n` = `n_disp_bins` in `stream/start`) +| `loudness` | `uint16` (2) | % of full scale, logarithmically adjusted to human hearing | +| `f_peak` (frequency with highest amplitude) | `uint16` (2) | Hz | +| `spectrum` (FFT) | `uint16[n]` (2*n) | `n` display bins from low to high frequency, each a `uint16`. `n` = `n_disp_bins` in [`stream/start`](#server--client-streamstart-visualizer-object) | -For example, for types `["loudness", "f_peak"]` the message `08 01 <8 timestamp bytes> 7F FF 04 00` both specifies the loudness (~50% of peak) and the peak frequency (1024 Hz). +For example, for types `["loudness", "f_peak"]` a single-frame message `08 01 <8 timestamp bytes> 7F FF 04 00` specifies loudness (~50% of peak) and peak frequency (1024 Hz). ### Server → Client: Visualization Data - Beats (Binary) For the `beat` visualizer type, a separate binary message type is used. - Byte 0: message type `9` (uint8) -- Byte 1: number of frames batched as part of this message. Each frame is simply the timestamp where a beat occurs. Frames sent in one message must be in chronological order, with the earliest timestamp occuring first. -- Byte 2-9: timestamp (big-endian int64) - server clock time in microseconds when the beat occurs -- (Byte 10...): next beat timestamp (big-endian int64)... \ No newline at end of file +- Byte 1: number of frames batched in this message (uint8). Frames must be in chronological order, earliest first +- Remaining bytes: consecutive timestamps (big-endian int64 each) - server clock time in microseconds when each beat occurs From 666986f2b8ee3c01f6b0e40b46b63896f0dfd712 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 16 Feb 2026 10:57:15 +0100 Subject: [PATCH 5/9] docs: specify visualizer data value ranges and encoding --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 92375a5..cabdbf8 100644 --- a/README.md +++ b/README.md @@ -738,17 +738,19 @@ Each frame is: - 8 bytes: timestamp (big-endian int64) - server clock time in microseconds when this data should be displayed. Clients must translate this server timestamp to their local clock using the offset computed from clock synchronization - Data bytes: visualization data in the order given by the `types` array in [`stream/start`](#server--client-streamstart-visualizer-object). The data length per frame is fixed for the duration of a stream -| Type name | Data type + length (bytes) | Unit | +All `uint16` values use the full range 0-65535, where 0 = silence and 65535 = full scale. The server applies perceptual weighting before encoding so clients can map values linearly to their display. + +| Type name | Data type + length (bytes) | Description | |---|---|---| -| `loudness` | `uint16` (2) | % of full scale, logarithmically adjusted to human hearing | -| `f_peak` (frequency with highest amplitude) | `uint16` (2) | Hz | +| `loudness` | `uint16` (2) | Overall loudness, 0-65535 | +| `f_peak` (frequency with highest amplitude) | `uint16` (2) | Frequency in Hz | | `spectrum` (FFT) | `uint16[n]` (2*n) | `n` display bins from low to high frequency, each a `uint16`. `n` = `n_disp_bins` in [`stream/start`](#server--client-streamstart-visualizer-object) | For example, for types `["loudness", "f_peak"]` a single-frame message `10 01 <8 timestamp bytes> 7F FF 04 00` specifies loudness (~50% of peak) and peak frequency (1024 Hz). ### Server → Client: Visualization Data - Beats (Binary) -For the `beat` visualizer type, a separate binary message type is used. +Beat events are sent separately from other visualization data using their own binary message type. - Byte 0: message type `17` (uint8) - Byte 1: number of frames batched in this message (uint8). Frames must be in chronological order, earliest first From 5bbcc3bb7e69011fd952d90b0a260297922c6b32 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 16 Feb 2026 10:59:24 +0100 Subject: [PATCH 6/9] feat: add placeholder for visualizer `stream/request-format` --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cabdbf8..6c114da 100644 --- a/README.md +++ b/README.md @@ -388,10 +388,11 @@ Instructs clients to clear buffers without ending the stream. Used for seek oper ### Client → Server: `stream/request-format` -Request different stream format (upgrade or downgrade). Available for clients with the `player` or `artwork` role. +Request different stream format (upgrade or downgrade). Available for clients with the `player`, `artwork`, or `visualizer` role. - `player?`: object - only for clients with the `player` role ([see player object details](#client--server-streamrequest-format-player-object)) - `artwork?`: object - only for clients with the `artwork` role ([see artwork object details](#client--server-streamrequest-format-artwork-object)) +- `visualizer?`: object - only for clients with the `visualizer` role ([see visualizer object details](#client--server-streamrequest-format-visualizer-object)) [Application-specific roles](#application-specific-roles) may also include objects in this message (keys starting with `_`). @@ -722,6 +723,14 @@ The `visualizer` object in [`stream/start`](#server--client-streamstart) has thi - `f_max`: integer - maximum frequency in Hz - `rate_max`: integer - spectrum updates per second +### Client → Server: `stream/request-format` visualizer object + + + +The `visualizer` object in [`stream/request-format`](#client--server-streamrequest-format) has this structure: + +To be determined. + ### Server → Client: `stream/clear` visualizer When [`stream/clear`](#server--client-streamclear) includes the visualizer role, clients should clear all buffered visualization data and continue with data received after this message. From dbcdaa5c3bf748f5f8142ebd4fe9e22865040b54 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 16 Feb 2026 11:00:56 +0100 Subject: [PATCH 7/9] refactor: rename visualizer role version to `_draft_r1` --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6c114da..3f4f3d5 100644 --- a/README.md +++ b/README.md @@ -270,10 +270,10 @@ Players that can output audio should have the role `player`. - `controller@v1` - controls the current Sendspin group - `metadata@v1` - displays text metadata describing the currently playing audio - `artwork@v1` - displays artwork images - - `visualizer@v1` - visualizes audio + - `visualizer@_draft_r1` - visualizes audio - `player@v1_support?`: object - only if `player@v1` is listed ([see player@v1 support object details](#client--server-clienthello-playerv1-support-object)) - `artwork@v1_support?`: object - only if `artwork@v1` is listed ([see artwork@v1 support object details](#client--server-clienthello-artworkv1-support-object)) -- `visualizer@v1_support?`: object - only if `visualizer@v1` is listed ([see visualizer@v1 support object details](#client--server-clienthello-visualizerv1-support-object)) +- `visualizer@_draft_r1_support?`: object - only if `visualizer@_draft_r1` is listed ([see visualizer@_draft_r1 support object details](#client--server-clienthello-visualizer_draft_r1-support-object)) **Note:** Each role version may have its own support object (e.g., `player@v1_support`, `player@v2_support`). Application-specific roles or role versions follow the same pattern (e.g., `_myapp_display@v1_support`, `player@_experimental_support`). @@ -695,11 +695,11 @@ The timestamp indicates when this artwork should be displayed. Clients must tran ## Visualizer messages This section describes messages specific to clients with the `visualizer` role, which create visual representations of the audio being played. Visualizer clients receive audio analysis data like FFT information that corresponds to the current audio timeline. -### Client → Server: `client/hello` visualizer@v1 support object +### Client → Server: `client/hello` visualizer@_draft_r1 support object -The `visualizer@v1_support` object in [`client/hello`](#client--server-clienthello) has this structure: +The `visualizer@_draft_r1_support` object in [`client/hello`](#client--server-clienthello) has this structure: -- `visualizer@v1_support`: object +- `visualizer@_draft_r1_support`: object - `types`: string[] - visualization data types requested by the client. Server may ignore types it doesn't support. Currently defined: 'beat', 'loudness', 'f_peak', 'spectrum' - `buffer_capacity`: integer - max size in bytes of visualization messages that the client is able to buffer - `batch_max`: integer - max number of logical messages with separate timestamps the server may batch into a single WebSocket binary message From 038aa0feab65a61707cccb67df730b86a5152111 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 16 Feb 2026 11:08:37 +0100 Subject: [PATCH 8/9] fix: scope `uint16` range description to `loudness` and `spectrum` only --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3f4f3d5..db06baa 100644 --- a/README.md +++ b/README.md @@ -747,12 +747,12 @@ Each frame is: - 8 bytes: timestamp (big-endian int64) - server clock time in microseconds when this data should be displayed. Clients must translate this server timestamp to their local clock using the offset computed from clock synchronization - Data bytes: visualization data in the order given by the `types` array in [`stream/start`](#server--client-streamstart-visualizer-object). The data length per frame is fixed for the duration of a stream -All `uint16` values use the full range 0-65535, where 0 = silence and 65535 = full scale. The server applies perceptual weighting before encoding so clients can map values linearly to their display. +`loudness` and `spectrum` values use the full `uint16` range 0-65535, where 0 = silence and 65535 = full scale. The server applies perceptual weighting before encoding so clients can map values linearly to their display. | Type name | Data type + length (bytes) | Description | |---|---|---| | `loudness` | `uint16` (2) | Overall loudness, 0-65535 | -| `f_peak` (frequency with highest amplitude) | `uint16` (2) | Frequency in Hz | +| `f_peak` (frequency with highest amplitude) | `uint16` (2) | Raw frequency in Hz (0 = no peak detected) | | `spectrum` (FFT) | `uint16[n]` (2*n) | `n` display bins from low to high frequency, each a `uint16`. `n` = `n_disp_bins` in [`stream/start`](#server--client-streamstart-visualizer-object) | For example, for types `["loudness", "f_peak"]` a single-frame message `10 01 <8 timestamp bytes> 7F FF 04 00` specifies loudness (~50% of peak) and peak frequency (1024 Hz). From 2962bb85642f3d133b13937c3b9d04445242c065 Mon Sep 17 00:00:00 2001 From: Maxim Raznatovski Date: Mon, 16 Feb 2026 11:18:44 +0100 Subject: [PATCH 9/9] docs: echo `batch_max` in `stream/start` visualizer object --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index db06baa..57a1ef9 100644 --- a/README.md +++ b/README.md @@ -716,6 +716,7 @@ The `visualizer` object in [`stream/start`](#server--client-streamstart) has thi - `visualizer`: object - `types`: string[] - visualization data types the server will stream + - `batch_max`: integer - max number of frames the server will batch into a single binary message - `spectrum?`: object - spectrum configuration, only if `types` includes 'spectrum' - `n_disp_bins`: integer - number of display bins - `scale`: 'mel' | 'log' | 'lin' - mapping from FFT frequencies to display bins