← back to inhesrom__signal-kit.rs

Function bodies 301 total

All specs Real LLM only Function bodies
generate_clean function · rust · L97-L122 (26 LOC)
src/generate/carrier.rs
    pub fn generate_clean<T: Float>(&self, num_samples: usize) -> ComplexVec<T> {
        // Calculate symbol rate from bandwidth
        // bandwidth = (symbol_rate * (1 + rolloff)) / sample_rate
        // symbol_rate = (bandwidth * sample_rate) / (1 + rolloff)
        let symbol_rate = (self.bandwidth * self.sample_rate_hz) / (1.0 + self.rolloff);

        // Generate baseband signal using appropriate carrier type
        let mut iq_samples = match self.modulation {
            ModType::_BPSK | ModType::_QPSK | ModType::_8PSK | ModType::_16APSK
            | ModType::_16QAM | ModType::_32QAM | ModType::_64QAM => {
                self.generate_psk_based(symbol_rate, num_samples)
            }
            // FSK handling would go here if we support it
            ModType::_CW => {
                self.generate_cw(num_samples)
            }
        };

        // Frequency shift to center frequency (if not baseband)
        if self.center_freq.abs() > 1e-9 {
            let freq_offse
generate function · rust · L134-L156 (23 LOC)
src/generate/carrier.rs
    pub fn generate<T: Float>(&self, num_samples: usize) -> ComplexVec<T> {
        let iq_samples = self.generate_clean::<T>(num_samples);

        // Measure signal power
        let oversample_rate = 1.0_f64 / self.bandwidth;
        let signal_power = iq_samples.measure_power(Some(oversample_rate));

        // Add AWGN to achieve target SNR
        // SNR_dB = 10 * log10(signal_power / noise_power)
        // noise_power = signal_power / 10^(SNR_dB/10)
        let snr_linear = 10.0_f64.powf(self.snr_db / 10.0);
        let noise_power = signal_power / snr_linear;

        let mut awgn = match self.seed {
            Some(s) => AWGN::new_from_seed(self.sample_rate_hz, num_samples, noise_power, s),
            None => AWGN::new_from_entropy(self.sample_rate_hz, num_samples, noise_power),
        };

        let noise = awgn.generate_block::<T>();
        let result = iq_samples + noise;

        result
    }
generate_psk_based function · rust · L159-L187 (29 LOC)
src/generate/carrier.rs
    fn generate_psk_based<T: Float>(&self, symbol_rate: f64, num_samples: usize) -> ComplexVec<T> {
        // Estimate block size (will be refined by PSK carrier)
        let block_size = (num_samples as f64 * symbol_rate / self.sample_rate_hz).ceil() as usize;

        let mut psk = PskCarrier::<T>::new(
            T::from(self.sample_rate_hz).unwrap(),
            T::from(symbol_rate).unwrap(),
            self.modulation,
            T::from(self.rolloff).unwrap(),
            block_size,
            91, // Default filter taps
            self.seed,
        );

        // Generate blocks until we have enough samples
        let mut result = ComplexVec::new();
        while result.len() < num_samples {
            let block = psk.generate_block();
            result.extend(block.iter().cloned());
        }

        // Trim to exact sample count
        let vec: Vec<_> = result
            .iter()
            .take(num_samples)
            .cloned()
            .collect();
        C
generate_cw function · rust · L190-L196 (7 LOC)
src/generate/carrier.rs
    fn generate_cw<T: Float>(&self, num_samples: usize) -> ComplexVec<T> {
        // CW is just a constant magnitude signal at baseband (0 Hz)
        // Generate as if it's a CW at frequency 0
        let mut cw = CW::new(0.0, self.sample_rate_hz, num_samples);
        let samples = cw.generate_block::<T>();
        ComplexVec::from_vec(samples)
    }
test_carrier_qpsk_creation function · rust · L211-L223 (13 LOC)
src/generate/carrier.rs
    fn test_carrier_qpsk_creation() {
        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        assert_eq!(carrier.modulation, ModType::_QPSK);
        assert_eq!(carrier.snr_db, 10.0);
    }
test_carrier_generate_qpsk function · rust · L226-L238 (13 LOC)
src/generate/carrier.rs
    fn test_carrier_generate_qpsk() {
        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.0,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let iq = carrier.generate::<f64>(1000);
        assert_eq!(iq.len(), 1000);
    }
test_carrier_generate_cw function · rust · L241-L253 (13 LOC)
src/generate/carrier.rs
    fn test_carrier_generate_cw() {
        let carrier = Carrier::new(
            ModType::_CW,
            0.1,
            0.0,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let iq = carrier.generate::<f64>(1000);
        assert_eq!(iq.len(), 1000);
    }
Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
test_carrier_with_frequency_shift function · rust · L256-L268 (13 LOC)
src/generate/carrier.rs
    fn test_carrier_with_frequency_shift() {
        let carrier = Carrier::new(
            ModType::_CW,
            0.1,
            0.25, // Shift to 250 kHz
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let iq = carrier.generate::<f64>(100);
        assert_eq!(iq.len(), 100);
    }
test_invalid_bandwidth function · rust · L271-L284 (14 LOC)
src/generate/carrier.rs
    fn test_invalid_bandwidth() {
        let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
            Carrier::new(
                ModType::_QPSK,
                1.5, // Invalid: > 1.0
                0.0,
                10.0,
                0.35,
                1e6,
                None,
            );
        }));
        assert!(result.is_err());
    }
test_invalid_center_freq function · rust · L287-L300 (14 LOC)
src/generate/carrier.rs
    fn test_invalid_center_freq() {
        let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
            Carrier::new(
                ModType::_QPSK,
                0.1,
                0.6, // Invalid: > 0.5
                10.0,
                0.35,
                1e6,
                None,
            );
        }));
        assert!(result.is_err());
    }
test_carrier_combination_spectrum function · rust · L303-L370 (68 LOC)
src/generate/carrier.rs
    fn test_carrier_combination_spectrum() {
        use crate::spectrum::welch::welch;
        use crate::spectrum::window::WindowType;
        use crate::vector_ops;
        use crate::plot::plot_spectrum;
        use crate::test_utils::should_plot;

        // Check if plotting is enabled
        if !should_plot() {
            println!("Skipping carrier combination spectrum plot (set PLOT=true to enable)");
            return;
        }

        let sample_rate = 1e6;

        // Create two carriers with contrasting characteristics
        // Carrier 1: Strong, narrow bandwidth signal
        let carrier1 = Carrier::new(
            ModType::_QPSK,
            0.05,     // 50 kHz bandwidth (narrow)
            0.15,     // 150 kHz center freq
            15.0,     // 25 dB SNR (high power)
            0.35,     // RRC rolloff
            sample_rate,
            Some(42),
        );

        // Carrier 2: Weak, wide bandwidth signal (interference/noise)
        let carrier2 = Carri
test_carrier_with_awgn function · rust · L373-L387 (15 LOC)
src/generate/carrier.rs
    fn test_carrier_with_awgn() {
        use num_complex::Complex;
        use crate::vector_ops;

        let carrier = Carrier::new(ModType::_QPSK, 0.25, 0.0, 10.0, 0.15, 1e6, Some(0));
        let _oversample_rate = 1.0f64 / carrier.bandwidth;
        let signal_iq = carrier.generate(1_000_000);

        let slice: &[Complex<f32>] = &signal_iq;
        let (freqs, spectrum) = welch(slice, 1e6, 2048, Some(512), Some(2048), crate::spectrum::window::WindowType::Rectangular, Some(AveragingMethod::Median));

        if crate::test_utils::should_plot() {
            plot_spectrum(&freqs, &vector_ops::to_db(&spectrum), "SNR Comparison");
        }
    }
new function · rust · L54-L61 (8 LOC)
src/generate/channel.rs
    pub fn new(carriers: Vec<Carrier>) -> Self {
        Channel {
            carriers,
            noise_floor_db: None,
            seed: None,
            impairments: Vec::new(),
        }
    }
noise_floor_to_power function · rust · L117-L122 (6 LOC)
src/generate/channel.rs
    fn noise_floor_to_power(&self) -> f64 {
        match self.noise_floor_db {
            Some(db) => 10.0_f64.powf(db / 10.0),
            None => panic!("Noise floor must be set before generating channel. Use set_noise_floor_db() or set_noise_floor_linear()"),
        }
    }
generate function · rust · L143-L218 (76 LOC)
src/generate/channel.rs
    pub fn generate<T: Float>(&self, num_samples: usize) -> ComplexVec<T> {
        if self.carriers.is_empty() {
            panic!("Channel must have at least one carrier");
        }

        // Get noise power from the noise floor (required for SNR scaling)
        let noise_power = self.noise_floor_to_power();

        // Generate, scale, and combine carriers to achieve target SNRs
        let mut combined = ComplexVec::new();
        for carrier in &self.carriers {
            // Generate clean signal
            let clean_signal = carrier.generate_clean::<T>(num_samples);

            // Calculate oversample rate for power measurement (accounts for in-band power)
            let oversample_rate = 1.0 / carrier.bandwidth;

            // Scale to achieve target SNR
            // SNR = P_signal / P_noise  =>  P_signal = SNR_linear * P_noise
            let snr_linear = 10.0_f64.powf(carrier.snr_db / 10.0);
            let target_power = snr_linear * noise_power;

            // S
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
generate_clean function · rust · L233-L266 (34 LOC)
src/generate/channel.rs
    pub fn generate_clean<T: Float>(&self, num_samples: usize) -> ComplexVec<T> {
        if self.carriers.is_empty() {
            panic!("Channel must have at least one carrier");
        }

        // Get noise power from the noise floor (required for SNR scaling)
        let noise_power = self.noise_floor_to_power();

        // Generate, scale, and combine clean signals from all carriers
        let mut combined = ComplexVec::new();
        for carrier in &self.carriers {
            // Generate clean signal
            let clean_signal = carrier.generate_clean::<T>(num_samples);

            // Calculate oversample rate for power measurement
            let oversample_rate = 1.0 / carrier.bandwidth;

            // Scale to achieve target SNR
            let snr_linear = 10.0_f64.powf(carrier.snr_db / 10.0);
            let target_power = snr_linear * noise_power;

            // Scale the carrier to target power
            let scaled_signal = clean_signal.scale_to_power(target_
test_channel_creation function · rust · L285-L297 (13 LOC)
src/generate/channel.rs
    fn test_channel_creation() {
        let carrier1 = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let channel = Channel::new(vec![carrier1]);
        assert_eq!(channel.num_carriers(), 1);
    }
test_channel_single_carrier function · rust · L300-L315 (16 LOC)
src/generate/channel.rs
    fn test_channel_single_carrier() {
        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let mut channel = Channel::new(vec![carrier]);
        channel.set_noise_floor_db(-100.0);

        let result = channel.generate::<f64>(1000);
        assert_eq!(result.len(), 1000);
    }
test_channel_two_carriers function · rust · L318-L343 (26 LOC)
src/generate/channel.rs
    fn test_channel_two_carriers() {
        let carrier1 = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let carrier2 = Carrier::new(
            ModType::_QPSK,
            0.1,
            -0.1,
            15.0,
            0.35,
            1e6,
            Some(43),
        );

        let mut channel = Channel::new(vec![carrier1, carrier2]);
        channel.set_noise_floor_db(-100.0);

        let result = channel.generate::<f64>(1000);
        assert_eq!(result.len(), 1000);
    }
test_channel_generate_clean function · rust · L346-L361 (16 LOC)
src/generate/channel.rs
    fn test_channel_generate_clean() {
        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let mut channel = Channel::new(vec![carrier]);
        channel.set_noise_floor_db(-100.0);

        let clean = channel.generate_clean::<f64>(1000);
        assert_eq!(clean.len(), 1000);
    }
test_channel_noise_floor_linear function · rust · L364-L381 (18 LOC)
src/generate/channel.rs
    fn test_channel_noise_floor_linear() {
        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let mut channel = Channel::new(vec![carrier]);

        // Set noise floor as linear value
        channel.set_noise_floor_linear(0.01);

        let result = channel.generate::<f64>(1000);
        assert_eq!(result.len(), 1000);
    }
test_channel_with_seed function · rust · L384-L421 (38 LOC)
src/generate/channel.rs
    fn test_channel_with_seed() {
        let carrier1 = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let carrier2 = Carrier::new(
            ModType::_QPSK,
            0.1,
            -0.1,
            10.0,
            0.35,
            1e6,
            Some(43),
        );

        // Generate with same seed - should get same result
        let mut channel1 = Channel::new(vec![carrier1.clone(), carrier2.clone()]);
        channel1.set_noise_floor_db(-100.0);
        channel1.set_seed(999);

        let mut channel2 = Channel::new(vec![carrier1, carrier2]);
        channel2.set_noise_floor_db(-100.0);
        channel2.set_seed(999);

        let result1 = channel1.generate::<f64>(1000);
        let result2 = channel2.generate::<f64>(1000);

        // Results should be identical with same seed
        for (s1, s2) in result1.iter().zip(result2.iter()) {
    
test_channel_no_noise_floor function · rust · L425-L439 (15 LOC)
src/generate/channel.rs
    fn test_channel_no_noise_floor() {
        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let channel = Channel::new(vec![carrier]);

        // Should panic because noise floor was never set
        let _ = channel.generate::<f64>(1000);
    }
Repobility · MCP-ready · https://repobility.com
test_channel_spectrum_with_snr_verification function · rust · L449-L538 (90 LOC)
src/generate/channel.rs
    fn test_channel_spectrum_with_snr_verification() {
        use crate::spectrum::welch::welch;
        use crate::spectrum::window::WindowType;
        use crate::vector_ops;
        use crate::plot::plot_spectrum;
        use crate::test_utils::should_plot;

        let sample_rate = 1e6;
        let num_samples = (2.0).powf(20.0) as usize;

        // Create two carriers with different target SNRs
        let carrier1 = Carrier::new(
            ModType::_QPSK,
            0.05,     // 50 kHz bandwidth (narrow)
            0.15,     // 150 kHz center freq
            10.0,     // Target 10 dB SNR
            0.35,     // RRC rolloff
            sample_rate,
            Some(42),
        );

        let carrier2 = Carrier::new(
            ModType::_16QAM,
            0.10,     // 100 kHz bandwidth (wider)
            -0.20,    // -200 kHz center freq
            5.0,      // Target 5 dB SNR
            0.35,
            sample_rate,
            Some(43),
        );

        // Def
test_channel_with_single_impairment function · rust · L541-L557 (17 LOC)
src/generate/channel.rs
    fn test_channel_with_single_impairment() {
        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            1e6,
            Some(42),
        );
        let mut channel = Channel::new(vec![carrier]);
        channel.set_noise_floor_db(-100.0);
        channel.add_impairment(Impairment::DigitizerDroopAD9361);

        let result = channel.generate::<f64>(1000);
        assert_eq!(result.len(), 1000);
    }
test_channel_with_multiple_impairments function · rust · L560-L639 (80 LOC)
src/generate/channel.rs
    fn test_channel_with_multiple_impairments() {
        use crate::spectrum::welch::welch;
        use crate::spectrum::window::WindowType;
        use crate::vector_ops;
        use crate::plot::plot_spectrum;
        use crate::test_utils::should_plot;

        let sample_rate = 1e6;
        let num_samples = 1_000_000;

        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.1,
            10.0,
            0.35,
            sample_rate,
            Some(1),
        );

        let carrier2 = Carrier::new(
            ModType::_QPSK,
            0.05,
            -0.25,
            3.0,
            0.20,
            sample_rate,
            Some(2),
        );

        let carrier3 = Carrier::new(
            ModType::_QPSK,
            0.02,
            0.2,
            5.0,
            0.15,
            sample_rate,
            Some(3),
        );

        let mut channel = Channel::new(vec![carrier, carrier2, carrier3]);
        channel.se
test_channel_with_custom_digitizer_droop function · rust · L642-L705 (64 LOC)
src/generate/channel.rs
    fn test_channel_with_custom_digitizer_droop() {
        use crate::spectrum::welch::welch;
        use crate::spectrum::window::WindowType;
        use crate::vector_ops;
        use crate::plot::plot_spectrum;
        use crate::test_utils::should_plot;

        let sample_rate = 1e6;
        let num_samples = 25000;

        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,
            0.0,
            10.0,
            0.35,
            sample_rate,
            Some(42),
        );

        let mut channel = Channel::new(vec![carrier]);
        channel.set_noise_floor_db(-50.0);
        channel.set_seed(999);

        // Add custom digitizer droop (4th order, higher cutoff)
        channel.add_impairment(Impairment::DigitizerDroop {
            order: 9,
            cutoff: 0.45,
        });

        let result = channel.generate::<f64>(num_samples);
        assert_eq!(result.len(), num_samples);

        println!("\n=== Channel with Custom Digitizer Droop
new function · rust · L15-L22 (8 LOC)
src/generate/cw.rs
    pub fn new(freq_hz: f64, sample_rate_hz: f64, block_size: usize) -> Self {
        CW {
            freq_hz: freq_hz,
            sample_rate_hz: sample_rate_hz,
            block_size: block_size,
            sample_num: 0,
        }
    }
generate_block function · rust · L23-L34 (12 LOC)
src/generate/cw.rs
    pub fn generate_block<T: Float>(&mut self) -> Vec<Complex<T>> {
        let mut cw_block = Vec::with_capacity(self.block_size);
        for _ in 0..self.block_size {
            let t: T = T::from(self.sample_num).unwrap() / T::from(self.sample_rate_hz).unwrap();
            let i = (T::from(2.0).unwrap() * T::from(PI).unwrap() * T::from(self.freq_hz).unwrap() * t).cos();
            let q = (T::from(2.0).unwrap() * T::from(PI).unwrap() * T::from(self.freq_hz).unwrap() * t).sin();
            cw_block.push(Complex::<T>::new(i, q));
            self.sample_num += 1;
        }
        cw_block
    }
test_cw_block_gen function · rust · L45-L69 (25 LOC)
src/generate/cw.rs
    fn test_cw_block_gen() {
        let block_size: usize = 1024;
        let num_blocks = 100;
        let freq_hz = -100e3;
        let sample_rate_hz = 500e3;
        let mut generator = CW::new(freq_hz, sample_rate_hz, block_size);

        let mut samples: Vec<_> = (0..num_blocks)
            .flat_map(|_| generator.generate_block::<f64>())
            .collect();

        assert_eq!(samples.len(), block_size * num_blocks);

        if crate::test_utils::should_plot() {
            fft::fft::<f64>(&mut samples);
            let mut cw_fft = ComplexVec::from_vec(samples);
            let mut cw_fft_abs: Vec<f64> = cw_fft.abs();

            fft::fftshift::<f64>(&mut cw_fft_abs);
            let freqs: Vec<f64> = fft::fftfreqs::<f64>((-sample_rate_hz/2_f64) as f64, (sample_rate_hz/2_f64) as f64, cw_fft_abs.len());

            use crate::plot::plot_spectrum;
            plot_spectrum(&freqs, &cw_fft_abs, "CW Signal Spectrum");
        }
    }
new function · rust · L53-L78 (26 LOC)
src/generate/fsk_carrier.rs
    pub fn new(
        sample_rate_hz: f64,
        symbol_rate_hz: f64,
        carrier_freq_hz: f64,
        freq_deviation_hz: f64,
        block_size: usize,
        seed: Option<u64>,
    ) -> Self {
        let samples_per_symbol = (sample_rate_hz / symbol_rate_hz).round() as usize;

        let bit_gen = match seed {
            Some(s) => BitGenerator::new_from_seed(s),
            None => BitGenerator::new_from_entropy(),
        };

        FskCarrier {
            sample_rate_hz: T::from(sample_rate_hz).unwrap(),
            symbol_rate_hz: T::from(symbol_rate_hz).unwrap(),
            carrier_freq_hz: T::from(carrier_freq_hz).unwrap(),
            freq_deviation_hz: T::from(freq_deviation_hz).unwrap(),
            block_size,
            accumulated_phase: T::zero(),
            bit_gen,
            samples_per_symbol,
        }
    }
If a scraper extracted this row, it came from Repobility (https://repobility.com)
generate_block function · rust · L88-L160 (73 LOC)
src/generate/fsk_carrier.rs
    pub fn generate_block(&mut self) -> ComplexVec<T> {
        let num_symbols = self.block_size / self.samples_per_symbol;
        let mut samples = Vec::with_capacity(self.block_size);

        let two_pi = T::from(2.0 * PI).unwrap();
        let half = T::from(0.5).unwrap();

        for _ in 0..num_symbols {
            // Get next bit
            let bit = self.bit_gen.next_bit();

            // Calculate instantaneous frequency for this symbol
            // bit 0 -> fc - Df/2
            // bit 1 -> fc + Df/2
            let freq = if bit {
                self.carrier_freq_hz + self.freq_deviation_hz * half
            } else {
                self.carrier_freq_hz - self.freq_deviation_hz * half
            };

            // Generate samples for this symbol
            for _ in 0..self.samples_per_symbol {
                // Calculate phase increment for this sample
                let phase_increment = two_pi * freq / self.sample_rate_hz;

                // Accumulate phas
test_fsk_basic function · rust · L181-L207 (27 LOC)
src/generate/fsk_carrier.rs
    fn test_fsk_basic() {
        let sample_rate = 1e6;
        let symbol_rate = 1e5;
        let carrier_freq = 2.5e5;
        let deviation = 5e4;
        let block_size = 1000;

        let mut fsk: FskCarrier<f64> = FskCarrier::new(
            sample_rate,
            symbol_rate,
            carrier_freq,
            deviation,
            block_size,
            Some(42),
        );

        let block = fsk.generate_block();

        // Verify block size
        assert_eq!(block.len(), block_size);

        // Verify samples are unit magnitude (approximately)
        for i in 0..block.len() {
            let mag = block[i].norm();
            assert!((mag - 1.0).abs() < 1e-10, "Sample {} has magnitude {}, expected 1.0", i, mag);
        }
    }
test_fsk_phase_continuity function · rust · L210-L241 (32 LOC)
src/generate/fsk_carrier.rs
    fn test_fsk_phase_continuity() {
        let sample_rate = 1e6;
        let symbol_rate = 1e5;
        let carrier_freq = 2.5e5;
        let deviation = 5e4;
        let block_size = 100;

        let mut fsk: FskCarrier<f64> = FskCarrier::new(
            sample_rate,
            symbol_rate,
            carrier_freq,
            deviation,
            block_size,
            Some(123),
        );

        // Generate multiple blocks and verify phase continuity
        let block1 = fsk.generate_block();
        let block2 = fsk.generate_block();

        // Blocks should not be identical (different random bits)
        let blocks_identical = block1.iter().zip(block2.iter()).all(|(a, b)| a == b);
        assert!(!blocks_identical, "Blocks should not be identical due to different random bits");

        // All samples should have unit magnitude
        for i in 0..block1.len() {
            assert!((block1[i].norm() - 1.0).abs() < 1e-10);
        }
        for i in 0..block2.len() {
test_fsk_modulation_index function · rust · L244-L251 (8 LOC)
src/generate/fsk_carrier.rs
    fn test_fsk_modulation_index() {
        let fsk: FskCarrier<f64> = FskCarrier::new(1e6, 1e5, 2.5e5, 5e4, 1000, Some(42));

        let h = fsk.modulation_index();

        // For these parameters: h = 50000 / 100000 = 0.5 (MSK)
        assert!((h - 0.5).abs() < 1e-10);
    }
test_fsk_with_awgn_spectrum function · rust · L254-L339 (86 LOC)
src/generate/fsk_carrier.rs
    fn test_fsk_with_awgn_spectrum() {
        use crate::test_utils::should_plot;
        
        if !should_plot() {
            println!("Skipping FSK with AWGN spectrum plot (set PLOT=true to enable)");
            return;
        }

        println!("\n=== FSK with AWGN Spectrum Test ===");

        // FSK parameters
        let sample_rate = 1e6_f64;
        let symbol_rate = 1e5_f64;
        let carrier_freq = 2.5e5_f64;
        let deviation = 5e4_f64;  // Two frequencies: 200 kHz and 300 kHz
        let block_size = 4096;

        println!("Sample rate: {} Hz", sample_rate);
        println!("Symbol rate: {} Hz", symbol_rate);
        println!("Carrier freq: {} Hz", carrier_freq);
        println!("Deviation: {} Hz", deviation);
        println!("Frequencies: {} Hz and {} Hz",
                 carrier_freq - deviation/2.0,
                 carrier_freq + deviation/2.0);

        // Generate FSK signal
        let mut fsk: FskCarrier<f64> = FskCarrier::new(
            sample_
apply function · rust · L120-L159 (40 LOC)
src/generate/impairment.rs
    pub fn apply(&self, signal: &mut [Complex<f64>]) {
        match self {
            Impairment::DigitizerDroop { order, cutoff } => {
                apply_butterworth_filter(signal, *order, *cutoff);
            }
            Impairment::DigitizerDroopAD9361 => {
                apply_digitizer_droop_ad9361(signal);
            }
            Impairment::DigitizerDroopTraditional => {
                apply_digitizer_droop_traditional(signal);
            }
            Impairment::FrequencyVariation {
                amplitude_db,
                cycles,
                phase_offset,
            } => {
                // Generate frequency-domain variation pattern
                let variation = frequency_dependent_amplitude_variation(
                    signal.len(),
                    *amplitude_db,
                    *cycles,
                    *phase_offset,
                );
                let variation_lin = to_linear(&variation);

                // Apply in frequency d
frequency_dependent_amplitude_variation function · rust · L161-L176 (16 LOC)
src/generate/impairment.rs
pub fn frequency_dependent_amplitude_variation<T: Float>(num_samples: usize, amplitude_db: T, cycles: T, phase_offset: T,
) -> Vec<T> {
    let pi = T::from(PI).unwrap();
    (0..num_samples)
        .into_iter()
        .map(|idx| {
            amplitude_db
                * (T::from(2.0).unwrap() * pi * T::from(idx).unwrap()
                    / T::from(num_samples).unwrap()
                    * cycles
                    + phase_offset)
                    .sin()
        })
            .collect()
    }
test_freq_ampl_variation function · rust · L251-L291 (41 LOC)
src/generate/impairment.rs
    fn test_freq_ampl_variation() {
        use crate::test_utils::should_plot;

        if !should_plot() {
            println!("Skipping frequency-dependent amplitude variation plot (set PLOT=true to enable)");
            return;
        }

        let sample_rate = 1e6_f64;
        let num_samples = (2.0_f64).powf(20.0) as usize;  // Use power of 2 for better FFT performance
        // Generate three different frequency variation patterns
        let freq_var_1 = frequency_dependent_amplitude_variation(num_samples, 1.0, 2.0, 0.0);
        let freq_var_2 = frequency_dependent_amplitude_variation(num_samples, 0.6, 5.0, 0.0);
        let freq_var_3 = frequency_dependent_amplitude_variation(num_samples, 0.4, 1.0, 1.5);
        // Combine all variations
        let total_variation_db = add(&add(&freq_var_1, &freq_var_2), &freq_var_3);
        let total_variation_lin = to_linear(&total_variation_db);
        // Generate white noise
        let mut awgn = AWGN::new_from_seed(sample_rate,
Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
test_random_freq_ampl_variation function · rust · L294-L345 (52 LOC)
src/generate/impairment.rs
    fn test_random_freq_ampl_variation() {
        use std::env;
        use std::f64::consts::PI;

        let plot = env::var("PLOT").unwrap_or_else(|_| "false".to_string());
        if plot.to_lowercase() != "true" {
            println!("Skipping frequency-dependent amplitude variation plot (set PLOT=true to enable)");
            return;
        }

        let seed = 2; // or any u64
        let mut rng = StdRng::seed_from_u64(seed);
        let sample_rate = 1e6_f64;
        let num_samples = (2.0_f64).powf(20.0) as usize;  // Use power of 2 for better FFT performance

        let mut awgn = AWGN::new_from_seed(sample_rate, num_samples, 1.0, 0);
        let mut noise: ComplexVec<f32> = awgn.generate_block();
        fft::fft(&mut noise);

        // Apply frequency-dependent amplitude variation in frequency domain
        let num_variations = rand::thread_rng().gen_range(1..=5);
        let mut freq_var_total: Vec<f32> = vec![0.0; num_samples];
        for _ in 0..num_variations 
test_digitizer_droop function · rust · L348-L440 (93 LOC)
src/generate/impairment.rs
    fn test_digitizer_droop() {
        use std::env;

        let plot = env::var("PLOT").unwrap_or_else(|_| "false".to_string());
        if plot.to_lowercase() != "true" {
            println!("Skipping digitizer droop plot (set PLOT=true to enable)");
            return;
        }

        println!("\n=== Digitizer Channel Droop Impairment ===\n");

        let sample_rate = 1e6;
        let n_samples = (2.0_f64).powf(20.0) as usize;

        // Generate white noise
        println!("Generating AWGN...");
        let mut awgn = AWGN::new_from_seed(sample_rate, n_samples, 1.0, 0);
        let noise: Vec<Complex<f64>> = awgn.generate_block::<f64>().to_vec();

        // Compute PSD of UNFILTERED noise
        let (freqs, psd_unfiltered) = welch(
            &noise,
            sample_rate,
            2048,
            None,
            None,
            WindowType::Hann,
            None,
        );
        let psd_unfiltered_db: Vec<f64> = vector_ops::to_db(&psd_unfiltered);

     
test_digitizer_droop_comparison function · rust · L443-L491 (49 LOC)
src/generate/impairment.rs
    fn test_digitizer_droop_comparison() {
        use std::env;

        let plot = env::var("PLOT").unwrap_or_else(|_| "false".to_string());
        if plot.to_lowercase() != "true" {
            println!("Skipping digitizer droop comparison plot (set PLOT=true to enable)");
            return;
        }

        println!("\n=== Digitizer Droop: Order Comparison ===\n");

        let sample_rate = 1e6;
        let n_samples = (2.0_f64).powf(20.0) as usize;

        // Generate white noise
        let mut awgn = AWGN::new_from_seed(sample_rate, n_samples, 1.0, 42);
        let noise: Vec<Complex<f64>> = awgn.generate_block::<f64>().to_vec();

        // Test different filter orders with same cutoff
        let cutoff = 0.45;
        let orders = vec![2, 3, 4, 6, 8];

        for order in orders {
            let mut filtered = noise.clone();
            apply_digitizer_droop(&mut filtered, order, cutoff);

            let (freqs, psd) = welch(
                &filtered,
              
test_digitizer_droop_on_carrier function · rust · L494-L563 (70 LOC)
src/generate/impairment.rs
    fn test_digitizer_droop_on_carrier() {
        use std::env;
        use crate::generate::carrier::Carrier;
        use crate::ModType;

        let plot = env::var("PLOT").unwrap_or_else(|_| "false".to_string());
        if plot.to_lowercase() != "true" {
            println!("Skipping digitizer droop on carrier plot (set PLOT=true to enable)");
            return;
        }

        println!("\n=== Digitizer Droop Applied to QPSK Carrier ===\n");

        let sample_rate = 1e6;
        let n_samples = (2.0_f64).powf(20.0) as usize;

        // Create a QPSK carrier
        let carrier = Carrier::new(
            ModType::_QPSK,
            0.1,        // 10% bandwidth
            0.0,        // Centered
            15.0,       // 15 dB SNR
            0.35,       // RRC rolloff
            sample_rate,
            Some(42),
        );

        // Generate clean carrier signal
        println!("Generating QPSK carrier (clean)...");
        let clean_signal: Vec<Complex<f64>> = car
new function · rust · L26-L71 (46 LOC)
src/generate/psk_carrier.rs
    pub fn new(sample_rate_hz: T, symbol_rate_hz: T, mod_type: ModType, rolloff_factor: T, block_size: usize, filter_taps: usize, seed: Option<u64>) -> Self {
        let bit_gen = match seed {
            Some(s) => BitGenerator::new_from_seed(s),
            None => BitGenerator::new_from_entropy(),
        };

        // Calculate integer upsampling factor
        // For 1MHz sample rate / 800kHz symbol rate = 1.25, we round to nearest integer
        let sps_exact = sample_rate_hz.to_f64().unwrap() / symbol_rate_hz.to_f64().unwrap();
        let samples_per_symbol = sps_exact.round() as usize;
        if samples_per_symbol == 0 {
            panic!("samples_per_symbol must be at least 1");
        }

        // Build RRC filter once during initialization
        let rrc = RRCFilter::new(
            filter_taps,
            sample_rate_hz.to_f64().unwrap(),
            symbol_rate_hz.to_f64().unwrap(),
            rolloff_factor.to_f64().unwrap(),
        );
        let rrc_filter 
generate_block function · rust · L72-L120 (49 LOC)
src/generate/psk_carrier.rs
    pub fn generate_block(&mut self) -> ComplexVec<T> {
        // Calculate how many symbols we need to generate to get block_size samples
        // For sps=1: 1 symbol -> 1 sample (after upsampling and filtering)
        // We need to account for the overlap and filter delay
        let num_symbols = if self.samples_per_symbol == 1 {
            self.block_size
        } else {
            // For upsampling: symbols * sps ≈ samples
            (self.block_size + self.samples_per_symbol - 1) / self.samples_per_symbol
        };

        // Generate symbols for this block using the pre-built modulation
        let new_symbols = self.generate_symbols(num_symbols);

        // Combine overlap from previous block with new symbols
        let mut all_symbols = self.overlap_symbols.clone();
        all_symbols.extend(new_symbols.iter().cloned());

        // Upsample symbols by inserting zeros between them
        let upsampled = if self.samples_per_symbol > 1 {
            self.upsample_
upsample_symbols function · rust · L123-L138 (16 LOC)
src/generate/psk_carrier.rs
    fn upsample_symbols(&self, symbols: &ComplexVec<T>) -> ComplexVec<T> {
        let mut upsampled = Vec::new();
        let zero = num_complex::Complex::new(T::zero(), T::zero());

        for i in 0..symbols.len() {
            upsampled.push(symbols[i]);
            // Insert (sps - 1) zeros after each symbol (except the last one)
            if i < symbols.len() - 1 {
                for _ in 0..(self.samples_per_symbol - 1) {
                    upsampled.push(zero);
                }
            }
        }

        ComplexVec::from_vec(upsampled)
    }
generate_symbols function · rust · L139-L204 (66 LOC)
src/generate/psk_carrier.rs
    fn generate_symbols(&mut self, count: usize) -> ComplexVec<T> {
        let mut symbols = Vec::new();

        match &self.modulation {
            modulation::Modulation::BPSK(bpsk) => {
                for _ in 0..count {
                    let bit = self.bit_gen.next_bit();
                    let bits = if bit { 1u8 } else { 0u8 };
                    if let Some(symbol) = bpsk.modulate(bits) {
                        symbols.push(symbol);
                    }
                }
            },
            modulation::Modulation::QPSK(qpsk) => {
                for _ in 0..count {
                    let bits = self.bit_gen.next_2_bits();
                    if let Some(symbol) = qpsk.modulate(bits) {
                        symbols.push(symbol);
                    }
                }
            },
            modulation::Modulation::PSK8(psk8) => {
                for _ in 0..count {
                    let bits = self.bit_gen.next_3_bits();
                    if let Some(
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
extract_last_symbols function · rust · L205-L218 (14 LOC)
src/generate/psk_carrier.rs
    fn extract_last_symbols(&self, symbols: &ComplexVec<T>, count: usize) -> ComplexVec<T> {
        let start_idx = if symbols.len() > count {
            symbols.len() - count
        } else {
            0
        };

        let mut last_symbols = Vec::new();
        for i in start_idx..symbols.len() {
            last_symbols.push(symbols[i]);
        }
        ComplexVec::from_vec(last_symbols)
    }
test_qpsk_carrier_block_gen function · rust · L229-L321 (93 LOC)
src/generate/psk_carrier.rs
    fn test_qpsk_carrier_block_gen() {
        let block_size: usize = 1e6 as usize;
        let num_blocks = 1;
        let sample_rate_hz = 1e6_f64;
        let symbol_rate_hz = 800e3_f64;
        let filter_taps = 51;
        let rolloff_factor = 0.05_f64;

        let mut carrier = PskCarrier::new(
            sample_rate_hz,
            symbol_rate_hz,
            ModType::_QPSK,
            rolloff_factor,
            block_size,
            filter_taps,
            Some(42), // Seed for reproducibility
        );

        println!("\n=== QPSK Carrier Configuration ===");
        println!("Block size: {}", block_size);
        println!("Sample rate: {} Hz", sample_rate_hz);
        println!("Symbol rate: {} Hz", symbol_rate_hz);
        println!("Samples per symbol: {}", carrier.samples_per_symbol);
        println!("Filter taps: {}", filter_taps);
        println!("Rolloff factor: {}", rolloff_factor);

        // Generate blocks and merge into single ComplexVec
        let mut 
test_qpsk_symbols_constellation function · rust · L324-L390 (67 LOC)
src/generate/psk_carrier.rs
    fn test_qpsk_symbols_constellation() {
        use std::env;
        use plotly::{Plot, Scatter};
        use plotly::common::Mode;

        let plot_env = env::var("PLOT").unwrap_or_else(|_| "false".to_string());
        if plot_env.to_lowercase() != "true" {
            println!("Skipping symbols constellation plot (set PLOT=true to enable)");
            return;
        }

        let sample_rate_hz = 1e6_f64;
        let symbol_rate_hz = 800e3_f64;
        let filter_taps = 51;
        let rolloff_factor = 0.05_f64;

        let mut carrier = PskCarrier::new(
            sample_rate_hz,
            symbol_rate_hz,
            ModType::_QPSK,
            rolloff_factor,
            1000, // Small block for visualization
            filter_taps,
            Some(42),
        );

        // Generate just the raw symbols (before pulse shaping) for visualization
        let num_symbols = 1000;
        let symbols = carrier.generate_symbols(num_symbols);

        // Extract I and Q v
‹ prevpage 3 / 7next ›