feat: rms + peak meters
This commit is contained in:
+1
-1
@@ -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**
|
||||
|
||||
|
||||
@@ -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<DeviceResponseType, ProtocolError>
|
||||
|
||||
// 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<f32> = (0..36)
|
||||
let channels: Vec<Meter> = (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),
|
||||
|
||||
@@ -77,8 +77,3 @@ pub fn output_link_mask(channel: u8) -> Option<u8> {
|
||||
_ => 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;
|
||||
|
||||
+2
-1
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -32,3 +32,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 10020100 27 40 263df7 263dfd 263dfd 263dfd 063d8d 063d63 263dcf 263dfd 263df6 263dcf 263dcf 263dcf 0300 10038b
|
||||
|
||||
Reference in New Issue
Block a user