use alloc::vec::Vec;
use core::marker::PhantomData;
use crate::engine::Protocol;
use crate::fec::qra::FadingModel;
use crate::msg::ApHint;
use super::Q65Result;
use super::search::SearchParams;
pub trait Q65SubMode: Protocol {}
impl Q65SubMode for super::Q65a15 {}
impl Q65SubMode for super::Q65a30 {}
impl Q65SubMode for super::Q65a60 {}
impl Q65SubMode for super::Q65b60 {}
impl Q65SubMode for super::Q65c60 {}
impl Q65SubMode for super::Q65d60 {}
impl Q65SubMode for super::Q65e60 {}
impl Q65SubMode for super::Q65d120 {}
impl Q65SubMode for super::Q65e120 {}
impl Q65SubMode for super::Q65a300 {}
pub struct DecodeRequest<'a, P: Q65SubMode> {
audio: &'a [f32],
sample_rate: u32,
nominal_start_sample: usize,
params: SearchParams,
ap_hint: Option<&'a ApHint>,
ap_list: Option<&'a [[i32; 63]]>,
fading: Option<(FadingModel, f32)>,
_marker: PhantomData<P>,
}
impl<'a, P: Q65SubMode> DecodeRequest<'a, P> {
pub fn new(
audio: &'a [f32],
sample_rate: u32,
nominal_start_sample: usize,
params: SearchParams,
) -> Self {
Self {
audio,
sample_rate,
nominal_start_sample,
params,
ap_hint: None,
ap_list: None,
fading: None,
_marker: PhantomData,
}
}
pub fn sniper(
audio: &'a [f32],
sample_rate: u32,
start_sample: usize,
base_freq_hz: f32,
) -> SniperRequest<'a, P> {
SniperRequest::new(audio, sample_rate, start_sample, base_freq_hz)
}
pub fn ap_hint(mut self, hint: &'a ApHint) -> Self {
self.ap_hint = Some(hint);
self
}
pub fn ap_list(mut self, candidates: &'a [[i32; 63]]) -> Self {
self.ap_list = Some(candidates);
self
}
pub fn fading(mut self, model: FadingModel, b90_ts: f32) -> Self {
self.fading = Some((model, b90_ts));
self
}
pub fn decode(&self) -> Vec<Q65Result> {
if let Some(candidates) = self.ap_list {
return super::rx::decode_scan_with_ap_list_for::<P>(
self.audio,
self.sample_rate,
self.nominal_start_sample,
&self.params,
candidates,
);
}
if let Some((model, b90_ts)) = self.fading {
return super::rx::decode_scan_fading_for::<P>(
self.audio,
self.sample_rate,
self.nominal_start_sample,
&self.params,
b90_ts,
model,
self.ap_hint,
);
}
match self.ap_hint {
Some(hint) => super::rx::decode_scan_with_ap_for::<P>(
self.audio,
self.sample_rate,
self.nominal_start_sample,
&self.params,
hint,
),
None => super::rx::decode_scan_for::<P>(
self.audio,
self.sample_rate,
self.nominal_start_sample,
&self.params,
),
}
}
}
pub struct SniperRequest<'a, P: Q65SubMode> {
audio: &'a [f32],
sample_rate: u32,
start_sample: usize,
base_freq_hz: f32,
ap_hint: Option<&'a ApHint>,
ap_list: Option<&'a [[i32; 63]]>,
fading: Option<(FadingModel, f32)>,
_marker: PhantomData<P>,
}
impl<'a, P: Q65SubMode> SniperRequest<'a, P> {
pub fn new(audio: &'a [f32], sample_rate: u32, start_sample: usize, base_freq_hz: f32) -> Self {
Self {
audio,
sample_rate,
start_sample,
base_freq_hz,
ap_hint: None,
ap_list: None,
fading: None,
_marker: PhantomData,
}
}
pub fn ap_hint(mut self, hint: &'a ApHint) -> Self {
self.ap_hint = Some(hint);
self
}
pub fn ap_list(mut self, candidates: &'a [[i32; 63]]) -> Self {
self.ap_list = Some(candidates);
self
}
pub fn fading(mut self, model: FadingModel, b90_ts: f32) -> Self {
self.fading = Some((model, b90_ts));
self
}
pub fn decode(&self) -> Option<Q65Result> {
if let Some(candidates) = self.ap_list {
return super::rx::decode_at_with_ap_list_for::<P>(
self.audio,
self.sample_rate,
self.start_sample,
self.base_freq_hz,
candidates,
);
}
if let Some((model, b90_ts)) = self.fading {
return super::rx::decode_at_fading_for::<P>(
self.audio,
self.sample_rate,
self.start_sample,
self.base_freq_hz,
b90_ts,
model,
self.ap_hint,
);
}
match self.ap_hint {
Some(hint) => super::rx::decode_at_with_ap_for::<P>(
self.audio,
self.sample_rate,
self.start_sample,
self.base_freq_hz,
hint,
),
None => super::rx::decode_at_for::<P>(
self.audio,
self.sample_rate,
self.start_sample,
self.base_freq_hz,
),
}
}
}
pub struct MultiPeriodRequest<'a, P: Q65SubMode> {
audio_slots: &'a [&'a [f32]],
sample_rate: u32,
nominal_start_sample: usize,
params: SearchParams,
ap_list: Option<&'a [[i32; 63]]>,
_marker: PhantomData<P>,
}
impl<'a, P: Q65SubMode> MultiPeriodRequest<'a, P> {
pub fn new(
audio_slots: &'a [&'a [f32]],
sample_rate: u32,
nominal_start_sample: usize,
params: SearchParams,
) -> Self {
Self {
audio_slots,
sample_rate,
nominal_start_sample,
params,
ap_list: None,
_marker: PhantomData,
}
}
pub fn ap_list(mut self, candidates: &'a [[i32; 63]]) -> Self {
self.ap_list = Some(candidates);
self
}
pub fn decode(&self) -> Vec<Q65Result> {
super::rx::decode_multi_period_for::<P>(
self.audio_slots,
self.sample_rate,
self.nominal_start_sample,
&self.params,
self.ap_list,
)
}
}