docs: def from_elan(cls: Type[CorpusT], org_dir: Path, tgt_dir: Path,
                    feat_type: str = "fbank", label_type: str = "phonemes",
                    utterance_filter: Callable[[Utterance], bool] = None,
                    label_segmenter: Optional[LabelSegmenter] = None,
                    speakers: List[str] = None, lazy: bool = True,
                    tier_prefixes: Tuple[str, ...] = ("xv", "rf")) -> CorpusT:
          """ Construct a `Corpus` from ELAN files.
  
          Args:
              org_dir: A path to the directory containing the unpreprocessed
                  data.
              tgt_dir: A path to the directory where the preprocessed data will
                  be stored.
              feat_type: A string describing the input speech features. For
                         example, "fbank" for log Mel filterbank features.
              label_type: A string describing the transcription labels. For example,
                           "phonemes" or "tones".
              utterance_filter: A function that returns False if an utterance
                  should not be included in the corpus and True otherwise. This
                  can be used to remove undesirable utterances for training, such as
                  codeswitched utterances.
              label_segmenter: An object that has an attribute `segment_labels`,
                  which is creates new `Utterance` instances from old ones,
                  by segmenting the tokens in their `text` attribute. Note,
                  `LabelSegmenter` might be better as a function, the only issue
                  is it needs to carry with it a list of labels. This could
                  potentially be a function attribute.
              speakers: A list of speakers to filter for. If `None`, utterances
                  from all speakers are included.
              tier_prefixes: A collection of strings that prefix ELAN tiers to
                  filter for. For example, if this is `("xv", "rf")`, then tiers
                  named "xv", "xv@Mark", "rf@Rose" would be extracted if they
                  existed.
  
          """
          # This currently bails out if label_segmenter is not provided
          if not label_segmenter:
              raise ValueError("A label segmenter must be provided via label_segmenter")
  
          # In case path is supplied as a string, make it a Path
          if isinstance(tgt_dir, str):
              tgt_dir = Path(tgt_dir)
  
          # Read utterances from org_dir.
          utterances = elan.utterances_from_dir(org_dir,
                                                tier_prefixes=tier_prefixes)
  
          # Filter utterances based on some criteria (such as codeswitching).
          if utterance_filter:
              utterances = [utter for utter in utterances if utterance_filter(utter)]
          utterances = utterance.remove_duplicates(utterances)
  
          # Segment the labels in the utterances appropriately
          if label_segmenter:
              utterances = [label_segmenter.segment_labels(utter) for utter in utterances]
  
          # Remove utterances without transcriptions.
          utterances = utterance.remove_empty_text(utterances)
  
          # Remove utterances with exceptionally short wav_files that are too
          # short for CTC to work.
          utterances = utterance.remove_too_short(utterances)
  
          tgt_dir.mkdir(parents=True, exist_ok=True)
  
          # TODO A lot of these methods aren't ELAN-specific. preprocess.elan was
          # only used to get the utterances. There could be another Corpus
          # factory method that takes Utterance objects. the fromElan and
          # fromPangloss constructors could call this.
  
          # Writes the transcriptions to the tgt_dir/label/ dir
          utterance.write_transcriptions(utterances, (tgt_dir / "label"),
                                 label_type, lazy=lazy)
          # Extracts utterance level WAV information from the input file.
          wav.extract_wavs(utterances, (tgt_dir / "wav"), lazy=lazy)
  
          corpus = cls(feat_type, label_type, tgt_dir,
                       labels=label_segmenter.labels, speakers=speakers)
          corpus.utterances = utterances
          return corpus