From 7ef059fa5bea5f75870b48a3ac9d8316fd8b6baf Mon Sep 17 00:00:00 2001 From: William P Date: Tue, 25 Mar 2025 21:49:51 -0400 Subject: [PATCH] play with FSK more --- amps-handset-emu/src/audio.rs | 22 +++++++++++++++++---- amps-handset-emu/src/fsk.rs | 37 ++++++++++++++++++++++++++++------- amps-handset-emu/src/main.rs | 14 +++++++++---- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/amps-handset-emu/src/audio.rs b/amps-handset-emu/src/audio.rs index c3bc7a1..7b7c93f 100644 --- a/amps-handset-emu/src/audio.rs +++ b/amps-handset-emu/src/audio.rs @@ -1,20 +1,34 @@ -use cpal::{StreamConfig, traits::{DeviceTrait, HostTrait}}; +use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; +use std::sync::{Arc, Mutex}; pub fn play_audio(signal: &[f32]) -> Result<(), Box> { let host = cpal::default_host(); - let device = host.default_output_device()?.config(); + let device = host.default_output_device().ok_or("No output device found")?; let config = device.default_output_config()?.config(); + let signal = Arc::new(Mutex::new(signal.to_vec())); + let singal_clone = Arc::clone(&signal); + let mut index = 0; + let stream = device.build_output_stream( &config, move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { - data.copy_from_slice(&signal[..data.len()]); + let signal = singal_clone.lock().unwrap(); + + for sample in data.iter_mut() { + *sample = if index < signal.len() { + signal[index] + } else { + 0.0 + }; + index += 1; + } }, |err| eprintln!("Error: {:?}", err), None )?; stream.play()?; - std::thread::sleep(std::time::Duration::from_secs(5)); + std::thread::sleep(std::time::Duration::from_secs(1)); Ok(()) } \ No newline at end of file diff --git a/amps-handset-emu/src/fsk.rs b/amps-handset-emu/src/fsk.rs index 0ca938a..1d72508 100644 --- a/amps-handset-emu/src/fsk.rs +++ b/amps-handset-emu/src/fsk.rs @@ -1,20 +1,43 @@ use std::f32::consts::PI; -use dasp_signal::Signal; const SAMPLE_RATE: f32 = 44100.0; const BAUD_RATE: f32 = 1200.0; const FREQ_MARK: f32 = 1200.0; const FREQ_SPACE: f32 = 2200.0; -pub fn fsk_modulate(bits: &[u8]) -> Vec { +pub fn fsk_modulate(data: &[u8]) -> Vec { let samples_per_bit = (SAMPLE_RATE / BAUD_RATE) as usize; let mut signal = Vec::new(); - for &bit in bits { - let freq = if bit == 1 { FREQ_MARK } else { FREQ_SPACE }; - for i in 0..samples_per_bit { - let t = i as f32 / SAMPLE_RATE; - signal.push((2.0 * PI * freq * t).sin()); + for &byte in data { + for i in (0..8).rev() { + let bit = (byte >> i) & 1; + let freq = if bit == 1 { FREQ_MARK } else { FREQ_SPACE }; + + for j in 0..samples_per_bit { + let t = (signal.len() + j) as f32 / SAMPLE_RATE; + signal.push((2.0 * PI * freq * t).sin()); + } + } + } + signal +} + +pub fn afsk_modulate(data: &[u8], carrier_freq: f32) -> Vec { + let samples_per_bit = (SAMPLE_RATE / BAUD_RATE) as usize; + let mut signal = Vec::new(); + + for &byte in data { + for i in (0..8).rev() { + let bit = (byte >> i) & 1; + let freq = if bit == 1 { FREQ_MARK } else { FREQ_SPACE }; + + for j in 0..samples_per_bit { + let t = (signal.len() + j) as f32 / SAMPLE_RATE; + let fsk_wave = (2.0 * PI * freq * t).sin(); + let carrier_wave = (2.0 * PI * carrier_freq * t).sin(); + signal.push(fsk_wave * carrier_wave); // Modulate FSK onto the carrier + } } } signal diff --git a/amps-handset-emu/src/main.rs b/amps-handset-emu/src/main.rs index 7579915..f70eb30 100644 --- a/amps-handset-emu/src/main.rs +++ b/amps-handset-emu/src/main.rs @@ -1,4 +1,5 @@ -use fsk::fsk_modulate; +use audio::play_audio; +use fsk::afsk_modulate; use text_io::scan; use std::io; @@ -15,9 +16,14 @@ fn main() -> Result<(), io::Error> { match a { 1 => { println!("1 has been pressed! No test tone implemented yet"); - let tone: signal; - tone = fsk_modulate([0x25, 0x08, 0x00, 0x25, 0xA0]); - play_audio(tone); + let tone: Vec; + tone = afsk_modulate(&[ + 0b10101010, 0b01010101, 0b10101010, 0b01010101, 0b10101010, 0b01010101, 0b10101010, 0b01010101, 0b10101010, 0b01010101, + 0b1000101,0b11111111,0b1000101,0b11111111,0b11111111,0b1000101,0b11111111,0b11111111,0b1000101,0b11111111,0b11111111, + ], 1700.0); + let repeated_tone: Vec = tone.iter().cloned().cycle().take(tone.len() * 10).collect(); + + play_audio(&repeated_tone); return main(); }, 0 => {