Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update pitch_mark and pitch2sin #73

Merged
merged 4 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ set(CC_SOURCES
${SOURCE_DIR}/generation/m_sequence_generation.cc
${SOURCE_DIR}/generation/nonrecursive_maximum_likelihood_parameter_generation.cc
${SOURCE_DIR}/generation/normal_distributed_random_value_generation.cc
${SOURCE_DIR}/generation/periodic_waveform_generation.cc
${SOURCE_DIR}/generation/recursive_maximum_likelihood_parameter_generation.cc
${SOURCE_DIR}/generation/sinusoidal_generation.cc
${SOURCE_DIR}/input/input_source_delay.cc
${SOURCE_DIR}/input/input_source_filling_magic_number.cc
${SOURCE_DIR}/input/input_source_from_array.cc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,33 @@
// limitations under the License. //
// ------------------------------------------------------------------------ //

#ifndef SPTK_GENERATION_SINUSOIDAL_GENERATION_H_
#define SPTK_GENERATION_SINUSOIDAL_GENERATION_H_
#ifndef SPTK_GENERATION_PERIODIC_WAVEFORM_GENERATION_H_
#define SPTK_GENERATION_PERIODIC_WAVEFORM_GENERATION_H_

#include "SPTK/input/input_source_interpolation_with_magic_number.h"
#include "SPTK/utils/sptk_utils.h"

namespace sptk {

/**
* Generate sinusoidal sequence.
* Generate periodic waveform from pitch value.
*
* The input is a sequence of pitch value which can be either a continuous value
* or a magic number. The output is the sinusoidal signal given the input
* or a magic number. The output is the periodic waveform generated by the input
* sequence.
*/
class SinusoidalGeneration {
class PeriodicWaveformGeneration {
public:
/**
* @param[in] unvoiced_value Value on unvoiced region.
* @param[in] strict If true, strictly drop sinusoidal in an unvoiced region.
* @param[in] input_source Input source.
*/
explicit SinusoidalGeneration(
bool strict, InputSourceInterpolationWithMagicNumber* input_source);
PeriodicWaveformGeneration(
double unvoiced_value, bool strict,
InputSourceInterpolationWithMagicNumber* input_source);

virtual ~SinusoidalGeneration() {
virtual ~PeriodicWaveformGeneration() {
}

/**
Expand All @@ -49,16 +51,18 @@ class SinusoidalGeneration {
}

/**
* Get sinusoidal signal.
* Get periodic waveform.
*
* @param[out] sin Sine waveform (optional).
* @param[out] cos Cosine waveform (optional).
* @param[out] sawtooth Sawtooth waveform (optional).
* @param[out] pitch Pitch (optional).
* @return True on success, false on failure.
*/
bool Get(double* sin, double* cos, double* pitch);
bool Get(double* sin, double* cos, double* sawtooth, double* pitch);

private:
const double unvoiced_value_;
const bool strict_;

InputSourceInterpolationWithMagicNumber* input_source_;
Expand All @@ -72,9 +76,9 @@ class SinusoidalGeneration {
double voiced_pitch_;
bool extending_;

DISALLOW_COPY_AND_ASSIGN(SinusoidalGeneration);
DISALLOW_COPY_AND_ASSIGN(PeriodicWaveformGeneration);
};

} // namespace sptk

#endif // SPTK_GENERATION_SINUSOIDAL_GENERATION_H_
#endif // SPTK_GENERATION_PERIODIC_WAVEFORM_GENERATION_H_
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@
// limitations under the License. //
// ------------------------------------------------------------------------ //

#include "SPTK/generation/sinusoidal_generation.h"
#include "SPTK/generation/periodic_waveform_generation.h"

#include <cmath> // std::cos, std::sin
#include <vector> // std::vector

namespace sptk {

SinusoidalGeneration::SinusoidalGeneration(
bool strict, InputSourceInterpolationWithMagicNumber* input_source)
: strict_(strict),
PeriodicWaveformGeneration::PeriodicWaveformGeneration(
double unvoiced_value, bool strict,
InputSourceInterpolationWithMagicNumber* input_source)
: unvoiced_value_(unvoiced_value),
strict_(strict),
input_source_(input_source),
is_valid_(true),
phase_(0.0),
Expand All @@ -35,7 +37,8 @@ SinusoidalGeneration::SinusoidalGeneration(
}
}

bool SinusoidalGeneration::Get(double* sin, double* cos, double* pitch) {
bool PeriodicWaveformGeneration::Get(double* sin, double* cos, double* sawtooth,
double* pitch) {
if (!is_valid_) {
return false;
}
Expand Down Expand Up @@ -64,10 +67,13 @@ bool SinusoidalGeneration::Get(double* sin, double* cos, double* pitch) {
if (input_source_->GetMagicNumber() == pitch_in_current_point) {
phase_ = 0.0;
if (sin) {
*sin = 0.0;
*sin = unvoiced_value_;
}
if (cos) {
*cos = 0.0;
*cos = unvoiced_value_;
}
if (sawtooth) {
*sawtooth = unvoiced_value_;
}
return true;
}
Expand All @@ -78,6 +84,9 @@ bool SinusoidalGeneration::Get(double* sin, double* cos, double* pitch) {
if (cos) {
*cos = std::cos(phase_);
}
if (sawtooth) {
*sawtooth = phase_ / sptk::kPi - 1.0;
}

if (!strict_) {
extending_ = true;
Expand Down
46 changes: 32 additions & 14 deletions src/main/pitch2sin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@
#include <sstream> // std::ostringstream

#include "GETOPT/ya_getopt.h"
#include "SPTK/generation/sinusoidal_generation.h"
#include "SPTK/generation/periodic_waveform_generation.h"
#include "SPTK/input/input_source_from_stream.h"
#include "SPTK/input/input_source_interpolation_with_magic_number.h"
#include "SPTK/utils/sptk_utils.h"

namespace {

enum OutputFormats { kSine = 0, kCosine, kNumOutputFormats };
enum OutputFormats { kSine = 0, kCosine, kSawtooth, kNumOutputFormats };

const int kDefaultFramePeriod(100);
const int kDefaultInterpolationPeriod(1);
const OutputFormats kDefaultOutputFormat(kSine);
const bool kDefaultStrictFlag(false);
const double kDefaultUnvoicedValue(0.0);
const double kMagicNumberForUnvoicedFrame(0.0);

void PrintUsage(std::ostream* stream) {
Expand All @@ -45,9 +46,12 @@ void PrintUsage(std::ostream* stream) {
*stream << " options:" << std::endl;
*stream << " -p p : frame period ( int)[" << std::setw(5) << std::right << kDefaultFramePeriod << "][ 1 <= p <= ]" << std::endl; // NOLINT
*stream << " -i i : interpolation period ( int)[" << std::setw(5) << std::right << kDefaultInterpolationPeriod << "][ 0 <= i <= p/2 ]" << std::endl; // NOLINT
*stream << " -o o : output format ( int)[" << std::setw(5) << std::right << kDefaultOutputFormat << "][ 0 <= o <= 1 ]" << std::endl; // NOLINT
*stream << " -o o : output format ( int)[" << std::setw(5) << std::right << kDefaultOutputFormat << "][ 0 <= o <= 2 ]" << std::endl; // NOLINT
*stream << " 0 (sine)" << std::endl;
*stream << " 1 (cosine)" << std::endl;
*stream << " 2 (sawtooth)" << std::endl;
*stream << " -u u : value on unvoiced (double)[" << std::setw(5) << std::right << kDefaultUnvoicedValue << "][ <= u <= ]" << std::endl; // NOLINT
*stream << " region" << std::endl;
*stream << " -s : strictly drop signal ( bool)[" << std::setw(5) << std::right << sptk::ConvertBooleanToString(kDefaultStrictFlag) << "]" << std::endl; // NOLINT
*stream << " in unvoiced region" << std::endl;
*stream << " -h : print this message" << std::endl;
Expand Down Expand Up @@ -77,6 +81,9 @@ void PrintUsage(std::ostream* stream) {
* - output format
* \arg @c 0 sine
* \arg @c 1 cosine
* \arg @c 2 sawtooth
* - @b -u @e double
* - value on unvoiced region
* - @b -s
* - strictly drop sinusoidal in unvoiced region
* - @b infile @e str
Expand All @@ -98,10 +105,11 @@ int main(int argc, char* argv[]) {
int frame_period(kDefaultFramePeriod);
int interpolation_period(kDefaultInterpolationPeriod);
OutputFormats output_format(kDefaultOutputFormat);
double unvoiced_value(kDefaultUnvoicedValue);
bool strict(kDefaultStrictFlag);

for (;;) {
const int option_char(getopt_long(argc, argv, "p:i:o:sh", NULL, NULL));
const int option_char(getopt_long(argc, argv, "p:i:o:u:sh", NULL, NULL));
if (-1 == option_char) break;

switch (option_char) {
Expand Down Expand Up @@ -142,6 +150,15 @@ int main(int argc, char* argv[]) {
output_format = static_cast<OutputFormats>(tmp);
break;
}
case 'u': {
if (!sptk::ConvertStringToDouble(optarg, &unvoiced_value)) {
std::ostringstream error_message;
error_message << "The argument for the -u option must be a number";
sptk::PrintErrorMessage("pitch2sin", error_message);
return 1;
}
break;
}
case 's': {
strict = true;
break;
Expand Down Expand Up @@ -205,22 +222,23 @@ int main(int argc, char* argv[]) {
return 1;
}

sptk::SinusoidalGeneration sinusoidal_generation(
strict, &input_source_interpolation_with_magic_number);
if (!sinusoidal_generation.IsValid()) {
sptk::PeriodicWaveformGeneration waveform_generation(
unvoiced_value, strict, &input_source_interpolation_with_magic_number);
if (!waveform_generation.IsValid()) {
std::ostringstream error_message;
error_message << "Failed to initialize SinusoidalGeneration";
error_message << "Failed to initialize PeriodicWaveformGeneration";
sptk::PrintErrorMessage("pitch2sin", error_message);
return 1;
}

double sinusoidal;
while (sinusoidal_generation.Get(
kSine == output_format ? &sinusoidal : NULL,
kCosine == output_format ? &sinusoidal : NULL, NULL)) {
if (!sptk::WriteStream(sinusoidal, &std::cout)) {
double signal;
while (waveform_generation.Get(kSine == output_format ? &signal : NULL,
kCosine == output_format ? &signal : NULL,
kSawtooth == output_format ? &signal : NULL,
NULL)) {
if (!sptk::WriteStream(signal, &std::cout)) {
std::ostringstream error_message;
error_message << "Failed to write sinusoidal";
error_message << "Failed to write a periodic waveform";
sptk::PrintErrorMessage("pitch2sin", error_message);
return 1;
}
Expand Down
45 changes: 26 additions & 19 deletions src/main/pitch_mark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ enum OutputFormats {
kPositionInSamples,
kSine,
kCosine,
kBipolarSawtooth,
kUnipolarSawtooth,
kSawtooth,
kNumOutputFormats
};

Expand All @@ -45,6 +44,7 @@ const double kDefaultLowerF0(60.0);
const double kDefaultUpperF0(240.0);
const double kDefaultVoicingThreshold(0.9);
const OutputFormats kDefaultOutputFormat(kBinarySequence);
const double kDefaultUnvoicedValue(0.0);

void PrintUsage(std::ostream* stream) {
// clang-format off
Expand All @@ -60,14 +60,14 @@ void PrintUsage(std::ostream* stream) {
*stream << " -H H : maximum fundamental frequency (double)[" << std::setw(5) << std::right << kDefaultUpperF0 << "][ L < H < 500*s ]" << std::endl; // NOLINT
*stream << " to search for [Hz]" << std::endl;
*stream << " -t t : voicing threshold (double)[" << std::setw(5) << std::right << kDefaultVoicingThreshold << "][ -0.5 <= t <= 1.6 ]" << std::endl; // NOLINT
*stream << " -o o : output format ( int)[" << std::setw(5) << std::right << kDefaultOutputFormat << "][ 0 <= o <= 4 ]" << std::endl; // NOLINT
*stream << " -o o : output format ( int)[" << std::setw(5) << std::right << kDefaultOutputFormat << "][ 0 <= o <= 5 ]" << std::endl; // NOLINT
*stream << " 0 (binary sequence)" << std::endl;
*stream << " 1 (position in seconds)" << std::endl;
*stream << " 2 (position in samples)" << std::endl;
*stream << " 3 (sine waveform)" << std::endl;
*stream << " 4 (cosine waveform)" << std::endl;
*stream << " 5 (sawtooth waveform (bipolar))" << std::endl;
*stream << " 6 (sawtooth waveform (unipolar))" << std::endl;
*stream << " 5 (sawtooth waveform)" << std::endl;
*stream << " -u u : value on unvoiced region (double)[" << std::setw(5) << std::right << kDefaultUnvoicedValue << "][ <= u <= ]" << std::endl; // NOLINT
*stream << " -h : print this message" << std::endl;
*stream << " infile:" << std::endl;
*stream << " waveform (double)[stdin]" << std::endl; // NOLINT
Expand All @@ -77,6 +77,7 @@ void PrintUsage(std::ostream* stream) {
*stream << " if t is raised, the number of pitch marks increase" << std::endl; // NOLINT
*stream << " the value of t should be in the recommended range but values outside the range can be given" << std::endl; // NOLINT
*stream << " if o = 0, value 1 or -1 indicating pitch mark is outputted considering polarity" << std::endl; // NOLINT
*stream << " -u option is valid only o >= 3" << std::endl;
*stream << std::endl;
*stream << " SPTK: version " << sptk::kVersion << std::endl;
*stream << std::endl;
Expand All @@ -103,8 +104,9 @@ void PrintUsage(std::ostream* stream) {
* @arg @c 2 position in samples
* @arg @c 3 sine waveform
* @arg @c 4 cosine waveform
* @arg @c 5 bipolar sawtooth waveform
* @arg @c 6 unipolar sawtooth waveform
* @arg @c 5 sawtooth waveform
* - @b -u @e double
* - value on unvoiced region
* - @b infile @e str
* - double-type waveform
* - @b stdout
Expand All @@ -128,9 +130,10 @@ int main(int argc, char* argv[]) {
double upper_f0(kDefaultUpperF0);
double voicing_threshold(kDefaultVoicingThreshold);
OutputFormats output_format(kDefaultOutputFormat);
double unvoiced_value(kDefaultUnvoicedValue);

for (;;) {
const int option_char(getopt_long(argc, argv, "s:L:H:t:o:h", NULL, NULL));
const int option_char(getopt_long(argc, argv, "s:L:H:t:o:u:h", NULL, NULL));
if (-1 == option_char) break;

switch (option_char) {
Expand Down Expand Up @@ -193,6 +196,15 @@ int main(int argc, char* argv[]) {
output_format = static_cast<OutputFormats>(tmp);
break;
}
case 'u': {
if (!sptk::ConvertStringToDouble(optarg, &unvoiced_value)) {
std::ostringstream error_message;
error_message << "The argument for the -u option must be a number";
sptk::PrintErrorMessage("pitch_mark", error_message);
return 1;
}
break;
}
case 'h': {
PrintUsage(&std::cout);
return 0;
Expand Down Expand Up @@ -340,8 +352,7 @@ int main(int argc, char* argv[]) {
}
case kSine:
case kCosine:
case kBipolarSawtooth:
case kUnipolarSawtooth: {
case kSawtooth: {
for (int n(0), i(0); n <= num_pitch_marks; ++n) {
const int next_pitch_mark(
n < num_pitch_marks ? static_cast<int>(std::round(pitch_mark[n]))
Expand All @@ -354,7 +365,7 @@ int main(int argc, char* argv[]) {
}
}

// Output sinusoidal sequence.
// Output periodic sequence.
if (i < j) {
const double sum_f0(
std::accumulate(f0.begin() + i, f0.begin() + j, 0.0));
Expand All @@ -372,21 +383,17 @@ int main(int argc, char* argv[]) {
value = std::cos(phase);
break;
}
case kBipolarSawtooth: {
case kSawtooth: {
value = std::fmod(phase, sptk::kTwoPi) / sptk::kPi - 1.0;
break;
}
case kUnipolarSawtooth: {
value = std::fmod(phase, sptk::kTwoPi) / sptk::kTwoPi;
break;
}
default: {
return 1;
}
}
if (!sptk::WriteStream(binary_polarity * value, &std::cout)) {
std::ostringstream error_message;
error_message << "Failed to write sinusoidal sequence";
error_message << "Failed to write periodic sequence";
sptk::PrintErrorMessage("pitch_mark", error_message);
return 1;
}
Expand All @@ -396,9 +403,9 @@ int main(int argc, char* argv[]) {

// Output unvoiced sequence.
for (int k(j); k < next_pitch_mark; ++k) {
if (!sptk::WriteStream(0.0, &std::cout)) {
if (!sptk::WriteStream(unvoiced_value, &std::cout)) {
std::ostringstream error_message;
error_message << "Failed to write sinusoidal sequence";
error_message << "Failed to write periodic sequence";
sptk::PrintErrorMessage("pitch_mark", error_message);
return 1;
}
Expand Down
Loading