!26244 [assistant][ops] Add new data PhaseVocoder

Merge pull request !26244 from TR-nbu/PhaseVocoder
This commit is contained in:
i-robot 2022-01-26 06:46:36 +00:00 committed by Gitee
commit 2b82ba1e49
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
17 changed files with 637 additions and 3 deletions

View File

@ -45,6 +45,7 @@
#include "minddata/dataset/audio/ir/kernels/mu_law_decoding_ir.h"
#include "minddata/dataset/audio/ir/kernels/mu_law_encoding_ir.h"
#include "minddata/dataset/audio/ir/kernels/overdrive_ir.h"
#include "minddata/dataset/audio/ir/kernels/phase_vocoder_ir.h"
#include "minddata/dataset/audio/ir/kernels/phaser_ir.h"
#include "minddata/dataset/audio/ir/kernels/riaa_biquad_ir.h"
#include "minddata/dataset/audio/ir/kernels/sliding_window_cmn_ir.h"
@ -583,6 +584,26 @@ std::shared_ptr<TensorOperation> Phaser::Parse() {
data_->decay_, data_->mod_speed_, data_->sinusoidal_);
}
// PhaseVocoder Transofrm Operation.
struct PhaseVocoder::Data {
Data(float rate, const MSTensor &phase_advance) : rate_(rate), phase_advance_(phase_advance) {}
float rate_;
MSTensor phase_advance_;
};
PhaseVocoder::PhaseVocoder(float rate, const MSTensor &phase_advance)
: data_(std::make_shared<Data>(rate, phase_advance)) {}
std::shared_ptr<TensorOperation> PhaseVocoder::Parse() {
std::shared_ptr<Tensor> phase_advance;
Status rc = Tensor::CreateFromMSTensor(data_->phase_advance_, &phase_advance);
if (rc.IsError()) {
MS_LOG(ERROR) << "Error creating phase_vocoder constant tensor." << rc;
return nullptr;
}
return std::make_shared<PhaseVocoderOperation>(data_->rate_, phase_advance);
}
// RiaaBiquad Transform Operation.
struct RiaaBiquad::Data {
explicit Data(int32_t sample_rate) : sample_rate_(sample_rate) {}

View File

@ -49,6 +49,7 @@
#include "minddata/dataset/audio/ir/kernels/mu_law_decoding_ir.h"
#include "minddata/dataset/audio/ir/kernels/mu_law_encoding_ir.h"
#include "minddata/dataset/audio/ir/kernels/overdrive_ir.h"
#include "minddata/dataset/audio/ir/kernels/phase_vocoder_ir.h"
#include "minddata/dataset/audio/ir/kernels/phaser_ir.h"
#include "minddata/dataset/audio/ir/kernels/riaa_biquad_ir.h"
#include "minddata/dataset/audio/ir/kernels/sliding_window_cmn_ir.h"
@ -432,6 +433,17 @@ PYBIND_REGISTER(PhaserOperation, 1, ([](const py::module *m) {
}));
}));
PYBIND_REGISTER(
PhaseVocoderOperation, 1, ([](const py::module *m) {
(void)py::class_<audio::PhaseVocoderOperation, TensorOperation, std::shared_ptr<audio::PhaseVocoderOperation>>(
*m, "PhaseVocoderOperation")
.def(py::init([](float rate, const std::shared_ptr<Tensor> &phase_advance) {
auto phase_vocoder = std::make_shared<audio::PhaseVocoderOperation>(rate, phase_advance);
THROW_IF_ERROR(phase_vocoder->ValidateParams());
return phase_vocoder;
}));
}));
PYBIND_REGISTER(
RiaaBiquadOperation, 1, ([](const py::module *m) {
(void)py::class_<audio::RiaaBiquadOperation, TensorOperation, std::shared_ptr<audio::RiaaBiquadOperation>>(

View File

@ -31,6 +31,7 @@ add_library(audio-ir-kernels OBJECT
mu_law_decoding_ir.cc
mu_law_encoding_ir.cc
overdrive_ir.cc
phase_vocoder_ir.cc
phaser_ir.cc
riaa_biquad_ir.cc
sliding_window_cmn_ir.cc

View File

@ -0,0 +1,56 @@
/**
* 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/phase_vocoder_ir.h"
#include "minddata/dataset/audio/ir/validators.h"
#include "minddata/dataset/audio/kernels/phase_vocoder_op.h"
namespace mindspore {
namespace dataset {
namespace audio {
PhaseVocoderOperation::PhaseVocoderOperation(float rate, const std::shared_ptr<Tensor> &phase_advance)
: rate_(rate), phase_advance_(phase_advance) {}
PhaseVocoderOperation::~PhaseVocoderOperation() = default;
Status PhaseVocoderOperation::ValidateParams() {
const int kPhaseAdvanceRank = 2;
const int kLastDim = -1;
const int kLastDimSize = 1;
RETURN_IF_NOT_OK(ValidateFloatScalarPositive("PhaseVocoder", "rate", rate_));
CHECK_FAIL_RETURN_SYNTAX_ERROR(
phase_advance_->Rank() == kPhaseAdvanceRank && phase_advance_->shape()[kLastDim] == kLastDimSize,
"PhaseVocoder: invalid parameter, 'phase_advance' should be in shape of <freq, 1>.");
return Status::OK();
}
std::string PhaseVocoderOperation::Name() const { return kPhaseVocoderOperation; }
std::shared_ptr<TensorOp> PhaseVocoderOperation::Build() {
std::shared_ptr<PhaseVocoderOp> tensor_op = std::make_shared<PhaseVocoderOp>(rate_, phase_advance_);
return tensor_op;
}
Status PhaseVocoderOperation::to_json(nlohmann::json *out_json) {
nlohmann::json args;
args["rate"] = rate_;
RETURN_IF_NOT_OK(phase_advance_->to_json(&args));
*out_json = args;
return Status::OK();
}
} // namespace audio
} // namespace dataset
} // namespace mindspore

View File

@ -0,0 +1,52 @@
/**
* 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_PHASE_VOCODER_IR_H_
#define MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_IR_KERNELS_PHASE_VOCODER_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 kPhaseVocoderOperation[] = "PhaseVocoder";
class PhaseVocoderOperation : public TensorOperation {
public:
PhaseVocoderOperation(float rate, const std::shared_ptr<Tensor> &phase_advance);
~PhaseVocoderOperation();
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
std::string Name() const override;
Status to_json(nlohmann::json *out_json) override;
private:
float rate_;
std::shared_ptr<Tensor> phase_advance_;
};
} // namespace audio
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_IR_KERNELS_PHASE_VOCODER_IR_H_

View File

@ -32,6 +32,7 @@ add_library(audio-kernels OBJECT
mu_law_decoding_op.cc
mu_law_encoding_op.cc
overdrive_op.cc
phase_vocoder_op.cc
phaser_op.cc
riaa_biquad_op.cc
sliding_window_cmn_op.cc

View File

@ -475,6 +475,29 @@ Status TimeStretch(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor>
return Status::OK();
}
Status PhaseVocoder(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, float rate,
const std::shared_ptr<Tensor> &phase_advance) {
const int32_t kFrequencePosInComplex = -3;
RETURN_IF_NOT_OK(ValidateTensorShape("PhaseVocoder", input->shape().Size() > kDefaultAudioDim && input->IsComplex(),
"<..., freq, num_frame, complex=2>"));
RETURN_IF_NOT_OK(ValidateTensorNumeric("PhaseVocoder", input));
RETURN_IF_NOT_OK(ValidateEqual("PhaseVocoder", "first dimension of 'phase_advance'", phase_advance->shape()[0],
"freq dimension length of input tensor", input->shape()[kFrequencePosInComplex]));
CHECK_FAIL_RETURN_UNEXPECTED(phase_advance->type() == input->type(),
"PhaseVocoder: invalid parameter, data type of phase_advance should be equal to data "
"type of input tensor, but got: data type of phase_advance " +
phase_advance->type().ToString() + " while data type of input tensor " +
input->type().ToString() + ".");
std::shared_ptr<Tensor> input_tensor;
if (input->type().value() != DataType::DE_FLOAT64) {
RETURN_IF_NOT_OK(TypeCast(input, &input_tensor, DataType(DataType::DE_FLOAT32)));
RETURN_IF_NOT_OK(TimeStretch<float>(input_tensor, output, rate, phase_advance));
} else {
RETURN_IF_NOT_OK(TimeStretch<double>(input, output, rate, phase_advance));
}
return Status::OK();
}
Status Dct(std::shared_ptr<Tensor> *output, int n_mfcc, int n_mels, NormMode norm) {
TensorShape dct_shape({n_mels, n_mfcc});
Tensor::CreateEmpty(dct_shape, DataType(DataType::DE_FLOAT32), output);

View File

@ -445,6 +445,15 @@ Status SpectralCentroid(const std::shared_ptr<Tensor> &input, std::shared_ptr<Te
Status TimeStretch(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, float rate, float hop_length,
float n_freq);
/// \brief Stretch STFT in time at a given rate, without changing the pitch.
/// \param[in] input Tensor of shape <..., freq, time, 2>.
/// \param[in] output Tensor of shape <..., freq, ceil(time/rate), 2>.
/// \param[in] rate Speed-up factor.
/// \param[in] phase_advance Expected phase advance in each bin in shape of (freq, 1).
/// \return Status code.
Status PhaseVocoder(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, float rate,
const std::shared_ptr<Tensor> &phase_advance);
/// \brief Apply a mask along axis.
/// \param input: Tensor of shape <..., freq, time>.
/// \param output: Tensor of shape <..., freq, time>.

View File

@ -0,0 +1,57 @@
/**
* 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/phase_vocoder_op.h"
#include "minddata/dataset/audio/kernels/audio_utils.h"
#include "minddata/dataset/kernels/data/data_utils.h"
namespace mindspore {
namespace dataset {
Status PhaseVocoderOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
IO_CHECK(input, output);
return PhaseVocoder(input, output, rate_, phase_advance_);
}
Status PhaseVocoderOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs));
outputs.clear();
const int32_t kTimePos = -2;
const int32_t kComplexDimSize = 2;
for (auto s : inputs) {
std::vector<dsize_t> s_vec = s.AsVector();
s_vec.pop_back();
s_vec.pop_back();
s_vec.push_back(std::ceil(s[kTimePos] / rate_));
s_vec.push_back(kComplexDimSize);
outputs.emplace_back(TensorShape(s_vec));
}
CHECK_FAIL_RETURN_UNEXPECTED(!outputs.empty(), "PhaseVocoder: invalid shape of input tensor.");
return Status::OK();
}
Status PhaseVocoderOp::OutputType(const std::vector<DataType> &inputs, std::vector<DataType> &outputs) {
RETURN_IF_NOT_OK(TensorOp::OutputType(inputs, outputs));
RETURN_IF_NOT_OK(
ValidateTensorType("PhaseVocoder", 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

View File

@ -0,0 +1,53 @@
/**
* 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_PHASE_VOCODER_OP_H_
#define MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_PHASE_VOCODER_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 PhaseVocoderOp : public TensorOp {
public:
/// \brief Constructor.
/// \param[in] rate Speed-up factor.
/// \param[in] phase_advance Expected phase advance in each bin in shape of (freq, 1).
PhaseVocoderOp(float rate, const std::shared_ptr<Tensor> &phase_advance)
: rate_(rate), phase_advance_(phase_advance) {}
~PhaseVocoderOp() override = default;
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
std::string Name() const override { return kPhaseVocoderOp; }
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
Status OutputType(const std::vector<DataType> &inputs, std::vector<DataType> &outputs) override;
private:
float rate_;
std::shared_ptr<Tensor> phase_advance_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_AUDIO_KERNELS_PHASE_VOCODER_OP_H_

View File

@ -751,6 +751,28 @@ class MS_API Phaser final : public TensorTransform {
std::shared_ptr<Data> data_;
};
/// \brief PhaseVocoder TensorTransform
/// \notes Given a STFT tensor, speed up in time without modifying pitch by factor of rate.
class MS_API PhaseVocoder final : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] rate Speed-up factor.
/// \param[in] phase_advance Expected phase advance in each bin in shape of (freq, 1).
PhaseVocoder(float rate, const MSTensor &phase_advance);
/// \brief Destructor.
~PhaseVocoder() = 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 Apply RIAA vinyl playback equalization.
class MS_API RiaaBiquad final : public TensorTransform {
public:

View File

@ -176,6 +176,7 @@ constexpr char kMuLawDecodingOp[] = "MuLawDecodingOp";
constexpr char kMuLawEncodingOp[] = "MuLawEncodingOp";
constexpr char kOverdriveOp[] = "OverdriveOp";
constexpr char kPhaserOp[] = "PhaserOp";
constexpr char kPhaseVocoderOp[] = "PhaseVocoderOp";
constexpr char kRiaaBiquadOp[] = "RiaaBiquadOp";
constexpr char kSlidingWindowCmnOp[] = "SlidingWindowCmnOp";
constexpr char kSpectralCentroidOp[] = "SpectralCentroidOp";

View File

@ -30,8 +30,8 @@ from .validators import check_allpass_biquad, check_amplitude_to_db, check_band_
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_masking, check_mel_scale, check_mu_law_coding, \
check_overdrive, check_phaser, check_riaa_biquad, check_sliding_window_cmn, check_spectral_centroid, \
check_spectrogram, check_time_stretch, check_treble_biquad, check_vol
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):
@ -1114,6 +1114,33 @@ class Phaser(AudioTensorOperation):
self.delay_ms, self.decay, self.mod_speed, self.sinusoidal)
class PhaseVocoder(AudioTensorOperation):
"""
Given a STFT tensor, speed up in time without modifying pitch by a factor of rate.
Args:
rate (float): Speed-up factor.
phase_advance (numpy.ndarray): Expected phase advance in each bin in shape of (freq, 1).
Examples:
>>> import numpy as np
>>>
>>> waveform = np.random.randn(2, 44, 10, 2)
>>> numpy_slices_dataset = ds.NumpySlicesDataset(data=waveform, column_names=["audio"])
>>> phase_advance = np.random.randn(44, 1)
>>> transforms = [audio.PhaseVocoder(rate=2, phase_advance=phase_advance)]
>>> numpy_slices_dataset = numpy_slices_dataset.map(operations=transforms, input_columns=["audio"])
"""
@check_phase_vocoder
def __init__(self, rate, phase_advance):
self.rate = rate
self.phase_advance = cde.Tensor(phase_advance)
def parse(self):
return cde.PhaseVocoderOperation(self.rate, self.phase_advance)
class RiaaBiquad(AudioTensorOperation):
"""
Apply RIAA vinyl playback equalization. Similar to SoX implementation.

View File

@ -18,6 +18,8 @@ Validators for TensorOps.
from functools import wraps
import numpy as np
from mindspore.dataset.core.validator_helpers import check_float32, check_float32_not_zero, check_int32, \
check_int32_not_zero, check_list_same_size, check_non_negative_float32, check_non_negative_int32, \
check_pos_float32, check_pos_int32, check_value, INT32_MAX, parse_user_args, type_check
@ -721,3 +723,17 @@ def check_spectral_centroid(method):
return method(self, *args, **kwargs)
return new_method
def check_phase_vocoder(method):
"""Wrapper method to check the parameters of PhaseVocoder."""
@wraps(method)
def new_method(self, *args, **kwargs):
[rate, phase_advance], _ = parse_user_args(method, *args, **kwargs)
type_check(rate, (int, float), "rate")
check_pos_float32(rate, "rate")
type_check(phase_advance, (np.ndarray,), "phase_advance")
return method(self, *args, **kwargs)
return new_method

View File

@ -1,5 +1,5 @@
/**
* Copyright 2021 Huawei Technologies Co., Ltd
* Copyright 2021-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.
@ -2245,3 +2245,99 @@ TEST_F(MindDataTestPipeline, TestMelScaleWrongArgs) {
iter = ds->CreateIterator();
EXPECT_EQ(iter, nullptr);
}
/// Feature: PhaseVocoder
/// Description: test PhaseVocoder in pipeline mode
/// Expectation: the data is processed successfully
TEST_F(MindDataTestPipeline, TestPhaseVocoderPipeline) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestPhaseVocoderPipeline.";
std::shared_ptr<SchemaObj> schema = Schema();
int freq = 1025;
int hop_length = 512;
ASSERT_OK(schema->add_column("waveform", mindspore::DataType::kNumberTypeFloat32, {2, freq, 30, 2}));
std::vector<float> phase_advance;
float tpnum = 0;
float step = (1.0 * M_PI * hop_length / (freq - 1));
for (int i = 0; i < freq; i++) {
phase_advance.push_back(tpnum);
tpnum += step;
}
std::shared_ptr<Dataset> ds = RandomData(5, schema);
EXPECT_NE(ds, nullptr);
ds = ds->SetNumWorkers(4);
EXPECT_NE(ds, nullptr);
std::shared_ptr<Tensor> phase_advance_tensor;
Tensor::CreateFromVector(phase_advance, TensorShape({1025, 1}), &phase_advance_tensor);
auto input_ms = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(phase_advance_tensor));
float rate = 1.3;
auto PhaseVocoder = audio::PhaseVocoder(rate, input_ms);
ds = ds->Map({PhaseVocoder});
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 = {2, 1025, 24, 2};
int i = 0;
while (row.size() != 0) {
auto col = row["waveform"];
ASSERT_EQ(col.Shape(), expected);
ASSERT_EQ(col.Shape().size(), 4);
ASSERT_EQ(col.DataType(), mindspore::DataType::kNumberTypeFloat32);
ASSERT_OK(iter->GetNextRow(&row));
i++;
}
EXPECT_EQ(i, 5);
iter->Stop();
}
/// Feature: PhaseVocoder
/// Description: test PhaseVocoder with wrong input
/// Expectation: Throw exception as expected.
TEST_F(MindDataTestPipeline, TestPhaseVocoderWrongArgs) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestPhaseVocoderWrongArgs.";
std::shared_ptr<SchemaObj> schema = Schema();
int freq = 1025;
int hop_length = 512;
ASSERT_OK(schema->add_column("waveform", mindspore::DataType::kNumberTypeFloat32, {2, freq, 30, 2}));
std::vector<float> phase_advance;
float tpnum = 0;
float step = (1.0 * M_PI * hop_length / (freq - 1));
for (int i = 0; i < freq; i++) {
phase_advance.push_back(tpnum);
tpnum += step;
}
std::shared_ptr<Tensor> phase_advance_tensor;
Tensor::CreateFromVector(phase_advance, TensorShape({1025, 1}), &phase_advance_tensor);
auto input_ms = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(phase_advance_tensor));
std::shared_ptr<Dataset> ds = RandomData(50, schema);
EXPECT_NE(ds, nullptr);
ds = ds->SetNumWorkers(4);
EXPECT_NE(ds, nullptr);
float rate = -2.0;
auto PhaseVocoder = audio::PhaseVocoder(rate, input_ms);
ds = ds->Map({PhaseVocoder});
EXPECT_NE(ds, nullptr);
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_EQ(iter, nullptr);
}

View File

@ -2161,6 +2161,32 @@ TEST_F(MindDataTestExecute, TestDBToAmplitudeWithEager) {
EXPECT_TRUE(s01.IsOk());
}
/// Feature: PhaseVocoder
/// Description: test PhaseVocoder in eager mode
/// Expectation: the data is processed successfully
TEST_F(MindDataTestExecute, TestPhaseVocoderEager) {
MS_LOG(INFO) << "Doing MindDataTestExecute-TestPhaseVocoderEager.";
// testing
std::shared_ptr<Tensor> input_tensor, input_phase_advance_tensor;
Tensor::CreateFromVector(
std::vector<float>({0.1468, -1.1094, 0.0525, -0.3742, -0.7729, -0.7138, 0.3253, 0.0419, 0.8433, -0.5313,
-0.0988, -0.0927, -0.7071, -0.7740, -1.1087, -1.1925, -1.2749, -0.0862, 0.0693, 0.2937,
0.1676, 0.2356, 2.7333, 2.5171, 0.8055, 0.7380, -0.4437, -0.7257, -0.7154, 0.1801,
-1.9323, 1.8184, 0.8196, 0.1371, -0.0677, -2.2315, 0.0662, -0.0071, -0.8639, 0.6215,
-0.5144, 0.8373, -0.1072, 0.6184, 0.1985, -0.7692, -0.5879, -0.0029, 0.0676, -0.5520}),
TensorShape({1, 5, 5, 2}), &input_tensor);
auto input_tensor_ms = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(input_tensor));
float rate = 2;
std::vector<float> phase_advance{0.0000, 1.5708, 3.1416, 4.7124, 6.2832};
Tensor::CreateFromVector(phase_advance, TensorShape({5, 1}), &input_phase_advance_tensor);
auto phase_advance_ms =
mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(input_phase_advance_tensor));
std::shared_ptr<TensorTransform> pv = std::make_shared<audio::PhaseVocoder>(rate, phase_advance_ms);
mindspore::dataset::Execute transform({pv});
Status status = transform(input_tensor_ms, &input_tensor_ms);
EXPECT_TRUE(status.IsOk());
}
/// Feature: SlidingWindowCmn
/// Description: test basic function of SlidingWindowCmn
/// Expectation: get correct number of data

View File

@ -0,0 +1,161 @@
# 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.
# ==============================================================================
import numpy as np
import pytest
import mindspore.dataset as ds
import mindspore.dataset.audio.transforms as audio
from mindspore import log as logger
def gen(shape):
np.random.seed(0)
data = np.random.random(shape)
yield (np.array(data, dtype=np.float32),)
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_phase_vocoder_compare():
"""
Feature: PhaseVocoder
Description: mindspore eager mode checking precision
Expectation: the returned result is as expected
"""
indata_0 = np.array([[[[0.43189, 2.3049924],
[-0.01202229, 0.9176453],
[-0.6258611, 0.66475236],
[0.13541847, 1.2829605],
[0.9725325, 1.1669061]],
[[-0.35001752, -1.0989336],
[-1.4930767, 0.86829656],
[0.3355314, -0.41216415],
[-1.1828239, 1.0075365],
[-0.19343425, 0.38364533]]]]).astype('float32')
indata_1 = np.array([[[[0.43189, 2.3049924],
[-0.01202229, 0.9176453],
[-0.6258611, 0.66475236],
[0.13541847, 1.2829605],
[0.9725325, 1.1669061]],
[[-0.35001752, -1.0989336],
[-1.4930767, 0.86829656],
[0.3355314, -0.41216415],
[-1.1828239, 1.0075365],
[-0.19343425, 0.38364533]]]]).astype('float64')
rate = 2.
phase_advance_0 = np.array([[0.0000], [3.9270]]).astype('float32')
op_0 = audio.PhaseVocoder(rate, phase_advance_0)
phase_advance_1 = np.array([[0.0000], [3.9270]]).astype('float64')
op_1 = audio.PhaseVocoder(rate, phase_advance_1)
outdata_0 = op_0(indata_0)
outdata_1 = op_1(indata_1)
stand_outdata = np.array([[[[0.43189007, 2.3049924],
[-0.01196056, 0.9129374],
[1.1385509, 1.00558]],
[[-0.35001755, -1.0989336],
[-0.4594292, 0.26718047],
[0.404371, -0.14520557]]]]).astype('float32')
allclose_nparray(outdata_0, stand_outdata, 0.0001, 0.0001)
allclose_nparray(outdata_1, stand_outdata, 0.0001, 0.0001)
def test_phase_vocoder_eager():
"""
Feature: PhaseVocoder
Description: mindspore eager mode with normal testcase
Expectation: the returned result is as expected
"""
logger.info("test PhaseVocoder op in eager mode")
stft = next(gen([10, 10, 10, 2]))[0]
out_put = audio.PhaseVocoder(1.3, np.random.randn(10, 1).astype('float32'))(stft)
assert out_put.shape == (10, 10, 8, 2)
def test_phase_vocoder_pipeline():
"""
Feature: PhaseVocoder
Description: mindspore pipeline mode with normal testcase
Expectation: the returned result is as expected
"""
logger.info("test PhaseVocoder op in pipeline mode")
generator = gen([32, 33, 333, 2])
data1 = ds.GeneratorDataset(source=generator, column_names=["input"])
transforms = [audio.PhaseVocoder(0.8, np.random.randn(33, 1).astype('float32'))]
data1 = data1.map(operations=transforms, input_columns=["input"])
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
out_put = item["input"]
assert out_put.shape == (32, 33, 417, 2)
def test_phase_vocoder_invalid_input():
"""
Feature: PhaseVocoder
Description: mindspore eager mode with invalid input
Expectation: the returned result is as expected
"""
def test_invalid_param(test_name, rate, phase_advance, error, error_msg):
logger.info("Test PhaseVocoder with wrong params: {0}".format(test_name))
with pytest.raises(error) as error_info:
_ = audio.PhaseVocoder(rate, phase_advance)
assert error_msg in str(error_info.value)
def test_invalid_input(test_name, spec, rate, phase_advance, error, error_msg):
logger.info("Test PhaseVocoder with wrong params: {0}".format(test_name))
with pytest.raises(error) as error_info:
_ = audio.PhaseVocoder(rate, phase_advance)(spec)
assert error_msg in str(error_info.value)
test_invalid_param("invalid phase_advance", 2, None, TypeError,
"Argument phase_advance with value None is not of type")
test_invalid_param("invalid phase_advance", 0, np.random.randn(4, 1), ValueError,
"Input rate is not within the required interval of (0, 16777216].")
spec = next(gen([1, 2, 2]))[0]
test_invalid_input("invalid phase_advance", spec, 1.23, np.random.randn(4), RuntimeError,
"PhaseVocoder: invalid parameter, 'phase_advance' should be in shape of <freq, 1>.")
test_invalid_input("invalid phase_advance", spec, 1.1, np.random.randn(4, 4, 1), RuntimeError,
"PhaseVocoder: invalid parameter, 'phase_advance' should be in shape of <freq, 1>.")
test_invalid_input("invalid input tensor", spec, 2, np.random.randn(3, 1), RuntimeError,
"PhaseVocoder: invalid parameter, 'first dimension of 'phase_advance'' should be equal")
input_tensor = np.random.randn(4, 4, 2).astype('float32')
input_phase_advance = np.random.randn(4, 1).astype('float64')
test_invalid_input("invalid input tensor", input_tensor, 2, input_phase_advance, RuntimeError,
"PhaseVocoder: invalid parameter, data type of phase_advance should be equal to data")
if __name__ == "__main__":
test_phase_vocoder_compare()
test_phase_vocoder_eager()
test_phase_vocoder_pipeline()
test_phase_vocoder_invalid_input()