Play your rhythm game hitsounds with less latency by utilizing ASIO

refactor & add taiko mode

added 3rd user question for mode
reworked don & kat to be quieter
extracted pop audio keys to consts

angelo.fyi 26bf03fb fe01562d

verified
Changed files
+75 -24
src
+75 -24
src/main.rs
··· 5 5 use win_hotkeys::{VKey, hook::KeyboardEvent, state::KeyboardState}; 6 6 7 7 const POP_AUDIO_BYTES: &[u8; 25668] = include_bytes!("../assets/pop.wav"); 8 + const DON_AUDIO_BYTES: &[u8; 77832] = include_bytes!("../assets/don.wav"); 9 + const KAT_AUDIO_BYTES: &[u8; 31176] = include_bytes!("../assets/kat.wav"); 10 + 11 + const POP_AUDIO_KEYS: &[u16] = &[ 12 + VKey::Z.to_vk_code(), 13 + VKey::X.to_vk_code(), 14 + VKey::Q.to_vk_code(), 15 + VKey::Oem1.to_vk_code(), 16 + VKey::E.to_vk_code(), 17 + VKey::U.to_vk_code(), 18 + VKey::H.to_vk_code(), 19 + VKey::T.to_vk_code(), 20 + VKey::D.to_vk_code(), 21 + VKey::F.to_vk_code(), 22 + VKey::J.to_vk_code(), 23 + VKey::K.to_vk_code(), 24 + VKey::L.to_vk_code(), 25 + ]; 26 + const DON_AUDIO_KEYS: &[u16] = &[ 27 + VKey::F.to_vk_code(), 28 + VKey::J.to_vk_code(), 29 + VKey::U.to_vk_code(), 30 + VKey::H.to_vk_code(), 31 + ]; 32 + const KAT_AUDIO_KEYS: &[u16] = &[ 33 + VKey::D.to_vk_code(), 34 + VKey::K.to_vk_code(), 35 + VKey::E.to_vk_code(), 36 + VKey::T.to_vk_code(), 37 + ]; 8 38 9 39 #[tokio::main] 10 40 async fn main() { 11 - let listened_keys = vec![ 12 - VKey::Z, 13 - VKey::X, 14 - VKey::Q, 15 - VKey::Oem1, 16 - VKey::E, 17 - VKey::U, 18 - VKey::H, 19 - VKey::T, 20 - VKey::D, 21 - VKey::F, 22 - VKey::J, 23 - VKey::K, 24 - VKey::L, 25 - ]; 26 - 27 - let audio_seekable = Cursor::new(POP_AUDIO_BYTES); 28 - let audio_buffer = rodio::Decoder::try_from(audio_seekable.clone()) 29 - .unwrap() 30 - .buffered(); 31 - 32 41 let asio_host = cpal::host_from_id(cpal::HostId::Asio).expect("failed to initialise ASIO host"); 33 42 34 43 let output_devices: Vec<cpal::Device> = asio_host 35 44 .output_devices() 36 45 .expect("No ASIO output devices available in this host") 37 46 .collect(); 47 + 48 + println!("Use arrow keys to select an item below"); 49 + println!(); 38 50 let asio_out_idx = dialoguer::Select::new() 39 51 .with_prompt("1. Select an ASIO output device to use") 40 52 .items(output_devices.iter().map(|d| d.name().unwrap())) 53 + .default(0) 41 54 .interact() 42 55 .unwrap(); 43 56 ··· 62 75 c.buffer_size(), 63 76 ) 64 77 })) 78 + .default(0) 65 79 .interact() 66 80 .unwrap(); 67 81 ··· 84 98 .open_stream_or_fallback() 85 99 .expect("Unable to stream audio to ASIO output device"); 86 100 101 + let mode_idx = dialoguer::Select::new() 102 + .with_prompt("3. Select hitsound mode") 103 + .items(vec!["Pop", "Taiko DFJK"]) 104 + .default(0) 105 + .interact() 106 + .unwrap(); 107 + 108 + let pop_seekable = Cursor::new(POP_AUDIO_BYTES); 109 + let pop_buffer = rodio::Decoder::try_from(pop_seekable).unwrap().buffered(); 110 + let don_seekable = Cursor::new(DON_AUDIO_BYTES); 111 + let don_buffer = rodio::Decoder::try_from(don_seekable) 112 + .unwrap() 113 + .amplify(0.25) 114 + .buffered(); 115 + let kat_seekable = Cursor::new(KAT_AUDIO_BYTES); 116 + let kat_buffer = rodio::Decoder::try_from(kat_seekable) 117 + .unwrap() 118 + .amplify(0.25) 119 + .buffered(); 120 + 87 121 println!(); 88 122 println!("Connected to {} using config:", out_name,); 89 123 println!("{:?}", rodio_stream.config()); ··· 105 139 vk_code, 106 140 keyboard_state, 107 141 } => { 108 - for k in &listened_keys { 109 - if vk_code == k.to_vk_code() && !prev_key_state.is_down(vk_code) { 110 - rodio_stream.mixer().add(audio_buffer.clone()); 142 + match mode_idx { 143 + 0 => { 144 + for k in POP_AUDIO_KEYS { 145 + if vk_code == *k && !prev_key_state.is_down(vk_code) { 146 + rodio_stream.mixer().add(pop_buffer.clone()); 147 + } 148 + } 111 149 } 150 + 1 => { 151 + for k in DON_AUDIO_KEYS { 152 + if vk_code == *k && !prev_key_state.is_down(vk_code) { 153 + rodio_stream.mixer().add(don_buffer.clone()); 154 + } 155 + } 156 + for k in KAT_AUDIO_KEYS { 157 + if vk_code == *k && !prev_key_state.is_down(vk_code) { 158 + rodio_stream.mixer().add(kat_buffer.clone()); 159 + } 160 + } 161 + } 162 + _ => unreachable!(), 112 163 } 113 164 114 165 prev_key_state = keyboard_state;