forked from huawei/mindspore2022
!16667 [assistant][ComplexNorm]
Merge pull request !16667 from QingfengLi/ComplexNorm
This commit is contained in:
commit
4ba337e0f5
|
|
@ -23,6 +23,7 @@
|
|||
#include "minddata/dataset/audio/ir/kernels/bandpass_biquad_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/bandreject_biquad_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/bass_biquad_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/complex_norm_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/frequency_masking_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/time_masking_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/time_stretch_ir.h"
|
||||
|
|
@ -136,6 +137,16 @@ std::shared_ptr<TensorOperation> BassBiquad::Parse() {
|
|||
return std::make_shared<BassBiquadOperation>(data_->sample_rate_, data_->gain_, data_->central_freq_, data_->Q_);
|
||||
}
|
||||
|
||||
// ComplexNorm Transform Operation.
|
||||
struct ComplexNorm::Data {
|
||||
explicit Data(float power) : power_(power) {}
|
||||
float power_;
|
||||
};
|
||||
|
||||
ComplexNorm::ComplexNorm(float power) : data_(std::make_shared<Data>(power)) {}
|
||||
|
||||
std::shared_ptr<TensorOperation> ComplexNorm::Parse() { return std::make_shared<ComplexNormOperation>(data_->power_); }
|
||||
|
||||
// FrequencyMasking Transform Operation.
|
||||
struct FrequencyMasking::Data {
|
||||
Data(bool iid_masks, int32_t frequency_mask_param, int32_t mask_start, double mask_value)
|
||||
|
|
@ -190,6 +201,7 @@ TimeStretch::TimeStretch(float hop_length, int n_freq, float fixed_rate)
|
|||
std::shared_ptr<TensorOperation> TimeStretch::Parse() {
|
||||
return std::make_shared<TimeStretchOperation>(data_->hop_length_, data_->n_freq_, data_->fixed_rate_);
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "minddata/dataset/audio/ir/kernels/bandpass_biquad_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/bandreject_biquad_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/bass_biquad_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/complex_norm_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/frequency_masking_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/time_masking_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/time_stretch_ir.h"
|
||||
|
|
@ -117,6 +118,17 @@ PYBIND_REGISTER(
|
|||
}));
|
||||
}));
|
||||
|
||||
PYBIND_REGISTER(
|
||||
ComplexNormOperation, 1, ([](const py::module *m) {
|
||||
(void)py::class_<audio::ComplexNormOperation, TensorOperation, std::shared_ptr<audio::ComplexNormOperation>>(
|
||||
*m, "ComplexNormOperation")
|
||||
.def(py::init([](float power) {
|
||||
auto complex_norm = std::make_shared<audio::ComplexNormOperation>(power);
|
||||
THROW_IF_ERROR(complex_norm->ValidateParams());
|
||||
return complex_norm;
|
||||
}));
|
||||
}));
|
||||
|
||||
PYBIND_REGISTER(
|
||||
FrequencyMaskingOperation, 1, ([](const py::module *m) {
|
||||
(void)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ add_library(audio-ir-kernels OBJECT
|
|||
bandpass_biquad_ir.cc
|
||||
bandreject_biquad_ir.cc
|
||||
bass_biquad_ir.cc
|
||||
complex_norm_ir.cc
|
||||
frequency_masking_ir.cc
|
||||
time_masking_ir.cc
|
||||
time_stretch_ir.cc
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "minddata/dataset/audio/ir/kernels/complex_norm_ir.h"
|
||||
|
||||
#include "minddata/dataset/audio/ir/validators.h"
|
||||
#include "minddata/dataset/audio/kernels/complex_norm_op.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
|
||||
namespace audio {
|
||||
|
||||
ComplexNormOperation::ComplexNormOperation(float power) : power_(power) {}
|
||||
|
||||
ComplexNormOperation::~ComplexNormOperation() = default;
|
||||
|
||||
Status ComplexNormOperation::ValidateParams() {
|
||||
RETURN_IF_NOT_OK(ValidateFloatScalarNonNegative("ComplexNorm", "power", power_));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status ComplexNormOperation::to_json(nlohmann::json *out_json) {
|
||||
nlohmann::json args;
|
||||
args["power"] = power_;
|
||||
*out_json = args;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
std::shared_ptr<TensorOp> ComplexNormOperation::Build() {
|
||||
std::shared_ptr<ComplexNormOp> tensor_op = std::make_shared<ComplexNormOp>(power_);
|
||||
return tensor_op;
|
||||
}
|
||||
|
||||
std::string ComplexNormOperation::Name() const { return kComplexNormOperation; }
|
||||
|
||||
} // namespace audio
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_IR_KERNELS_COMPLEX_NORM_IR_H_
|
||||
#define MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_IR_KERNELS_COMPLEX_NORM_IR_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "include/api/status.h"
|
||||
#include "minddata/dataset/kernels/ir/tensor_operation.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
namespace audio {
|
||||
|
||||
constexpr char kComplexNormOperation[] = "ComplexNorm";
|
||||
|
||||
class ComplexNormOperation : public TensorOperation {
|
||||
public:
|
||||
explicit ComplexNormOperation(float power);
|
||||
|
||||
~ComplexNormOperation();
|
||||
|
||||
std::shared_ptr<TensorOp> Build() override;
|
||||
|
||||
Status ValidateParams() override;
|
||||
|
||||
std::string Name() const override;
|
||||
|
||||
Status to_json(nlohmann::json *out_json) override;
|
||||
|
||||
private:
|
||||
float power_;
|
||||
}; // class ComplexNormOperation
|
||||
|
||||
} // namespace audio
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_IR_KERNELS_COMPLEX_NORM_IR_H_
|
||||
|
|
@ -10,6 +10,7 @@ add_library(audio-kernels OBJECT
|
|||
bandpass_biquad_op.cc
|
||||
bandreject_biquad_op.cc
|
||||
bass_biquad_op.cc
|
||||
complex_norm_op.cc
|
||||
frequency_masking_op.cc
|
||||
time_masking_op.cc
|
||||
time_stretch_op.cc
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@
|
|||
|
||||
#include "minddata/dataset/audio/kernels/audio_utils.h"
|
||||
|
||||
#include <complex>
|
||||
|
||||
#include "mindspore/core/base/float16.h"
|
||||
#include "minddata/dataset/core/type_id.h"
|
||||
#include "minddata/dataset/kernels/data/data_utils.h"
|
||||
#include "minddata/dataset/util/random.h"
|
||||
#include "minddata/dataset/util/status.h"
|
||||
|
||||
|
|
@ -412,5 +417,93 @@ Status MaskAlongAxis(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tenso
|
|||
*output = input;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status Norm(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, float power) {
|
||||
// calcutate total complex num
|
||||
int32_t dim = input->shape().Size();
|
||||
int32_t total_num = 1;
|
||||
for (int32_t i = 0; i < (dim - 1); i++) {
|
||||
total_num *= (input->shape()[i]);
|
||||
}
|
||||
|
||||
// calculate the output dimension
|
||||
auto input_size = input->shape().AsVector();
|
||||
int32_t dim_back = input_size.back();
|
||||
CHECK_FAIL_RETURN_UNEXPECTED(
|
||||
dim_back == 2, "ComplexNorm: expect complex input of shape <..., 2>, but got: " + std::to_string(dim_back));
|
||||
input_size.pop_back();
|
||||
int32_t complex_num = input_size.back();
|
||||
int32_t iter_num = total_num / complex_num;
|
||||
// TensorShape out_put_shape{}
|
||||
input_size.pop_back();
|
||||
input_size.emplace_back(2);
|
||||
TensorShape out_shape = TensorShape(input_size);
|
||||
RETURN_IF_NOT_OK(Tensor::CreateEmpty(out_shape, input->type(), output));
|
||||
|
||||
// slice input into real tensor and imaginary tensor
|
||||
std::shared_ptr<Tensor> re_tensor;
|
||||
std::shared_ptr<Tensor> im_tensor;
|
||||
RETURN_IF_NOT_OK(Tensor::CreateEmpty(TensorShape({total_num, 1}), input->type(), &re_tensor));
|
||||
RETURN_IF_NOT_OK(Tensor::CreateEmpty(TensorShape({total_num, 1}), input->type(), &im_tensor));
|
||||
std::vector<SliceOption> slice_re = {};
|
||||
std::vector<SliceOption> slice_im = {};
|
||||
for (int32_t i = 0; i < (dim - 1); i++) {
|
||||
slice_re.emplace_back(SliceOption(true));
|
||||
slice_im.emplace_back(SliceOption(true));
|
||||
}
|
||||
slice_re.emplace_back(SliceOption(std::vector<dsize_t>{0}));
|
||||
slice_im.emplace_back(SliceOption(std::vector<dsize_t>{1}));
|
||||
RETURN_IF_NOT_OK(input->Slice(&re_tensor, slice_re));
|
||||
RETURN_IF_NOT_OK(input->Slice(&im_tensor, slice_im));
|
||||
|
||||
// calculate norm, using: .pow(2.).sum(-1).pow(0.5 * power)
|
||||
auto itr_out = (*output)->begin<T>();
|
||||
auto itr_re = re_tensor->begin<T>();
|
||||
auto itr_im = im_tensor->begin<T>();
|
||||
for (int32_t i = 0; i < iter_num; i++) {
|
||||
double re = 0.0;
|
||||
double im = 0.0;
|
||||
for (int32_t j = complex_num * i; j < complex_num * (i + 1); j++) {
|
||||
double a = static_cast<double>(*itr_re);
|
||||
double b = static_cast<double>(*itr_im);
|
||||
re = re + (pow(a, 2) - pow(b, 2));
|
||||
im = im + (2 * a * b);
|
||||
++itr_re;
|
||||
++itr_im;
|
||||
}
|
||||
std::complex<double> comp(re, im);
|
||||
comp = std::pow(comp, (0.5 * power));
|
||||
*itr_out = static_cast<T>(comp.real());
|
||||
++itr_out;
|
||||
*itr_out = static_cast<T>(comp.imag());
|
||||
++itr_out;
|
||||
}
|
||||
RETURN_IF_NOT_OK((*output)->Reshape(out_shape));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status ComplexNorm(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, float power) {
|
||||
try {
|
||||
if (input->type().value() >= DataType::DE_INT8 && input->type().value() <= DataType::DE_FLOAT16) {
|
||||
// convert the data type to float
|
||||
std::shared_ptr<Tensor> input_tensor;
|
||||
RETURN_IF_NOT_OK(Tensor::CreateEmpty(input->shape(), DataType(DataType::DE_FLOAT32), &input_tensor));
|
||||
RETURN_IF_NOT_OK(TypeCast(input, &input_tensor, DataType(DataType::DE_FLOAT32)));
|
||||
|
||||
Norm<float>(input_tensor, output, power);
|
||||
} else if (input->type().value() == DataType::DE_FLOAT32) {
|
||||
Norm<float>(input, output, power);
|
||||
} else if (input->type().value() == DataType::DE_FLOAT64) {
|
||||
Norm<double>(input, output, power);
|
||||
} else {
|
||||
RETURN_STATUS_UNEXPECTED("ComplexNorm: input tensor type should be int, float or double, but got: " +
|
||||
input->type().ToString());
|
||||
}
|
||||
return Status::OK();
|
||||
} catch (std::runtime_error &e) {
|
||||
RETURN_STATUS_UNEXPECTED("ComplexNorm: " + std::string(e.what()));
|
||||
}
|
||||
}
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
|
|
|||
|
|
@ -245,6 +245,14 @@ Status RandomMaskAlongAxis(const std::shared_ptr<Tensor> &input, std::shared_ptr
|
|||
/// \return Status code.
|
||||
Status MaskAlongAxis(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, int64_t mask_width,
|
||||
int64_t mask_start, double mask_value, int axis);
|
||||
|
||||
/// \brief Compute the norm of complex tensor input.
|
||||
/// \param power Power of the norm description (optional).
|
||||
/// \param input Tensor shape of <..., complex=2>.
|
||||
/// \param output Tensor shape of <..., complex=2>.
|
||||
/// \return Status code.
|
||||
Status ComplexNorm(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, float power);
|
||||
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_AUDIO_UTILS_H_
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "minddata/dataset/audio/kernels/complex_norm_op.h"
|
||||
|
||||
#include "minddata/dataset/audio/kernels/audio_utils.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
|
||||
// constructor
|
||||
ComplexNormOp::ComplexNormOp(float power) : power_(power) {}
|
||||
|
||||
// main function
|
||||
Status ComplexNormOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
|
||||
IO_CHECK(input, output);
|
||||
CHECK_FAIL_RETURN_UNEXPECTED(input->Rank() >= 2, "ComplexNorm: input tensor is not in shape of <..., 2>.");
|
||||
|
||||
return ComplexNorm(input, output, power_);
|
||||
}
|
||||
|
||||
Status ComplexNormOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
|
||||
RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs));
|
||||
outputs.clear();
|
||||
auto input_size = inputs[0].AsVector();
|
||||
input_size.pop_back();
|
||||
input_size.pop_back();
|
||||
input_size.emplace_back(2);
|
||||
TensorShape out = TensorShape(input_size);
|
||||
outputs.emplace_back(out);
|
||||
if (!outputs.empty()) return Status::OK();
|
||||
return Status(StatusCode::kMDUnexpectedError, "ComplexNorm: invalid input shape.");
|
||||
}
|
||||
|
||||
Status ComplexNormOp::OutputType(const std::vector<DataType> &inputs, std::vector<DataType> &outputs) {
|
||||
RETURN_IF_NOT_OK(TensorOp::OutputType(inputs, outputs));
|
||||
if (inputs[0] == DataType(DataType::DE_FLOAT64)) {
|
||||
outputs[0] = DataType(DataType::DE_FLOAT64);
|
||||
} else {
|
||||
outputs[0] = DataType(DataType::DE_FLOAT32);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
void ComplexNormOp::Print(std::ostream &out) const { out << "ComplexNormOp: power " << power_; }
|
||||
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_COMPLEX_NORM_OP_H_
|
||||
#define MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_COMPLEX_NORM_OP_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "minddata/dataset/core/tensor.h"
|
||||
#include "minddata/dataset/kernels/tensor_op.h"
|
||||
#include "minddata/dataset/util/status.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
|
||||
class ComplexNormOp : public TensorOp {
|
||||
public:
|
||||
/// \brief Constructor for ComplexNormOp.
|
||||
/// \param[in] power Power of the norm (Optional).
|
||||
explicit ComplexNormOp(float power = 1.0);
|
||||
|
||||
~ComplexNormOp() override = default;
|
||||
|
||||
void Print(std::ostream &out) const override;
|
||||
|
||||
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
|
||||
|
||||
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
|
||||
|
||||
Status OutputType(const std::vector<DataType> &inputs, std::vector<DataType> &outputs) override;
|
||||
|
||||
std::string Name() const override { return kComplexNormOp; }
|
||||
|
||||
private:
|
||||
float power_;
|
||||
};
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_COMPLEX_NORM_OP_H_
|
||||
|
|
@ -188,6 +188,27 @@ class BassBiquad final : public TensorTransform {
|
|||
std::shared_ptr<Data> data_;
|
||||
};
|
||||
|
||||
/// \brief ComplexNorm TensorTransform.
|
||||
/// \notes Compute the norm of complex tensor input.
|
||||
class ComplexNorm final : public TensorTransform {
|
||||
public:
|
||||
/// \brief Constructor.
|
||||
/// \param[in] power Power of the norm, which must be non-negative (Default: 1.0).
|
||||
explicit ComplexNorm(float power = 1.0);
|
||||
|
||||
/// \brief Destructor.
|
||||
~ComplexNorm() = default;
|
||||
|
||||
protected:
|
||||
/// \brief Function to convert TensorTransform object into a TensorOperation object.
|
||||
/// \return Shared pointer to TensorOperation object.
|
||||
std::shared_ptr<TensorOperation> Parse() override;
|
||||
|
||||
private:
|
||||
struct Data;
|
||||
std::shared_ptr<Data> data_;
|
||||
};
|
||||
|
||||
/// \brief FrequencyMasking TensorTransform.
|
||||
/// \notes Apply masking to a spectrogram in the frequency domain.
|
||||
class FrequencyMasking final : public TensorTransform {
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ constexpr char kBandBiquadOp[] = "BandBiquadOp";
|
|||
constexpr char kBandpassBiquadOp[] = "BandpassBiquadOp";
|
||||
constexpr char kBandrejectBiquadOp[] = "BandrejectBiquadOp";
|
||||
constexpr char kBassBiquadOp[] = "BassBiquadOp";
|
||||
constexpr char kComplexNormOp[] = "ComplexNormOp";
|
||||
constexpr char kFrequencyMaskingOp[] = "FrequencyMaskingOp";
|
||||
constexpr char kTimeMaskingOp[] = "TimeMaskingOp";
|
||||
constexpr char kTimeStretchOp[] = "TimeStretchOp";
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import mindspore._c_dataengine as cde
|
|||
from ..transforms.c_transforms import TensorOperation
|
||||
from .utils import ScaleType
|
||||
from .validators import check_allpass_biquad, check_amplitude_to_db, check_band_biquad, check_bandpass_biquad, \
|
||||
check_bandreject_biquad, check_bass_biquad, check_masking, check_time_stretch
|
||||
check_bandreject_biquad, check_bass_biquad, check_complex_norm, check_masking, check_time_stretch
|
||||
|
||||
|
||||
class AudioTensorOperation(TensorOperation):
|
||||
|
|
@ -244,6 +244,29 @@ class BassBiquad(AudioTensorOperation):
|
|||
return cde.BassBiquadOperation(self.sample_rate, self.gain, self.central_freq, self.Q)
|
||||
|
||||
|
||||
class ComplexNorm(AudioTensorOperation):
|
||||
"""
|
||||
Compute the norm of complex tensor input.
|
||||
|
||||
Args:
|
||||
power (float, optional): Power of the norm, which must be non-negative (default=1.0).
|
||||
|
||||
Examples:
|
||||
>>> import numpy as np
|
||||
>>>
|
||||
>>> waveform = np.random.random([2, 4, 2])
|
||||
>>> numpy_slices_dataset = ds.NumpySlicesDataset(data=waveform, column_names=["audio"])
|
||||
>>> transforms = [audio.ComplexNorm()]
|
||||
>>> numpy_slices_dataset = numpy_slices_dataset.map(operations=transforms, input_columns=["audio"])
|
||||
"""
|
||||
@check_complex_norm
|
||||
def __init__(self, power=1.0):
|
||||
self.power = power
|
||||
|
||||
def parse(self):
|
||||
return cde.ComplexNormOperation(self.power)
|
||||
|
||||
|
||||
class FrequencyMasking(AudioTensorOperation):
|
||||
"""
|
||||
Apply masking to a spectrogram in the frequency domain.
|
||||
|
|
|
|||
|
|
@ -208,3 +208,14 @@ def check_masking(method):
|
|||
return method(self, *args, **kwargs)
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
def check_complex_norm(method):
|
||||
"""Wrapper method to check the parameters of ComplexNorm."""
|
||||
@wraps(method)
|
||||
def new_method(self, *args, **kwargs):
|
||||
[power], _ = parse_user_args(method, *args, **kwargs)
|
||||
check_non_negative_float32(power, "power")
|
||||
return method(self, *args, **kwargs)
|
||||
|
||||
return new_method
|
||||
|
|
|
|||
|
|
@ -549,3 +549,61 @@ TEST_F(MindDataTestPipeline, TestFrequencyMaskingWrongArgs) {
|
|||
// Expect failure
|
||||
EXPECT_EQ(iter, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(MindDataTestPipeline, TestComplexNormBasic) {
|
||||
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestComplexNormBasic.";
|
||||
|
||||
// Original waveform
|
||||
std::shared_ptr<SchemaObj> schema = Schema();
|
||||
ASSERT_OK(schema->add_column("inputData", mindspore::DataType::kNumberTypeInt64, {3, 2, 4, 2}));
|
||||
std::shared_ptr<Dataset> ds = RandomData(50, schema);
|
||||
EXPECT_NE(ds, nullptr);
|
||||
|
||||
ds = ds->SetNumWorkers(4);
|
||||
EXPECT_NE(ds, nullptr);
|
||||
|
||||
auto ComplexNormOp = audio::ComplexNorm(3.0);
|
||||
|
||||
ds = ds->Map({ComplexNormOp});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
|
||||
// Filtered waveform by ComplexNorm
|
||||
std::shared_ptr<Iterator> iter = ds->CreateIterator();
|
||||
EXPECT_NE(ds, nullptr);
|
||||
|
||||
std::unordered_map<std::string, mindspore::MSTensor> row;
|
||||
ASSERT_OK(iter->GetNextRow(&row));
|
||||
|
||||
std::vector<int64_t> expected = {3, 2, 2};
|
||||
|
||||
int i = 0;
|
||||
while (row.size() != 0) {
|
||||
auto col = row["inputData"];
|
||||
ASSERT_EQ(col.Shape(), expected);
|
||||
ASSERT_EQ(col.DataType(), mindspore::DataType::kNumberTypeFloat32);
|
||||
ASSERT_OK(iter->GetNextRow(&row));
|
||||
i++;
|
||||
}
|
||||
EXPECT_EQ(i, 50);
|
||||
|
||||
iter->Stop();
|
||||
}
|
||||
|
||||
TEST_F(MindDataTestPipeline, TestComplexNormWrongArgs) {
|
||||
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestComplexNormWrongArgs.";
|
||||
|
||||
// Original waveform
|
||||
std::shared_ptr<SchemaObj> schema = Schema();
|
||||
ASSERT_OK(schema->add_column("inputData", mindspore::DataType::kNumberTypeInt64, {3, 2, 4, 2}));
|
||||
std::shared_ptr<Dataset> ds = RandomData(50, schema);
|
||||
EXPECT_NE(ds, nullptr);
|
||||
|
||||
ds = ds->SetNumWorkers(4);
|
||||
EXPECT_NE(ds, nullptr);
|
||||
|
||||
auto ComplexNormOp = audio::ComplexNorm(-10);
|
||||
|
||||
ds = ds->Map({ComplexNormOp});
|
||||
std::shared_ptr<Iterator> iter1 = ds->CreateIterator();
|
||||
EXPECT_EQ(iter1, nullptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -641,3 +641,18 @@ TEST_F(MindDataTestExecute, TestRGB2BGREager) {
|
|||
|
||||
EXPECT_EQ(rc, Status::OK());
|
||||
}
|
||||
|
||||
TEST_F(MindDataTestExecute, TestComplexNormEager) {
|
||||
MS_LOG(INFO) << "Doing MindDataTestExecute-TestComplexNormEager.";
|
||||
// testing
|
||||
std::shared_ptr<Tensor> input_tensor_;
|
||||
Tensor::CreateFromVector(std::vector<float>({1.0, 1.0, 2.0, 3.0, 4.0, 4.0}), TensorShape({3, 2}), &input_tensor_);
|
||||
|
||||
auto input_02 = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(input_tensor_));
|
||||
std::shared_ptr<TensorTransform> complex_norm_01 = std::make_shared<audio::ComplexNorm>(4.0);
|
||||
|
||||
// Filtered waveform by complexnorm
|
||||
mindspore::dataset::Execute Transform01({complex_norm_01});
|
||||
Status s01 = Transform01(input_02, &input_02);
|
||||
EXPECT_TRUE(s01.IsOk());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
# Copyright 2021 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
"""
|
||||
Testing ComplexNorm op in DE.
|
||||
"""
|
||||
import numpy as np
|
||||
from numpy import random
|
||||
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.audio.transforms as audio
|
||||
from mindspore import log as logger
|
||||
|
||||
|
||||
def test_complex_norm():
|
||||
"""
|
||||
Test complex_norm (pipeline).
|
||||
"""
|
||||
logger.info("Test ComplexNorm.")
|
||||
|
||||
def gen():
|
||||
data = np.array([[1.0, 1.0], [2.0, 3.0], [4.0, 4.0]])
|
||||
yield (np.array(data, dtype=np.float32),)
|
||||
|
||||
dataset = ds.GeneratorDataset(source=gen, column_names=["multi_dim_data"])
|
||||
|
||||
dataset = dataset.map(operations=audio.ComplexNorm(2.), input_columns=["multi_dim_data"])
|
||||
|
||||
for i in dataset.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
assert i["multi_dim_data"].shape == (2,)
|
||||
expected = np.array([-5., 46.])
|
||||
assert np.array_equal(i["multi_dim_data"], expected)
|
||||
|
||||
logger.info("Finish testing ComplexNorm.")
|
||||
|
||||
|
||||
def test_complex_norm_eager():
|
||||
"""
|
||||
Test complex_norm callable (eager).
|
||||
"""
|
||||
logger.info("Test ComplexNorm callable.")
|
||||
|
||||
input_t = np.array([[1.0, 1.0], [2.0, 3.0], [4.0, 4.0]])
|
||||
output_t = audio.ComplexNorm(3)(input_t)
|
||||
assert output_t.shape == (2,)
|
||||
expected = np.array([-255.6179621231501, 183.64515392460598])
|
||||
assert np.array_equal(output_t, expected)
|
||||
|
||||
logger.info("Finish testing ComplexNorm.")
|
||||
|
||||
|
||||
def test_complex_norm_uncallable():
|
||||
"""
|
||||
Test complex_norm_op not callable.
|
||||
"""
|
||||
logger.info("Test ComplexNorm not callable.")
|
||||
|
||||
try:
|
||||
input_t = random.rand(2, 4, 3, 2)
|
||||
output_t = audio.ComplexNorm(-3.)(input_t)
|
||||
assert output_t.shape == (2, 4, 2)
|
||||
except ValueError as e:
|
||||
assert 'Input power is not within the required interval of [0, 16777216].' in str(e)
|
||||
|
||||
logger.info("Finish testing ComplexNorm.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_complex_norm()
|
||||
test_complex_norm_eager()
|
||||
test_complex_norm_uncallable()
|
||||
Loading…
Reference in New Issue