class_docstr: Audio samples IO handling within a given dora xp.
  
  The sample manager handles the dumping and loading logic for generated and
  references samples across epochs for a given xp, providing a simple API to
  store, retrieve and compare audio samples.
  
  Args:
      xp (dora.XP): Dora experiment object. The XP contains information on the XP folder
          where all outputs are stored and the configuration of the experiment,
          which is useful to retrieve audio-related parameters.
      map_reference_to_sample_id (bool): Whether to use the sample_id for all reference samples
          instead of generating a dedicated hash id. This is useful to allow easier comparison
          with ground truth sample from the files directly without having to read the JSON metadata
          to do the mapping (at the cost of potentially dumping duplicate prompts/references
          depending on the task).
docstr: Adds a batch of samples.
  The samples are stored in the XP's sample output directory, under a corresponding
  epoch folder. Each sample is assigned an id which is computed using the input data and their batch index.
  In addition to the sample itself, a json file containing associated metadata is stored next to it.
  
  Args:
      sample_wavs (torch.Tensor): Batch of audio wavs to store. Tensor of shape [batch_size, channels, shape].
      epoch (int): Current training epoch.
      conditioning (list of dict[str, str], optional): List of conditions used during generation,
          one per sample in the batch.
      prompt_wavs (torch.Tensor, optional): Prompts used during generation. Tensor of shape
          [batch_size, channels, shape].
      ground_truth_wav (torch.Tensor, optional): Reference audio where prompts were extracted from.
          Tensor of shape [batch_size, channels, shape].
      generation_args (dict[str, Any], optional): Dictionary of other arguments used during generation.
  Returns:
      samples (list of Sample): The saved audio samples with prompts, ground truth and metadata.
docstr_tok: ["Adds","a","batch","of","samples",".","The","samples","are","stored","in","the","XP","'s","sample","output","directory",",","under","a","corresponding","epoch","folder",".","Each","sample","is","assigned","an","id","which","is","computed","using","the","input","data","and","their","batch","index",".","In","addition","to","the","sample","itself",",","a","json","file","containing","associated","metadata","is","stored","next","to","it",".","Args",":","sample_wavs","(","torch.Tensor",")",":","Batch","of","audio","wavs","to","store",".","Tensor","of","shape","[","batch_size",",","channels",",","shape","]",".","epoch","(","int",")",":","Current","training","epoch",".","conditioning","(","list","of","dict","[","str",",","str","]",",","optional",")",":","List","of","conditions","used","during","generation",",","one","per","sample","in","the","batch",".","prompt_wavs","(","torch.Tensor",",","optional",")",":","Prompts","used","during","generation",".","Tensor","of","shape","[","batch_size",",","channels",",","shape","]",".","ground_truth_wav","(","torch.Tensor",",","optional",")",":","Reference","audio","where","prompts","were","extracted","from",".","Tensor","of","shape","[","batch_size",",","channels",",","shape","]",".","generation_args","(","dict","[","str",",","Any","]",",","optional",")",":","Dictionary","of","other","arguments","used","during","generation",".","Returns",":","samples","(","list","of","Sample",")",":","The","saved","audio","samples","with","prompts",",","ground","truth","and","metadata","."]
code: def add_samples(
      self,
      samples_wavs: torch.Tensor,
      epoch: int,
      conditioning: tp.Optional[tp.List[tp.Dict[str, tp.Any]]] = None,
      prompt_wavs: tp.Optional[torch.Tensor] = None,
      ground_truth_wavs: tp.Optional[torch.Tensor] = None,
      generation_args: tp.Optional[tp.Dict[str, tp.Any]] = None,
  ) -> tp.List[Sample]:
      """Adds a batch of samples.
      The samples are stored in the XP's sample output directory, under a corresponding
      epoch folder. Each sample is assigned an id which is computed using the input data and their batch index.
      In addition to the sample itself, a json file containing associated metadata is stored next to it.
  
      Args:
          sample_wavs (torch.Tensor): Batch of audio wavs to store. Tensor of shape [batch_size, channels, shape].
          epoch (int): Current training epoch.
          conditioning (list of dict[str, str], optional): List of conditions used during generation,
              one per sample in the batch.
          prompt_wavs (torch.Tensor, optional): Prompts used during generation. Tensor of shape
              [batch_size, channels, shape].
          ground_truth_wav (torch.Tensor, optional): Reference audio where prompts were extracted from.
              Tensor of shape [batch_size, channels, shape].
          generation_args (dict[str, Any], optional): Dictionary of other arguments used during generation.
      Returns:
          samples (list of Sample): The saved audio samples with prompts, ground truth and metadata.
      """
      samples = []
      for idx, wav in enumerate(samples_wavs):
          prompt_wav = (
              prompt_wavs[idx] if prompt_wavs is not None else None
          )
          gt_wav = (
              ground_truth_wavs[idx]
              if ground_truth_wavs is not None
              else None
          )
          conditions = (
              conditioning[idx] if conditioning is not None else None
          )
          samples.append(
              self.add_sample(
                  wav,
                  epoch,
                  idx,
                  conditions,
                  prompt_wav,
                  gt_wav,
                  generation_args,
              )
          )
      return samples
  
imports: from concurrent.futures import ThreadPoolExecutor
  from dataclasses import asdict, dataclass
  from functools import lru_cache
  import hashlib
  import json
  import logging
  from pathlib import Path
  import re
  import typing
  import unicodedata
  import uuid
  import dora
  import torch
  from ...data.audio import audio_read, audio_write
label_desc: Use image node_id 10 for calling the SampleManager obj's underlying member method code with example usage: obj.add_samples(samples_wavs, epoch, conditioning, prompt_wavs, ground_truth_wavs, generation_args) and returns: samples