opus1 0.3.0

Pure-Rust implementation of the Opus audio codec (RFC 6716), following libopus 1.x
Documentation
//! The PLC model, which predicts the features of lost frames in deep packet
//! loss concealment (deep PLC): its layers and the constants of its C header.
//!
//! Generated by `tools/dnn-gen` from libopus 1.6.1 `dnn/plc_data.h` and
//! `dnn/plc_data.c` (`init_plcmodel`). Do not edit: change the generator and
//! run it again (`tools/dnn-gen/README.md`).

use crate::Error;
use super::{Layer, LayerSpec, LinearSpec};
use crate::dnn::nnet::LinearLayer;
use crate::dnn::weights::WeightList;

/// The file of this model's weights in `dnn-weights/`.
pub const BLOB_FILE: &str = "plc.bin";

// The constants of `dnn/plc_data.h`, in the same order.

/// `PLC_DENSE_IN_OUT_SIZE`.
pub const PLC_DENSE_IN_OUT_SIZE: usize = 128;

/// `PLC_DENSE_OUT_OUT_SIZE`.
pub const PLC_DENSE_OUT_OUT_SIZE: usize = 20;

/// `PLC_GRU1_OUT_SIZE`.
pub const PLC_GRU1_OUT_SIZE: usize = 192;

/// `PLC_GRU1_STATE_SIZE`.
pub const PLC_GRU1_STATE_SIZE: usize = 192;

/// `PLC_GRU2_OUT_SIZE`.
pub const PLC_GRU2_OUT_SIZE: usize = 192;

/// `PLC_GRU2_STATE_SIZE`.
pub const PLC_GRU2_STATE_SIZE: usize = 192;

/// `PLC_MAX_RNN_UNITS`.
pub const PLC_MAX_RNN_UNITS: usize = 192;

/// The layers in the order of `init_plcmodel`: the arrays that each one reads,
/// and its shape. The names are the array names of the blob.
pub const LAYERS: [LayerSpec; 6] = [
    LayerSpec::Linear(LinearSpec {
        name: "plc_dense_in",
        bias: Some("plc_dense_in_bias"),
        subias: None,
        weights: None,
        float_weights: Some("plc_dense_in_weights_float"),
        weights_idx: None,
        diag: None,
        scale: None,
        nb_inputs: 57,
        nb_outputs: 128,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "plc_dense_out",
        bias: Some("plc_dense_out_bias"),
        subias: None,
        weights: None,
        float_weights: Some("plc_dense_out_weights_float"),
        weights_idx: None,
        diag: None,
        scale: None,
        nb_inputs: 192,
        nb_outputs: 20,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "plc_gru1_input",
        bias: Some("plc_gru1_input_bias"),
        subias: Some("plc_gru1_input_subias"),
        weights: Some("plc_gru1_input_weights_int8"),
        float_weights: Some("plc_gru1_input_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("plc_gru1_input_scale"),
        nb_inputs: 128,
        nb_outputs: 576,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "plc_gru1_recurrent",
        bias: Some("plc_gru1_recurrent_bias"),
        subias: Some("plc_gru1_recurrent_subias"),
        weights: Some("plc_gru1_recurrent_weights_int8"),
        float_weights: Some("plc_gru1_recurrent_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("plc_gru1_recurrent_scale"),
        nb_inputs: 192,
        nb_outputs: 576,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "plc_gru2_input",
        bias: Some("plc_gru2_input_bias"),
        subias: Some("plc_gru2_input_subias"),
        weights: Some("plc_gru2_input_weights_int8"),
        float_weights: Some("plc_gru2_input_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("plc_gru2_input_scale"),
        nb_inputs: 192,
        nb_outputs: 576,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "plc_gru2_recurrent",
        bias: Some("plc_gru2_recurrent_bias"),
        subias: Some("plc_gru2_recurrent_subias"),
        weights: Some("plc_gru2_recurrent_weights_int8"),
        float_weights: Some("plc_gru2_recurrent_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("plc_gru2_recurrent_scale"),
        nb_inputs: 192,
        nb_outputs: 576,
    }),
];

/// libopus `PLCModel` (`dnn/plc_data.h`): the layers of the model, in the order
/// of the C struct. Each layer borrows its arrays from a weight list.
#[derive(Clone, Copy, Default)]
pub struct PlcModel<'w> {
    /// `plc_dense_in`: float weights, 57 inputs, 128 outputs.
    pub plc_dense_in: LinearLayer<'w>,
    /// `plc_dense_out`: float weights, 192 inputs, 20 outputs.
    pub plc_dense_out: LinearLayer<'w>,
    /// `plc_gru1_input`: int8 weights, 128 inputs, 576 outputs.
    pub plc_gru1_input: LinearLayer<'w>,
    /// `plc_gru1_recurrent`: int8 weights, 192 inputs, 576 outputs.
    pub plc_gru1_recurrent: LinearLayer<'w>,
    /// `plc_gru2_input`: int8 weights, 192 inputs, 576 outputs.
    pub plc_gru2_input: LinearLayer<'w>,
    /// `plc_gru2_recurrent`: int8 weights, 192 inputs, 576 outputs.
    pub plc_gru2_recurrent: LinearLayer<'w>,
}

impl<'w> PlcModel<'w> {
    /// libopus `init_plcmodel`: builds every layer from the arrays of `list`,
    /// in the order of `LAYERS`. Fails at the first layer whose arrays are
    /// missing, have the wrong size or are malformed; then nothing is built.
    pub fn init(list: &WeightList<'w>) -> Result<Self, Error> {
        Ok(PlcModel {
            plc_dense_in: LAYERS[0].linear(list)?,
            plc_dense_out: LAYERS[1].linear(list)?,
            plc_gru1_input: LAYERS[2].linear(list)?,
            plc_gru1_recurrent: LAYERS[3].linear(list)?,
            plc_gru2_input: LAYERS[4].linear(list)?,
            plc_gru2_recurrent: LAYERS[5].linear(list)?,
        })
    }

    /// Every layer, in the order of `LAYERS`.
    pub fn layers(&self) -> [Layer<'_, 'w>; 6] {
        [
            Layer::Linear(&self.plc_dense_in),
            Layer::Linear(&self.plc_dense_out),
            Layer::Linear(&self.plc_gru1_input),
            Layer::Linear(&self.plc_gru1_recurrent),
            Layer::Linear(&self.plc_gru2_input),
            Layer::Linear(&self.plc_gru2_recurrent),
        ]
    }
}