forked from huawei/mindspore2022
[feat][assistant][I3CECZ] add op griffinlim
This commit is contained in:
parent
2886b66281
commit
e19dc02b47
|
|
@ -37,6 +37,7 @@
|
|||
#include "minddata/dataset/audio/ir/kernels/flanger_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/frequency_masking_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/gain_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/griffin_lim_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/highpass_biquad_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/lfilter_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/lowpass_biquad_ir.h"
|
||||
|
|
@ -413,6 +414,41 @@ Gain::Gain(float gain_db) : data_(std::make_shared<Data>(gain_db)) {}
|
|||
|
||||
std::shared_ptr<TensorOperation> Gain::Parse() { return std::make_shared<GainOperation>(data_->gain_db_); }
|
||||
|
||||
// GriffinLim Transform Operation.
|
||||
struct GriffinLim::Data {
|
||||
Data(int32_t n_fft, int32_t n_iter, int32_t win_length, int32_t hop_length, WindowType window_type, float power,
|
||||
float momentum, int32_t length, bool rand_init)
|
||||
: n_fft_(n_fft),
|
||||
n_iter_(n_iter),
|
||||
win_length_(win_length),
|
||||
hop_length_(hop_length),
|
||||
window_type_(window_type),
|
||||
power_(power),
|
||||
momentum_(momentum),
|
||||
length_(length),
|
||||
rand_init_(rand_init) {}
|
||||
int32_t n_fft_;
|
||||
int32_t n_iter_;
|
||||
int32_t win_length_;
|
||||
int32_t hop_length_;
|
||||
WindowType window_type_;
|
||||
float power_;
|
||||
float momentum_;
|
||||
int32_t length_;
|
||||
bool rand_init_;
|
||||
};
|
||||
|
||||
GriffinLim::GriffinLim(int32_t n_fft, int32_t n_iter, int32_t win_length, int32_t hop_length, WindowType window_type,
|
||||
float power, float momentum, int32_t length, bool rand_init)
|
||||
: data_(std::make_shared<Data>(n_fft, n_iter, win_length, hop_length, window_type, power, momentum, length,
|
||||
rand_init)) {}
|
||||
|
||||
std::shared_ptr<TensorOperation> GriffinLim::Parse() {
|
||||
return std::make_shared<GriffinLimOperation>(data_->n_fft_, data_->n_iter_, data_->win_length_, data_->hop_length_,
|
||||
data_->window_type_, data_->power_, data_->momentum_, data_->length_,
|
||||
data_->rand_init_);
|
||||
}
|
||||
|
||||
// HighpassBiquad Transform Operation.
|
||||
struct HighpassBiquad::Data {
|
||||
Data(int32_t sample_rate, float cutoff_freq, float Q) : sample_rate_(sample_rate), cutoff_freq_(cutoff_freq), Q_(Q) {}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "minddata/dataset/audio/ir/kernels/flanger_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/frequency_masking_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/gain_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/griffin_lim_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/highpass_biquad_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/lfilter_ir.h"
|
||||
#include "minddata/dataset/audio/ir/kernels/lowpass_biquad_ir.h"
|
||||
|
|
@ -334,6 +335,19 @@ PYBIND_REGISTER(GainOperation, 1, ([](const py::module *m) {
|
|||
}));
|
||||
}));
|
||||
|
||||
PYBIND_REGISTER(
|
||||
GriffinLimOperation, 1, ([](const py::module *m) {
|
||||
(void)py::class_<audio::GriffinLimOperation, TensorOperation, std::shared_ptr<audio::GriffinLimOperation>>(
|
||||
*m, "GriffinLimOperation")
|
||||
.def(py::init([](int32_t n_fft, int32_t n_iter, int32_t win_length, int32_t hop_length, WindowType window_type,
|
||||
float power, float momentum, int32_t length, bool rand_init) {
|
||||
auto griffin_lim = std::make_shared<audio::GriffinLimOperation>(
|
||||
n_fft, n_iter, win_length, hop_length, window_type, power, momentum, length, rand_init);
|
||||
THROW_IF_ERROR(griffin_lim->ValidateParams());
|
||||
return griffin_lim;
|
||||
}));
|
||||
}));
|
||||
|
||||
PYBIND_REGISTER(
|
||||
HighpassBiquadOperation, 1, ([](const py::module *m) {
|
||||
(void)py::class_<audio::HighpassBiquadOperation, TensorOperation, std::shared_ptr<audio::HighpassBiquadOperation>>(
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ add_library(audio-ir-kernels OBJECT
|
|||
flanger_ir.cc
|
||||
frequency_masking_ir.cc
|
||||
gain_ir.cc
|
||||
griffin_lim_ir.cc
|
||||
highpass_biquad_ir.cc
|
||||
lfilter_ir.cc
|
||||
lowpass_biquad_ir.cc
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* Copyright 2022 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/griffin_lim_ir.h"
|
||||
|
||||
#include "minddata/dataset/audio/ir/validators.h"
|
||||
#include "minddata/dataset/audio/kernels/griffin_lim_op.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
namespace audio {
|
||||
// GriffinLim
|
||||
GriffinLimOperation::GriffinLimOperation(int32_t n_fft, int32_t n_iter, int32_t win_length, int32_t hop_length,
|
||||
WindowType window_type, float power, float momentum, int32_t length,
|
||||
bool rand_init)
|
||||
: n_fft_(n_fft),
|
||||
n_iter_(n_iter),
|
||||
win_length_(win_length),
|
||||
hop_length_(hop_length),
|
||||
window_type_(window_type),
|
||||
power_(power),
|
||||
momentum_(momentum),
|
||||
length_(length),
|
||||
rand_init_(rand_init) {}
|
||||
|
||||
GriffinLimOperation::~GriffinLimOperation() = default;
|
||||
|
||||
std::string GriffinLimOperation::Name() const { return kGriffinLimOperation; }
|
||||
|
||||
Status GriffinLimOperation::ValidateParams() {
|
||||
RETURN_IF_NOT_OK(ValidateIntScalarPositive("GriffinLim", "n_fft", n_fft_));
|
||||
RETURN_IF_NOT_OK(ValidateIntScalarPositive("GriffinLim", "n_iter", n_iter_));
|
||||
RETURN_IF_NOT_OK(ValidateIntScalarNonNegative("GriffinLim", "win_length", win_length_));
|
||||
RETURN_IF_NOT_OK(ValidateIntScalarNonNegative("GriffinLim", "hop_length", hop_length_));
|
||||
RETURN_IF_NOT_OK(ValidateFloatScalarPositive("GriffinLim", "power", power_));
|
||||
RETURN_IF_NOT_OK(ValidateFloatScalarNonNegative("GriffinLim", "momentum", momentum_));
|
||||
RETURN_IF_NOT_OK(ValidateIntScalarNonNegative("GriffinLim", "length", length_));
|
||||
if (length_ != 0 && n_fft_ >= length_) {
|
||||
std::string err_msg = "GriffinLim: n_fft must be less than length.";
|
||||
LOG_AND_RETURN_STATUS_SYNTAX_ERROR(err_msg);
|
||||
}
|
||||
|
||||
CHECK_FAIL_RETURN_SYNTAX_ERROR(
|
||||
momentum_ < 1,
|
||||
"GriffinLim: momentum equal to or greater than 1 can be unstable, but got: " + std::to_string(momentum_));
|
||||
CHECK_FAIL_RETURN_SYNTAX_ERROR(momentum_ >= 0,
|
||||
"GriffinLim: momentum can not be less than 0, but got: " + std::to_string(momentum_));
|
||||
CHECK_FAIL_RETURN_SYNTAX_ERROR(win_length_ <= n_fft_,
|
||||
"GriffinLim: win_length must be less than or equal to n_fft, but got win_length: " +
|
||||
std::to_string(win_length_) + ", n_fft: " + std::to_string(n_fft_));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
std::shared_ptr<TensorOp> GriffinLimOperation::Build() {
|
||||
int32_t win_length = (win_length_ == 0) ? n_fft_ : win_length_;
|
||||
int32_t hop_length = (hop_length_ == 0) ? win_length / 2 : hop_length_;
|
||||
float momentum = momentum_ / (1 + momentum_);
|
||||
std::shared_ptr<GriffinLimOp> tensor_op = std::make_shared<GriffinLimOp>(
|
||||
n_fft_, n_iter_, win_length, hop_length, window_type_, power_, momentum, length_, rand_init_);
|
||||
return tensor_op;
|
||||
}
|
||||
|
||||
Status GriffinLimOperation::to_json(nlohmann::json *out_json) {
|
||||
nlohmann::json args;
|
||||
args["n_fft"] = n_fft_;
|
||||
args["n_iter"] = n_iter_;
|
||||
args["win_length"] = win_length_;
|
||||
args["hop_length"] = hop_length_;
|
||||
args["window_type"] = window_type_;
|
||||
args["power"] = power_;
|
||||
args["momentum"] = momentum_;
|
||||
args["length"] = length_;
|
||||
args["rand_init"] = rand_init_;
|
||||
*out_json = args;
|
||||
return Status::OK();
|
||||
}
|
||||
} // namespace audio
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Copyright 2022 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_GRIFFIN_LIM_IR_H_
|
||||
#define MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_IR_KERNELS_GRIFFIN_LIM_IR_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "include/api/status.h"
|
||||
#include "minddata/dataset/include/dataset/constants.h"
|
||||
#include "minddata/dataset/kernels/ir/tensor_operation.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
namespace audio {
|
||||
constexpr char kGriffinLimOperation[] = "GriffinLim";
|
||||
|
||||
class GriffinLimOperation : public TensorOperation {
|
||||
public:
|
||||
GriffinLimOperation(int32_t n_fft, int32_t n_iter, int32_t win_length, int32_t hop_length, WindowType window_type,
|
||||
float power, float momentum, int32_t length, bool rand_init);
|
||||
|
||||
~GriffinLimOperation();
|
||||
|
||||
std::shared_ptr<TensorOp> Build() override;
|
||||
|
||||
Status ValidateParams() override;
|
||||
|
||||
std::string Name() const override;
|
||||
|
||||
Status to_json(nlohmann::json *out_json) override;
|
||||
|
||||
private:
|
||||
int32_t n_fft_;
|
||||
int32_t n_iter_;
|
||||
int32_t win_length_;
|
||||
int32_t hop_length_;
|
||||
WindowType window_type_;
|
||||
float power_;
|
||||
float momentum_;
|
||||
int32_t length_;
|
||||
bool rand_init_;
|
||||
};
|
||||
} // namespace audio
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_IR_KERNELS_GRIFFIN_LIM_IR_H_
|
||||
|
|
@ -24,6 +24,7 @@ add_library(audio-kernels OBJECT
|
|||
flanger_op.cc
|
||||
frequency_masking_op.cc
|
||||
gain_op.cc
|
||||
griffin_lim_op.cc
|
||||
highpass_biquad_op.cc
|
||||
lfilter_op.cc
|
||||
lowpass_biquad_op.cc
|
||||
|
|
|
|||
|
|
@ -1769,5 +1769,286 @@ Status ComputeDeltas(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tenso
|
|||
RETURN_IF_NOT_OK((*output)->Reshape(raw_shape));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
/// \brief IRFFT.
|
||||
Status IRFFT(const Eigen::MatrixXcd &stft_matrix, Eigen::MatrixXd *inverse) {
|
||||
int32_t n = 2 * (stft_matrix.rows() - 1);
|
||||
int32_t s = stft_matrix.rows() - 1;
|
||||
Eigen::FFT<double> fft;
|
||||
for (int k = 0; k < stft_matrix.cols(); ++k) {
|
||||
Eigen::VectorXcd output_complex(n);
|
||||
// pad input
|
||||
Eigen::VectorXcd input(n);
|
||||
input.head(s + 1) = stft_matrix.col(k);
|
||||
auto reverse_pad = stft_matrix.col(k).segment(1, s - 1).colwise().reverse().conjugate();
|
||||
input.segment(s + 1, s - 1) = reverse_pad;
|
||||
fft.inv(output_complex, input);
|
||||
Eigen::VectorXd output_real = output_complex.real().eval();
|
||||
inverse->col(k) = Eigen::Map<Eigen::MatrixXd>(output_real.data(), n, 1);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
/// \brief Overlap Add
|
||||
Status OverlapAdd(Eigen::VectorXd *out_buf, const Eigen::MatrixXd &win_inverse_stft, int32_t hop_lengh) {
|
||||
int32_t n_fft = win_inverse_stft.rows();
|
||||
for (int frame = 0; frame < win_inverse_stft.cols(); frame++) {
|
||||
int32_t sample = frame * hop_lengh;
|
||||
out_buf->middleRows(sample, n_fft) += win_inverse_stft.col(frame);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
/// \brief Window Sum Square
|
||||
Status WindowSumSquare(const Eigen::MatrixXf &window_matrix, Eigen::VectorXf *win_sum_square, const int32_t n_frames,
|
||||
int32_t n_fft, int32_t hop_length) {
|
||||
Eigen::MatrixXf win_norm = window_matrix.array().pow(2);
|
||||
// window sum square fill
|
||||
int32_t n = n_fft + hop_length * (n_frames - 1);
|
||||
// check n_fft
|
||||
CHECK_FAIL_RETURN_UNEXPECTED(
|
||||
n_fft == win_norm.rows(),
|
||||
"GriffinLim: n_fft must be equal to the length of the window during window sum square calculation.");
|
||||
for (int ind = 0; ind < n_frames; ind++) {
|
||||
int sample = ind * hop_length;
|
||||
int end_ss = std::min(n, sample + n_fft);
|
||||
int end_win = std::max(0, std::min(n_fft, n - sample));
|
||||
win_sum_square->segment(sample, end_ss - sample) += win_norm.col(0).head(end_win);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
/// \brief ISTFT.
|
||||
/// \param input: Complex matrix of eigen, shape of <freq, time>.
|
||||
/// \param output: Tensor of shape <time>.
|
||||
/// \param n_fft: Size of Fourier transform.
|
||||
/// \param hop_length: The distance between neighboring sliding window frames.
|
||||
/// \param win_length: The size of window frame and STFT filter.
|
||||
/// \param window_type: The type of window function.
|
||||
/// \param center: Whether input was padded on both sides so that the `t`-th frame is centered at time
|
||||
/// `t * hop_length`.
|
||||
/// \param normalized: Whether the STFT was normalized.
|
||||
/// \param onesided: Whether the STFT was onesided.
|
||||
/// \param length: The amount to trim the signal by (i.e. the original signal length).
|
||||
/// \return Status code.
|
||||
template <typename T>
|
||||
Status ISTFT(const Eigen::MatrixXcd &stft_matrix, std::shared_ptr<Tensor> *output, int32_t n_fft, int32_t hop_length,
|
||||
int32_t win_length, WindowType window_type, bool center, bool normalized, bool onesided, int32_t length) {
|
||||
// check input
|
||||
CHECK_FAIL_RETURN_UNEXPECTED(n_fft == ((stft_matrix.rows() - 1) * 2),
|
||||
"GriffinLim: the frequency of the input should equal to n_fft / 2 + 1");
|
||||
|
||||
// window
|
||||
std::shared_ptr<Tensor> ifft_window_tensor;
|
||||
RETURN_IF_NOT_OK(Window(&ifft_window_tensor, window_type, win_length));
|
||||
if (win_length == 1) {
|
||||
RETURN_IF_NOT_OK(Tensor::CreateEmpty(TensorShape({1}), DataType(DataType::DE_FLOAT32), &ifft_window_tensor));
|
||||
auto win = ifft_window_tensor->begin<float>();
|
||||
*(win) = 1;
|
||||
}
|
||||
// pad window to match n_fft, and add a broadcasting axis
|
||||
std::shared_ptr<Tensor> ifft_window_pad;
|
||||
ifft_window_pad = ifft_window_tensor;
|
||||
if (win_length < n_fft) {
|
||||
RETURN_IF_NOT_OK(Tensor::CreateEmpty(TensorShape({n_fft}), DataType(DataType::DE_FLOAT32), &ifft_window_pad));
|
||||
int pad_left = (n_fft - win_length) / 2;
|
||||
int pad_right = n_fft - win_length - pad_left;
|
||||
RETURN_IF_NOT_OK(Pad<float>(ifft_window_tensor, &ifft_window_pad, pad_left, pad_right, BorderType::kConstant));
|
||||
}
|
||||
|
||||
int32_t n_frames = 0;
|
||||
if ((length != 0) && (hop_length != 0)) {
|
||||
int32_t padded_length = center ? (length + n_fft) : length;
|
||||
n_frames = std::min(static_cast<int32_t>(stft_matrix.cols()),
|
||||
static_cast<int32_t>(std::ceil(static_cast<float>(padded_length) / hop_length)));
|
||||
} else {
|
||||
n_frames = stft_matrix.cols();
|
||||
}
|
||||
int32_t expected_signal_len = n_fft + hop_length * (n_frames - 1);
|
||||
Eigen::VectorXd y(expected_signal_len);
|
||||
y.setZero();
|
||||
|
||||
// constrain STFT block sizes to 256 KB
|
||||
int32_t max_mem_block = std::pow(2, 8) * std::pow(2, 10);
|
||||
int32_t n_columns = max_mem_block / (stft_matrix.rows() * sizeof(T) * TWO);
|
||||
n_columns = std::max(n_columns, 1);
|
||||
|
||||
// turn window to eigen matrix
|
||||
auto data_ptr = &*ifft_window_pad->begin<float>();
|
||||
Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>> ifft_window_matrix(data_ptr,
|
||||
ifft_window_pad->shape()[0], 1);
|
||||
for (int bl_s = 0, frame = 0; bl_s < n_frames;) {
|
||||
int bl_t = std::min(bl_s + n_columns, n_frames);
|
||||
// calculate ifft
|
||||
Eigen::MatrixXcd stft_temp = stft_matrix.middleCols(bl_s, bl_t - bl_s).eval();
|
||||
Eigen::MatrixXd inverse(TWO * (stft_temp.rows() - 1), stft_temp.cols());
|
||||
inverse.setZero();
|
||||
RETURN_IF_NOT_OK(IRFFT(stft_temp, &inverse));
|
||||
auto ytmp = ifft_window_matrix.template cast<double>().replicate(1, inverse.cols()).cwiseProduct(inverse);
|
||||
RETURN_IF_NOT_OK(OverlapAdd(&y, ytmp, hop_length));
|
||||
frame += bl_t - bl_s;
|
||||
bl_s += n_columns;
|
||||
}
|
||||
// normalize by sum of squared window
|
||||
int32_t n = n_fft + hop_length * (n_frames - 1);
|
||||
Eigen::VectorXf ifft_win_sum(n);
|
||||
ifft_win_sum.setZero();
|
||||
RETURN_IF_NOT_OK(WindowSumSquare(ifft_window_matrix, &ifft_win_sum, n_frames, n_fft, hop_length));
|
||||
|
||||
for (int32_t ind = 0; ind < y.rows(); ind++) {
|
||||
if (ifft_win_sum[ind] > std::numeric_limits<float>::min()) {
|
||||
y[ind] /= ifft_win_sum[ind];
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Tensor> res_tensor;
|
||||
if (length == 0 && center) {
|
||||
int32_t y_start = n_fft / 2;
|
||||
int32_t y_end = y.rows() - y_start;
|
||||
auto tmp = y.middleRows(y_start, y_end - y_start);
|
||||
std::vector<T> y_res(tmp.data(), tmp.data() + tmp.rows() * tmp.cols());
|
||||
RETURN_IF_NOT_OK(Tensor::CreateFromVector(y_res, TensorShape({tmp.size()}), &res_tensor));
|
||||
} else {
|
||||
int32_t start = center ? n_fft / 2 : 0;
|
||||
auto tmp = y.tail(y.rows() - start);
|
||||
// fix length
|
||||
std::vector<T> y_res(tmp.data(), tmp.data() + tmp.rows() * tmp.cols());
|
||||
if (length > y_res.size()) {
|
||||
while (y_res.size() != length) {
|
||||
y_res.push_back(0);
|
||||
}
|
||||
} else if (length < tmp.rows()) {
|
||||
while (y_res.size() != length) {
|
||||
y_res.pop_back();
|
||||
}
|
||||
}
|
||||
RETURN_IF_NOT_OK(Tensor::CreateFromVector(y_res, TensorShape({length}), &res_tensor));
|
||||
}
|
||||
*output = res_tensor;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status GriffinLimImpl(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, int32_t n_fft,
|
||||
int32_t n_iter, int32_t win_length, int32_t hop_length, WindowType window_type, float power,
|
||||
float momentum, int32_t length, bool rand_init, std::mt19937 rnd) {
|
||||
// pack
|
||||
TensorShape shape = input->shape();
|
||||
TensorShape new_shape({input->Size() / shape[-1] / shape[-2], shape[-2], shape[-1]});
|
||||
RETURN_IF_NOT_OK(input->Reshape(new_shape));
|
||||
// power
|
||||
CHECK_FAIL_RETURN_UNEXPECTED(power != 0, "GriffinLim: power can not be zero.");
|
||||
for (auto itr = input->begin<T>(); itr != input->end<T>(); itr++) {
|
||||
*itr = pow(*itr, 1 / power);
|
||||
}
|
||||
// window
|
||||
std::shared_ptr<Tensor> fft_window_tensor;
|
||||
RETURN_IF_NOT_OK(Window(&fft_window_tensor, window_type, win_length));
|
||||
if (win_length == 1) {
|
||||
RETURN_IF_NOT_OK(Tensor::CreateEmpty(TensorShape({1}), DataType(DataType::DE_FLOAT32), &fft_window_tensor));
|
||||
auto win = fft_window_tensor->begin<float>();
|
||||
*(win) = 1;
|
||||
}
|
||||
std::shared_ptr<Tensor> final_results;
|
||||
for (int dim = 0; dim < new_shape[0]; dim++) {
|
||||
// init complex phase
|
||||
Eigen::MatrixXcd angles(shape[(-1) * TWO], shape[-1]);
|
||||
if (rand_init) {
|
||||
// static std::default_random_engine e;
|
||||
std::uniform_real_distribution<double> dist(0, 1);
|
||||
angles = angles.unaryExpr(
|
||||
[&dist, &rnd](std::complex<double> value) { return std::complex<double>(dist(rnd), dist(rnd)); });
|
||||
} else {
|
||||
angles = angles.unaryExpr([](std::complex<double> value) { return std::complex<double>(1, 0); });
|
||||
}
|
||||
// slice and squeeze the first dim
|
||||
std::shared_ptr<Tensor> spec_tensor_slice;
|
||||
RETURN_IF_NOT_OK(input->Slice(
|
||||
&spec_tensor_slice,
|
||||
std::vector<SliceOption>({SliceOption(std::vector<dsize_t>{dim}), SliceOption(true), SliceOption(true)})));
|
||||
TensorShape new_slice_shape({shape[-2], shape[-1]});
|
||||
RETURN_IF_NOT_OK(spec_tensor_slice->Reshape(new_slice_shape));
|
||||
// turn tensor into eigen MatrixXd
|
||||
auto data_ptr = &*spec_tensor_slice->begin<T>();
|
||||
Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>> spec_matrix_transpose(data_ptr, shape[-1],
|
||||
shape[(-1) * TWO]);
|
||||
Eigen::MatrixXd spec_matrix = spec_matrix_transpose.transpose().template cast<double>();
|
||||
auto stft_complex = angles.cwiseProduct(spec_matrix);
|
||||
|
||||
// init tprev zero mat
|
||||
Eigen::MatrixXcd tprev(shape[(-1) * TWO], shape[-1]);
|
||||
Eigen::MatrixXcd rebuilt(shape[(-1) * TWO], shape[-1]);
|
||||
tprev.setZero();
|
||||
rebuilt.setZero();
|
||||
for (int iter = 0; iter < n_iter; iter++) {
|
||||
// istft
|
||||
std::shared_ptr<Tensor> inverse;
|
||||
RETURN_IF_NOT_OK(
|
||||
ISTFT<T>(stft_complex, &inverse, n_fft, hop_length, win_length, window_type, true, false, true, length));
|
||||
// stft
|
||||
std::shared_ptr<Tensor> stft_out;
|
||||
RETURN_IF_NOT_OK(SpectrogramImpl<T>(inverse, &stft_out, 0, window_type, n_fft, hop_length, win_length, 0, false,
|
||||
true, BorderType::kReflect, true));
|
||||
|
||||
rebuilt.transposeInPlace();
|
||||
Tensor::TensorIterator<T> itr = stft_out->begin<T>();
|
||||
rebuilt = rebuilt.unaryExpr([&itr](std::complex<double> value) {
|
||||
T real = *(itr++);
|
||||
T img = *(itr++);
|
||||
return std::complex<double>(real, img);
|
||||
});
|
||||
rebuilt.transposeInPlace();
|
||||
angles = rebuilt.array();
|
||||
|
||||
if (momentum != 0) {
|
||||
tprev = tprev * ((momentum) / (1 + momentum));
|
||||
angles = angles.array() - tprev.array();
|
||||
}
|
||||
|
||||
float eps = 1e-16;
|
||||
auto angles_abs = angles.cwiseAbs().eval();
|
||||
angles_abs.array() += eps;
|
||||
angles = angles.array() / angles_abs.array();
|
||||
tprev = rebuilt.array();
|
||||
}
|
||||
|
||||
// istft calculate final phase
|
||||
auto stft_complex_fin = angles.cwiseProduct(spec_matrix);
|
||||
std::shared_ptr<Tensor> waveform;
|
||||
RETURN_IF_NOT_OK(
|
||||
ISTFT<T>(stft_complex_fin, &waveform, n_fft, hop_length, win_length, window_type, true, false, true, length));
|
||||
|
||||
if (shape.Rank() == TWO) {
|
||||
// do not expand dim
|
||||
final_results = waveform;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (final_results != nullptr) {
|
||||
RETURN_IF_NOT_OK(final_results->InsertTensor({dim}, waveform));
|
||||
} else {
|
||||
RETURN_IF_NOT_OK(
|
||||
Tensor::CreateEmpty(TensorShape({new_shape[0], waveform->shape()[0]}), waveform->type(), &final_results));
|
||||
RETURN_IF_NOT_OK(final_results->InsertTensor({dim}, waveform));
|
||||
}
|
||||
}
|
||||
*output = final_results;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status GriffinLim(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, int32_t n_fft, int32_t n_iter,
|
||||
int32_t win_length, int32_t hop_length, WindowType window_type, float power, float momentum,
|
||||
int32_t length, bool rand_init, std::mt19937 rnd) {
|
||||
std::shared_ptr<Tensor> input_tensor;
|
||||
if (input->type() != DataType::DE_FLOAT64) {
|
||||
RETURN_IF_NOT_OK(TypeCast(input, &input_tensor, DataType(DataType::DE_FLOAT32)));
|
||||
return GriffinLimImpl<float>(input_tensor, output, n_fft, n_iter, win_length, hop_length, window_type, power,
|
||||
momentum, length, rand_init, rnd);
|
||||
} else {
|
||||
input_tensor = input;
|
||||
return GriffinLimImpl<double>(input_tensor, output, n_fft, n_iter, win_length, hop_length, window_type, power,
|
||||
momentum, length, rand_init, rnd);
|
||||
}
|
||||
}
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#define MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_AUDIO_UTILS_H_
|
||||
|
||||
#include <Eigen/Dense>
|
||||
#include <unsupported/Eigen/FFT>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
|
@ -1469,6 +1470,24 @@ Status Dither(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *out
|
|||
return Status::OK();
|
||||
}
|
||||
|
||||
/// \brief Apply GriffinLim to calculate waveform from linear scalar amplitude spectrogram.
|
||||
/// \param input Tensor of shape <..., freq, time>.
|
||||
/// \param output Tensor of shape <..., time>.
|
||||
/// \param n_fft Size of FFT.
|
||||
/// \param n_iter Number of iteration for phase recovery.
|
||||
/// \param win_length Window size for GriffinLim.
|
||||
/// \param hop_length Length of hop between STFT windows.
|
||||
/// \param window_type Window type for GriffinLim.
|
||||
/// \param power Exponent for the magnitude spectrogram.
|
||||
/// \param momentum The momentum for fast GriffinLim.
|
||||
/// \param length Length of the expected output waveform.
|
||||
/// \param rand_init Flag for random phase initialization or all-zero phase initialization.
|
||||
/// \param rnd Random generator.
|
||||
/// \return Status code.
|
||||
Status GriffinLim(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, int32_t n_fft, int32_t n_iter,
|
||||
int32_t win_length, int32_t hop_length, WindowType window_type, float power, float momentum,
|
||||
int32_t length, bool rand_init, std::mt19937 rnd);
|
||||
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_AUDIO_UTILS_H_
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright 2022 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/griffin_lim_op.h"
|
||||
|
||||
#include "minddata/dataset/audio/kernels/audio_utils.h"
|
||||
#include "minddata/dataset/kernels/data/data_utils.h"
|
||||
#include "minddata/dataset/util/status.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
Status GriffinLimOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
|
||||
IO_CHECK(input, output);
|
||||
return GriffinLim(input, output, n_fft_, n_iter_, win_length_, hop_length_, window_type_, power_, momentum_, length_,
|
||||
rand_init_, rnd_);
|
||||
}
|
||||
|
||||
Status GriffinLimOp::OutputType(const std::vector<DataType> &inputs, std::vector<DataType> &outputs) {
|
||||
RETURN_IF_NOT_OK(TensorOp::OutputType(inputs, outputs));
|
||||
RETURN_IF_NOT_OK(
|
||||
ValidateTensorType("GriffinLim", inputs[0].IsNumeric(), "[int, float, double]", inputs[0].ToString()));
|
||||
if (inputs[0] == DataType(DataType::DE_FLOAT64)) {
|
||||
outputs[0] = DataType(DataType::DE_FLOAT64);
|
||||
} else {
|
||||
outputs[0] = DataType(DataType::DE_FLOAT32);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* Copyright 2022 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_GRIFFIN_LIM_OP_H_
|
||||
#define MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_GRIFFIN_LIM_OP_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "minddata/dataset/include/dataset/constants.h"
|
||||
#include "minddata/dataset/kernels/tensor_op.h"
|
||||
#include "minddata/dataset/util/random.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
class GriffinLimOp : public TensorOp {
|
||||
public:
|
||||
GriffinLimOp(int32_t n_fft, int32_t n_iter, int32_t win_length, int32_t hop_length, WindowType window_type,
|
||||
float power, float momentum, int32_t length, bool rand_init)
|
||||
: n_fft_(n_fft),
|
||||
n_iter_(n_iter),
|
||||
win_length_(win_length),
|
||||
hop_length_(hop_length),
|
||||
window_type_(window_type),
|
||||
power_(power),
|
||||
momentum_(momentum),
|
||||
length_(length),
|
||||
rand_init_(rand_init) {
|
||||
rnd_.seed(GetSeed());
|
||||
}
|
||||
|
||||
~GriffinLimOp() override = default;
|
||||
|
||||
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
|
||||
|
||||
std::string Name() const override { return kGriffinLimOp; }
|
||||
|
||||
Status OutputType(const std::vector<DataType> &inputs, std::vector<DataType> &outputs) override;
|
||||
|
||||
private:
|
||||
int32_t n_fft_;
|
||||
int32_t n_iter_;
|
||||
int32_t win_length_;
|
||||
int32_t hop_length_;
|
||||
WindowType window_type_;
|
||||
float power_;
|
||||
float momentum_;
|
||||
int32_t length_;
|
||||
bool rand_init_;
|
||||
std::mt19937 rnd_;
|
||||
};
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_GRIFFIN_LIM_OP_H_
|
||||
|
|
@ -528,6 +528,41 @@ class MS_API Gain final : public TensorTransform {
|
|||
std::shared_ptr<Data> data_;
|
||||
};
|
||||
|
||||
/// \brief Waveform calculation from linear scalar amplitude spectrogram using GriffinLim transform.
|
||||
class MS_API GriffinLim final : public TensorTransform {
|
||||
public:
|
||||
/// \brief Constructor.
|
||||
/// \notes Calculated by formula:
|
||||
/// x(n)=\frac{\sum_{m=-\infty}^{\infty} w(m S-n) y_{w}(m S, n)}{\sum_{m=-\infty}^{\infty} w^{2}(m S-n)}
|
||||
/// where w represents the window function, y represents the reconstructed signal of each frame and x represents
|
||||
/// the whole signal.
|
||||
/// \param[in] n_fft Size of FFT (Default: 400).
|
||||
/// \param[in] n_iter Number of iteration for phase recovery (Default: 32).
|
||||
/// \param[in] win_length Window size for GriffinLim (Default: 0, will be set to n_fft).
|
||||
/// \param[in] hop_length Length of hop between STFT windows (Default: 0, will be set to win_length / 2).
|
||||
/// \param[in] window_type Window type for GriffinLim (Default: WindowType::kHann).
|
||||
/// \param[in] power Exponent for the magnitude spectrogram (Default: 2.0).
|
||||
/// \param[in] momentum The momentum for fast Griffin-Lim (Default: 0.99).
|
||||
/// \param[in] length Length of the expected output waveform (Default: 0.0, will be set to the value of last
|
||||
/// dimension of the stft matrix).
|
||||
/// \param[in] rand_init Flag for random phase initialization or all-zero phase initialization (Default: true).
|
||||
explicit GriffinLim(int32_t n_fft = 400, int32_t n_iter = 32, int32_t win_length = 0, int32_t hop_length = 0,
|
||||
WindowType window_type = WindowType::kHann, float power = 2.0, float momentum = 0.99,
|
||||
int32_t length = 0, bool rand_init = true);
|
||||
|
||||
/// \brief Destructor.
|
||||
~GriffinLim() = 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 HighpassBiquad TensorTransform. Apply highpass biquad filter on audio.
|
||||
class MS_API HighpassBiquad final : public TensorTransform {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ constexpr char kFadeOp[] = "FadeOp";
|
|||
constexpr char kFlangerOp[] = "FlangerOp";
|
||||
constexpr char kFrequencyMaskingOp[] = "FrequencyMaskingOp";
|
||||
constexpr char kGainOp[] = "GainOp";
|
||||
constexpr char kGriffinLimOp[] = "GriffinLimOp";
|
||||
constexpr char kHighpassBiquadOp[] = "HighpassBiquadOp";
|
||||
constexpr char kLFilterOp[] = "LFilterOp";
|
||||
constexpr char kLowpassBiquadOp[] = "LowpassBiquadOp";
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ from .utils import BorderType, DensityFunction, FadeShape, GainType, Interpolati
|
|||
from .validators import check_allpass_biquad, check_amplitude_to_db, check_band_biquad, check_bandpass_biquad, \
|
||||
check_bandreject_biquad, check_bass_biquad, check_biquad, check_complex_norm, check_compute_deltas, \
|
||||
check_contrast, check_db_to_amplitude, check_dc_shift, check_deemph_biquad, check_detect_pitch_frequency, \
|
||||
check_dither, check_equalizer_biquad, check_fade, check_flanger, check_gain, check_highpass_biquad, \
|
||||
check_lfilter, check_lowpass_biquad, check_magphase, check_mask_along_axis, check_mask_along_axis_iid, \
|
||||
check_masking, check_mel_scale, check_mu_law_coding, check_overdrive, check_phase_vocoder, check_phaser, \
|
||||
check_riaa_biquad, check_sliding_window_cmn, check_spectral_centroid, check_spectrogram, check_time_stretch, \
|
||||
check_treble_biquad, check_vol
|
||||
check_dither, check_equalizer_biquad, check_fade, check_flanger, check_gain, check_griffin_lim, \
|
||||
check_highpass_biquad, check_lfilter, check_lowpass_biquad, check_magphase, check_mask_along_axis, \
|
||||
check_mask_along_axis_iid, check_masking, check_mel_scale, check_mu_law_coding, check_overdrive, \
|
||||
check_phase_vocoder, check_phaser, check_riaa_biquad, check_sliding_window_cmn, check_spectral_centroid, \
|
||||
check_spectrogram, check_time_stretch, check_treble_biquad, check_vol
|
||||
|
||||
|
||||
class AudioTensorOperation(TensorOperation):
|
||||
|
|
@ -929,6 +929,59 @@ class Gain(AudioTensorOperation):
|
|||
return cde.GainOperation(self.gain_db)
|
||||
|
||||
|
||||
class GriffinLim(AudioTensorOperation):
|
||||
r"""
|
||||
Approximate magnitude spectrogram inversion using the GriffinLim algorithm.
|
||||
|
||||
.. math::
|
||||
x(n)=\frac{\sum_{m=-\infty}^{\infty} w(m S-n) y_{w}(m S, n)}{\sum_{m=-\infty}^{\infty} w^{2}(m S-n)}
|
||||
|
||||
where w represents the window function, y represents the reconstructed signal of each frame and x represents the
|
||||
whole signal.
|
||||
|
||||
Args:
|
||||
n_fft (int, optional): Size of FFT (default=400).
|
||||
n_iter (int, optional): Number of iteration for phase recovery (default=32).
|
||||
win_length (int, optional): Window size for GriffinLim (default=None, will be set to n_fft).
|
||||
hop_length (int, optional): Length of hop between STFT windows (default=None, will be set to win_length // 2).
|
||||
window_type (WindowType, optional): Window type for GriffinLim, which can be WindowType.BARTLETT,
|
||||
WindowType.BLACKMAN, WindowType.HAMMING, WindowType.HANN or WindowType.KAISER (default=WindowType.HANN).
|
||||
Currently kaiser window is not supported on macOS.
|
||||
power (float, optional): Exponent for the magnitude spectrogram (default=2.0).
|
||||
momentum (float, optional): The momentum for fast Griffin-Lim (default=0.99).
|
||||
length (int, optional): Length of the expected output waveform (default=None, will be set to the value of last
|
||||
dimension of the stft matrix).
|
||||
rand_init (bool, optional): Flag for random phase initialization or all-zero phase initialization
|
||||
(default=True).
|
||||
|
||||
Examples:
|
||||
>>> import numpy as np
|
||||
>>>
|
||||
>>> waveform = np.random.random([201, 6])
|
||||
>>> numpy_slices_dataset = ds.NumpySlicesDataset(data=waveform, column_names=["audio"])
|
||||
>>> transforms = [audio.GriffinLim(n_fft=400)]
|
||||
>>> numpy_slices_dataset = numpy_slices_dataset.map(operations=transforms, input_columns=["audio"])
|
||||
"""
|
||||
|
||||
@check_griffin_lim
|
||||
def __init__(self, n_fft=400, n_iter=32, win_length=None, hop_length=None, window_type=WindowType.HANN,
|
||||
power=2, momentum=0.99, length=None, rand_init=True):
|
||||
self.n_fft = n_fft
|
||||
self.n_iter = n_iter
|
||||
self.win_length = win_length if win_length else self.n_fft
|
||||
self.hop_length = hop_length if hop_length else self.win_length // 2
|
||||
self.window_type = window_type
|
||||
self.power = power
|
||||
self.momentum = momentum
|
||||
self.length = length if length else 0
|
||||
self.rand_init = rand_init
|
||||
|
||||
def parse(self):
|
||||
return cde.GriffinLimOperation(self.n_fft, self.n_iter, self.win_length, self.hop_length,
|
||||
DE_C_WINDOW_TYPE.get(self.window_type), self.power, self.momentum, self.length,
|
||||
self.rand_init)
|
||||
|
||||
|
||||
class HighpassBiquad(AudioTensorOperation):
|
||||
"""
|
||||
Design biquad highpass filter and perform filtering. Similar to SoX implementation.
|
||||
|
|
|
|||
|
|
@ -621,6 +621,42 @@ def check_fade(method):
|
|||
return new_method
|
||||
|
||||
|
||||
def check_griffin_lim(method):
|
||||
"""Wrapper method to check the parameters of GriffinLim."""
|
||||
|
||||
@wraps(method)
|
||||
def new_method(self, *args, **kwargs):
|
||||
[n_fft, n_iter, win_length, hop_length, window_type, power, momentum, length,
|
||||
rand_init], _ = parse_user_args(method, *args, **kwargs)
|
||||
|
||||
type_check(n_fft, (int,), "n_fft")
|
||||
check_pos_int32(n_fft, "n_fft")
|
||||
type_check(n_iter, (int,), "n_iter")
|
||||
check_pos_int32(n_iter, "n_iter")
|
||||
if win_length is not None:
|
||||
type_check(win_length, (int,), "win_length")
|
||||
check_non_negative_int32(win_length, "win_length")
|
||||
if win_length > n_fft:
|
||||
raise ValueError(
|
||||
"Input win_length should be no more than n_fft, but got win_length: {0} and n_fft: {1}.".format(
|
||||
win_length, n_fft))
|
||||
if hop_length is not None:
|
||||
type_check(hop_length, (int,), "hop_length")
|
||||
check_non_negative_int32(hop_length, "hop_length")
|
||||
type_check(window_type, (WindowType,), "window_type")
|
||||
type_check(power, (int, float), "power")
|
||||
check_pos_float32(power, "power")
|
||||
type_check(momentum, (int, float), "momentum")
|
||||
check_non_negative_float32(momentum, "momentum")
|
||||
if length is not None:
|
||||
type_check(length, (int,), "length")
|
||||
check_non_negative_int32(length, "length")
|
||||
type_check(rand_init, (bool,), "rand_init")
|
||||
return method(self, *args, **kwargs)
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
def check_vol(method):
|
||||
"""Wrapper method to check the parameters of Vol."""
|
||||
|
||||
|
|
|
|||
|
|
@ -1007,6 +1007,143 @@ TEST_F(MindDataTestPipeline, TestTrebleBiquadWrongArg) {
|
|||
EXPECT_EQ(iter02, nullptr);
|
||||
}
|
||||
|
||||
/// Feature: GriffinLim.
|
||||
/// Description: test pipeline.
|
||||
/// Expectation: success.
|
||||
TEST_F(MindDataTestPipeline, TestGriffinLimPipeline) {
|
||||
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestGriffinLimPipeline.";
|
||||
// Original waveform
|
||||
std::shared_ptr<SchemaObj> schema = Schema();
|
||||
ASSERT_OK(schema->add_column("waveform", mindspore::DataType::kNumberTypeFloat32, {201, 6}));
|
||||
std::shared_ptr<Dataset> ds = RandomData(50, schema);
|
||||
EXPECT_NE(ds, nullptr);
|
||||
ds = ds->SetNumWorkers(4);
|
||||
EXPECT_NE(ds, nullptr);
|
||||
auto griffin_lim = audio::GriffinLim(400, 32, 0, 0, WindowType::kHann, 2.0, 0.99, 0, true);
|
||||
ds = ds->Map({griffin_lim});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
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 = {1000};
|
||||
int i = 0;
|
||||
while (row.size() != 0) {
|
||||
auto col = row["waveform"];
|
||||
ASSERT_EQ(col.Shape(), expected);
|
||||
ASSERT_EQ(col.Shape().size(), 1);
|
||||
ASSERT_EQ(col.DataType(), mindspore::DataType::kNumberTypeFloat32);
|
||||
ASSERT_OK(iter->GetNextRow(&row));
|
||||
i++;
|
||||
}
|
||||
EXPECT_EQ(i, 50);
|
||||
iter->Stop();
|
||||
|
||||
// Original waveform
|
||||
std::shared_ptr<SchemaObj> schema2 = Schema();
|
||||
ASSERT_OK(schema2->add_column("waveform", mindspore::DataType::kNumberTypeFloat64, {2, 301, 6}));
|
||||
std::shared_ptr<Dataset> ds2 = RandomData(50, schema2);
|
||||
EXPECT_NE(ds2, nullptr);
|
||||
ds2 = ds2->SetNumWorkers(4);
|
||||
EXPECT_NE(ds2, nullptr);
|
||||
auto griffin_lim2 = audio::GriffinLim(600, 10, 0, 300, WindowType::kHann, 1.0, 0.99, 0, false);
|
||||
ds2 = ds2->Map({griffin_lim2});
|
||||
EXPECT_NE(ds2, nullptr);
|
||||
std::shared_ptr<Iterator> iter2 = ds2->CreateIterator();
|
||||
EXPECT_NE(ds2, nullptr);
|
||||
std::unordered_map<std::string, mindspore::MSTensor> row2;
|
||||
ASSERT_OK(iter2->GetNextRow(&row2));
|
||||
std::vector<int64_t> expected2 = {2, 1500};
|
||||
i = 0;
|
||||
while (row2.size() != 0) {
|
||||
auto col = row2["waveform"];
|
||||
ASSERT_EQ(col.Shape(), expected2);
|
||||
ASSERT_EQ(col.Shape().size(), 2);
|
||||
ASSERT_EQ(col.DataType(), mindspore::DataType::kNumberTypeFloat64);
|
||||
ASSERT_OK(iter2->GetNextRow(&row2));
|
||||
i++;
|
||||
}
|
||||
EXPECT_EQ(i, 50);
|
||||
iter->Stop();
|
||||
}
|
||||
|
||||
/// Feature: GriffinLim.
|
||||
/// Description: test some invalid parameters.
|
||||
/// Expectation: success.
|
||||
TEST_F(MindDataTestPipeline, TestGriffinLimWrongArgs) {
|
||||
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestGriffinLimWrongArgs.";
|
||||
// Original waveform
|
||||
std::shared_ptr<SchemaObj> schema = Schema();
|
||||
ASSERT_OK(schema->add_column("waveform", mindspore::DataType::kNumberTypeFloat32, {201, 6}));
|
||||
std::shared_ptr<Dataset> ds = RandomData(50, schema);
|
||||
EXPECT_NE(ds, nullptr);
|
||||
|
||||
ds = ds->SetNumWorkers(4);
|
||||
EXPECT_NE(ds, nullptr);
|
||||
|
||||
// invalid n_fft
|
||||
auto griffin_lim_op = audio::GriffinLim(-10);
|
||||
ds = ds->Map({griffin_lim_op});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
std::shared_ptr<Iterator> iter = ds->CreateIterator();
|
||||
// Expect failure
|
||||
EXPECT_EQ(iter, nullptr);
|
||||
|
||||
// invalid n_iter
|
||||
griffin_lim_op = audio::GriffinLim(400, -10);
|
||||
ds = ds->Map({griffin_lim_op});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
iter = ds->CreateIterator();
|
||||
// Expect failure
|
||||
EXPECT_EQ(iter, nullptr);
|
||||
|
||||
// invalid win_length
|
||||
griffin_lim_op = audio::GriffinLim(400, 10, -2);
|
||||
ds = ds->Map({griffin_lim_op});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
iter = ds->CreateIterator();
|
||||
// Expect failure
|
||||
EXPECT_EQ(iter, nullptr);
|
||||
griffin_lim_op = audio::GriffinLim(400, 10, 500);
|
||||
ds = ds->Map({griffin_lim_op});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
iter = ds->CreateIterator();
|
||||
// Expect failure
|
||||
EXPECT_EQ(iter, nullptr);
|
||||
|
||||
// invalid hop_length
|
||||
griffin_lim_op = audio::GriffinLim(400, 10, 0, -10);
|
||||
ds = ds->Map({griffin_lim_op});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
iter = ds->CreateIterator();
|
||||
// Expect failure
|
||||
EXPECT_EQ(iter, nullptr);
|
||||
|
||||
// invalid power
|
||||
griffin_lim_op = audio::GriffinLim(400, 10, 0, 0, WindowType::kHann, -2);
|
||||
ds = ds->Map({griffin_lim_op});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
iter = ds->CreateIterator();
|
||||
// Expect failure
|
||||
EXPECT_EQ(iter, nullptr);
|
||||
|
||||
// invalid momentum
|
||||
griffin_lim_op = audio::GriffinLim(400, 10, 0, 0, WindowType::kHann, 2, -10);
|
||||
ds = ds->Map({griffin_lim_op});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
iter = ds->CreateIterator();
|
||||
// Expect failure
|
||||
EXPECT_EQ(iter, nullptr);
|
||||
|
||||
// invalid length
|
||||
griffin_lim_op = audio::GriffinLim(400, 10, 0, 0, WindowType::kHann, 2, 0.9, -3);
|
||||
ds = ds->Map({griffin_lim_op});
|
||||
EXPECT_NE(ds, nullptr);
|
||||
iter = ds->CreateIterator();
|
||||
// Expect failure
|
||||
EXPECT_EQ(iter, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(MindDataTestPipeline, TestVolPipeline) {
|
||||
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestVolPipeline.";
|
||||
// Original waveform
|
||||
|
|
|
|||
|
|
@ -1435,6 +1435,30 @@ TEST_F(MindDataTestExecute, TestFadeWithBool) {
|
|||
EXPECT_TRUE(s01.IsOk());
|
||||
}
|
||||
|
||||
|
||||
/// Feature: GriffinLim
|
||||
/// Description: test basic usage of GriffinLim
|
||||
/// Expectation: success
|
||||
TEST_F(MindDataTestExecute, TestGriffinLimDefaultValue) {
|
||||
MS_LOG(INFO) << "Doing MindDataTestExecute-TestGriffinLimDefaultValue.";
|
||||
// Random waveform
|
||||
std::mt19937 gen;
|
||||
std::normal_distribution<float> distribution(1.0, 0.5);
|
||||
std::vector<float> vec;
|
||||
for (int i = 0; i < 1206; ++i) {
|
||||
vec.push_back(distribution(gen));
|
||||
}
|
||||
std::shared_ptr<Tensor> input;
|
||||
ASSERT_OK(Tensor::CreateFromVector(vec, TensorShape({1, 201, 6}), &input));
|
||||
auto input_ms = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(input));
|
||||
std::shared_ptr<TensorTransform> griffin_lim_op = std::make_shared<audio::GriffinLim>();
|
||||
// apply griffinlim
|
||||
mindspore::dataset::Execute trans({griffin_lim_op});
|
||||
Status status = trans(input_ms, &input_ms);
|
||||
EXPECT_TRUE(status.IsOk());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(MindDataTestExecute, TestVolDefalutValue) {
|
||||
MS_LOG(INFO) << "Doing MindDataTestExecute-TestVolDefalutValue.";
|
||||
std::shared_ptr<Tensor> input_tensor_;
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,245 @@
|
|||
# Copyright 2022 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 GriffinLim op in DE
|
||||
"""
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.audio.transforms as c_audio
|
||||
from mindspore import log as logger
|
||||
|
||||
DATA_DIR = "../data/dataset/audiorecord/"
|
||||
|
||||
|
||||
def count_unequal_element(data_expected, data_me, rtol, atol):
|
||||
assert data_expected.shape == data_me.shape
|
||||
total_count = len(data_expected.flatten())
|
||||
error = np.abs(data_expected - data_me)
|
||||
greater = np.greater(error, atol + np.abs(data_expected) * rtol)
|
||||
loss_count = np.count_nonzero(greater)
|
||||
assert (loss_count / total_count) < rtol, \
|
||||
"\ndata_expected_std:{0}\ndata_me_error:{1}\nloss:{2}". \
|
||||
format(data_expected[greater], data_me[greater], error[greater])
|
||||
|
||||
|
||||
def allclose_nparray(data_expected, data_me, rtol, atol, equal_nan=True):
|
||||
if np.any(np.isnan(data_expected)):
|
||||
assert np.allclose(data_me, data_expected, rtol, atol, equal_nan=equal_nan)
|
||||
elif not np.allclose(data_me, data_expected, rtol, atol, equal_nan=equal_nan):
|
||||
count_unequal_element(data_expected, data_me, rtol, atol)
|
||||
|
||||
|
||||
def test_griffin_lim_pipeline():
|
||||
"""
|
||||
Feature: GriffinLim
|
||||
Description: test GriffinLim cpp op in pipeline
|
||||
Expectation: equal results from Mindspore and benchmark
|
||||
"""
|
||||
# <101, 6>
|
||||
in_data = np.load(DATA_DIR + "griffinlim_101x6.npy")[np.newaxis, :]
|
||||
out_expect = np.load(DATA_DIR + "griffinlim_101x6_out.npy")
|
||||
dataset = ds.NumpySlicesDataset(in_data, column_names=["multi_dimensional_data"], shuffle=False)
|
||||
transforms = [c_audio.GriffinLim(n_fft=200, rand_init=False)]
|
||||
dataset = dataset.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in dataset.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
out_put = item["multi_dimensional_data"]
|
||||
allclose_nparray(out_put, out_expect, 0.001, 0.001)
|
||||
|
||||
# <151, 8>
|
||||
in_data = np.load(DATA_DIR + "griffinlim_151x8.npy")[np.newaxis, :]
|
||||
out_expect = np.load(DATA_DIR + "griffinlim_151x8_out.npy")
|
||||
dataset = ds.NumpySlicesDataset(in_data, column_names=["multi_dimensional_data"], shuffle=False)
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=20, win_length=240, hop_length=120, rand_init=False, power=1.2)]
|
||||
dataset = dataset.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in dataset.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
out_put = item["multi_dimensional_data"]
|
||||
allclose_nparray(out_put, out_expect, 0.001, 0.001)
|
||||
|
||||
# <2, 301, 4> hop_length greater than half of win_length
|
||||
in_data = np.load(DATA_DIR + "griffinlim_2x301x4.npy")[np.newaxis, :]
|
||||
out_expect = np.load(DATA_DIR + "griffinlim_2x301x4_out.npy")
|
||||
dataset = ds.NumpySlicesDataset(in_data, column_names=["multi_dimensional_data"], shuffle=False)
|
||||
transforms = [c_audio.GriffinLim(n_fft=600, n_iter=10, win_length=240, hop_length=130, rand_init=False)]
|
||||
dataset = dataset.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in dataset.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
out_put = item["multi_dimensional_data"]
|
||||
allclose_nparray(out_put, out_expect, 0.001, 0.001)
|
||||
|
||||
|
||||
def test_griffin_lim_pipeline_invalid_param_range():
|
||||
"""
|
||||
Feature: GriffinLim
|
||||
Description: test GriffinLim with invalid input parameters
|
||||
Expectation: throw ValueError
|
||||
"""
|
||||
logger.info("test GriffinLim op with default values")
|
||||
in_data = np.load(DATA_DIR + "griffinlim_151x8.npy")[np.newaxis, :]
|
||||
data1 = ds.NumpySlicesDataset(in_data, column_names=["multi_dimensional_data"], shuffle=False)
|
||||
|
||||
with pytest.raises(ValueError, match=r"Input n_fft is not within the required interval of \[1, 2147483647\]."):
|
||||
transforms = [c_audio.GriffinLim(n_fft=-10)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(ValueError, match=r"Input n_iter is not within the required interval of \[1, 2147483647\]."):
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=-10)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(ValueError, match=r"Input win_length is not within the required interval of \[0, 2147483647\]."):
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=10, win_length=-10)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(ValueError,
|
||||
match=r"Input win_length should be no more than n_fft, but got win_length: 400 " +
|
||||
r"and n_fft: 300."):
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=10, win_length=400)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(ValueError, match=r"Input hop_length is not within the required interval of \[0, 2147483647\]."):
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=10, win_length=0, hop_length=-10)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(ValueError, match=r"Input power is not within the required interval of \(0, 16777216\]."):
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=10, win_length=0, hop_length=0, power=-3)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(ValueError, match=r"Input momentum is not within the required interval of \[0, 16777216\]."):
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=10, win_length=0, hop_length=0, power=2, momentum=-10)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(ValueError, match=r"Input length is not within the required interval of \[0, 2147483647\]."):
|
||||
transforms = [
|
||||
c_audio.GriffinLim(n_fft=300, n_iter=10, win_length=0, hop_length=0, power=2, momentum=0.9, length=-2)
|
||||
]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
|
||||
def test_griffin_lim_pipeline_invalid_param_constraint():
|
||||
"""
|
||||
Feature: GriffinLim
|
||||
Description: test GriffinLim with invalid input parameters
|
||||
Expectation: throw RuntimeError
|
||||
"""
|
||||
logger.info("test GriffinLim op with default values")
|
||||
in_data = np.load(DATA_DIR + "griffinlim_151x8.npy")[np.newaxis, :]
|
||||
data1 = ds.NumpySlicesDataset(in_data, column_names=["multi_dimensional_data"], shuffle=False)
|
||||
|
||||
with pytest.raises(RuntimeError,
|
||||
match=r"Unexpected error. map operation: \[GriffinLim\] failed. " +
|
||||
r"GriffinLim: the frequency of the input should equal to n_fft / 2 \+ 1"):
|
||||
transforms = [c_audio.GriffinLim(n_fft=100)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(RuntimeError,
|
||||
match=r"Unexpected error. map operation: \[GriffinLim\] failed. " +
|
||||
r"GriffinLim: the frequency of the input should equal to n_fft / 2 \+ 1"):
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=10, win_length=0, hop_length=120)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(RuntimeError,
|
||||
match=r"Syntax error. GriffinLim: momentum equal to or greater than 1 can be unstable, " +
|
||||
"but got: 1.000000"):
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=10, win_length=0, hop_length=0, power=2, momentum=1)]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
|
||||
def test_griffin_lim_pipeline_invalid_param_type():
|
||||
"""
|
||||
Feature: GriffinLim
|
||||
Description: test GriffinLim with invalid input parameters
|
||||
Expectation: throw TypeError
|
||||
"""
|
||||
logger.info("test GriffinLim op with default values")
|
||||
in_data = np.load(DATA_DIR + "griffinlim_151x8.npy")[np.newaxis, :]
|
||||
data1 = ds.NumpySlicesDataset(in_data, column_names=["multi_dimensional_data"], shuffle=False)
|
||||
|
||||
with pytest.raises(TypeError,
|
||||
match=r"Argument window_type with value type is not of type " +
|
||||
r"\[<enum \'WindowType\'>\], but got <class \'str\'>."):
|
||||
transforms = [c_audio.GriffinLim(n_fft=300, n_iter=10, win_length=0, hop_length=0, window_type="type")]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
with pytest.raises(TypeError,
|
||||
match=r"Argument rand_init with value true is not of type \[<class \'bool\'>\], " +
|
||||
r"but got <class \'str\'>."):
|
||||
transforms = [
|
||||
c_audio.GriffinLim(n_fft=300,
|
||||
n_iter=10,
|
||||
win_length=0,
|
||||
hop_length=0,
|
||||
power=2,
|
||||
momentum=0.9,
|
||||
length=0,
|
||||
rand_init='true')
|
||||
]
|
||||
data1 = data1.map(operations=transforms, input_columns=["multi_dimensional_data"])
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
_ = item["multi_dimensional_data"]
|
||||
|
||||
|
||||
def test_griffin_lim_eager():
|
||||
"""
|
||||
Feature: GriffinLim
|
||||
Description: test GriffinLim cpp op with eager mode
|
||||
Expectation: equal results from Mindspore and benchmark
|
||||
"""
|
||||
# <freq, time>
|
||||
spectrogram = np.load(DATA_DIR + "griffinlim_101x6.npy").astype(np.float64)
|
||||
out_expect = np.load(DATA_DIR + "griffinlim_101x6_out.npy").astype(np.float64)
|
||||
out_ms = c_audio.GriffinLim(n_fft=200, rand_init=False)(spectrogram)
|
||||
allclose_nparray(out_ms, out_expect, 0.001, 0.001)
|
||||
# <1, freq, time>
|
||||
spectrogram = np.load(DATA_DIR + "griffinlim_1x201x6.npy").astype(np.float64)
|
||||
out_expect = np.load(DATA_DIR + "griffinlim_1x201x6_out.npy").astype(np.float64)
|
||||
out_ms = c_audio.GriffinLim(rand_init=False)(spectrogram)
|
||||
allclose_nparray(out_ms, out_expect, 0.001, 0.001)
|
||||
# <2, freq, time>
|
||||
spectrogram = np.load(DATA_DIR + "griffinlim_2x301x6.npy").astype(np.float64)
|
||||
out_expect = np.load(DATA_DIR + "griffinlim_2x301x6_out.npy").astype(np.float64)
|
||||
out_ms = c_audio.GriffinLim(n_fft=600, rand_init=False)(spectrogram)
|
||||
allclose_nparray(out_ms, out_expect, 0.001, 0.001)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_griffin_lim_pipeline()
|
||||
test_griffin_lim_pipeline_invalid_param_range()
|
||||
test_griffin_lim_pipeline_invalid_param_constraint()
|
||||
test_griffin_lim_pipeline_invalid_param_type()
|
||||
test_griffin_lim_eager()
|
||||
Loading…
Reference in New Issue