Adding long-form audio speaker diarization (clustering) class and functions
State: closed | Pull request: yes
Labels: name: ASR

name: Speaker Tasks

# What does this PR do ?

This PR adds long-form audio speaker diarization feature by adding LongFormSpeakerClustering class.
Two parameters are added to yaml file for long form audio clustering.

This is forward function for long-form speaker clustering.
Please refer to `SpeakerClustering` class for the original argument information.

**Please read the following text to understand the long-form clustering**
In the function `long_forward_infer` in `LongFormSpeakerClustering` class:

1. Input embeddings are divided into smaller windows of size `unit_window_len`. It is usually order of 10K. `unit_window_len=10000` is default value.
2. Each window undergoes overclustering, resulting in `sub_cluster_n` fine-grained clusters.  Default `sub_cluster_n=50`.
3. These fine-grained clusters are merged to form the aggregated clustering labels `Y_aggr`.
4. The `unpack_labels` function is then employed to map the aggregated labels `Y_aggr` back to the original labels for all `org_len` input embeddings: `Y_unpack`.

* Theoretically, the maximum length of audio can be extended by a factor of `unit_window_len/sub_cluster_n`. For instance, by default, if the original clustering hits the memory limit at the 1-hour mark, the long-form clustering could handle up to **20 hours without exhausting the memory**.
* The added long-form audio clustering re-uses (repurposes) the online clustering functions and offline clustering functions except `unpack_labels`. 
* The main `forward_unit_infer` clustering execution function and `unpack_labels` functions are added to the `test_diar_utils.py`.
(1) `forward_unit_infer` function performs a simple 1-scale clustering without time-stamp processing. 
(2) `LongFormSpeakerClustering` has `forward_infer` function that chooses one of these two functions:
-- `long_forward_infer` if the input number of segments are larger than `self.unit_window_len`.
-- `short_forward_infer` if the input number of segments are smaller or equal to `self.unit_window_len`.

**Collection**: ASR - Speaker Tasks - Speaker Diarization 

# Changelog 

Updated files:
- All three diarization inference yaml files
- speaker_utils.py
- test_diar_utils.py
- longform_clustering.py - Major change of adding `LongFormSpeakerClustering`
- offline_clustering.py

# Usage
* You can potentially add a usage example below

```
python offline_diar_with_asr_infer.py \
    diarizer.manifest_filepath=<path to manifest file> \
    diarizer.out_dir='demo_asr_output' \
    diarizer.speaker_embeddings.model_path=<pretrained modelname or path to .nemo> \
    diarizer.asr.model_path=<pretrained modelname or path to .nemo> \
    diarizer.asr.parameters.asr_based_vad=True \
    diarizer.speaker_embeddings.parameters.save_embeddings=False
```

# Before your PR is "Ready for review"
**Pre checks**:
- [x] Make sure you read and followed [Contributor guidelines](https://github.com/NVIDIA/NeMo/blob/main/CONTRIBUTING.md)
- [x] Did you write any new necessary tests?
- [ ] Did you add or update any necessary documentation?
- [ ] Does the PR affect components that are optional to install? (Ex: Numba, Pynini, Apex etc)
  - [ ] Reviewer: Does the PR have correct import guards for all optional libraries?
  
**PR Type**:
- [x] New Feature
- [ ] Bugfix
- [ ] Documentation

If you haven't finished some of the above items you can still open "Draft" PR.


## Who can review?

Anyone in the ASR