Skip to content

Commit

Permalink
support spectrum input
Browse files Browse the repository at this point in the history
  • Loading branch information
takenori-y committed Feb 22, 2022
1 parent 8dda147 commit d166ba8
Show file tree
Hide file tree
Showing 13 changed files with 606 additions and 43 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ set(CC_SOURCES
${SOURCE_DIR}/analysis/adaptive_generalized_cepstral_analysis.cc
${SOURCE_DIR}/analysis/adaptive_mel_cepstral_analysis.cc
${SOURCE_DIR}/analysis/adaptive_mel_generalized_cepstral_analysis.cc
${SOURCE_DIR}/analysis/autocorrelation_analysis.cc
${SOURCE_DIR}/analysis/fast_fourier_transform_cepstral_analysis.cc
${SOURCE_DIR}/analysis/mel_cepstral_analysis.cc
${SOURCE_DIR}/analysis/mel_filter_bank_analysis.cc
Expand Down Expand Up @@ -117,6 +118,7 @@ set(CC_SOURCES
${SOURCE_DIR}/conversion/negative_derivative_of_phase_spectrum_to_cepstrum.cc
${SOURCE_DIR}/conversion/parcor_coefficients_to_linear_predictive_coefficients.cc
${SOURCE_DIR}/conversion/parcor_coefficients_to_log_area_ratio.cc
${SOURCE_DIR}/conversion/spectrum_to_autocorrelation.cc
${SOURCE_DIR}/conversion/spectrum_to_spectrum.cc
${SOURCE_DIR}/conversion/waveform_to_autocorrelation.cc
${SOURCE_DIR}/conversion/waveform_to_spectrum.cc
Expand Down
8 changes: 7 additions & 1 deletion doc/main/acorr.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ acorr

.. doxygenfile:: acorr.cc

.. seealso:: :ref:`c2acr` :ref:`levdur`
.. seealso:: :ref:`c2acr` :ref:`levdur` :ref:`lpc`

.. doxygenclass:: sptk::AutocorrelationAnalysis
:members:

.. doxygenclass:: sptk::WaveformToAutocorrelation
:members:

.. doxygenclass:: sptk::SpectrumToAutocorrelation
:members:
91 changes: 91 additions & 0 deletions include/SPTK/analysis/autocorrelation_analysis.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// ------------------------------------------------------------------------ //
// Copyright 2021 SPTK Working Group //
// //
// 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 SPTK_ANALYSIS_AUTOCORRELATION_ANALYSIS_H_
#define SPTK_ANALYSIS_AUTOCORRELATION_ANALYSIS_H_

#include <vector> // std::vector

#include "SPTK/conversion/spectrum_to_autocorrelation.h"
#include "SPTK/conversion/waveform_to_autocorrelation.h"
#include "SPTK/utils/sptk_utils.h"

namespace sptk {

/**
* Calculate autocorrelation from waveform or spectrum.
*/
class AutocorrelationAnalysis {
public:
/**
* Buffer for AutocorrelationAnalysis class.
*/
class Buffer {
public:
Buffer() {
}

virtual ~Buffer() {
}

private:
SpectrumToAutocorrelation::Buffer buffer_;

friend class AutocorrelationAnalysis;
DISALLOW_COPY_AND_ASSIGN(Buffer);
};

/**
* @param[in] frame_length Frame length or number of FFT bins, @f$L@f$.
* @param[in] num_order Order of autocorrelation, @f$M@f$.
* @param[in] waveform_input If true, assume waveform input.
*/
AutocorrelationAnalysis(int frame_length, int num_order, bool waveform_input);

virtual ~AutocorrelationAnalysis();

/**
* @return True if this object is valid.
*/
bool IsValid() const {
return is_valid_;
}

/**
* @param[in] input @f$L@f$-length waveform or @f$(L/2+1)@f$-length power
* spectrum.
* @param[out] autocorrelation @f$M@f$-th order autocorrelation coefficients.
* @param[out] buffer Buffer.
* @return True on success, false on failure.
*/
bool Run(const std::vector<double>& input,
std::vector<double>* autocorrelation,
AutocorrelationAnalysis::Buffer* buffer) const;

private:
const bool waveform_input_;

WaveformToAutocorrelation* waveform_to_autocorrelation_;
SpectrumToAutocorrelation* spectrum_to_autocorrelation_;

bool is_valid_;

DISALLOW_COPY_AND_ASSIGN(AutocorrelationAnalysis);
};

} // namespace sptk

#endif // SPTK_ANALYSIS_AUTOCORRELATION_ANALYSIS_H_
125 changes: 125 additions & 0 deletions include/SPTK/conversion/spectrum_to_autocorrelation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// ------------------------------------------------------------------------ //
// Copyright 2021 SPTK Working Group //
// //
// 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 SPTK_CONVERSION_SPECTRUM_TO_AUTOCORRELATION_H_
#define SPTK_CONVERSION_SPECTRUM_TO_AUTOCORRELATION_H_

#include <vector> // std::vector

#include "SPTK/math/real_valued_inverse_fast_fourier_transform.h"
#include "SPTK/utils/sptk_utils.h"

namespace sptk {

/**
* Calculate autocorrelation from power spectrum.
*
* The input is the half of power spectrum:
* @f[
* \begin{array}{cccc}
* |X(0)|^2, & |X(1)|^2, & \ldots, & |X(L/2)|^2,
* \end{array}
* @f]
* where @f$L@f$ is the FFT length. The output is the @f$M@f$-th order
* autocorrelation coefficients:
* @f[
* \begin{array}{cccc}
* r(0), & r(1), & \ldots, & r(M).
* \end{array}
* @f]
* The autocorrelation is given by
* @f[
* r(m) = \frac{1}{L} \sum_{l=0}^{L-1} |X(l)|^2 e^{j \frac{2\pi}{L} lm},
* @f]
* where @f$m@f$ is the lag.
*/
class SpectrumToAutocorrelation {
public:
/**
* Buffer for SpectrumToAutocorrelation class.
*/
class Buffer {
public:
Buffer() {
}

virtual ~Buffer() {
}

private:
std::vector<double> real_part_;
std::vector<double> imag_part_;

RealValuedInverseFastFourierTransform::Buffer
buffer_for_inverse_fast_fourier_transform_;

friend class SpectrumToAutocorrelation;
DISALLOW_COPY_AND_ASSIGN(Buffer);
};

/**
* @param[in] fft_length Number of FFT bins, @f$N@f$.
* @param[in] num_order Order of autocorrelation, @f$M@f$.
*/
SpectrumToAutocorrelation(int fft_length, int num_order);

virtual ~SpectrumToAutocorrelation() {
}

/**
* @return FFT length.
*/
int GetFftLength() const {
return inverse_fast_fourier_transform_.GetFftLength();
}

/**
* @return Order of autocorrelation.
*/
int GetNumOrder() const {
return num_order_;
}

/**
* @return True if this object is valid.
*/
bool IsValid() const {
return is_valid_;
}

/**
* @param[in] power_spectrum @f$(L/2+1)@f$-length power spectrum.
* @param[out] autocorrelation @f$M@f$-th order autocorrelation coefficients.
* @param[out] buffer Buffer.
* @return True on success, false on failure.
*/
bool Run(const std::vector<double>& power_spectrum,
std::vector<double>* autocorrelation,
SpectrumToAutocorrelation::Buffer* buffer) const;

private:
const int num_order_;

const RealValuedInverseFastFourierTransform inverse_fast_fourier_transform_;

bool is_valid_;

DISALLOW_COPY_AND_ASSIGN(SpectrumToAutocorrelation);
};

} // namespace sptk

#endif // SPTK_CONVERSION_SPECTRUM_TO_AUTOCORRELATION_H_
62 changes: 62 additions & 0 deletions src/analysis/autocorrelation_analysis.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// ------------------------------------------------------------------------ //
// Copyright 2021 SPTK Working Group //
// //
// 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 "SPTK/analysis/autocorrelation_analysis.h"

namespace sptk {

AutocorrelationAnalysis::AutocorrelationAnalysis(int frame_length,
int num_order,
bool waveform_input)
: waveform_input_(waveform_input),
waveform_to_autocorrelation_(NULL),
spectrum_to_autocorrelation_(NULL),
is_valid_(true) {
if (waveform_input_) {
waveform_to_autocorrelation_ =
new WaveformToAutocorrelation(frame_length, num_order);
is_valid_ = waveform_to_autocorrelation_->IsValid();
} else {
spectrum_to_autocorrelation_ =
new SpectrumToAutocorrelation(frame_length, num_order);
is_valid_ = spectrum_to_autocorrelation_->IsValid();
}
}

AutocorrelationAnalysis::~AutocorrelationAnalysis() {
if (waveform_input_) {
delete waveform_to_autocorrelation_;
} else {
delete spectrum_to_autocorrelation_;
}
}

bool AutocorrelationAnalysis::Run(
const std::vector<double>& input, std::vector<double>* autocorrelation,
AutocorrelationAnalysis::Buffer* buffer) const {
if (!is_valid_ || NULL == buffer) {
return false;
}

if (waveform_input_) {
return waveform_to_autocorrelation_->Run(input, autocorrelation);
} else {
return spectrum_to_autocorrelation_->Run(input, autocorrelation,
&buffer->buffer_);
}
}

} // namespace sptk
2 changes: 1 addition & 1 deletion src/analysis/fast_fourier_transform_cepstral_analysis.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ bool FastFourierTransformCepstralAnalysis::Run(
const std::vector<double>& power_spectrum, std::vector<double>* cepstrum,
FastFourierTransformCepstralAnalysis::Buffer* buffer) const {
// Check inputs.
const int fft_length(fast_fourier_transform_.GetFftLength());
const int fft_length(GetFftLength());
if (!is_valid_ ||
power_spectrum.size() != static_cast<std::size_t>(fft_length / 2 + 1) ||
NULL == cepstrum || NULL == buffer) {
Expand Down
78 changes: 78 additions & 0 deletions src/conversion/spectrum_to_autocorrelation.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// ------------------------------------------------------------------------ //
// Copyright 2021 SPTK Working Group //
// //
// 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 "SPTK/conversion/spectrum_to_autocorrelation.h"

#include <algorithm> // std::copy, std::reverse_copy
#include <cstddef> // std::size_t

namespace sptk {

SpectrumToAutocorrelation::SpectrumToAutocorrelation(int fft_length,
int num_order)
: num_order_(num_order),
inverse_fast_fourier_transform_(fft_length),
is_valid_(true) {
if (num_order_ < 0 || fft_length < 2 * num_order_ ||
!inverse_fast_fourier_transform_.IsValid()) {
is_valid_ = false;
return;
}
}

bool SpectrumToAutocorrelation::Run(
const std::vector<double>& power_spectrum,
std::vector<double>* autocorrelation,
SpectrumToAutocorrelation::Buffer* buffer) const {
// Check inputs.
const int fft_length(GetFftLength());
if (!is_valid_ ||
power_spectrum.size() != static_cast<std::size_t>(fft_length / 2 + 1) ||
NULL == autocorrelation || NULL == buffer) {
return false;
}

// Prepare memories.
if (autocorrelation->size() != static_cast<std::size_t>(num_order_ + 1)) {
autocorrelation->resize(num_order_ + 1);
}
if (buffer->real_part_.size() != static_cast<std::size_t>(fft_length)) {
buffer->real_part_.resize(fft_length);
}

// Make full power spectrum.
std::copy(power_spectrum.begin(), power_spectrum.end(),
buffer->real_part_.begin());
std::reverse_copy(buffer->real_part_.begin() + 1,
buffer->real_part_.begin() + power_spectrum.size() - 1,
buffer->real_part_.begin() + power_spectrum.size());

// Obtain autocorrelation.
if (!inverse_fast_fourier_transform_.Run(
&buffer->real_part_, &buffer->imag_part_,
&buffer->buffer_for_inverse_fast_fourier_transform_)) {
return false;
}

// Save outputs.
std::copy(buffer->real_part_.begin(),
buffer->real_part_.begin() + autocorrelation->size(),
autocorrelation->begin());

return true;
}

} // namespace sptk
Loading

0 comments on commit d166ba8

Please sign in to comment.