U
    %dA                     @   s  d Z ddlZddlmZmZ ddlZddlmZ ddl	m
Z
 e rLddlZddd	d
dd
ddddddddddddd	ddddddd	d
dZdd Zddddddddddd
ZeedddZe d6eee e
dddZddd d!d"d#d$Ze d7eeeeeee eejef d'd(d)Zejeed*d+d,Zeed-d.d/Zejeeed0d1d2Ze d8eejeeee ee ee ee d3d4d5ZdS )9zCThe new soundfile backend which will become default in 0.8.0 onward    N)OptionalTuple)module_utils   )AudioMetaData             @         )PCM_S8PCM_16PCM_24PCM_32PCM_U8FLOATDOUBLEULAWALAWZ	IMA_ADPCMZMS_ADPCMZGSM610Z	VOX_ADPCMZG721_32ZG723_24ZG723_40ZDWVW_12ZDWVW_16ZDWVW_24ZDWVW_NZDPCM_8ZDPCM_16VORBISZALAC_16ZALAC_20ZALAC_24ZALAC_32c                 C   s&   | t krtd|  d t | dS )NzThe z subtype is unknown to TorchAudio. As a result, the bits_per_sample attribute will be set to 0. If you are seeing this warning, please report by opening an issue on github (after checking for existing/closed ones). You may otherwise ignore this warning.r   )_SUBTYPE_TO_BITS_PER_SAMPLEwarningswarnget)subtype r   H/tmp/pip-unpacked-wheel-lbdmvq91/torchaudio/backend/soundfile_backend.py_get_bit_depth5   s
    
r   PCM_SPCM_UPCM_Fr   r   r   )
r   r   r   r   r   r   r   r   r   r   formatr   c                 C   s   | dkrdS t |dS )NZFLACUNKNOWN)_SUBTYPE_TO_ENCODINGr   r#   r   r   r   _get_encodingN   s    r'   )filepathr$   returnc                 C   s2   t | }t|j|j|jt|jt|j	|jdS )ag  Get signal information of an audio file.

    Note:
        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts
        ``pathlib.Path`` object as well. This is for the consistency with ``"sox_io"`` backend,
        which has a restriction on type annotation due to TorchScript compiler compatiblity.

    Args:
        filepath (path-like object or file-like object):
            Source of audio data.
        format (str or None, optional):
            Not used. PySoundFile does not accept format hint.

    Returns:
        AudioMetaData: meta data of the given audio.

    )bits_per_sampleencoding)
	soundfileinfor   
samplerateframesZchannelsr   r   r'   r$   )r(   r$   sinfor   r   r   r-   T   s    
r-   Zint8uint8int16int32float32float64)r   r   r   r   r   r   T)r(   frame_offset
num_frames	normalizechannels_firstr$   r)   c              	   C   s   t | dd}|jdks|r"d}n&|jtkr>td|j n
t|j }||d|}|j||dd}	|j}
W 5 Q R X t	
|	}	|r|	 }	|	|
fS )a  Load audio data from file.

    Note:
        The formats this function can handle depend on the soundfile installation.
        This function is tested on the following formats;

        * WAV

            * 32-bit floating-point
            * 32-bit signed integer
            * 16-bit signed integer
            * 8-bit unsigned integer

        * FLAC
        * OGG/VORBIS
        * SPHERE

    By default (``normalize=True``, ``channels_first=True``), this function returns Tensor with
    ``float32`` dtype, and the shape of `[channel, time]`.

    .. warning::

       ``normalize`` argument does not perform volume normalization.
       It only converts the sample type to `torch.float32` from the native sample
       type.

       When the input format is WAV with integer type, such as 32-bit signed integer, 16-bit
       signed integer, 24-bit signed integer, and 8-bit unsigned integer, by providing ``normalize=False``,
       this function can return integer Tensor, where the samples are expressed within the whole range
       of the corresponding dtype, that is, ``int32`` tensor for 32-bit signed PCM,
       ``int16`` for 16-bit signed PCM and ``uint8`` for 8-bit unsigned PCM. Since torch does not
       support ``int24`` dtype, 24-bit signed PCM are converted to ``int32`` tensors.

       ``normalize`` argument has no effect on 32-bit floating-point WAV and other formats, such as
       ``flac`` and ``mp3``.

       For these formats, this function always returns ``float32`` Tensor with values.

    Note:
        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts
        ``pathlib.Path`` object as well. This is for the consistency with ``"sox_io"`` backend,
        which has a restriction on type annotation due to TorchScript compiler compatiblity.

    Args:
        filepath (path-like object or file-like object):
            Source of audio data.
        frame_offset (int, optional):
            Number of frames to skip before start reading data.
        num_frames (int, optional):
            Maximum number of frames to read. ``-1`` reads all the remaining samples,
            starting from ``frame_offset``.
            This function may return the less number of frames if there is not enough
            frames in the given file.
        normalize (bool, optional):
            When ``True``, this function converts the native sample type to ``float32``.
            Default: ``True``.

            If input file is integer WAV, giving ``False`` will change the resulting Tensor type to
            integer type.
            This argument has no effect for formats other than integer WAV type.

        channels_first (bool, optional):
            When True, the returned Tensor has dimension `[channel, time]`.
            Otherwise, the returned Tensor's dimension is `[time, channel]`.
        format (str or None, optional):
            Not used. PySoundFile does not accept format hint.

    Returns:
        (torch.Tensor, int): Resulting Tensor and sample rate.
            If the input file has integer wav format and normalization is off, then it has
            integer type, else ``float32`` type. If ``channels_first=True``, it has
            `[channel, time]` else `[time, channel]`.
    rZWAVr4   zUnsupported subtype: NT)Z	always_2d)r,   Z	SoundFiler$   r   _SUBTYPE2DTYPE
ValueErrorZ_prepare_readreadr.   torchZ
from_numpyt)r(   r7   r8   r9   r:   r$   file_dtyper/   Zwaveformsample_rater   r   r   load{   s    R


rD   )rB   r+   r*   c              
   C   s  |s\|sFt jdt jdt jdt jdt jdi| }|sBtd|  |S |dkrRdS d| S |d	kr|sldS |dkr|td
d| S |dkr|dkrdS td|dkr|dkrdS |dkrdS td|dkr|dkrdS td|dkr|dkrdS tdtd| dd S )Nr   r   r   r   r   zUnsupported dtype for wav: r   PCM_r    z/wav does not support 8-bit signed PCM encoding.r!   Nr   z.wav only supports 8-bit unsigned PCM encoding.r"   )Nr
   r   z/wav only supports 32/64-bit float PCM encoding.r   z(wav only supports 8-bit mu-law encoding.r   z'wav only supports 8-bit a-law encoding.zwav does not support .)r?   r1   r2   r3   r4   r5   r   r=   )rB   r+   r*   r   r   r   r   _get_subtype_for_wav   s\         


rH   r+   r*   c                 C   sn   | dkr|rd| S dS | dkr2t d|  d| dkrN|dkrFdS t d	| d
krZd
S t d|  dd S )N)Nr    rE   r   )r!   r"   zsph does not support z
 encoding.r   rF   z,sph only supports 8-bit for mu-law encoding.r   rG   )r=   rI   r   r   r   _get_subtype_for_sphere
  s    rJ   rB   r$   r+   r*   c                 C   s   |dkrt | ||S |dkrV|r(td|s0dS |dkr@td|dkrLdS d	| S |d
krr|sf|rntddS |dkrt||S |dkrdS td| d S )NZwavZflaczflac does not support encoding.r   r	   z+flac does not support bits_per_sample > 24.r   r   rE   )ZoggZvorbisz5ogg/vorbis does not support encoding/bits_per_sample.r   sph)nisnistzUnsupported format: )rH   r=   rJ   rK   r   r   r   _get_subtype  s&    
rO   )r(   srcrC   r:   compressionr$   r+   r*   c           
      C   s   |j dkrtd|j  d|dk	r.td t| drR|dkrHtd| }nt| dd	  }|d
krxtd|dkrtd t	|j
|||}	|dkr|dkrd}|r| }tj| |||	|d dS )a  Save audio data to file.

    Note:
        The formats this function can handle depend on the soundfile installation.
        This function is tested on the following formats;

        * WAV

            * 32-bit floating-point
            * 32-bit signed integer
            * 16-bit signed integer
            * 8-bit unsigned integer

        * FLAC
        * OGG/VORBIS
        * SPHERE

    Note:
        ``filepath`` argument is intentionally annotated as ``str`` only, even though it accepts
        ``pathlib.Path`` object as well. This is for the consistency with ``"sox_io"`` backend,
        which has a restriction on type annotation due to TorchScript compiler compatiblity.

    Args:
        filepath (str or pathlib.Path): Path to audio file.
        src (torch.Tensor): Audio data to save. must be 2D tensor.
        sample_rate (int): sampling rate
        channels_first (bool, optional): If ``True``, the given tensor is interpreted as `[channel, time]`,
            otherwise `[time, channel]`.
        compression (float of None, optional): Not used.
            It is here only for interface compatibility reson with "sox_io" backend.
        format (str or None, optional): Override the audio format.
            When ``filepath`` argument is path-like object, audio format is
            inferred from file extension. If the file extension is missing or
            different, you can specify the correct format with this argument.

            When ``filepath`` argument is file-like object,
            this argument is required.

            Valid values are ``"wav"``, ``"ogg"``, ``"vorbis"``,
            ``"flac"`` and ``"sph"``.
        encoding (str or None, optional): Changes the encoding for supported formats.
            This argument is effective only for supported formats, sush as
            ``"wav"``, ``""flac"`` and ``"sph"``. Valid values are;

                - ``"PCM_S"`` (signed integer Linear PCM)
                - ``"PCM_U"`` (unsigned integer Linear PCM)
                - ``"PCM_F"`` (floating point PCM)
                - ``"ULAW"`` (mu-law)
                - ``"ALAW"`` (a-law)

        bits_per_sample (int or None, optional): Changes the bit depth for the
            supported formats.
            When ``format`` is one of ``"wav"``, ``"flac"`` or ``"sph"``,
            you can change the bit depth.
            Valid values are ``8``, ``16``, ``24``, ``32`` and ``64``.

    Supported formats/encodings/bit depth/compression are:

    ``"wav"``
        - 32-bit floating-point PCM
        - 32-bit signed integer PCM
        - 24-bit signed integer PCM
        - 16-bit signed integer PCM
        - 8-bit unsigned integer PCM
        - 8-bit mu-law
        - 8-bit a-law

        Note:
            Default encoding/bit depth is determined by the dtype of
            the input Tensor.

    ``"flac"``
        - 8-bit
        - 16-bit (default)
        - 24-bit

    ``"ogg"``, ``"vorbis"``
        - Doesn't accept changing configuration.

    ``"sph"``
        - 8-bit signed integer PCM
        - 16-bit signed integer PCM
        - 24-bit signed integer PCM
        - 32-bit signed integer PCM (default)
        - 8-bit mu-law
        - 8-bit a-law
        - 16-bit a-law
        - 24-bit a-law
        - 32-bit a-law

       zExpected 2D Tensor, got zD.Nzr`save` function of "soundfile" backend does not support "compression" parameter. The argument is silently ignored.writez0`format` is required when saving to file object.rG   r6   )Nr   r   r	   r
   r   zInvalid bits_per_sample.r	   zvSaving audio with 24 bits per sample might warp samples near -1. Using 16 bits per sample might be able to avoid this.)rM   rN   rL   ZNIST)filedatar.   r   r$   )ndimr=   r   r   hasattrRuntimeErrorlowerstrsplitrO   rB   r@   r,   rS   )
r(   rP   rC   r:   rQ   r$   r+   r*   extr   r   r   r   save.  s.    f


r]   )N)r   r6   TTN)TNNNN)__doc__r   typingr   r   r?   Ztorchaudio._internalr   Z
_mod_utilscommonr   Zis_soundfile_availabler,   r   r   r&   rZ   r'   Zrequires_soundfiler-   r<   intboolZTensorrD   rB   rH   rJ   rO   floatr]   r   r   r   r   <module>   s   
     c+     