diff --git a/dsp408-protocol.md b/dsp408-protocol.md index 1de5817..f8f4498 100644 --- a/dsp408-protocol.md +++ b/dsp408-protocol.md @@ -1868,7 +1868,7 @@ Sine Wave: |---|---|---|---| | `Byte 1-36` | 12 meter channels | 3 bytes × 12 | [Enc §8.1 Meter Level](#81-meter-level) | | `Byte 37` | Input clip indicator | 1 byte bitmask | Same OR bitmask pattern as [Enc §4.1](#41-matrix-input-mask) | -| `Byte 38` | Output clip indicator | 1 byte bitmask | Same OR bitmask pattern as [Enc §4.1](#41-matrix-input-mask) | +| `Byte 38` | Output limit indicator | 1 byte bitmask | Same OR bitmask pattern as [Enc §4.1](#41-matrix-input-mask) | **Example — Query** diff --git a/src/dsp408/mapper/response.rs b/src/dsp408/mapper/response.rs index 009842b..d76bbdf 100644 --- a/src/dsp408/mapper/response.rs +++ b/src/dsp408/mapper/response.rs @@ -1,10 +1,7 @@ use crate::{ common::errors::ProtocolError, dsp408::{ - protocol::{ - constants::{METERS_HIGH_STEP, METERS_LOW_STEP, METERS_SPLIT, METERS_SPLIT_LEVEL_DB}, - frame::Frame, - }, + protocol::frame::Frame, types::{ Acknowledgement, AuthenticationResult, ConfigChunk, CurrentPreset, DeviceFlags, DeviceInfo, DeviceResponseType, HandshakeAck, Meter, Meters, ModifiedPreset, @@ -166,43 +163,35 @@ pub fn map_response(frame: &Frame) -> Result // Command `0x40` (Get Level Meters) if cmd == 0x40 { + fn float_to_db(v: f32) -> f32 { + 40.0 * v.abs().max(1e-12).log10() + } + if payload.len() != 38 { return Err(ProtocolError::new("Not enough bytes for meter levels")); } - // Bytes 0..36 = 12 × 3-byte meter levels - let levels: Vec = (0..36) + let channels: Vec = (0..36) .step_by(3) - .map(|i| decode_float16(payload[i], payload[i + 1]).unwrap_or_default()) - .map(|f| { - if f < METERS_SPLIT { - METERS_SPLIT_LEVEL_DB + (f - METERS_SPLIT) / METERS_LOW_STEP - } else { - METERS_SPLIT_LEVEL_DB + (f - METERS_SPLIT) / METERS_HIGH_STEP - } - }) - .collect(); - - // Byte 36 = input clip bitmask - let input_clip_mask = payload[36]; - - // Byte 37 = output clip bitmask - let output_clip_mask = payload[37]; - - let channels = levels - .into_iter() .enumerate() - .map(|(index, level)| { + .map(|(index, i)| { + let rms = decode_float16(payload[i], payload[i + 1]).unwrap_or_default(); + let peak = decode_float16(payload[i + 2], payload[i + 1]).unwrap_or_default(); + + let rms_db = float_to_db(rms); + let peak_db = float_to_db(peak); + let clip = if index < 4 { - // InA..InD - input_clip_mask & (1 << index) != 0 + payload[36] & (1 << index) != 0 } else { - // Out1..Out8 - let output_index = index - 4; - output_clip_mask & (1 << output_index) != 0 + payload[37] & (1 << (index - 4)) != 0 }; - Meter { level, clip } + Meter { + rms: rms_db, + peak: peak_db, + clip, + } }) .collect(); @@ -438,7 +427,7 @@ mod tests { assert_eq!(m.channels.len(), 12); for channel in m.channels { - assert!(channel.level.is_finite()); + assert!(channel.rms.is_finite()); } } other => panic!("unexpected {:?}", other), diff --git a/src/dsp408/protocol/constants.rs b/src/dsp408/protocol/constants.rs index 6509390..7710135 100644 --- a/src/dsp408/protocol/constants.rs +++ b/src/dsp408/protocol/constants.rs @@ -77,8 +77,3 @@ pub fn output_link_mask(channel: u8) -> Option { _ => None, } } - -pub const METERS_SPLIT: f32 = 1.0; -pub const METERS_SPLIT_LEVEL_DB: f32 = -18.0; -pub const METERS_LOW_STEP: f32 = 0.0104; -pub const METERS_HIGH_STEP: f32 = 0.0208; diff --git a/src/dsp408/types.rs b/src/dsp408/types.rs index 7559bbe..bf63d91 100644 --- a/src/dsp408/types.rs +++ b/src/dsp408/types.rs @@ -221,7 +221,8 @@ pub struct AuthenticationResult { #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] #[derive(Debug, Clone, Copy, PartialEq)] pub struct Meter { - pub level: f32, + pub rms: f32, + pub peak: f32, pub clip: bool, } diff --git a/src/main.rs b/src/main.rs index 7666a42..36ddd43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,3 +32,5 @@ fn main() -> Result<(), Box> { Ok(()) } + +// 10020100 27 40 263df7 263dfd 263dfd 263dfd 063d8d 063d63 263dcf 263dfd 263df6 263dcf 263dcf 263dcf 0300 10038b