o
    8wiQ4                     @   s   d dl Z d dlmZmZ d dlmZ d dlmZmZm	Z	m
Z
mZ d dlZd dlZddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZmZ erXd dlmZ ddlmZ eG dd dZ ddde!fddZ"dS )    N)	dataclassfield)BytesIO)TYPE_CHECKINGAnyClassVarOptionalUnion   )config)DownloadConfig)
array_cast)is_local_pathxopen)no_op_if_value_is_nullstring_to_dictAudioDecoder   )FeatureTypec                   @   sN  e Zd ZU dZdZee ed< dZe	ed< dZ
ee ed< edddZee ed	< d
Zee ed< ee e dZee ed< ed dddZeed< dd Zdeeeeedf defddZ	d"dedeeeeee	df f  ddfddZdedeedf f fddZdeejej f dej fddZ!d"dej dej fd d!Z"dS )#AudioaJ  Audio [`Feature`] to extract audio data from an audio file.

    Input: The Audio feature accepts as input:
    - A `str`: Absolute path to the audio file (i.e. random access is allowed).
    - A `dict` with the keys:

        - `path`: String with relative path of the audio file to the archive file.
        - `bytes`: Bytes content of the audio file.

      This is useful for parquet or webdataset files which embed audio files.

    - A `dict` with the keys:

        - `array`: Array containing the audio sample
        - `sampling_rate`: Integer corresponding to the sampling rate of the audio sample.

    - A `torchcodec.decoders.AudioDecoder`: torchcodec audio decoder object.

    Output: The Audio features output data as `torchcodec.decoders.AudioDecoder` objects, with additional keys:

    - `array`: Array containing the audio sample
    - `sampling_rate`: Integer corresponding to the sampling rate of the audio sample.

    Args:
        sampling_rate (`int`, *optional*):
            Target sampling rate. If `None`, the native sampling rate is used.
        mono (`bool`, defaults to `True`):
            Whether to convert the audio signal to mono by averaging samples across
            channels.
        decode (`bool`, defaults to `True`):
            Whether to decode the audio data. If `False`,
            returns the underlying dictionary in the format `{"path": audio_path, "bytes": audio_bytes}`.
        stream_index (`int`, *optional*):
            The streaming index to use from the file. If `None` defaults to the "best" index.

    Example:

    ```py
    >>> from datasets import load_dataset, Audio
    >>> ds = load_dataset("PolyAI/minds14", name="en-US", split="train")
    >>> ds = ds.cast_column("audio", Audio(sampling_rate=44100))
    >>> ds[0]["audio"]
    <datasets.features._torchcodec.AudioDecoder object at 0x11642b6a0>
    >>> audio = ds[0]["audio"]
    >>> audio.get_samples_played_in_range(0, 10)
    AudioSamples:
        data (shape): torch.Size([2, 110592])
        pts_seconds: 0.0
        duration_seconds: 2.507755102040816
        sample_rate: 44100
    ```
    Nsampling_rateTdecodestream_indexF)defaultrepriddictdtypebytespathpa_type)r   initr   _typec                 C   s   | j S N)r"   )self r'   T/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/datasets/features/audio.py__call__V   s   zAudio.__call__valuer   returnc              
   C   s  zddl }W n ty } ztd|d}~ww |du r tdtjr*ddlm} nd}t|tr6d|dS t|t	t
frB|ddS |durOt||rOt|S d|v rkt }|j||d j|d d	d
 | ddS |ddurtj|d r|d dr|ddu rtd|drtj|d tjdtjd }ntj|d dddtjd }td}|j|||d d	d
 | ddS d|ddS |ddus|ddur|d|ddS td| d)zEncode example into a format for Arrow.

        Args:
            value (`str`, `bytes`,`bytearray`,`dict`, `AudioDecoder`):
                Data passed as input to Audio feature.

        Returns:
            `dict`
        r   N;To support encoding audio data, please install 'soundfile'.zvalue must be providedr   r   arrayr   wavformatr!   pcmzBTo use PCM files, please specify a 'sampling_rate' in Audio objectr    )r   i  hr)r   mode    zUAn audio sample should have one of 'path' or 'bytes' but they are missing or None in .)	soundfileImportError
ValueErrorr   TORCHCODEC_AVAILABLEtorchcodec.decodersr   
isinstancestrr    	bytearrayencode_torchcodec_audior   writeTgetvaluegetosr!   isfileendswithKeyErrornp
frombufferint16astypefloat32memmap)r&   r*   sferrr   bufferbytes_valuer'   r'   r(   encode_exampleY   sJ   





" 
zAudio.encode_exampletoken_per_repo_idc                 C   sJ  t jr
ddlm} ntd| jstd|d dur#|d |d fn|d df\}}|du r;|du r;td| d	|du rMt|rM||| j	| j
d
}nL|du r|pTi }|dd }|t jret jnt j}t||}	|	durx||	d nd}
t|
d}t|d|d}||| j	| j
d
}n	||| j	| j
d
}||d|_||j_|S )a,  Decode example audio file into audio data.

        Args:
            value (`dict`):
                A dictionary with keys:

                - `path`: String with relative audio file path.
                - `bytes`: Bytes of the audio file.
            token_per_repo_id (`dict`, *optional*):
                To access and decode
                audio files from private repositories on the Hub, you can pass
                a dictionary repo_id (`str`) -> token (`bool` or `str`)

        Returns:
            `torchcodec.decoders.AudioDecoder`
        r   r   z<To support decoding audio data, please install 'torchcodec'.zMDecoding is disabled for this feature. Please use Audio(decode=True) instead.r    Nr!   zJAn audio sample should have one of 'path' or 'bytes' but both are None in r6   )r   sample_rate::repo_idtokenrbdownload_config)r!   r    )r   r:   _torchcodecr   r8   r   RuntimeErrorr9   r   r   r   split
startswithHF_ENDPOINTHUB_DATASETS_URLHUB_DATASETS_HFFS_URLr   rC   r   r   _hf_encodedmetadatar!   )r&   r*   rS   r   r!   r    audio
source_urlpatternsource_url_fieldsrY   r\   fr'   r'   r(   decode_example   s0   ,

zAudio.decode_exampler   c                 C   s,   ddl m} | jrtd|d|ddS )z[If in the decodable state, raise an error, otherwise flatten the feature into a dictionary.r   )Valuez'Cannot flatten a decoded Audio feature.binarystringr   )featuresrl   r   r9   )r&   rl   r'   r'   r(   flatten   s   zAudio.flattenstoragec                 C   sp  t j|jr%t jdgt| t  d}t jj||gddg|	 d}nt j
|jrJt jdgt| t  d}t jj||gddg|	 d}nht j|jrd|jdrdt dd | D }nNt j|jr|jdd	kry|d}nt jdgt| t  d}|jdd	kr|d}nt jdgt| t  d}t jj||gddg|	 d}t|| jS )
a  Cast an Arrow array to the Audio arrow storage type.
        The Arrow types that can be converted to the Audio pyarrow storage type are:

        - `pa.string()` - it must contain the "path" data
        - `pa.binary()` - it must contain the audio bytes
        - `pa.struct({"bytes": pa.binary()})`
        - `pa.struct({"path": pa.string()})`
        - `pa.struct({"bytes": pa.binary(), "path": pa.string()})`  - order doesn't matter

        Args:
            storage (`Union[pa.StringArray, pa.StructArray]`):
                PyArrow array to cast.

        Returns:
            `pa.StructArray`: Array in the Audio arrow storage type, that is
                `pa.struct({"bytes": pa.binary(), "path": pa.string()})`
        Ntyper    r!   maskr-   c                 S   s$   g | ]}|d urt  |nd qS r%   )r   rR   .0xr'   r'   r(   
<listcomp>      $ z&Audio.cast_storage.<locals>.<listcomp>r   )patypes	is_stringrs   r-   lenrm   StructArrayfrom_arraysis_null	is_binaryrn   	is_structget_all_field_indices	to_pylistget_field_indexr   r   r"   )r&   rq   bytes_array
path_arrayr'   r'   r(   cast_storage   s"     zAudio.cast_storagec                    s   du ri t fdd tj fdd| D t d}tjdd |d D t d}tjj||gd	dg|	 d
}t
|| jS )a8  Embed audio files into the Arrow array.

        Args:
            storage (`pa.StructArray`):
                PyArrow array to embed.

        Returns:
            `pa.StructArray`: Array in the Audio arrow storage type, that is
                `pa.struct({"bytes": pa.binary(), "path": pa.string()})`.
        Nc                    s   |  dd }|tjrtjntj}t||}|d ur# |d nd }t|d}t	| d|d}|
 W  d    S 1 s@w   Y  d S )NrU   rV   rW   rX   rZ   r[   )r_   r`   r   ra   rb   rc   r   rC   r   r   read)r!   rg   rh   ri   rY   r\   rj   )rS   r'   r(   path_to_bytes
  s   

$z*Audio.embed_storage.<locals>.path_to_bytesc                    s8   g | ]}|d ur|d d u r |d n|d nd qS )Nr    r!   r'   rv   )r   r'   r(   ry     s    *z'Audio.embed_storage.<locals>.<listcomp>rr   c                 S   s$   g | ]}|d urt j|nd qS r%   )rD   r!   basename)rw   r!   r'   r'   r(   ry     rz   r!   r    rt   )r   r{   r-   r   rm   r   rn   r   r   r   r   r"   )r&   rq   rS   r   r   r'   )r   rS   r(   embed_storage   s    
zAudio.embed_storager%   )#__name__
__module____qualname____doc__r   r   int__annotations__r   boolr   r   r   r=   r   r   r{   structrm   rn   r"   r   r$   r)   r	   r    r>   r   rR   rk   rp   StringArrayr   r   r   r'   r'   r'   r(   r      s,   
 5$ >
5 &r   rf   r   r+   c              
   C   s   t | dr| jS zdd l}W n ty } ztd|d }~ww |  }|j  }t }|j	||j
|jdd | d dS )Nrd   r   r,   r.   r/   r   )hasattrrd   r7   r8   get_all_samplesdatacpunumpyr   r@   rA   rT   rB   )rf   rN   rO   samplesr-   rP   r'   r'   r(   r?   %  s   

r?   )#rD   dataclassesr   r   ior   typingr   r   r   r   r	   r   rH   pyarrowr{    r   download.download_configr   tabler   utils.file_utilsr   r   utils.py_utilsr   r   r;   r   ro   r   r   r   r?   r'   r'   r'   r(   <module>   s&      