diff --git a/src/parselmouth.cpp b/src/parselmouth.cpp index 44c60a0d..be30880e 100644 --- a/src/parselmouth.cpp +++ b/src/parselmouth.cpp @@ -35,7 +35,6 @@ Thing_declare(Daata); Thing_declare(Formant); Thing_declare(Function); Thing_declare(Harmonicity); -Thing_declare(Harmonicity); Thing_declare(Intensity); Thing_declare(Matrix); Thing_declare(MFCC); @@ -119,6 +118,7 @@ using PraatBindings = Bindings */ +#include +#include + +#include + #include "Parselmouth.h" +#include "Harmonicity_docstrings.h" #include "TimeClassAspects.h" #include @@ -31,13 +37,147 @@ namespace parselmouth { PRAAT_CLASS_BINDING(Harmonicity) { addTimeFrameSampledMixin(*this); - // TODO Get value in frame + doc() = HARMONICITY_CLASS_DOCSTRING; + + // TODO Mixins (or something else?) for TimeFrameSampled, TimeFunction, and + // TimeVector functionality + + def(py::init([](std::vector data, std::optional T, + double tmin, double tmax, std::optional t1) { + // set domain and sample interval + auto n = data.size(); + auto tfirst = t1 ? *t1 : tmin; + if (tmax <= tfirst && (!T || *T <= 0)) + throw std::invalid_argument("Neither positive dt is defined nor " + "end_time > t1"); + + if (tmax <= tfirst) tmax = tmin + *T * n; + double dt = T ? *T : (tmax - tmin) / double(n); + + // create Praat object & copy the data + auto self = Harmonicity_create(tmin, tmax, n, dt, tfirst); + std::copy(data.begin(), data.end(), self->z.cells); + return self; + }), + "data"_a, "time_step"_a = nullptr, "start_time"_a = 0.0, + "end_time"_a = 0.0, "t1"_a = nullptr); + + // Make PointProcess class a s sequence-like Python class + def( + "__getitem__", + [](Harmonicity self, long i) { + if (i < 0) i += self->nx; + if (i < 0 || i >= self->nx) + throw std::out_of_range("index out of range"); + return self->z[1][i + 1]; + }, + "i"_a); + + def("__len__", [](Harmonicity self) { return self->nx; }); + + def( + "__iter__", + [](Harmonicity self) { + return py::make_iterator(self->z.cells, self->z.cells + self->nx); + }, + py::keep_alive<0, 1>()); + + // Harmonicity: Get value at time... + def( + "get_value",// TODO Should be part of Vector class + [](Harmonicity self, double time, + kVector_valueInterpolation interpolation) { + return Vector_getValueAtX(self, time, 1, interpolation); + }, + "time"_a, "interpolation"_a = kVector_valueInterpolation::CUBIC, + GET_VALUE_DOCSTRING); + + // Harmonicity: Get value in frame... + def( + "get_value_in_frame", + [](Harmonicity self, int frameNumber) { + return (frameNumber < 1 || frameNumber > self->nx + ? undefined + : self->z[1][frameNumber]); + }, + "frame_number"_a, GET_VALUE_IN_FRAME_DOCSTRING); + + // Harmonicity: Formula... + // def( + // "formula", + // [](Harmonicity self, conststring32 formula) { + // Interpreter interpreter; + // return Matrix_formula(self, formula, interpreter, nullptr); + // }, + // "formula"_a); + + // Harmonicity: Get maximum... + def( + "get_maximum", + [](Harmonicity self, double fromTime, double toTime, + kVector_peakInterpolation interpolation) { + return Vector_getMaximum(self, fromTime, toTime, interpolation); + }, + "from_time"_a = 0.0, "to_time"_a = 0.0, + "interpolation"_a = kVector_peakInterpolation::PARABOLIC, + GET_MAXIMUM_DOCSTRING); + + // Harmonicity: Get mean... + def( + "get_mean", + [](Harmonicity self, double fromTime, double toTime) { + return Harmonicity_getMean(self, fromTime, toTime); + }, + "from_time"_a = 0.0, "to_time"_a = 0.0, GET_MEAN_DOCSTRING); + + // Harmonicity: Get minimum... + def( + "get_minimum", + [](Harmonicity self, double fromTime, double toTime, + kVector_peakInterpolation interpolation) { + return Vector_getMinimum(self, fromTime, toTime, interpolation); + }, + "from_time"_a = 0.0, "to_time"_a = 0.0, + "interpolation"_a = kVector_peakInterpolation::PARABOLIC, + GET_MINIMUM_DOCSTRING); + + // Harmonicity: Get standard deviation... + def( + "get_standard_deviation", + [](Harmonicity self, double fromTime, double toTime) { + return Harmonicity_getStandardDeviation(self, fromTime, toTime); + }, + "from_time"_a = 0.0, "to_time"_a = 0.0, GET_STANDARD_DEVIATION_DOCSTRING); + + // Harmonicity: Get time of maximum... + def( + "get_time_of_maximum", + [](Harmonicity self, double fromTime, double toTime, + kVector_peakInterpolation interpolation) { + return Vector_getXOfMaximum(self, fromTime, toTime, interpolation); + }, + "from_time"_a = 0.0, "to_time"_a = 0.0, + "interpolation"_a = kVector_peakInterpolation::PARABOLIC, + GET_TIME_OF_MAXIMUM_DOCSTRING); - // TODO Mixins (or something else?) for TimeFrameSampled, TimeFunction, and TimeVector functionality + // Harmonicity: Get time of minimum... + def( + "get_time_of_minimum", + [](Harmonicity self, double fromTime, double toTime, + kVector_peakInterpolation interpolation) { + return Vector_getXOfMinimum(self, fromTime, toTime, interpolation); + }, + "from_time"_a = 0.0, "to_time"_a = 0.0, + "interpolation"_a = kVector_peakInterpolation::PARABOLIC, + GET_TIME_OF_MINIMUM_DOCSTRING); - def("get_value", // TODO Should be part of Vector class - [](Harmonicity self, double time, kVector_valueInterpolation interpolation) { return Vector_getValueAtX(self, time, 1, interpolation); }, - "time"_a, "interpolation"_a = kVector_valueInterpolation::CUBIC); + // double Harmonicity_getQuantile (Harmonicity me, double quantile) { + def( + "get_quantile", + [](Harmonicity self, double quantile) { + return Harmonicity_getQuantile(self, quantile); + }, + "quantile"_a, GET_QUANTILE_DOCSTRING); } -} // namespace parselmouth +}// namespace parselmouth diff --git a/src/parselmouth/Harmonicity_docstrings.h b/src/parselmouth/Harmonicity_docstrings.h new file mode 100644 index 00000000..2f3bb45e --- /dev/null +++ b/src/parselmouth/Harmonicity_docstrings.h @@ -0,0 +1,257 @@ +namespace parselmouth { + + +constexpr auto HARMONICITY_CLASS_DOCSTRING = R"(Praat Harmonicity. + +A sequence object contain measures of the degree of acoustic periodicity, +also called Harmonics-to-Noise Ratio (HNR). Harmonicity is expressed in dB. + +In the most use cases, `parselmouth.Harmonicity` objects are generated from +`parselmouth.Sound` objects with the `parselmouth.Sound.to_harmonicity()` +method. To constuct manually, use the following parameters. + +Parameters +---------- +data : array_like of float + Harmonicity measure samples + +time_step : float, optional + Time increment between two successive samples in seconds. If omitted, + a valid `end_time` must be specified. + +start_time : float, default=0.0 + Starting time of the analysis domain in seconds + +end_time : float, default=0.0 + Ending time of the analysis domain in seconds. If <= `t1`, it is set to + cover all the samples in `data. + +t1 : float, optional + Time of the first harmonicity sample in seconds. If omitted, it is set + to `start_time`. + +Attributes +---------- +t1 : float, readonly + Time of the first harmonicity sample in seconds +time_step : float, readonly + Time increment between two successive samples in seconds +start_time : float, readonly + Starting time of the analysis domain in seconds +end_time : float, readonly + Ending time of the analysis domain in seconds + +Methods +------- +get_value(time, interpolation="CUBIC") + Get (interpolated) harmonicity value at the specified `time` + +get_value_in_frame(frame_number) + Get harmonicity value at the specified analysis (1-based) frame number + +formula(formula) + Modify the harmonicity data according to Praat script command + +get_maximum(from_time=0.0, to_time=0.0, interpolation="PARABOLIC") + Get maximum harmonicity value in the specified time range + +get_mean(from_time=0.0, to_time=0.0) + Get mean harmonicity value in the specified time range + +get_minimum(from_time=0.0, to_time=0.0, interpolation="PARABOLIC") + Get minimum harmonicity value in the specified time range + +get_standard_deviation(from_time=0.0, to_time=0.0) + Get standard deviation of the harmonicity values in the specified time + range + +get_time_of_maximum(from_time=0.0, to_time=0.0, interpolation="PARABOLIC") + Get the time when the maximum value is observed in the time range + +get_time_of_minimum(from_time=0.0, to_time=0.0, interpolation="PARABOLIC") + Get the time when the minimum value is observed in the time range + +get_quantile(quantile) + Get the quantile of the harmonicity samples, expressed in dB + +See Also +-------- +:praat:`Harmonicity` +)"; + +constexpr auto GET_VALUE_DOCSTRING = R"(Get estimated local HNR + +Returns the HNR estimate (in dB) at a specified time. If this time is +outside the time domain or outside the samples of the Harmonicity, the +result is undefined. + +Parameters +---------- +time : double + The time at which the value is evaluated + +interpolation : {'NEAREST', 'LINEAR', 'CUBIC', 'SINC70', 'SINC700'}, + default='CUBIC' + The interpolation method. + +See Also +-------- +:praat:`Harmonicity: Get value at time...` +)"; + +constexpr auto GET_VALUE_IN_FRAME_DOCSTRING = R"(Get local HNR + +Returns the HNR in dB. If the index is less than 1 or greater than the +number of frames, the result is undefined. + +Parameters +---------- +frame_number : int + The 1-base index of the target frame + +See Also +-------- +:praat:`Harmonicity: Get value in frame...` +)"; + +constexpr auto GET_MAXIMUM_DOCSTRING = R"(Get maximum HNR + +Returns the maximum HNR, expressed in dB. + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Harmonicity object is considered. + +interpolation : {'NONE', 'PARABOLIC', 'CUBIC', 'SINC70', 'SINC700'}, + default='PARABOLIC' + The method of vector peak interpolation. + +See Also +-------- +:praat:`Harmonicity: Get maximum...` +)"; + +constexpr auto GET_MEAN_DOCSTRING = R"(Get mean HNR + +Returns the mean HNR, expressed in dB. + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Harmonicity object is considered. + +See Also +-------- +:praat:`Harmonicity: Get mean...` +)"; + +constexpr auto GET_MINIMUM_DOCSTRING = R"(Get minimum HNR + +Returns the minimum HNR, expressed in dB. + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Harmonicity object is considered. + +interpolation : {'NONE', 'PARABOLIC', 'CUBIC', 'SINC70', 'SINC700'}, + default='PARABOLIC' + The method of vector peak interpolation. + +See Also +-------- +:praat:`Harmonicity: Get minimum...` +)"; + +constexpr auto GET_STANDARD_DEVIATION_DOCSTRING = R"(Get HNR standard deviation + +Returns the standard deviation of the HNR samples, expressed in dB. + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Harmonicity object is considered. + +See Also +-------- +:praat:`Harmonicity: Get standard deviation...` +)"; + +constexpr auto GET_TIME_OF_MAXIMUM_DOCSTRING = R"(Get time of maximum HNR + +Returns the time (in seconds) associated with the maximum HNR value. + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Harmonicity object is considered. + +interpolation : {'NONE', 'PARABOLIC', 'CUBIC', 'SINC70', 'SINC700'}, + default='PARABOLIC' + The method of vector peak interpolation. + +See Also +-------- +:praat:`Harmonicity: Get time of maximum...` +)"; + +constexpr auto GET_TIME_OF_MINIMUM_DOCSTRING = R"(Get time of minimum HNR + +Returns the time (in seconds) associated with the minimum HNR value. + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Harmonicity object is considered. + +interpolation : {'NONE', 'PARABOLIC', 'CUBIC', 'SINC70', 'SINC700'}, + default='PARABOLIC' + The method of vector peak interpolation. + +See Also +-------- +:praat:`Harmonicity: Get time of minimum...` +)"; + +constexpr auto GET_QUANTILE_DOCSTRING = R"(Get quantile of HNR samples + +Returns the quantile of the HNR samples, expressed in dB. + +Parameters +---------- +quantile : double + Quantile to compute, which must be between 0 and 1 inclusive. +)"; + +}// namespace parselmouth diff --git a/src/parselmouth/Parselmouth.h b/src/parselmouth/Parselmouth.h index 1cb7f18d..ae804ece 100644 --- a/src/parselmouth/Parselmouth.h +++ b/src/parselmouth/Parselmouth.h @@ -34,6 +34,7 @@ enum class kSound_windowShape; enum class kSounds_convolve_scaling; enum class kSounds_convolve_signalOutsideTimeDomain; enum class kVector_valueInterpolation; +enum class kVector_peakInterpolation; namespace parselmouth::detail { @@ -94,6 +95,7 @@ namespace parselmouth { enum class SoundFileFormat; using ValueInterpolation = kVector_valueInterpolation; +using PeakInterpolation = kVector_peakInterpolation; using WindowShape = kSound_windowShape; using AmplitudeScaling = kSounds_convolve_scaling; using SignalOutsideTimeDomain = kSounds_convolve_signalOutsideTimeDomain; diff --git a/src/parselmouth/Pitch.cpp b/src/parselmouth/Pitch.cpp index 00195485..d847fc49 100644 --- a/src/parselmouth/Pitch.cpp +++ b/src/parselmouth/Pitch.cpp @@ -21,6 +21,10 @@ #include "TimeClassAspects.h" +// Added by @hokiedsp on 2/17/21 +#include "Pitch_docstrings.h" +// End added by @hokiedsp on 2/17/21 + #include "utils/praat/MelderUtils.h" #include "utils/pybind11/ImplicitStringToEnumConversion.h" #include "utils/pybind11/NumericPredicates.h" @@ -148,7 +152,7 @@ PRAAT_CLASS_BINDING(Pitch) { "from_time"_a = std::nullopt, "to_time"_a = std::nullopt, "sampling_frequency"_a = 44100.0, "round_to_nearest_zero_crossing"_a = true); def("count_voiced_frames", - &Pitch_countVoicedFrames); + &Pitch_countVoicedFrames); def("get_value_at_time", [](Pitch self, double time, kPitch_unit unit, kVector_valueInterpolation interpolation) { @@ -228,15 +232,15 @@ PRAAT_CLASS_BINDING(Pitch) { &Pitch_interpolate); def("smooth", - args_cast<_, Positive<_>>(Pitch_smooth), - "bandwidth"_a = 10.0); + args_cast<_, Positive<_>>(Pitch_smooth), + "bandwidth"_a = 10.0); def("subtract_linear_fit", &Pitch_subtractLinearFit, - "unit"_a = kPitch_unit::HERTZ); + "unit"_a = kPitch_unit::HERTZ); def("kill_octave_jumps", - &Pitch_killOctaveJumps); + &Pitch_killOctaveJumps); // TODO To PitchTier: depends on PitchTier @@ -368,6 +372,59 @@ PRAAT_CLASS_BINDING(Pitch) { }, "from_time"_a = std::nullopt, "to_time"_a = std::nullopt); + // Added by @hokiedsp on 2/17/21 + def( + "get_mean", &Pitch_getMean, + "from_time"_a = 0.0, "to_time"_a = 0.0, "unit"_a = "HERTZ", + GET_MEAN_DOCSTRING); + + def( + "get_mean_strength", [](Pitch self, std::string type, double tmin, double tmax) { + const int strengthUnit = + (type == "ac") ? Pitch_STRENGTH_UNIT_AUTOCORRELATION : + (type == "nhr") ? Pitch_STRENGTH_UNIT_NOISE_HARMONICS_RATIO : + (type == "hnr_db") ? Pitch_STRENGTH_UNIT_HARMONICS_NOISE_DB : -1; + + if (strengthUnit < 0) + throw py::value_error("Invalid mean strength measure type specified."); + + return Pitch_getMeanStrength(self, tmin, tmax, strengthUnit); + }, + "type"_a = "hnr_db", "from_time"_a = 0.0, "to_time"_a = 0.0, + GET_MEAN_STRENGTH_DOCSTRING); + + def( + "get_quantile", [](Pitch self, double quantile, double tmin, double tmax, kPitch_unit unit) { + return Pitch_getQuantile(self, tmin, tmax, quantile, unit); + }, + "quantile"_a, "from_time"_a = 0.0, "to_time"_a = 0.0, "unit"_a = "HERTZ", GET_QUANTILE_DOCSTRING); + + def( + "get_standard_deviation", &Pitch_getStandardDeviation, "from_time"_a = 0.0, "to_time"_a = 0.0, "unit"_a = "HERTZ", + GET_STANDARD_DEVIATION_DOCSTRING); + + def( + "get_minimum", &Pitch_getMinimum, "from_time"_a = 0.0, "to_time"_a = 0.0, "unit"_a = "HERTZ", "interpolate"_a = true, + GET_MINIMUM_DOCSTRING); + + def( + "get_maximum", &Pitch_getMaximum, "from_time"_a = 0.0, "to_time"_a = 0.0, "unit"_a = "HERTZ", "interpolate"_a = true, + GET_MAXIMUM_DOCSTRING); + + def( + "get_fraction_of_locally_unvoiced_frames", + [](Pitch self, double tmin, double tmax, double ceiling, + double silenceThreshold, double voicingThreshold) { + MelderFraction out = Pitch_getFractionOfLocallyUnvoicedFrames(self, tmin, tmax, ceiling, + silenceThreshold, voicingThreshold); + + return std::make_tuple(out.numerator / out.denominator, out.numerator, out.denominator); + }, + "from_time"_a = 0.0, "to_time"_a = 0.0, "to_pitch"_a = 600.0, "silence_threshold"_a = 0.03, + "voicing_threshold"_a = 0.45, GET_FRACTION_OF_LOCALLY_UNVOICED_FRAMES_DOCSTRING); + + // End added by @hokiedsp on 2/17/21 + // TODO Pitch_Intensity_getMean & Pitch_Intensity_getMeanAbsoluteSlope ? (cfr. Intensity) } diff --git a/src/parselmouth/Pitch_docstrings.h b/src/parselmouth/Pitch_docstrings.h new file mode 100644 index 00000000..23a85675 --- /dev/null +++ b/src/parselmouth/Pitch_docstrings.h @@ -0,0 +1,187 @@ +namespace parselmouth +{ + +constexpr auto GET_MEAN_STRENGTH_DOCSTRING = R"(Get mean pitch strength measure + +Returns the value of user-selected measure of the periodicity strength. + +Parameters +---------- +type : {'ac', 'nhr', 'hnr_db'}, default="hnr_db" + Type of strength measure to compute + +from_time : double, default=0.0 + The start time of the compuation. Use 0.0 to start with the first + available frame + +end_time : double, default=0.0 + The end time of the compuation. Use 0.0 to end with the last available + frame + +See Also +-------- +:praat:`Voice report` +)"; + + +constexpr auto GET_MEAN_DOCSTRING = R"(Get mean frequency + +Returns the mean of periodicity frequency in the specified unit. + +Parameters +---------- +from_time : double, default=0.0 + The start time of the compuation. Use 0.0 to start with the first + available frame + +end_time : double, default=0.0 + The end time of the compuation. Use 0.0 to end with the last available + frame + +unit : {'HERTZ','HERTZ_LOGARITHMIC','MEL','LOG_HERTZ','SEMITONES_1', + 'SEMITONES_100','SEMITONES_200','SEMITONES_440','ERB'}, + default=HERTZ + Frequency unit + +See Also +-------- +:praat:`Voice report` +)"; + +constexpr auto GET_MAXIMUM_DOCSTRING = R"(Get maximum frequency + +Returns the maximum frequency in the specified unit + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Pitch object is considered. + +unit : {'HERTZ','HERTZ_LOGARITHMIC','MEL','LOG_HERTZ','SEMITONES_1', + 'SEMITONES_100','SEMITONES_200','SEMITONES_440','ERB'}, + default=HERTZ + Frequency unit + +interpolate : bool, default=True + True to evalaute parabolically interpolated pitch peaks; False to + select the raw frequency samples. + +See Also +-------- +:praat:`Voice report` +)"; + +constexpr auto GET_MINIMUM_DOCSTRING = R"(Get minimum frequency + +Returns the minimum frequency in the specified unit + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Pitch object is considered. + +unit : {'HERTZ','HERTZ_LOGARITHMIC','MEL','LOG_HERTZ','SEMITONES_1', + 'SEMITONES_100','SEMITONES_200','SEMITONES_440','ERB'}, + default=HERTZ + Frequency unit + +interpolate : bool, default=True + True to evalaute parabolically interpolated pitch peaks; False to + select the raw frequency samples. + +See Also +-------- +:praat:`Voice report` +)"; + +constexpr auto GET_STANDARD_DEVIATION_DOCSTRING = R"(Get standard deviation of frequency + +Returns the standard deviation of frequency samples in the specified unit + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Pitch object is considered. + +unit : {'HERTZ','HERTZ_LOGARITHMIC','MEL','LOG_HERTZ','SEMITONES_1', + 'SEMITONES_100','SEMITONES_200','SEMITONES_440','ERB'}, + default=HERTZ + Frequency unit + +See Also +-------- +:praat:`Voice report` +)"; + + +constexpr auto GET_QUANTILE_DOCSTRING = R"(Get quantile of frequency samples + +Returns the quantile of the frequency samples in the specified unit + +Parameters +---------- +quantile : double + Quantile to compute, which must be between 0 and 1 inclusive. + +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Pitch object is considered. + +unit : {'HERTZ','HERTZ_LOGARITHMIC','MEL','LOG_HERTZ','SEMITONES_1', + 'SEMITONES_100','SEMITONES_200','SEMITONES_440','ERB'}, + default=HERTZ + Frequency unit + +See Also +-------- +:praat:`Voice report` +)"; + +constexpr auto GET_FRACTION_OF_LOCALLY_UNVOICED_FRAMES_DOCSTRING = R"(Get unvoiced statistics + +Returns the statistics related to the unvoiced periods + +Parameters +---------- +from_time : double=0.0 + The starting time of the analysis time domain. + +to_time : double=0.0 + The ending time of the analysis time domain. Values outside this domain + are ignored. If `to_time` is not greater than `from_time`, the entire + time domain of the Pitch object is considered. + +to_pitch : double=600.0 + The maximum voice frequency + +silence_threshold : double=0.03 + The upper pitch strength limit of silent period + +voicing_threshold : double 0.45 + The lower pitch strength limit of voicing period + +See Also +-------- +:praat:`Voice report` +)"; + +}// namespace parselmouth diff --git a/src/parselmouth/Vector.cpp b/src/parselmouth/Vector.cpp index 542d1071..29be8473 100644 --- a/src/parselmouth/Vector.cpp +++ b/src/parselmouth/Vector.cpp @@ -42,6 +42,18 @@ PRAAT_ENUM_BINDING(ValueInterpolation) { make_implicitly_convertible_from_string(*this); } + +PRAAT_ENUM_BINDING(PeakInterpolation) +{ + value("NONE", kVector_peakInterpolation::NONE); + value("PARABOLIC", kVector_peakInterpolation::PARABOLIC); + value("CUBIC", kVector_peakInterpolation::CUBIC); + value("SINC70", kVector_peakInterpolation::SINC70); + value("SINC700", kVector_peakInterpolation::SINC700); + + make_implicitly_convertible_from_string(*this); +} + PRAAT_CLASS_BINDING(Vector) { using signature_cast_placeholder::_; diff --git a/tests/resource_fixtures.py b/tests/resource_fixtures.py index 82c733b5..3befd080 100644 --- a/tests/resource_fixtures.py +++ b/tests/resource_fixtures.py @@ -73,3 +73,8 @@ def text_grid(text_grid_path): @pytest.fixture def script_path(resources): yield resources["script.praat"] + +@pytest.fixture +def harmonicity(sound): + return sound.to_harmonicity("CC") # "AC", "GNE" + diff --git a/tests/test_harmonicity.py b/tests/test_harmonicity.py new file mode 100644 index 00000000..81d3a366 --- /dev/null +++ b/tests/test_harmonicity.py @@ -0,0 +1,100 @@ +import pytest +import numpy as np + +import parselmouth + + +@pytest.fixture +def rand_data(): + return np.random.rand(10) + + +@pytest.fixture +def rand_harmonicity(rand_data): + return parselmouth.Harmonicity(rand_data, 0.1) + + +def test_sequence(rand_data, rand_harmonicity): + """test compatibility with various sequence operations""" + N = len(rand_harmonicity) + assert N == rand_data.size + for i in range(N): + assert rand_harmonicity[i] == rand_data[i] + assert np.allclose(rand_harmonicity, rand_data) + + +def test_constructor(rand_data): + data = rand_data + T = 0.1 + start_time = 1.2 + end_time = 10.0 + t1 = 1.3 + h = parselmouth.Harmonicity(data, T, start_time, end_time, t1) + assert np.allclose(h, data) + assert h.xmin == start_time + assert h.xmax == end_time + assert h.dx == T + assert h.t1 == t1 + + h = parselmouth.Harmonicity(data, T, start_time, end_time) + assert h.t1 == start_time + + h = parselmouth.Harmonicity(data, T, start_time) + assert h.xmax == start_time + T * data.size + + h = parselmouth.Harmonicity(data, T) + assert h.xmin == 0.0 + assert h.xmax == T * data.size + + h = parselmouth.Harmonicity(data, start_time=start_time, end_time=end_time) + assert h.dx == (end_time - start_time) / data.size + + h = parselmouth.Harmonicity(data, end_time=end_time) + assert h.dx == end_time / data.size + + +def test_get_value(harmonicity): + t = (harmonicity.tmin + harmonicity.tmax) / 2.0 + harmonicity.get_value(t) + + +def test_get_value_in_frame(harmonicity): + harmonicity.get_value_in_frame(len(harmonicity) // 2 + 1) + + +# def test_formula(harmonicity): +# harmonicity.formula("") + + +def test_get_maximum(harmonicity): + + harmonicity.get_maximum() + # from_time=0.0, to_time=0.0, interpolation"PARABOLIC" + + +def test_get_mean(harmonicity): + harmonicity.get_mean() + # from_time=0.0, to_time=0.0 + + +def test_get_minimum(harmonicity): + harmonicity.get_minimum() + # from_time=0.0, to_time=0.0,interpolation="PARABOLIC" + + +def test_get_standard_deviation(harmonicity): + harmonicity.get_standard_deviation() + # from_time=0.0, to_time=0.0 + + +def test_get_time_of_maximum(harmonicity): + harmonicity.get_time_of_maximum() + # from_time=0.0, to_time=0.0,interpolation="PARABOLIC" + + +def test_get_time_of_minimum(harmonicity): + harmonicity.get_time_of_minimum() + # from_time=0.0,to_time=0.0,interpolation="PARABOLIC" + +def test_get_quantile(harmonicity): + harmonicity.get_quantile(0.5) diff --git a/tests/test_pitch.py b/tests/test_pitch.py new file mode 100644 index 00000000..3e99b69a --- /dev/null +++ b/tests/test_pitch.py @@ -0,0 +1,25 @@ +import pytest + +def test_get_mean_strength(pitch): + print(f"Mean autocorrelation={pitch.get_mean_strength(type='ac')}") + print(f"Mean noise-to-harmonics ratio={pitch.get_mean_strength(type='nhr')}") + print(f"Mean harmonics-to-noise ratio={pitch.get_mean_strength(type='hnr_db')} dB") + print(f"default={pitch.get_mean_strength()}") + +def test_get_mean(pitch): + print(f"Mean frequency={pitch.get_mean()}") + +def test_get_standard_deviation(pitch): + print(f"Standard_deviation={pitch.get_standard_deviation()}") + +def test_get_minimum(pitch): + print(f"Minimum={pitch.get_minimum()}") + +def test_get_maximum(pitch): + print(f"Maximum={pitch.get_maximum()}") + +def test_get_quantile(pitch): + print(f"10% Quantile={pitch.get_quantile(0.1)}") + +def test_get_fraction_of_locally_unvoiced_frames(pitch): + print(pitch.get_fraction_of_locally_unvoiced_frames())