opus1 0.3.0

Pure-Rust implementation of the Opus audio codec (RFC 6716), following libopus 1.x
Documentation
//! PitchDNN, the pitch estimator of 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/pitchdnn_data.h` and
//! `dnn/pitchdnn_data.c` (`init_pitchdnn`). Do not edit: change the generator
//! and run it again (`tools/dnn-gen/README.md`).

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

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

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

/// `DENSE_IF_UPSAMPLER_1_OUT_SIZE`.
pub const DENSE_IF_UPSAMPLER_1_OUT_SIZE: usize = 64;

/// `DENSE_IF_UPSAMPLER_2_OUT_SIZE`.
pub const DENSE_IF_UPSAMPLER_2_OUT_SIZE: usize = 64;

/// `DENSE_DOWNSAMPLER_OUT_SIZE`.
pub const DENSE_DOWNSAMPLER_OUT_SIZE: usize = 64;

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

/// `GRU_1_OUT_SIZE`.
pub const GRU_1_OUT_SIZE: usize = 64;

/// `GRU_1_STATE_SIZE`.
pub const GRU_1_STATE_SIZE: usize = 64;

/// `PITCH_DNN_MAX_RNN_UNITS`.
pub const PITCH_DNN_MAX_RNN_UNITS: usize = 64;

/// The layers in the order of `init_pitchdnn`: the arrays that each one reads,
/// and its shape. The names are the array names of the blob.
pub const LAYERS: [LayerSpec; 8] = [
    LayerSpec::Linear(LinearSpec {
        name: "dense_if_upsampler_1",
        bias: Some("dense_if_upsampler_1_bias"),
        subias: Some("dense_if_upsampler_1_subias"),
        weights: Some("dense_if_upsampler_1_weights_int8"),
        float_weights: Some("dense_if_upsampler_1_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("dense_if_upsampler_1_scale"),
        nb_inputs: 88,
        nb_outputs: 64,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "dense_if_upsampler_2",
        bias: Some("dense_if_upsampler_2_bias"),
        subias: Some("dense_if_upsampler_2_subias"),
        weights: Some("dense_if_upsampler_2_weights_int8"),
        float_weights: Some("dense_if_upsampler_2_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("dense_if_upsampler_2_scale"),
        nb_inputs: 64,
        nb_outputs: 64,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "dense_downsampler",
        bias: Some("dense_downsampler_bias"),
        subias: Some("dense_downsampler_subias"),
        weights: Some("dense_downsampler_weights_int8"),
        float_weights: Some("dense_downsampler_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("dense_downsampler_scale"),
        nb_inputs: 288,
        nb_outputs: 64,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "dense_final_upsampler",
        bias: Some("dense_final_upsampler_bias"),
        subias: Some("dense_final_upsampler_subias"),
        weights: Some("dense_final_upsampler_weights_int8"),
        float_weights: Some("dense_final_upsampler_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("dense_final_upsampler_scale"),
        nb_inputs: 64,
        nb_outputs: 192,
    }),
    LayerSpec::Conv2d(Conv2dSpec {
        name: "conv2d_1",
        bias: Some("conv2d_1_bias"),
        float_weights: Some("conv2d_1_weight_float"),
        in_channels: 1,
        out_channels: 4,
        ktime: 3,
        kheight: 3,
    }),
    LayerSpec::Conv2d(Conv2dSpec {
        name: "conv2d_2",
        bias: Some("conv2d_2_bias"),
        float_weights: Some("conv2d_2_weight_float"),
        in_channels: 4,
        out_channels: 1,
        ktime: 3,
        kheight: 3,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "gru_1_input",
        bias: Some("gru_1_input_bias"),
        subias: Some("gru_1_input_subias"),
        weights: Some("gru_1_input_weights_int8"),
        float_weights: Some("gru_1_input_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("gru_1_input_scale"),
        nb_inputs: 64,
        nb_outputs: 192,
    }),
    LayerSpec::Linear(LinearSpec {
        name: "gru_1_recurrent",
        bias: Some("gru_1_recurrent_bias"),
        subias: Some("gru_1_recurrent_subias"),
        weights: Some("gru_1_recurrent_weights_int8"),
        float_weights: Some("gru_1_recurrent_weights_float"),
        weights_idx: None,
        diag: None,
        scale: Some("gru_1_recurrent_scale"),
        nb_inputs: 64,
        nb_outputs: 192,
    }),
];

/// libopus `PitchDNN` (`dnn/pitchdnn_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 PitchDnn<'w> {
    /// `dense_if_upsampler_1`: int8 weights, 88 inputs, 64 outputs.
    pub dense_if_upsampler_1: LinearLayer<'w>,
    /// `dense_if_upsampler_2`: int8 weights, 64 inputs, 64 outputs.
    pub dense_if_upsampler_2: LinearLayer<'w>,
    /// `dense_downsampler`: int8 weights, 288 inputs, 64 outputs.
    pub dense_downsampler: LinearLayer<'w>,
    /// `dense_final_upsampler`: int8 weights, 64 inputs, 192 outputs.
    pub dense_final_upsampler: LinearLayer<'w>,
    /// `conv2d_1`: conv2d, 1 input channel and 4 output channels, kernel 3 × 3
    /// (time × height).
    pub conv2d_1: Conv2dLayer<'w>,
    /// `conv2d_2`: conv2d, 4 input channels and 1 output channel, kernel 3 × 3
    /// (time × height).
    pub conv2d_2: Conv2dLayer<'w>,
    /// `gru_1_input`: int8 weights, 64 inputs, 192 outputs.
    pub gru_1_input: LinearLayer<'w>,
    /// `gru_1_recurrent`: int8 weights, 64 inputs, 192 outputs.
    pub gru_1_recurrent: LinearLayer<'w>,
}

impl<'w> PitchDnn<'w> {
    /// libopus `init_pitchdnn`: 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(PitchDnn {
            dense_if_upsampler_1: LAYERS[0].linear(list)?,
            dense_if_upsampler_2: LAYERS[1].linear(list)?,
            dense_downsampler: LAYERS[2].linear(list)?,
            dense_final_upsampler: LAYERS[3].linear(list)?,
            conv2d_1: LAYERS[4].conv2d(list)?,
            conv2d_2: LAYERS[5].conv2d(list)?,
            gru_1_input: LAYERS[6].linear(list)?,
            gru_1_recurrent: LAYERS[7].linear(list)?,
        })
    }

    /// Every layer, in the order of `LAYERS`.
    pub fn layers(&self) -> [Layer<'_, 'w>; 8] {
        [
            Layer::Linear(&self.dense_if_upsampler_1),
            Layer::Linear(&self.dense_if_upsampler_2),
            Layer::Linear(&self.dense_downsampler),
            Layer::Linear(&self.dense_final_upsampler),
            Layer::Conv2d(&self.conv2d_1),
            Layer::Conv2d(&self.conv2d_2),
            Layer::Linear(&self.gru_1_input),
            Layer::Linear(&self.gru_1_recurrent),
        ]
    }
}