use crate::Error;
use super::holder::DnnModels;
use super::nnet::{Conv2dLayer, LinearLayer};
use super::weights::{WeightList, conv2d_init, linear_init};
#[cfg(feature = "deep-plc")]
pub mod pitchdnn;
#[cfg(feature = "deep-plc")]
pub mod plc;
#[cfg(feature = "deep-plc")]
pub mod fargan;
#[cfg(feature = "dred")]
pub mod dred_rdovae_enc;
#[cfg(feature = "dred")]
pub mod dred_rdovae_dec;
#[cfg(feature = "dred")]
pub mod dred_rdovae_stats;
#[cfg(feature = "osce")]
pub mod lace;
#[cfg(feature = "osce")]
pub mod nolace;
#[cfg(feature = "osce-bwe")]
pub mod bbwenet;
pub const ERR_LAYER_KIND: Error = Error::internal("DNN layer has another kind");
pub const ERR_NO_MODEL: Error = Error::bad_arg("DNN blob holds no model of this build");
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct LinearSpec {
pub name: &'static str,
pub bias: Option<&'static str>,
pub subias: Option<&'static str>,
pub weights: Option<&'static str>,
pub float_weights: Option<&'static str>,
pub weights_idx: Option<&'static str>,
pub diag: Option<&'static str>,
pub scale: Option<&'static str>,
pub nb_inputs: usize,
pub nb_outputs: usize,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Conv2dSpec {
pub name: &'static str,
pub bias: Option<&'static str>,
pub float_weights: Option<&'static str>,
pub in_channels: usize,
pub out_channels: usize,
pub ktime: usize,
pub kheight: usize,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LayerSpec {
Linear(LinearSpec),
Conv2d(Conv2dSpec),
}
impl LayerSpec {
pub const fn name(&self) -> &'static str {
match self {
LayerSpec::Linear(s) => s.name,
LayerSpec::Conv2d(s) => s.name,
}
}
pub fn linear<'w>(&self, list: &WeightList<'w>) -> Result<LinearLayer<'w>, Error> {
match self {
LayerSpec::Linear(s) => linear_init(
list,
s.bias,
s.subias,
s.weights,
s.float_weights,
s.weights_idx,
s.diag,
s.scale,
s.nb_inputs,
s.nb_outputs,
),
LayerSpec::Conv2d(_) => Err(ERR_LAYER_KIND),
}
}
pub fn conv2d<'w>(&self, list: &WeightList<'w>) -> Result<Conv2dLayer<'w>, Error> {
match self {
LayerSpec::Conv2d(s) => {
conv2d_init(list, s.bias, s.float_weights, s.in_channels, s.out_channels, s.ktime, s.kheight)
}
LayerSpec::Linear(_) => Err(ERR_LAYER_KIND),
}
}
}
#[derive(Clone, Copy)]
pub enum Layer<'a, 'w> {
Linear(&'a LinearLayer<'w>),
Conv2d(&'a Conv2dLayer<'w>),
}
#[cfg(feature = "deep-plc")]
#[derive(Clone, Copy, Default)]
pub struct DeepPlcModels<'w> {
pub plc: plc::PlcModel<'w>,
pub pitchdnn: pitchdnn::PitchDnn<'w>,
pub fargan: fargan::Fargan<'w>,
}
#[cfg(feature = "deep-plc")]
impl<'w> DeepPlcModels<'w> {
pub fn init(list: &WeightList<'w>) -> Result<Self, Error> {
Ok(DeepPlcModels {
plc: plc::PlcModel::init(list)?,
pitchdnn: pitchdnn::PitchDnn::init(list)?,
fargan: fargan::Fargan::init(list)?,
})
}
}
#[cfg(feature = "dred")]
#[derive(Clone, Copy, Default)]
pub struct DredEncModels<'w> {
pub rdovae: dred_rdovae_enc::RdovaeEnc<'w>,
pub pitchdnn: pitchdnn::PitchDnn<'w>,
}
#[cfg(feature = "dred")]
impl<'w> DredEncModels<'w> {
pub fn init(list: &WeightList<'w>) -> Result<Self, Error> {
Ok(DredEncModels {
rdovae: dred_rdovae_enc::RdovaeEnc::init(list)?,
pitchdnn: pitchdnn::PitchDnn::init(list)?,
})
}
}
#[derive(Clone, Copy, Default)]
pub struct ModelSet<'w> {
#[cfg(feature = "deep-plc")]
pub deep_plc: Option<DeepPlcModels<'w>>,
#[cfg(feature = "osce")]
pub lace: Option<lace::LaceLayers<'w>>,
#[cfg(feature = "osce")]
pub nolace: Option<nolace::NolaceLayers<'w>>,
#[cfg(feature = "osce-bwe")]
pub bbwenet: Option<bbwenet::BbwenetLayers<'w>>,
_weights: core::marker::PhantomData<&'w [u8]>,
}
impl<'w> ModelSet<'w> {
pub const fn new() -> Self {
ModelSet {
#[cfg(feature = "deep-plc")]
deep_plc: None,
#[cfg(feature = "osce")]
lace: None,
#[cfg(feature = "osce")]
nolace: None,
#[cfg(feature = "osce-bwe")]
bbwenet: None,
_weights: core::marker::PhantomData,
}
}
pub(crate) unsafe fn write_new(this: *mut Self) {
unsafe {
crate::in_place::write_fields!(this, {
#[cfg(feature = "deep-plc")]
deep_plc: None,
#[cfg(feature = "osce")]
lace: None,
#[cfg(feature = "osce")]
nolace: None,
#[cfg(feature = "osce-bwe")]
bbwenet: None,
_weights: core::marker::PhantomData,
});
}
}
pub fn models(&self) -> DnnModels {
#[allow(unused_mut)]
let mut m = DnnModels::NONE;
#[cfg(feature = "deep-plc")]
if self.deep_plc.is_some() {
m = m.union(DnnModels::DEEP_PLC);
}
#[cfg(feature = "osce")]
if self.lace.is_some() {
m = m.union(DnnModels::LACE);
}
#[cfg(feature = "osce")]
if self.nolace.is_some() {
m = m.union(DnnModels::NOLACE);
}
#[cfg(feature = "osce-bwe")]
if self.bbwenet.is_some() {
m = m.union(DnnModels::BBWENET);
}
m
}
pub fn load(&mut self, list: &WeightList<'w>) -> Result<DnnModels, Error> {
#[allow(unused_mut)]
let mut loaded = DnnModels::NONE;
#[cfg(feature = "deep-plc")]
if let Ok(m) = DeepPlcModels::init(list) {
self.deep_plc = Some(m);
loaded = loaded.union(DnnModels::DEEP_PLC);
}
#[cfg(feature = "osce")]
if let Ok(m) = lace::LaceLayers::init(list) {
self.lace = Some(m);
loaded = loaded.union(DnnModels::LACE);
}
#[cfg(feature = "osce")]
if let Ok(m) = nolace::NolaceLayers::init(list) {
self.nolace = Some(m);
loaded = loaded.union(DnnModels::NOLACE);
}
#[cfg(feature = "osce-bwe")]
if let Ok(m) = bbwenet::BbwenetLayers::init(list) {
self.bbwenet = Some(m);
loaded = loaded.union(DnnModels::BBWENET);
}
#[cfg(not(feature = "deep-plc"))]
let _ = list;
if loaded.is_empty() { Err(ERR_NO_MODEL) } else { Ok(loaded) }
}
}