sppas 5.1.0

https://sppas.org/

Module sppas.src.annotations

Class sppasFormants

Description

SPPAS integration of the automatic Formants estimator on intervals.

Estimate the formants of the center of segments, i.e. phonemes.

Constructor

__init__

Create a new sppasRMS instance.

Parameters
  • log: (sppasLog) Human-readable logs.
View Source
def __init__(self, log=None):
    """Create a new sppasRMS instance.

    :param log: (sppasLog) Human-readable logs.

    """
    super(sppasFormants, self).__init__('formants.json', log)
    self.__estimator = FormantsEstimator()

Public functions

fix_options

Fix all options.

Parameters
  • options: (sppasOption)
View Source
def fix_options(self, options):
    """Fix all options.

        :param options: (sppasOption)

        """
    for opt in options:
        key = opt.get_key()
        if 'threshold' == key:
            self.set_threshold(opt.get_value())
        elif 'win_length' == key:
            self.set_win_length(opt.get_value())
        elif 'order' == key:
            self.set_lpc_order(opt.get_value())
        elif 'floor_freq' == key:
            self.set_floor_frequency(opt.get_value())
        elif 'praat_max_freq' == key:
            self.set_praat_max_freq(opt.get_value())
        elif 'output_type' == key:
            self.set_output_type(opt.get_value())
        elif key in self.__estimator.get_available_method_names():
            self.__estimator.enable_method(key, opt.get_value())
        elif 'pattern' in key:
            self._options[key] = opt.get_value()
        else:
            raise AnnotationOptionError(key)

get_threshold

View Source
def get_threshold(self) -> float:
    return self._options['threshold']

get_win_length

View Source
def get_win_length(self) -> float:
    return self._options['win_length']

get_lpc_order

View Source
def get_lpc_order(self) -> int:
    return self._options['lpc_order']

get_floor_freq

View Source
def get_floor_freq(self) -> float:
    return self._options['floor_freq']

get_praat_max_freq

View Source
def get_praat_max_freq(self) -> float:
    return self._options['praat_max_freq']

get_enabled_method_names

Return the list of active method names.

Returns
  • (tuple) Names of the currently selected methods
View Source
def get_enabled_method_names(self) -> tuple:
    """Return the list of active method names.

        :return: (tuple) Names of the currently selected methods

        """
    return self.__estimator.get_enabled_method_names()

set_threshold

Set the RMS threshold value: 0 for automatic.

Parameters
  • value: (int) RMS value used as volume threshold
Raises
  • TypeError: Given value is not an integer.
  • ValueError: Given value must be between a positive integer.
View Source
def set_threshold(self, value: int):
    """Set the RMS threshold value: 0 for automatic.

        :param value: (int) RMS value used as volume threshold
        :raises: TypeError: Given value is not an integer.
        :raises: ValueError: Given value must be between a positive integer.

        """
    self.__estimator.set_rms_threshold(value)
    self._options['threshold'] = value

set_win_length

Set a new length of window for the estimation of formant values.

Parameters
  • value: (float) Hamming window duration in seconds.
Raises
  • TypeError: Given value is not a number.
  • ValueError: Given value must range 0.01 - 0.1.
View Source
def set_win_length(self, value: float):
    """Set a new length of window for the estimation of formant values.

        :param value: (float) Hamming window duration in seconds.
        :raises: TypeError: Given value is not a number.
        :raises: ValueError: Given value must range 0.01 - 0.1.

        """
    self.__estimator.set_win_dur(value)
    self._options['win_length'] = value

set_lpc_order

Set the LPC order.

Parameters
  • value: (int) Order value, between 6 and samplerate/100
Raises
  • TypeError: Given value is not an integer.
View Source
def set_lpc_order(self, value: int) -> None:
    """Set the LPC order.

        :param value: (int) Order value, between 6 and samplerate/100
        :raises: TypeError: Given value is not an integer.

        """
    self.__estimator.set_order(value)
    self._options['lpc_order'] = value

set_floor_frequency

Set the minimum frequency to consider for formants.

Parameters
  • value: (float)
Raises
  • TypeError: Given value is not a number.
  • ValueError: Given value must be between 50 and 500.
View Source
def set_floor_frequency(self, value: float) -> None:
    """Set the minimum frequency to consider for formants.

        :param value: (float)
        :raises: TypeError: Given value is not a number.
        :raises: ValueError: Given value must be between 50 and 500.

        """
    self.__estimator.set_floor_frequency(value)
    self._options['floor_freq'] = value

set_praat_max_freq

Set the highest frequency the Praat-based methods are analyzing.

Parameters
  • value: (float) Frequency in Hz, ranging 1000 - 10000
Raises
  • TypeError: Given value is not a number.
  • ValueError: Given value is out of range.
View Source
def set_praat_max_freq(self, value: float) -> None:
    """Set the highest frequency the Praat-based methods are analyzing.

        :param value: (float) Frequency in Hz, ranging 1000 - 10000
        :raises: TypeError: Given value is not a number.
        :raises: ValueError: Given value is out of range.

        """
    self.__estimator.set_max_freq(value)
    self._options['praat_max_freq'] = float(value)

set_output_type

Set the type of output, among center, mean or all.

Parameters
  • value: (str) One of the expected output type
Raises
  • ValueError: if out_type is invalid.
View Source
def set_output_type(self, value: str) -> None:
    """Set the type of output, among center, mean or all.

        :param value: (str) One of the expected output type
        :raises: ValueError: if out_type is invalid.

        """
    self.__estimator.set_output_type(value)

get_inputs

Return the audio filename and the tier with time-aligned phonemes.

Parameters
  • input_files: (list)
Raises

NoTierInputError

Returns
  • (str, sppasTier)
View Source
def get_inputs(self, input_files: list) -> tuple:
    """Return the audio filename and the tier with time-aligned phonemes.

        :param input_files: (list)
        :raise: NoTierInputError
        :return: (str, sppasTier)

        """
    ext = self.get_input_extensions()
    audio_ext = ext[0]
    annot_ext = ext[1]
    tier = None
    audio_filename = None
    for filename in input_files:
        fn, fe = os.path.splitext(filename)
        if audio_filename is None and fe in audio_ext:
            audio_speech = audioopy.aio.open(filename)
            n = audio_speech.get_nchannels()
            audio_speech.close()
            if n != 1:
                logging.error('An audio file with only one channel was expected.')
                raise NoChannelInputError()
            audio_filename = filename
        elif tier is None and fe in annot_ext:
            parser = sppasTrsRW(filename)
            trs_input = parser.read()
            tier = sppasFindTier.aligned_phones(trs_input)
    if tier is None:
        logging.error('A tier with time-aligned phonemes was not found in the given files: {:s}.'.format(str(input_files)))
        raise NoTierInputError
    if tier.is_interval() is False:
        logging.error('The tier should be of type: Interval.')
        raise AnnDataTypeError(tier.get_name(), 'IntervalTier')
    if tier.is_empty() is True:
        raise EmptyInputError(tier.get_name())
    extm = os.path.splitext(audio_filename)[1].lower()[1:]
    media = sppasMedia(os.path.abspath(audio_filename), mime_type='audio/' + extm)
    tier.set_media(media)
    return (audio_filename, tier)

run

Run the automatic annotation process on an input.

Input file is a tuple with 2 files: the audio file and the annotation file

Parameters
  • input_files: (list of str) (audio, time-aligned phonemes)
  • output: (str) the output name
Returns
  • (sppasTranscription)
View Source
def run(self, input_files, output=None):
    """Run the automatic annotation process on an input.

        Input file is a tuple with 2 files:
        the audio file and the annotation file

        :param input_files: (list of str) (audio, time-aligned phonemes)
        :param output: (str) the output name
        :return: (sppasTranscription)

        """
    audio_filename, tier = self.get_inputs(input_files)
    tiers = self.__estimator.estimate(audio_filename, tier)
    trs_output = sppasTranscription(self.name)
    trs_output.set_meta('annotation_result_of', input_files[0])
    for formant_tier in tiers:
        trs_output.append(formant_tier)
    if output is not None:
        if len(trs_output) > 0:
            output_file = self.fix_out_file_ext(output)
            parser = sppasTrsRW(output_file)
            parser.write(trs_output)
            return [output_file]
        else:
            raise EmptyOutputError
    return trs_output

get_output_pattern

Pattern this annotation uses in an output filename.

View Source
def get_output_pattern(self):
    """Pattern this annotation uses in an output filename."""
    return self._options.get('outputpattern', '-formants')

get_input_patterns

Pattern this annotation expects for its input filename.

View Source
def get_input_patterns(self):
    """Pattern this annotation expects for its input filename."""
    return [self._options.get('inputpattern1', ''), self._options.get('inputpattern2', '-palign')]

get_input_extensions

Extensions that the annotation expects for its input filename.

View Source
@staticmethod
def get_input_extensions():
    """Extensions that the annotation expects for its input filename."""
    return [sppasFiles.get_informat_extensions('AUDIO'), sppasFiles.get_informat_extensions('ANNOT_ANNOT')]