diff --git a/docs/framework/operators/tensor/tensor.mel_weight_matrix.md b/docs/framework/operators/tensor/tensor.mel_weight_matrix.md new file mode 100644 index 000000000..548f28e8e --- /dev/null +++ b/docs/framework/operators/tensor/tensor.mel_weight_matrix.md @@ -0,0 +1,51 @@ +# TensorTrait::mel_weight_matrix + +```rust + fn mel_weight_matrix(num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: T, upper_edge_hertz: T) -> Tensor; +``` + +Generate a MelWeightMatrix that can be used to re-weight a Tensor containing a linearly sampled frequency spectra (from DFT or STFT) into num_mel_bins frequency information based on the [lower_edge_hertz, upper_edge_hertz] range on the mel scale. +This function defines the mel scale in terms of a frequency in hertz according to the following formula: +``` +mel(f) = 2595 * log10(1 + f/700) +``` +In the returned matrix, all the triangles (filterbanks) have a peak value of 1.0. +The returned MelWeightMatrix can be used to right-multiply a spectrogram S of shape [frames, num_spectrogram_bins] of linear scale spectrum values (e.g. STFT magnitudes) to generate a “mel spectrogram” M of shape [frames, num_mel_bins]. +## Args + +* `num_mel_bins `(`usize`) - The number of bands in the mel spectrum. +* `dft_length `(`usize`) - The size of the original DFT. The size of the original DFT is used to infer the size of the onesided DFT, which is understood to be floor(dft_length/2) + 1, i.e. the spectrogram only contains the nonredundant DFT bins. +* `sample_rate `(`usize`) - Samples per second of the input signal used to create the spectrogram. Used to figure out the frequencies corresponding to each spectrogram bin, which dictates how they are mapped into the mel scale. +* `lower_edge_hertz `(T) - Lower bound on the frequencies to be included in the mel spectrum. This corresponds to the lower edge of the lowest triangular band. +* `upper_edge_hertz `(T) - The desired top edge of the highest frequency band. + +## Returns + +* A `Tensor` The Mel Weight Matrix. The output has the shape: [floor(dft_length/2) + 1][num_mel_bins]. + +## Examples + +```rust +use orion::operators::tensor::{FP16x16Tensor, FP16x16TensorAdd}; +use core::array::{ArrayTrait, SpanTrait}; +use orion::operators::tensor::FP16x16TensorPartialEq; +use orion::utils::{assert_eq, assert_seq_eq}; +use orion::operators::tensor::{TensorTrait, Tensor}; +use orion::numbers::{FixedTrait, FP16x16}; + + +fn example() -> Tensor { + return TensorTrait::mel_weight_matrix(8, 16, 8192, FP16x16 { mag: 0, sign: false }, FP16x16 { mag: 268435456, sign: false }); +} +>>> [ + [65536, 65536, 0, 0, 0, 0, 0, 0], + [0, 0, 65536, 65536, 0, 0, 0, 0], + [0, 0, 0, 0, 65536, 0, 0, 0], + [0, 0, 0, 0, 0, 65536, 0, 0], + [0, 0, 0, 0, 0, 0, 65536, 0], + [0, 0, 0, 0, 0, 0, 0, 65536], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + ] +``` diff --git a/nodegen/node/mel_weight_matrix.py b/nodegen/node/mel_weight_matrix.py new file mode 100644 index 000000000..e7bb707ad --- /dev/null +++ b/nodegen/node/mel_weight_matrix.py @@ -0,0 +1,97 @@ +import numpy as np +from nodegen.node import RunAll +from ..helpers import make_test, to_fp, Tensor, Dtype, FixedImpl, Trait, get_data_statement + +def mel_weight_matrix(num_mel_bins, dft_length, sample_rate, lower_edge_hertz, upper_edge_hertz) -> np.ndarray: # type: ignore + # num_mel_bins = np.int32(8) + # dft_length = np.int32(16) + # sample_rate = np.int32(8192) + # lower_edge_hertz = np.float32(0) + # upper_edge_hertz = np.float32(8192 / 2) + num_spectrogram_bins = dft_length // 2 + 1 + frequency_bins = np.arange(0, num_mel_bins + 2) + + low_frequency_mel = 2595 * np.log10(1 + lower_edge_hertz / 700) + high_frequency_mel = 2595 * np.log10(1 + upper_edge_hertz / 700) + mel_step = (high_frequency_mel - low_frequency_mel) / frequency_bins.shape[0] + + frequency_bins = frequency_bins * mel_step + low_frequency_mel + frequency_bins = 700 * (np.power(10, (frequency_bins / 2595)) - 1) + frequency_bins = ((dft_length + 1) * frequency_bins) // sample_rate + frequency_bins = frequency_bins.astype(int) + + output = np.zeros((num_spectrogram_bins, num_mel_bins)) + output.flags.writeable = True + + for i in range(num_mel_bins): + lower_frequency_value = frequency_bins[i] # left + center_frequency_point = frequency_bins[i + 1] # center + higher_frequency_point = frequency_bins[i + 2] # right + low_to_center = center_frequency_point - lower_frequency_value + if low_to_center == 0: + output[center_frequency_point, i] = 1 + else: + for j in range(lower_frequency_value, center_frequency_point + 1): + output[j, i] = float(j - lower_frequency_value) / float( + low_to_center + ) + center_to_high = higher_frequency_point - center_frequency_point + if center_to_high > 0: + for j in range(center_frequency_point, higher_frequency_point): + output[j, i] = float(higher_frequency_point - j) / float( + center_to_high + ) + return output + + +class Mel_weight_matrix(RunAll): + + # @staticmethod + # # We test here with u32 implementation. + # def u32(): + # num_mel_bins = np.int32(8) + # dft_length = np.int32(16) + # sample_rate = np.int32(256) + # lower_edge_hertz = np.int32(0) + # upper_edge_hertz = np.int32(256 / 2) + # args_str = get_data_statement(np.array([lower_edge_hertz, upper_edge_hertz]), Dtype.U32) + # y = mel_weight_matrix(num_mel_bins, dft_length, sample_rate, lower_edge_hertz, upper_edge_hertz) + # print(y) + + # # Convert the floats values in `y` to fixed points with `to_fp` method: + # y = Tensor(Dtype.U32, y.shape, y.flatten()) + + # # Define the name of the generated folder. + # name = "mel_weight_matrix_u32" + # # Invoke `make_test` method to generate corresponding Cairo tests: + # make_test( + # [], # List of input tensors. + # y, # The expected output result. + # f"TensorTrait::mel_weight_matrix({f'{num_mel_bins}, {dft_length}, {sample_rate}, '+', '.join(args_str)})", # The code signature. + # name # The name of the generated folder. + # ) + + @staticmethod + # We test here with fp16x16 implementation. + def fp16x16(): + num_mel_bins = np.int32(8) + dft_length = np.int32(16) + sample_rate = np.int32(8192) + lower_edge_hertz = np.float32(0) + upper_edge_hertz = np.float32(8192 / 2) + args_str = get_data_statement(to_fp(np.array([lower_edge_hertz, upper_edge_hertz]).flatten(), FixedImpl.FP16x16), Dtype.FP16x16) + y = mel_weight_matrix(num_mel_bins, dft_length, sample_rate, lower_edge_hertz, upper_edge_hertz) + print(y) + + # Convert the floats values in `y` to fixed points with `to_fp` method: + y = Tensor(Dtype.FP16x16, y.shape, to_fp(y.flatten(), FixedImpl.FP16x16)) + + # Define the name of the generated folder. + name = "mel_weight_matrix_fp16x16" + # Invoke `make_test` method to generate corresponding Cairo tests: + make_test( + [], # List of input tensors. + y, # The expected output result. + f"TensorTrait::mel_weight_matrix({f'{num_mel_bins}, {dft_length}, {sample_rate}, '+', '.join(args_str)})", # The code signature. + name # The name of the generated folder. + ) \ No newline at end of file diff --git a/src/operators/tensor/core.cairo b/src/operators/tensor/core.cairo index 0d21a4de3..3bb0dbddf 100644 --- a/src/operators/tensor/core.cairo +++ b/src/operators/tensor/core.cairo @@ -131,6 +131,7 @@ impl TensorSerde, impl TDrop: Drop> of Serde8Bit conversion of FP32 Input data. /// scatter_nd - The output of the operation is produced by creating a copy of the input data, and then updating its value to values specified by updates at specific index positions specified by indices. Its output shape is the same as the shape of data /// label_encoder - Maps each element in the input tensor to another value. +/// mel_weight_matrix - Generate a MelWeightMatrix that can be used to re-weight a Tensor containing a linearly sampled frequency spectra (from DFT or STFT) into num_mel_bins frequency information based on the [lower_edge_hertz, upper_edge_hertz] range on the mel scale. trait TensorTrait { /// # tensor.new /// @@ -5850,6 +5851,61 @@ trait TensorTrait { values: Option>, values_tensor: Option> ) -> Tensor; + /// # TensorTrait::mel_weight_matrix + /// + /// ```rust + /// fn mel_weight_matrix(num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: T, upper_edge_hertz: T) -> Tensor; + /// ``` + /// + /// Generate a MelWeightMatrix that can be used to re-weight a Tensor containing a linearly sampled frequency spectra (from DFT or STFT) into num_mel_bins frequency information based on the [lower_edge_hertz, upper_edge_hertz] range on the mel scale. + /// This function defines the mel scale in terms of a frequency in hertz according to the following formula: + /// ``` + /// mel(f) = 2595 * log10(1 + f/700) + /// ``` + /// In the returned matrix, all the triangles (filterbanks) have a peak value of 1.0. + /// The returned MelWeightMatrix can be used to right-multiply a spectrogram S of shape [frames, num_spectrogram_bins] of linear scale spectrum values (e.g. STFT magnitudes) to generate a “mel spectrogram” M of shape [frames, num_mel_bins]. + /// ## Args + /// + /// * `num_mel_bins `(`usize`) - The number of bands in the mel spectrum. + /// * `dft_length `(`usize`) - The size of the original DFT. The size of the original DFT is used to infer the size of the onesided DFT, which is understood to be floor(dft_length/2) + 1, i.e. the spectrogram only contains the nonredundant DFT bins. + /// * `sample_rate `(`usize`) - Samples per second of the input signal used to create the spectrogram. Used to figure out the frequencies corresponding to each spectrogram bin, which dictates how they are mapped into the mel scale. + /// * `lower_edge_hertz `(T) - Lower bound on the frequencies to be included in the mel spectrum. This corresponds to the lower edge of the lowest triangular band. + /// * `upper_edge_hertz `(T) - The desired top edge of the highest frequency band. + /// + /// ## Returns + /// + /// * A `Tensor` The Mel Weight Matrix. The output has the shape: [floor(dft_length/2) + 1][num_mel_bins]. + /// + /// ## Examples + /// + /// ```rust + /// use orion::operators::tensor::{FP16x16Tensor, FP16x16TensorAdd}; + /// use core::array::{ArrayTrait, SpanTrait}; + /// use orion::operators::tensor::FP16x16TensorPartialEq; + /// use orion::utils::{assert_eq, assert_seq_eq}; + /// use orion::operators::tensor::{TensorTrait, Tensor}; + /// use orion::numbers::{FixedTrait, FP16x16}; + /// + /// + /// fn example() -> Tensor { + /// return TensorTrait::mel_weight_matrix(8, 16, 8192, FP16x16 { mag: 0, sign: false }, FP16x16 { mag: 268435456, sign: false }); + /// } + /// >>> [ + /// [65536, 65536, 0, 0, 0, 0, 0, 0], + /// [0, 0, 65536, 65536, 0, 0, 0, 0], + /// [0, 0, 0, 0, 65536, 0, 0, 0], + /// [0, 0, 0, 0, 0, 65536, 0, 0], + /// [0, 0, 0, 0, 0, 0, 65536, 0], + /// [0, 0, 0, 0, 0, 0, 0, 65536], + /// [0, 0, 0, 0, 0, 0, 0, 0], + /// [0, 0, 0, 0, 0, 0, 0, 0], + /// [0, 0, 0, 0, 0, 0, 0, 0], + /// ] + /// ``` + /// + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: T, upper_edge_hertz: T + ) -> Tensor; } /// Cf: TensorTrait::new docstring diff --git a/src/operators/tensor/implementations/tensor_bool.cairo b/src/operators/tensor/implementations/tensor_bool.cairo index 612a397cc..b3d4a9795 100644 --- a/src/operators/tensor/implementations/tensor_bool.cairo +++ b/src/operators/tensor/implementations/tensor_bool.cairo @@ -547,6 +547,12 @@ impl BoolTensor of TensorTrait { ) -> Tensor { panic(array!['not supported!']) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: bool, upper_edge_hertz: bool + ) -> Tensor{ + panic(array!['not supported!']) + } } /// Implements partial equal for two `Tensor` using the `PartialEq` trait. diff --git a/src/operators/tensor/implementations/tensor_complex64.cairo b/src/operators/tensor/implementations/tensor_complex64.cairo index c9c31ae23..8782da586 100644 --- a/src/operators/tensor/implementations/tensor_complex64.cairo +++ b/src/operators/tensor/implementations/tensor_complex64.cairo @@ -585,6 +585,12 @@ impl Complex64Tensor of TensorTrait { ) -> Tensor { panic(array!['not supported!']) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: complex64, upper_edge_hertz: complex64 + ) -> Tensor{ + panic(array!['not supported!']) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/tensor_fp16x16.cairo b/src/operators/tensor/implementations/tensor_fp16x16.cairo index a37ed0442..ea7fa2573 100644 --- a/src/operators/tensor/implementations/tensor_fp16x16.cairo +++ b/src/operators/tensor/implementations/tensor_fp16x16.cairo @@ -639,6 +639,12 @@ impl FP16x16Tensor of TensorTrait { self, default_list, default_tensor, keys, keys_tensor, values, values_tensor ) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: FP16x16, upper_edge_hertz: FP16x16 + ) -> Tensor{ + math::mel_weight_matrix::mel_weight_matrix(num_mel_bins, dft_length, sample_rate, lower_edge_hertz, upper_edge_hertz) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/tensor_fp16x16wide.cairo b/src/operators/tensor/implementations/tensor_fp16x16wide.cairo index 2003b28ff..d097030b8 100644 --- a/src/operators/tensor/implementations/tensor_fp16x16wide.cairo +++ b/src/operators/tensor/implementations/tensor_fp16x16wide.cairo @@ -599,6 +599,12 @@ impl FP16x16WTensor of TensorTrait { self, default_list, default_tensor, keys, keys_tensor, values, values_tensor ) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: FP16x16W, upper_edge_hertz: FP16x16W + ) -> Tensor{ + math::mel_weight_matrix::mel_weight_matrix(num_mel_bins, dft_length, sample_rate, lower_edge_hertz, upper_edge_hertz) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/tensor_fp32x32.cairo b/src/operators/tensor/implementations/tensor_fp32x32.cairo index 4870226a1..15c7b5797 100644 --- a/src/operators/tensor/implementations/tensor_fp32x32.cairo +++ b/src/operators/tensor/implementations/tensor_fp32x32.cairo @@ -635,6 +635,12 @@ impl FP32x32Tensor of TensorTrait { self, default_list, default_tensor, keys, keys_tensor, values, values_tensor ) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: FP32x32, upper_edge_hertz: FP32x32 + ) -> Tensor{ + math::mel_weight_matrix::mel_weight_matrix(num_mel_bins, dft_length, sample_rate, lower_edge_hertz, upper_edge_hertz) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/tensor_fp64x64.cairo b/src/operators/tensor/implementations/tensor_fp64x64.cairo index 3a7214d18..35a32e218 100644 --- a/src/operators/tensor/implementations/tensor_fp64x64.cairo +++ b/src/operators/tensor/implementations/tensor_fp64x64.cairo @@ -635,6 +635,12 @@ impl FP64x64Tensor of TensorTrait { self, default_list, default_tensor, keys, keys_tensor, values, values_tensor ) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: FP64x64, upper_edge_hertz: FP64x64 + ) -> Tensor{ + math::mel_weight_matrix::mel_weight_matrix(num_mel_bins, dft_length, sample_rate, lower_edge_hertz, upper_edge_hertz) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/tensor_fp8x23.cairo b/src/operators/tensor/implementations/tensor_fp8x23.cairo index b4a26d749..3d5499114 100644 --- a/src/operators/tensor/implementations/tensor_fp8x23.cairo +++ b/src/operators/tensor/implementations/tensor_fp8x23.cairo @@ -633,6 +633,12 @@ impl FP8x23Tensor of TensorTrait { self, default_list, default_tensor, keys, keys_tensor, values, values_tensor ) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: FP8x23, upper_edge_hertz: FP8x23 + ) -> Tensor{ + panic(array!['not supported!']) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/tensor_fp8x23wide.cairo b/src/operators/tensor/implementations/tensor_fp8x23wide.cairo index 06a297b69..d084529a2 100644 --- a/src/operators/tensor/implementations/tensor_fp8x23wide.cairo +++ b/src/operators/tensor/implementations/tensor_fp8x23wide.cairo @@ -576,6 +576,12 @@ impl FP8x23WTensor of TensorTrait { self, default_list, default_tensor, keys, keys_tensor, values, values_tensor ) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: FP8x23W, upper_edge_hertz: FP8x23W + ) -> Tensor{ + panic(array!['not supported!']) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/tensor_i32.cairo b/src/operators/tensor/implementations/tensor_i32.cairo index 296876516..e3f901f28 100644 --- a/src/operators/tensor/implementations/tensor_i32.cairo +++ b/src/operators/tensor/implementations/tensor_i32.cairo @@ -599,6 +599,12 @@ impl I32Tensor of TensorTrait { self, default_list, default_tensor, keys, keys_tensor, values, values_tensor ) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: i32, upper_edge_hertz: i32 + ) -> Tensor{ + panic(array!['not supported!']) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/tensor_i8.cairo b/src/operators/tensor/implementations/tensor_i8.cairo index 42d807c68..cbd1cd871 100644 --- a/src/operators/tensor/implementations/tensor_i8.cairo +++ b/src/operators/tensor/implementations/tensor_i8.cairo @@ -602,6 +602,12 @@ impl I8Tensor of TensorTrait { self, default_list, default_tensor, keys, keys_tensor, values, values_tensor ) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: i8, upper_edge_hertz: i8 + ) -> Tensor{ + panic(array!['not supported!']) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/tensor_u32.cairo b/src/operators/tensor/implementations/tensor_u32.cairo index efb681a86..4893b2c01 100644 --- a/src/operators/tensor/implementations/tensor_u32.cairo +++ b/src/operators/tensor/implementations/tensor_u32.cairo @@ -546,6 +546,13 @@ impl U32Tensor of TensorTrait { self, default_list, default_tensor, keys, keys_tensor, values, values_tensor ) } + + fn mel_weight_matrix( + num_mel_bins: usize, dft_length: usize, sample_rate: usize, lower_edge_hertz: u32, upper_edge_hertz: u32 + ) -> Tensor{ + // Blocking at the 'log10' operator + panic(array!['not supported!']) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/math.cairo b/src/operators/tensor/math.cairo index b73f6d102..6ab14aa2e 100644 --- a/src/operators/tensor/math.cairo +++ b/src/operators/tensor/math.cairo @@ -68,3 +68,4 @@ mod hann_window; mod hamming_window; mod blackman_window; mod scatter_nd; +mod mel_weight_matrix; diff --git a/src/operators/tensor/math/mel_weight_matrix.cairo b/src/operators/tensor/math/mel_weight_matrix.cairo new file mode 100644 index 000000000..d6d43d8bd --- /dev/null +++ b/src/operators/tensor/math/mel_weight_matrix.cairo @@ -0,0 +1,129 @@ +use orion::numbers::fixed_point::core::FixedTrait; +use orion::numbers::NumberTrait; +use orion::operators::tensor::core::{Tensor, TensorTrait}; + +#[derive(Copy, Drop)] + +fn mel_weight_matrix< + T, + MAG, + impl TTensor: TensorTrait, + impl TNumber: NumberTrait, + impl TAdd: Add, + impl TSub: Sub, + impl TMul: Mul, + impl TDiv: Div, + impl TTensorAdd: Add>, + impl TPartialOrd: PartialOrd, + impl TAddEq: AddEq, + impl TCopy: Copy, + impl TDrop: Drop, + impl TTryInto: TryInto, + impl TInto: Into, +>( + num_mel_bins: usize, + dft_length: usize, + sample_rate: usize, + lower_edge_hertz: T, + upper_edge_hertz: T, +) -> Tensor { + let num_spectrogram_bins: usize = dft_length / 2 + 1; + let range_len = num_mel_bins + 2; + let range_len_T = NumberTrait::new_unscaled(range_len.into(), false); + let mut frequency_bins: Tensor = TensorTrait::range(NumberTrait::zero(), range_len_T, NumberTrait::one()); + let mut data: Array = array![]; + + // mel = 2595 * log10(1+f/700) + let mel_magic: usize = 2595; + let corner_frequency: usize = 700; + let power: usize = 10; + let mel_magic_T = NumberTrait::new_unscaled(mel_magic.into(), false); + let corner_frequency_T = NumberTrait::new_unscaled(corner_frequency.into(), false); + let power_T = NumberTrait::new_unscaled(power.into(), false); + + let low_frequency_mel: T = mel_magic_T * NumberTrait::log10(NumberTrait::one() + lower_edge_hertz / corner_frequency_T); + let high_frequency_mel: T = mel_magic_T * NumberTrait::log10(NumberTrait::one() + upper_edge_hertz / corner_frequency_T); + let mel_step: T = (high_frequency_mel - low_frequency_mel) / NumberTrait::new_unscaled((*frequency_bins.shape[0]).into(), false); + + + let mut frequency_bins_temp: Array = array![]; + let mut ones: Array<(usize, usize)> = array![]; + loop { + match (frequency_bins.data).pop_front() { + Option::Some(item) => { + let mut frequency_bin: T = *item * mel_step + low_frequency_mel; + frequency_bin = corner_frequency_T * (NumberTrait::pow(power_T, (frequency_bin / mel_magic_T)) - NumberTrait::one()); + frequency_bin = (NumberTrait::new_unscaled((dft_length + 1).into(), false) * frequency_bin) / NumberTrait::new_unscaled(sample_rate.into(), false); + let frequency_bin_int_type: u32 = NumberTrait::floor(frequency_bin).try_into().unwrap(); + frequency_bins_temp.append(frequency_bin_int_type); + }, + Option::None => { break; } + }; + }; + let mut index = 0; + while index < num_mel_bins{ + let lower_frequency_value = *frequency_bins_temp[index]; // left + let center_frequency_point = *frequency_bins_temp[index + 1]; // center + let higher_frequency_point = *frequency_bins_temp[index + 2]; // right + let low_to_center = center_frequency_point - lower_frequency_value; + + if low_to_center == 0{ + ones.append((center_frequency_point, index)); + } else { + let mut i = lower_frequency_value; + while center_frequency_point + 1 > i { + if (i-lower_frequency_value) / low_to_center == 1 { + ones.append((i, index)); + } + i += 1; + }; + } + let center_to_high = higher_frequency_point - center_frequency_point; + if center_to_high > 0 { + let mut i = center_frequency_point; + while higher_frequency_point > i { + if (higher_frequency_point-i) / center_to_high == 1 { + ones.append((i, index)); + } + i += 1; + }; + } + index += 1; + + }; + // Fall in data + loop { + match (ones).pop_front() { + // num_mel_bins * X + Y >= data_len + Option::Some((x, y)) => { + + if num_mel_bins * x + y > data.len() { + let mut distance = num_mel_bins * x + y - data.len(); + while distance > 0 { + data.append(NumberTrait::zero()); + distance -= 1; + }; + } + + if num_mel_bins * x + y >= data.len(){ + data.append(NumberTrait::one()); + } + + + }, + Option::None => { + // Complement + let output_len = num_spectrogram_bins*num_mel_bins; + while output_len > data.len() { + data.append(NumberTrait::zero()); + }; + break; + } + }; + }; + + TensorTrait::::new(array![num_spectrogram_bins, num_mel_bins].span(), data.span()) + +} + + diff --git a/tests/nodes.cairo b/tests/nodes.cairo index 29bebb762..f0a788069 100644 --- a/tests/nodes.cairo +++ b/tests/nodes.cairo @@ -1047,3 +1047,4 @@ mod label_encoder_fp8x23_default; mod label_encoder_i8_default; mod label_encoder_i32_default; mod label_encoder_u32_default; +mod mel_weight_matrix_fp16x16; diff --git a/tests/nodes/mel_weight_matrix_fp16x16.cairo b/tests/nodes/mel_weight_matrix_fp16x16.cairo new file mode 100644 index 000000000..56b94aee9 --- /dev/null +++ b/tests/nodes/mel_weight_matrix_fp16x16.cairo @@ -0,0 +1,20 @@ +mod output_0; + + +use orion::operators::tensor::{FP16x16Tensor, FP16x16TensorAdd}; +use core::array::{ArrayTrait, SpanTrait}; +use orion::operators::tensor::FP16x16TensorPartialEq; +use orion::utils::{assert_eq, assert_seq_eq}; +use orion::operators::tensor::{TensorTrait, Tensor}; +use orion::numbers::{FixedTrait, FP16x16}; + + +#[test] +#[available_gas(2000000000)] +fn test_mel_weight_matrix_fp16x16() { + let z_0 = output_0::output_0(); + + let y_0 = TensorTrait::mel_weight_matrix(8, 16, 8192, FP16x16 { mag: 0, sign: false }, FP16x16 { mag: 268435456, sign: false }); + + assert_eq(y_0, z_0); +} diff --git a/tests/nodes/mel_weight_matrix_fp16x16/output_0.cairo b/tests/nodes/mel_weight_matrix_fp16x16/output_0.cairo new file mode 100644 index 000000000..e493f283c --- /dev/null +++ b/tests/nodes/mel_weight_matrix_fp16x16/output_0.cairo @@ -0,0 +1,85 @@ +use core::array::{ArrayTrait, SpanTrait}; +use orion::operators::tensor::{TensorTrait, Tensor}; +use orion::operators::tensor::{FP16x16Tensor, FP16x16TensorAdd}; +use orion::numbers::{FixedTrait, FP16x16}; + +fn output_0() -> Tensor { + let mut shape = ArrayTrait::::new(); + shape.append(9); + shape.append(8); + + let mut data = ArrayTrait::new(); + data.append(FP16x16 { mag: 65536, sign: false }); + data.append(FP16x16 { mag: 65536, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 65536, sign: false }); + data.append(FP16x16 { mag: 65536, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 65536, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 65536, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 65536, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 65536, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + data.append(FP16x16 { mag: 0, sign: false }); + TensorTrait::new(shape.span(), data.span()) +}