adatcheck.rs (3530B)
1 //! ADAT-output diagnostic (READ-ONLY). Answers: are the ADAT outputs fed 2 //! straight from the DAW (PCM, like a normal Focusrite Control setup) or through 3 //! a mix bus (which, with the wall-of-unity mixer, would sum to a hot level)? 4 //! Also compares the meter levels feeding ADAT (PCM 13-20) vs headphones/main 5 //! (PCM 1-2) so we can see if the DAW itself is sending ADAT hotter. 6 //! 7 //! Run with Focusrite Control quit, ideally while playing audio: 8 //! cargo run -p spike --bin adatcheck 9 10 use scarlett_core::matrix::mixer_value_to_db; 11 use scarlett_core::meter::pcm_capture_level; 12 use scarlett_core::model::S18I20_GEN3; 13 use scarlett_core::mux::{id_to_num, num_dsts, Dir, MuxState, PORT_COUNT_18I20_GEN3}; 14 use scarlett_core::ports::source_name; 15 use scarlett_core::{Scarlett, UsbTransport}; 16 17 fn main() { 18 if let Err(e) = run() { 19 eprintln!("\x1b[31mADATCHECK FAILED:\x1b[0m {e}"); 20 std::process::exit(1); 21 } 22 } 23 24 fn run() -> Result<(), Box<dyn std::error::Error>> { 25 let mut dev = Scarlett::new(UsbTransport::open_default()?); 26 dev.init()?; 27 let pc = PORT_COUNT_18I20_GEN3; 28 println!("connected: {}\n", S18I20_GEN3.name); 29 30 // 1. What feeds each ADAT output right now? 31 let entries = dev.get_mux(num_dsts(&pc))?; 32 let st = MuxState::from_entries(pc, &entries); 33 println!("=== ADAT OUTPUT ROUTING ==="); 34 let mut via_mix = 0; 35 for i in 0..8u16 { 36 let out_num = id_to_num(&pc, Dir::Out, 0x200 + i).unwrap_or(0); 37 let src_num = st.get(out_num); 38 let src_id = id_to_num(&pc, Dir::In, src_num) // round-trip for label 39 .map(|_| src_num) 40 .unwrap_or(src_num); 41 let src_hw = scarlett_core::mux::num_to_id(&pc, Dir::In, src_id); 42 let name = source_name(src_hw); 43 let is_mix = (src_hw & 0xf00) == 0x300; 44 if is_mix { 45 via_mix += 1; 46 } 47 println!(" ADAT Out {} ← {name}{}", i + 1, if is_mix { " <-- via MIXER" } else { "" }); 48 } 49 if via_mix > 0 { 50 println!( 51 "\n\x1b[33m{via_mix}/8 ADAT outs are fed by a MIX bus.\x1b[0m With the wall-of-unity\n\ 52 mixer this sums many sources → HOT. Focusrite Control feeds ADAT from\n\ 53 PCM directly, which is why FC wasn't loud. Fix: route ADAT ← PCM\n\ 54 (Routing tab), or lower those mix buses." 55 ); 56 } else { 57 println!("\n\x1b[32mAll ADAT outs are fed directly from PCM (like FC).\x1b[0m"); 58 println!("So the level is the DAW's output or the external converter, not routing."); 59 } 60 61 // 2. Compare DAW send levels: PCM 13-20 (ADAT) vs PCM 1-2 (main/HP). 62 println!("\n=== DAW SEND LEVELS (play audio; peak over ~4s) ==="); 63 let mut peak = vec![0u32; S18I20_GEN3.meter_count as usize]; 64 for _ in 0..20 { 65 let raw = dev.get_meters(S18I20_GEN3.meter_count)?; 66 for (i, &v) in raw.iter().enumerate() { 67 if v > peak[i] { 68 peak[i] = v; 69 } 70 } 71 for _ in 0..4 { 72 let _ = dev.get_meters(4); 73 } 74 } 75 let db = |raw: u32| scarlett_core::meter::raw_to_dbfs(raw); 76 let pk = |n| pcm_capture_level(&peak, n); 77 println!(" PCM 1 (main/HP L): {:>6.1} dBFS", db(pk(1))); 78 println!(" PCM 2 (main/HP R): {:>6.1} dBFS", db(pk(2))); 79 println!(" PCM 13 (ADAT 1): {:>6.1} dBFS", db(pk(13))); 80 println!(" PCM 14 (ADAT 2): {:>6.1} dBFS", db(pk(14))); 81 let _ = mixer_value_to_db; // (kept for parity) 82 83 println!("\nADATCHECK DONE (read-only)."); 84 Ok(()) 85 }