U
    -eT                  #   @   s*  d Z dZddlZddlZddlmZmZmZ ddl	m
Z ddlmZ zeZW n ek
rd   eZY nX ddd	d
ddddddd
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,Zddd	d
ddddd-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFdG"ZddHdIdJdKZdLdLdLdLdLdLdLdLdLdMdMdLdNdLdLdLdLdLdLdLdOdPdLdLdQdRZdSdTdUdVdWZzejdXkrddYlmZ dZe  d[ Zn\ejd\krdd]lmZ dZe d  d^ Zn0ejd_krddYlmZ dZe  d` Znedaddl Z ej!"e j#Z$ej!%e$eZ&e'e&Z(W n ee)e*fk
r   z(edbZ+e+dkrBedce'e+Z(W n ek
r   ejdXkrrddZ,n&ejd\krdeZ,nejd_krdfZ,n ddYlmZ ejdXkre dgkrej!-dhrdhndiZ.e'ej!%e.e,Z(n
e'e,Z(Y nX Y nX e/e(0 1djdkZ2e23dlr0e2e4dld Z2ddqdrZ5ddsdtZ6ddudvZ7G dwdx dxe8Z9ddydzZ:d{d| Z;dd}d~Z<dddZ=dd Z>G dd de8Z?dddZ@dd ZAdd ZBdd ZCdd ZDdd ZEe(jFfddZGdd ZHdd ZIdd ZJG dd deKZLG dd deLeMZNG dd deNZOdS )ak  python-soundfile is an audio library based on libsndfile, CFFI and NumPy.

Sound files can be read or written directly using the functions
`read()` and `write()`.
To read a sound file in a block-wise fashion, use `blocks()`.
Alternatively, sound files can be opened as `SoundFile` objects.

For further information, see https://python-soundfile.readthedocs.io/.

z0.12.1    N)SEEK_SETSEEK_CURSEEK_END)find_library)ffi                        	      )
title	copyrightZsoftwareZartistcommentdateZalbumlicenseZtracknumberZgenrei   i   i   i   i   i   i   i   i  
 i   i   i   i   i   i   i   i   i   i   i   i   i   i    i  ! i  " i  # )WAVAIFFAURAWPAFSVXNISTVOCIRCAMW64MAT4MAT5PVFXIHTKSDSAVRWAVEXSD2FLACCAFWVEOGGMPC2KRF64MP3             !   "   #   $   0   1   2   @   A   B   C   P   Q   `   d   p   q   r   s            )"ZPCM_S8PCM_16ZPCM_24ZPCM_32ZPCM_U8FLOATDOUBLEZULAWALAWZ	IMA_ADPCMZMS_ADPCMZGSM610Z	VOX_ADPCMZNMS_ADPCM_16ZNMS_ADPCM_24ZNMS_ADPCM_32ZG721_32ZG723_24ZG723_40ZDWVW_12ZDWVW_16ZDWVW_24ZDWVW_NZDPCM_8DPCM_16VORBISZOPUSZALAC_16ZALAC_20ZALAC_24ZALAC_32ZMPEG_LAYER_IZMPEG_LAYER_IIMPEG_LAYER_IIIi   i    i   0)FILEZLITTLEZBIGZCPUrJ   rL   rN   rM   rO   rP   )r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   doublefloatintshort)float64Zfloat32Zint32Zint16darwin)machineZlibsndfile_z.dylibwin32)architecturez.dlllinuxz.soz%no packaged library for this platformZsndfilez8sndfile library not found using ctypes.util.find_libraryzlibsndfile.dylibzlibsndfile.dllzlibsndfile.soarm64z/opt/homebrew/lib/z/usr/local/lib/utf-8replacezlibsndfile-rV   FTc              	   C   sL   t | d||	|||
|&}||||}||||||}W 5 Q R X ||jfS )a  Provide audio data from a sound file as NumPy array.

    By default, the whole file is read from the beginning, but the
    position to start reading can be specified with *start* and the
    number of frames to read can be specified with *frames*.
    Alternatively, a range can be specified with *start* and *stop*.

    If there is less data left in the file than requested, the rest of
    the frames are filled with *fill_value*.
    If no *fill_value* is specified, a smaller array is returned.

    Parameters
    ----------
    file : str or int or file-like object
        The file to read from.  See `SoundFile` for details.
    frames : int, optional
        The number of frames to read. If *frames* is negative, the whole
        rest of the file is read.  Not allowed if *stop* is given.
    start : int, optional
        Where to start reading.  A negative value counts from the end.
    stop : int, optional
        The index after the last frame to be read.  A negative value
        counts from the end.  Not allowed if *frames* is given.
    dtype : {'float64', 'float32', 'int32', 'int16'}, optional
        Data type of the returned array, by default ``'float64'``.
        Floating point audio data is typically in the range from
        ``-1.0`` to ``1.0``.  Integer data is in the range from
        ``-2**15`` to ``2**15-1`` for ``'int16'`` and from ``-2**31`` to
        ``2**31-1`` for ``'int32'``.

        .. note:: Reading int values from a float file will *not*
            scale the data to [-1.0, 1.0). If the file contains
            ``np.array([42.6], dtype='float32')``, you will read
            ``np.array([43], dtype='int32')`` for ``dtype='int32'``.

    Returns
    -------
    audiodata : `numpy.ndarray` or type(out)
        A two-dimensional (frames x channels) NumPy array is returned.
        If the sound file has only one channel, a one-dimensional array
        is returned.  Use ``always_2d=True`` to return a two-dimensional
        array anyway.

        If *out* was specified, it is returned.  If *out* has more
        frames than available in the file (or if *frames* is smaller
        than the length of *out*) and no *fill_value* is given, then
        only a part of *out* is overwritten and a view containing all
        valid frames is returned.
    samplerate : int
        The sample rate of the audio file.

    Other Parameters
    ----------------
    always_2d : bool, optional
        By default, reading a mono sound file will return a
        one-dimensional array.  With ``always_2d=True``, audio data is
        always returned as a two-dimensional array, even if the audio
        file has only one channel.
    fill_value : float, optional
        If more frames are requested than available in the file, the
        rest of the output is be filled with *fill_value*.  If
        *fill_value* is not specified, a smaller array is returned.
    out : `numpy.ndarray` or subclass, optional
        If *out* is specified, the data is written into the given array
        instead of creating a new array.  In this case, the arguments
        *dtype* and *always_2d* are silently ignored!  If *frames* is
        not given, it is obtained from the length of *out*.
    samplerate, channels, format, subtype, endian, closefd
        See `SoundFile`.

    Examples
    --------
    >>> import soundfile as sf
    >>> data, samplerate = sf.read('stereo_file.wav')
    >>> data
    array([[ 0.71329652,  0.06294799],
           [-0.26450912, -0.38874483],
           ...
           [ 0.67398441, -0.11516333]])
    >>> samplerate
    44100

    r)	SoundFile_prepare_readread
samplerate)fileframesstartstopdtype	always_2d
fill_valueoutrd   channelsformatsubtypeendianclosefdfdata rt   J/var/www/html/Darija-Ai-Train/env/lib/python3.8/site-packages/soundfile.pyrc      s    V
   rc   c           
   	   C   s\   ddl }||}|jdkr"d}n
|jd }t| d||||||}	|	| W 5 Q R X dS )a  Write data to a sound file.

    .. note:: If *file* exists, it will be truncated and overwritten!

    Parameters
    ----------
    file : str or int or file-like object
        The file to write to.  See `SoundFile` for details.
    data : array_like
        The data to write.  Usually two-dimensional (frames x channels),
        but one-dimensional *data* can be used for mono files.
        Only the data types ``'float64'``, ``'float32'``, ``'int32'``
        and ``'int16'`` are supported.

        .. note:: The data type of *data* does **not** select the data
                  type of the written file. Audio data will be
                  converted to the given *subtype*. Writing int values
                  to a float file will *not* scale the values to
                  [-1.0, 1.0). If you write the value ``np.array([42],
                  dtype='int32')``, to a ``subtype='FLOAT'`` file, the
                  file will then contain ``np.array([42.],
                  dtype='float32')``.

    samplerate : int
        The sample rate of the audio data.
    subtype : str, optional
        See `default_subtype()` for the default value and
        `available_subtypes()` for all possible values.

    Other Parameters
    ----------------
    format, endian, closefd
        See `SoundFile`.

    Examples
    --------
    Write 10 frames of random data to a new file:

    >>> import numpy as np
    >>> import soundfile as sf
    >>> sf.write('stereo_file.wav', np.random.randn(10, 2), 44100, 'PCM_24')

    r   Nr   w)numpyZasarrayndimshapera   write)
re   rs   rd   ro   rp   rn   rq   nprm   rr   rt   rt   ru   rz   $  s    -



   rz   c              
   c   sV   t | d|
|||||6}||||}||||||||	D ]
}|V  q<W 5 Q R X dS )a8  Return a generator for block-wise reading.

    By default, iteration starts at the beginning and stops at the end
    of the file.  Use *start* to start at a later position and *frames*
    or *stop* to stop earlier.

    If you stop iterating over the generator before it's exhausted,
    the sound file is not closed. This is normally not a problem
    because the file is opened in read-only mode. To close the file
    properly, the generator's ``close()`` method can be called.

    Parameters
    ----------
    file : str or int or file-like object
        The file to read from.  See `SoundFile` for details.
    blocksize : int
        The number of frames to read per block.
        Either this or *out* must be given.
    overlap : int, optional
        The number of frames to rewind between each block.

    Yields
    ------
    `numpy.ndarray` or type(out)
        Blocks of audio data.
        If *out* was given, and the requested frames are not an integer
        multiple of the length of *out*, and no *fill_value* was given,
        the last block will be a smaller view into *out*.

    Other Parameters
    ----------------
    frames, start, stop
        See `read()`.
    dtype : {'float64', 'float32', 'int32', 'int16'}, optional
        See `read()`.
    always_2d, fill_value, out
        See `read()`.
    samplerate, channels, format, subtype, endian, closefd
        See `SoundFile`.

    Examples
    --------
    >>> import soundfile as sf
    >>> for block in sf.blocks('stereo_file.wav', blocksize=1024):
    >>>     pass  # do something with 'block'

    r`   N)ra   rb   blocks)re   	blocksizeoverlaprf   rg   rh   ri   rj   rk   rl   rd   rm   rn   ro   rp   rq   rr   blockrt   rt   ru   r|   \  s    3
   
   r|   c                   @   s,   e Zd ZdZdd Zedd Zdd ZdS )	_SoundFileInfozInformation about a SoundFilec              	   C   s   || _ t|p}|j| _|j| _|j| _|j| _t| j|j | _|j| _|j	| _	|j
| _
|j| _|j| _|j| _|j| _W 5 Q R X d S N)verbosera   namerd   rm   rf   rS   durationrn   ro   rp   format_infosubtype_infosections
extra_info)selfre   r   rr   rt   rt   ru   __init__  s    
z_SoundFileInfo.__init__c                 C   sp   t | jd\}}t |d\}}|dkr6d|||}n6|dkrLd||}n |dkrbd| j}n
d|}|S )Ni  <   r   z{0:.0g}:{1:02.0g}:{2:05.3f} hz{0:02.0g}:{1:05.3f} minz{0:d} samplesz	{0:.3f} s)divmodr   rn   rf   )r   hoursrestminutessecondsr   rt   rt   ru   _duration_str  s    
z_SoundFileInfo._duration_strc                 C   sR   d ddddddg}| jr4|d dd	d
ddg7 }d | jd}|| |S )N
z{0.name}zsamplerate: {0.samplerate} Hzzchannels: {0.channels}zduration: {0._duration_str}z$format: {0.format_info} [{0.format}]z'subtype: {0.subtype_info} [{0.subtype}]z
endian: {0.endian}zsections: {0.sections}zframes: {0.frames}zextra_info: """z
    {1}"""z
    )joinr   r   splitrn   )r   infoZindented_extra_infort   rt   ru   __repr__  s(    z_SoundFileInfo.__repr__N)__name__
__module____qualname____doc__r   propertyr   r   rt   rt   rt   ru   r     s
   
r   c                 C   s
   t | |S )zReturns an object with information about a `SoundFile`.

    Parameters
    ----------
    verbose : bool
        Whether to print additional information.
    )r   )re   r   rt   rt   ru   r     s    r   c                   C   s   t ttjtjS )a  Return a dictionary of available major formats.

    Examples
    --------
    >>> import soundfile as sf
    >>> sf.available_formats()
    {'FLAC': 'FLAC (FLAC Lossless Audio Codec)',
     'OGG': 'OGG (OGG Container format)',
     'WAV': 'WAV (Microsoft)',
     'AIFF': 'AIFF (Apple/SGI)',
     ...
     'WAVEX': 'WAVEX (Microsoft)',
     'RAW': 'RAW (header-less)',
     'MAT5': 'MAT5 (GNU Octave 2.1 / Matlab 5.0)'}

    )dict_available_formats_helper_sndZSFC_GET_FORMAT_MAJOR_COUNTZSFC_GET_FORMAT_MAJORrt   rt   rt   ru   available_formats  s    r   c                    s$   t tjtj}t fdd|D S )ad  Return a dictionary of available subtypes.

    Parameters
    ----------
    format : str
        If given, only compatible subtypes are returned.

    Examples
    --------
    >>> import soundfile as sf
    >>> sf.available_subtypes('FLAC')
    {'PCM_24': 'Signed 24 bit PCM',
     'PCM_16': 'Signed 16 bit PCM',
     'PCM_S8': 'Signed 8 bit PCM'}

    c                 3   s,   | ]$\}} d kst  |r||fV  qd S r   )check_format).0ro   r   rn   rt   ru   	<genexpr>  s     
z%available_subtypes.<locals>.<genexpr>)r   r   ZSFC_GET_FORMAT_SUBTYPE_COUNTZSFC_GET_FORMAT_SUBTYPEr   )rn   subtypesrt   r   ru   available_subtypes  s    r   c              	   C   s2   zt t| ||W S  ttfk
r,   Y dS X dS )zCheck if the combination of format/subtype/endian is valid.

    Examples
    --------
    >>> import soundfile as sf
    >>> sf.check_format('WAV', 'PCM_24')
    True
    >>> sf.check_format('FLAC', 'VORBIS')
    False

    FN)bool_format_int
ValueError	TypeError)rn   ro   rp   rt   rt   ru   r     s    r   c                 C   s   t |  t|  S )zReturn the default subtype for a given format.

    Examples
    --------
    >>> import soundfile as sf
    >>> sf.default_subtype('WAV')
    'PCM_16'
    >>> sf.default_subtype('MAT5')
    'DOUBLE'

    )_check_format_default_subtypesgetupperr   rt   rt   ru   default_subtype  s    r   c                   @   s  e Zd ZdZd_ddZedd Zed	d Zed
d Zedd Z	edd Z
edd Zedd Zedd Zedd Zedd Zedd Zedd Zedd Zedd ZdZdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zefd+d,Z d-d. Z!d`d2d3Z"dad4d5Z#d6d7 Z$d8d9 Z%d:d; Z&dbd=d>Z'dcd?d@Z(dAdB Z)dCdD Z*dEdF Z+dGdH Z,dIdJ Z-dKdL Z.dMdN Z/dOdP Z0dQdR Z1dSdT Z2dUdV Z3dWdX Z4dYdZ Z5d[d\ Z6d]d^ Z7dS )dra   zA sound file.

    For more documentation see the __init__() docstring (which is also
    used for the online documentation (https://python-soundfile.readthedocs.io/).

    r`   NTc	           
      C   s   t |dr| n|}|| _|dkr0t|dd}t|}	|| _t|||||||| _| ||	|| _	t
|dr|  r| d t| j	tjtjtj dS )a{  Open a sound file.

        If a file is opened with `mode` ``'r'`` (the default) or
        ``'r+'``, no sample rate, channels or file format need to be
        given because the information is obtained from the file. An
        exception is the ``'RAW'`` data format, which always requires
        these data points.

        File formats consist of three case-insensitive strings:

        * a *major format* which is by default obtained from the
          extension of the file name (if known) and which can be
          forced with the format argument (e.g. ``format='WAVEX'``).
        * a *subtype*, e.g. ``'PCM_24'``. Most major formats have a
          default subtype which is used if no subtype is specified.
        * an *endian-ness*, which doesn't have to be specified at all in
          most cases.

        A `SoundFile` object is a *context manager*, which means
        if used in a "with" statement, `close()` is automatically
        called when reaching the end of the code block inside the "with"
        statement.

        Parameters
        ----------
        file : str or int or file-like object
            The file to open.  This can be a file name, a file
            descriptor or a Python file object (or a similar object with
            the methods ``read()``/``readinto()``, ``write()``,
            ``seek()`` and ``tell()``).
        mode : {'r', 'r+', 'w', 'w+', 'x', 'x+'}, optional
            Open mode.  Has to begin with one of these three characters:
            ``'r'`` for reading, ``'w'`` for writing (truncates *file*)
            or ``'x'`` for writing (raises an error if *file* already
            exists).  Additionally, it may contain ``'+'`` to open
            *file* for both reading and writing.
            The character ``'b'`` for *binary mode* is implied because
            all sound files have to be opened in this mode.
            If *file* is a file descriptor or a file-like object,
            ``'w'`` doesn't truncate and ``'x'`` doesn't raise an error.
        samplerate : int
            The sample rate of the file.  If `mode` contains ``'r'``,
            this is obtained from the file (except for ``'RAW'`` files).
        channels : int
            The number of channels of the file.
            If `mode` contains ``'r'``, this is obtained from the file
            (except for ``'RAW'`` files).
        subtype : str, sometimes optional
            The subtype of the sound file.  If `mode` contains ``'r'``,
            this is obtained from the file (except for ``'RAW'``
            files), if not, the default value depends on the selected
            `format` (see `default_subtype()`).
            See `available_subtypes()` for all possible subtypes for
            a given `format`.
        endian : {'FILE', 'LITTLE', 'BIG', 'CPU'}, sometimes optional
            The endian-ness of the sound file.  If `mode` contains
            ``'r'``, this is obtained from the file (except for
            ``'RAW'`` files), if not, the default value is ``'FILE'``,
            which is correct in most cases.
        format : str, sometimes optional
            The major format of the sound file.  If `mode` contains
            ``'r'``, this is obtained from the file (except for
            ``'RAW'`` files), if not, the default value is determined
            from the file extension.  See `available_formats()` for
            all possible values.
        closefd : bool, optional
            Whether to close the file descriptor on `close()`. Only
            applicable if the *file* argument is a file descriptor.

        Examples
        --------
        >>> from soundfile import SoundFile

        Open an existing file for reading:

        >>> myfile = SoundFile('existing_file.wav')
        >>> # do something with myfile
        >>> myfile.close()

        Create a new sound file for reading and writing using a with
        statement:

        >>> with SoundFile('new_file.wav', 'x+', 44100, 2) as myfile:
        >>>     # do something with myfile
        >>>     # ...
        >>>     assert not myfile.closed
        >>>     # myfile.close() is called automatically at the end
        >>> assert myfile.closed

        
__fspath__Nmodezr+r   )hasattrr   _namegetattr_check_mode_mode_create_info_struct_info_open_fileset
issupersetseekableseekr   
sf_commandZSFC_SET_CLIPPING_ffiNULLSF_TRUE)
r   re   r   rd   rm   ro   rp   rn   rq   mode_intrt   rt   ru   r   ,  s"    ^
  
zSoundFile.__init__c                 C   s   | j S r   )r   r   rt   rt   ru   <lambda>      zSoundFile.<lambda>c                 C   s   | j S r   )r   r   rt   rt   ru   r     r   c                 C   s   | j jS r   )r   rd   r   rt   rt   ru   r     r   c                 C   s   | j jS r   r   rf   r   rt   rt   ru   r     r   c                 C   s   | j jS r   )r   rm   r   rt   rt   ru   r     r   c                 C   s   t | jjtj@ S r   )_format_strr   rn   r   SF_FORMAT_TYPEMASKr   rt   rt   ru   r     r   c                 C   s   t | jjtj@ S r   )r   r   rn   r   SF_FORMAT_SUBMASKr   rt   rt   ru   r     r   c                 C   s   t | jjtj@ S r   )r   r   rn   r   ZSF_FORMAT_ENDMASKr   rt   rt   ru   r     r   c                 C   s   t | jjtj@ d S Nr   )_format_infor   rn   r   r   r   rt   rt   ru   r     s   c                 C   s   t | jjtj@ d S r   )r   r   rn   r   r   r   rt   rt   ru   r     s   c                 C   s   | j jS r   )r   r   r   rt   rt   ru   r     r   c                 C   s
   | j d kS r   )r   r   rt   rt   ru   r     r   c                 C   s   t | jS r   )r   sf_errorr   r   rt   rt   ru   r     r   c                 C   s8   t dd}t| jtj|t | t |ddS )z8Retrieve the log string generated when opening the file.zchar[]i @  r]   r^   )	r   newr   r   r   ZSFC_GET_LOG_INFOsizeofstringdecode)r   r   rt   rt   ru   r     s     zSoundFile.extra_infoc                 C   s
   d | S )NzSoundFile({0.name!r}, mode={0.mode!r}, samplerate={0.samplerate}, channels={0.channels}, format={0.format!r}, subtype={0.subtype!r}, endian={0.endian!r})r   r   rt   rt   ru   r     s    zSoundFile.__repr__c                 C   s   |    d S r   closer   rt   rt   ru   __del__  s    zSoundFile.__del__c                 C   s   | S r   rt   r   rt   rt   ru   	__enter__  s    zSoundFile.__enter__c                 G   s   |    d S r   r   )r   argsrt   rt   ru   __exit__  s    zSoundFile.__exit__c                 C   sD   |t kr2|   t| jt | | }t| nt| || dS )z:Write text meta-data in the sound file through properties.N)	
_str_types_check_if_closedr   Zsf_set_stringr   encode_error_checkobject__setattr__)r   r   valueerrrt   rt   ru   r     s    
zSoundFile.__setattr__c                 C   sN   |t kr<|   t| jt | }|r8t|ddS dS td	|dS )z9Read text meta-data in the sound file through properties.r]   r^    z)'SoundFile' object has no attribute {0!r}N)
r   r   r   sf_get_stringr   r   r   r   AttributeErrorrn   )r   r   rs   rt   rt   ru   __getattr__  s    zSoundFile.__getattr__c                 C   s   | j jS r   r   r   rt   rt   ru   __len__  s    zSoundFile.__len__c                 C   s   dS )NTrt   r   rt   rt   ru   __bool__  s    zSoundFile.__bool__c                 C   s   |   S r   )r   r   rt   rt   ru   __nonzero__  s    zSoundFile.__nonzero__c                 C   s   | j jtjkS )z)Return True if the file supports seeking.)r   r   r   r   r   rt   rt   ru   r     s    zSoundFile.seekablec                 C   s&   |    t| j||}t| j |S )a  Set the read/write position.

        Parameters
        ----------
        frames : int
            The frame index or offset to seek.
        whence : {SEEK_SET, SEEK_CUR, SEEK_END}, optional
            By default (``whence=SEEK_SET``), *frames* are counted from
            the beginning of the file.
            ``whence=SEEK_CUR`` seeks from the current position
            (positive and negative values are allowed for *frames*).
            ``whence=SEEK_END`` seeks from the end (use negative value
            for *frames*).

        Returns
        -------
        int
            The new absolute read/write position in frames.

        Examples
        --------
        >>> from soundfile import SoundFile, SEEK_END
        >>> myfile = SoundFile('stereo_file.wav')

        Seek to the beginning of the file:

        >>> myfile.seek(0)
        0

        Seek to the end of the file:

        >>> myfile.seek(0, SEEK_END)
        44100  # this is the file length

        )r   r   Zsf_seekr   r   
_errorcode)r   rf   whencepositionrt   rt   ru   r     s    $
zSoundFile.seekc                 C   s   |  dtS )z'Return the current read/write position.r   )r   r   r   rt   rt   ru   tell%  s    zSoundFile.tellr_   rV   Fc                 C   s   |dkr$|  ||}| |||}n|dk s8|t|kr@t|}| d||}t||kr||dkrp|d| }n|||d< |S )a  Read from the file and return data as NumPy array.

        Reads the given number of frames in the given data format
        starting at the current read/write position.  This advances the
        read/write position by the same number of frames.
        By default, all frames from the current read/write position to
        the end of the file are returned.
        Use `seek()` to move the current read/write position.

        Parameters
        ----------
        frames : int, optional
            The number of frames to read. If ``frames < 0``, the whole
            rest of the file is read.
        dtype : {'float64', 'float32', 'int32', 'int16'}, optional
            Data type of the returned array, by default ``'float64'``.
            Floating point audio data is typically in the range from
            ``-1.0`` to ``1.0``. Integer data is in the range from
            ``-2**15`` to ``2**15-1`` for ``'int16'`` and from
            ``-2**31`` to ``2**31-1`` for ``'int32'``.

            .. note:: Reading int values from a float file will *not*
                scale the data to [-1.0, 1.0). If the file contains
                ``np.array([42.6], dtype='float32')``, you will read
                ``np.array([43], dtype='int32')`` for
                ``dtype='int32'``.

        Returns
        -------
        audiodata : `numpy.ndarray` or type(out)
            A two-dimensional NumPy (frames x channels) array is
            returned. If the sound file has only one channel, a
            one-dimensional array is returned. Use ``always_2d=True``
            to return a two-dimensional array anyway.

            If *out* was specified, it is returned. If *out* has more
            frames than available in the file (or if *frames* is
            smaller than the length of *out*) and no *fill_value* is
            given, then only a part of *out* is overwritten and a view
            containing all valid frames is returned.

        Other Parameters
        ----------------
        always_2d : bool, optional
            By default, reading a mono sound file will return a
            one-dimensional array. With ``always_2d=True``, audio data
            is always returned as a two-dimensional array, even if the
            audio file has only one channel.
        fill_value : float, optional
            If more frames are requested than available in the file,
            the rest of the output is be filled with *fill_value*. If
            *fill_value* is not specified, a smaller array is
            returned.
        out : `numpy.ndarray` or subclass, optional
            If *out* is specified, the data is written into the given
            array instead of creating a new array. In this case, the
            arguments *dtype* and *always_2d* are silently ignored! If
            *frames* is not given, it is obtained from the length of
            *out*.

        Examples
        --------
        >>> from soundfile import SoundFile
        >>> myfile = SoundFile('stereo_file.wav')

        Reading 3 frames from a stereo file:

        >>> myfile.read(3)
        array([[ 0.71329652,  0.06294799],
               [-0.26450912, -0.38874483],
               [ 0.67398441, -0.11516333]])
        >>> myfile.close()

        See Also
        --------
        buffer_read, .write

        Nr   rc   )_check_frames_create_empty_arraylen	_array_io)r   rf   ri   rj   rk   rl   rt   rt   ru   rc   )  s    PzSoundFile.readc                 C   sT   | j |dd}| |}t|d || j }| d|||}||ksJtt|S )a  Read from the file and return data as buffer object.

        Reads the given number of *frames* in the given data format
        starting at the current read/write position.  This advances the
        read/write position by the same number of frames.
        By default, all frames from the current read/write position to
        the end of the file are returned.
        Use `seek()` to move the current read/write position.

        Parameters
        ----------
        frames : int, optional
            The number of frames to read. If ``frames < 0``, the whole
            rest of the file is read.
        dtype : {'float64', 'float32', 'int32', 'int16'}
            Audio data will be converted to the given data type.

        Returns
        -------
        buffer
            A buffer containing the read data.

        See Also
        --------
        buffer_read_into, .read, buffer_write

        N)rk   z[]rc   )r   _check_dtyper   r   rm   	_cdata_ioAssertionErrorbuffer)r   rf   ri   ctypecdataZread_framesrt   rt   ru   buffer_read  s    
zSoundFile.buffer_readc                 C   s.   |  |}| ||\}}| d|||}|S )a  Read from the file into a given buffer object.

        Fills the given *buffer* with frames in the given data format
        starting at the current read/write position (which can be
        changed with `seek()`) until the buffer is full or the end
        of the file is reached.  This advances the read/write position
        by the number of frames that were read.

        Parameters
        ----------
        buffer : writable buffer
            Audio frames from the file are written to this buffer.
        dtype : {'float64', 'float32', 'int32', 'int16'}
            The data type of *buffer*.

        Returns
        -------
        int
            The number of frames that were read from the file.
            This can be less than the size of *buffer*.
            The rest of the buffer is not filled with meaningful data.

        See Also
        --------
        buffer_read, .read

        rc   )r   _check_bufferr   )r   r   ri   r   r   rf   rt   rt   ru   buffer_read_into  s    
zSoundFile.buffer_read_intoc                 C   sB   ddl }||}| d|t|}|t|ks4t| | dS )a  Write audio data from a NumPy array to the file.

        Writes a number of frames at the read/write position to the
        file. This also advances the read/write position by the same
        number of frames and enlarges the file if necessary.

        Note that writing int values to a float file will *not* scale
        the values to [-1.0, 1.0). If you write the value
        ``np.array([42], dtype='int32')``, to a ``subtype='FLOAT'``
        file, the file will then contain ``np.array([42.],
        dtype='float32')``.

        Parameters
        ----------
        data : array_like
            The data to write. Usually two-dimensional (frames x
            channels), but one-dimensional *data* can be used for mono
            files. Only the data types ``'float64'``, ``'float32'``,
            ``'int32'`` and ``'int16'`` are supported.

            .. note:: The data type of *data* does **not** select the
                  data type of the written file. Audio data will be
                  converted to the given *subtype*. Writing int values
                  to a float file will *not* scale the values to
                  [-1.0, 1.0). If you write the value ``np.array([42],
                  dtype='int32')``, to a ``subtype='FLOAT'`` file, the
                  file will then contain ``np.array([42.],
                  dtype='float32')``.

        Examples
        --------
        >>> import numpy as np
        >>> from soundfile import SoundFile
        >>> myfile = SoundFile('stereo_file.wav')

        Write 10 frames of random data to a new file:

        >>> with SoundFile('stereo_file.wav', 'w', 44100, 2, 'PCM_24') as f:
        >>>     f.write(np.random.randn(10, 2))

        See Also
        --------
        buffer_write, .read

        r   Nrz   )rw   Zascontiguousarrayr   r   r   _update_frames)r   rs   r{   writtenrt   rt   ru   rz     s
    .
zSoundFile.writec                 C   sD   |  |}| ||\}}| d|||}||ks6t| | dS )a  Write audio data from a buffer/bytes object to the file.

        Writes the contents of *data* to the file at the current
        read/write position.
        This also advances the read/write position by the number of
        frames that were written and enlarges the file if necessary.

        Parameters
        ----------
        data : buffer or bytes
            A buffer or bytes object containing the audio data to be
            written.
        dtype : {'float64', 'float32', 'int32', 'int16'}
            The data type of the audio data stored in *data*.

        See Also
        --------
        .write, buffer_read

        rz   N)r   r   r   r   r   )r   rs   ri   r   r   rf   r   rt   rt   ru   buffer_write   s
    
zSoundFile.buffer_writer   c              	   c   s\  ddl }d| jkr$d| jkr$td|dkrP|dkr<td| |||}d}	n|dk	r`tdt|}d	}	d}
| ||}|dkrX|
dkrd}nt|
}|
|d|< t|| |}| ||||||d  |r
|
dkr|	|| d }
n|| d |
dd< ||| kr4|dkr4|d||  }n|}|	rH|	|n|V  ||8 }q|dS )
a  Return a generator for block-wise reading.

        By default, the generator yields blocks of the given
        *blocksize* (using a given *overlap*) until the end of the file
        is reached; *frames* can be used to stop earlier.

        Parameters
        ----------
        blocksize : int
            The number of frames to read per block. Either this or *out*
            must be given.
        overlap : int, optional
            The number of frames to rewind between each block.
        frames : int, optional
            The number of frames to read.
            If ``frames < 0``, the file is read until the end.
        dtype : {'float64', 'float32', 'int32', 'int16'}, optional
            See `read()`.

        Yields
        ------
        `numpy.ndarray` or type(out)
            Blocks of audio data.
            If *out* was given, and the requested frames are not an
            integer multiple of the length of *out*, and no
            *fill_value* was given, the last block will be a smaller
            view into *out*.


        Other Parameters
        ----------------
        always_2d, fill_value, out
            See `read()`.
        fill_value : float, optional
            See `read()`.
        out : `numpy.ndarray` or subclass, optional
            If *out* is specified, the data is written into the given
            array instead of creating a new array. In this case, the
            arguments *dtype* and *always_2d* are silently ignored!

        Examples
        --------
        >>> from soundfile import SoundFile
        >>> with SoundFile('stereo_file.wav') as f:
        >>>     for block in f.blocks(blocksize=1024):
        >>>         pass  # do something with 'block'

        r   Nr`   +z*blocks() is not allowed in write-only modez)One of {blocksize, out} must be specifiedTz-Only one of {blocksize, out} may be specifiedF)
rw   r   SoundFileRuntimeErrorr   r   r   r   minrc   copy)r   r}   r~   rf   ri   rj   rk   rl   r{   Zcopy_outZoverlap_memoryZoutput_offsetZtoreadr   rt   rt   ru   r|     s@    2
zSoundFile.blocksc                 C   sX   |dkr|   }t| jtjtd|td}|rLt| j}t	|d|| j
_dS )an  Truncate the file to a given number of frames.

        After this command, the read/write position will be at the new
        end of the file.

        Parameters
        ----------
        frames : int, optional
            Only the data before *frames* is kept, the rest is deleted.
            If not specified, the current read/write position is used.

        Nzsf_count_t*Z
sf_count_tzError truncating the file)r   r   r   r   ZSFC_FILE_TRUNCATEr   r   r   r   LibsndfileErrorr   rf   )r   rf   r   rt   rt   ru   truncatew  s    

zSoundFile.truncatec                 C   s   |    t| j dS )aj  Write unwritten data to the file system.

        Data written with `write()` is not immediately written to
        the file system but buffered in memory to be written at a later
        time.  Calling `flush()` makes sure that all changes are
        actually written to the file system.

        This has no effect on files opened in read-only mode.

        N)r   r   Zsf_write_syncr   r   rt   rt   ru   flush  s    zSoundFile.flushc                 C   s,   | j s(|   t| j}d| _t| dS )z.Close the file.  Can be called multiple times.N)closedr   r   Zsf_closer   r   )r   r   rt   rt   ru   r     s
    zSoundFile.closec                 C   s6  t |ttfrtj|r`d| jkr6td| j	n*t
| jdr`tt|tjtjB  tj}t |trtjdkrtj}n|t }|||| j}nTt |trt||| j|}n6t||rt| ||| jtj}ntd| j	|tjkrt |}t!|d| j	d|tj"kr2d| j_#|S )	z9Call the appropriate sf_open*() function from libsndfile.xzFile exists: {0!r}zw+rY   zInvalid file: {0!r}zError opening {0!r}: prefixr   )$
isinstance_unicodebytes_ospathisfiler   OSErrorrn   r   r   r   r   openO_WRONLYO_TRUNCr   Zsf_open_sysplatformZsf_wchar_openr   getfilesystemencodingr   rT   Z
sf_open_fd_has_virtual_io_attrsZsf_open_virtual_init_virtual_ior   r   r   r   r   	SFM_WRITErf   )r   re   r   rq   ZopenfunctionZfile_ptrr   rt   rt   ru   r     s6    




  
zSoundFile._openc                    s   t d fdd}t d fdd}t d fdd	}t d
 fdd}t d fdd}|||||d| _t d| jS )z4Initialize callback functions for sf_open_virtual().Zsf_vio_get_filelenc                    s,      } dt    } |t |S Nr   )r   r   r   r   )	user_datacurrsizere   rt   ru   vio_get_filelen  s
    z3SoundFile._init_virtual_io.<locals>.vio_get_filelenZsf_vio_seekc                    s     | |   S r   )r   r   )offsetr   r  r  rt   ru   vio_seek  s    z,SoundFile._init_virtual_io.<locals>.vio_seekZsf_vio_readc                    s^   zt | |} |}W n> tk
rX    |}t|}t | |}||d|< Y nX |S r  )r   r   readintor   rc   r   )ptrcountr  bufZ	data_readrs   r  rt   ru   vio_read  s    
z,SoundFile._init_virtual_io.<locals>.vio_readZsf_vio_writec                    s2   t | |}|d d  } |}|d kr.|}|S r   )r   r   rz   )r  r  r  r   rs   r   r  rt   ru   	vio_write  s    
z-SoundFile._init_virtual_io.<locals>.vio_writeZsf_vio_tellc                    s      S r   )r   )r  r  rt   ru   vio_tell  s    z,SoundFile._init_virtual_io.<locals>.vio_tell)Zget_filelenr   rc   rz   r   zSF_VIRTUAL_IO*)r   callbackZ_virtual_ior   )r   re   r  r  r!  r"  r#  rt   r  ru   r    s"    	zSoundFile._init_virtual_ioc                 C   s   t S )zReturn all attributes used in __setattr__ and __getattr__.

        This is useful for auto-completion (e.g. IPython).

        )r   r   rt   rt   ru   _getAttributeNames  s    zSoundFile._getAttributeNamesc                 C   s   | j rtddS )zCheck if the file is closed and raise an error if it is.

        This should be used in every method that uses self._file.

        zI/O operation on closed fileN)r  r   r   rt   rt   ru   r     s    zSoundFile._check_if_closedc                 C   sH   |   r4| j|   }|dk s.||krD|dkrD|}n|dk rDtd|S )z8Reduce frames to no more than are available in the file.r   Nz/frames must be specified for non-seekable files)r   rf   r   r   )r   rf   rk   Zremaining_framesrt   rt   ru   r     s    zSoundFile._check_framesc                 C   sV   |t  kstt|ts$t|}tt|| j	t
| \}}|rNtd||fS )z1Convert buffer to cdata and check for valid size.z*Data size must be a multiple of frame size)
_ffi_typesvaluesr   r  r  r   Zfrom_bufferr   r   rm   r   r   )r   rs   r   rf   	remainderrt   rt   ru   r     s    

zSoundFile._check_bufferc                 C   s8   ddl }|s| jdkr"|| jf}n|f}|j||ddS )z-Create an empty array with appropriate shape.r   Nr   C)order)rw   rm   empty)r   rf   rj   ri   r{   ry   rt   rt   ru   r   $  s
    zSoundFile._create_empty_arrayc              	   C   s<   z
t | W S  tk
r6   tdtt  |Y nX dS )z7Check if dtype string is valid and return ctype string.z(dtype must be one of {0!r} and not {1!r}N)r&  KeyErrorr   rn   sortedkeys)r   ri   rt   rt   ru   r   -  s    

 zSoundFile._check_dtypec                 C   s   |j dks8|j dkr| jdks8|j dkrH|jd | jkrHtd|j|jjsXtd| |jj	}|jj
t|ks|tt|d |jd d }| ||||S )	z+Check array and call low-level IO function.)r   r   r   r   zInvalid shape: {0!r}zData must be C-contiguous*rs   r   )rx   rm   ry   r   rn   flagsc_contiguousr   ri   r   itemsizer   r   r   castZ__array_interface__r   )r   actionarrayrf   r   r   rt   rt   ru   r   5  s     
zSoundFile._array_ioc                 C   sr   |t  kst|   |  r(|  }ttd| d | }|| j||}t	| j
 |  rn| || t |S )z.Call one of libsndfile's read/write functions.Zsf_Zf_)r&  r'  r   r   r   r   r   r   r   r   r   r   r   )r   r4  rs   r   rf   r  funcrt   rt   ru   r   B  s    
zSoundFile._cdata_ioc                 C   sB   |   r.|  }| dt| j_| |t n| j j|7  _dS )z!Update self.frames after writing.r   N)r   r   r   r   r   rf   r   )r   r   r  rt   rt   ru   r   O  s
    zSoundFile._update_framesc                 C   s|   |dkr|   std|dkr0|dk	r0tdt||| j\}}}||k rT|}|dk rd|| }|   rx| |t |S )z)Seek to start frame and calculate length.r   z(start is only allowed for seekable filesNz&Only one of {frames, stop} may be used)r   r   r   sliceindicesrf   r   r   )r   rg   rh   rf   _rt   rt   ru   rb   X  s    zSoundFile._prepare_readc                 C   sB   i }t  D ]0\}}t| j|}|rt|dd||< q|S )a5  Get all metadata present in this SoundFile

        Returns
        -------

        metadata: dict[str, str]
            A dict with all metadata. Possible keys are: 'title', 'copyright',
            'software', 'artist', 'comment', 'date', 'album', 'license',
            'tracknumber' and 'genre'.
        r]   r^   )r   itemsr   r   r   r   r   r   )r   strsZstrtypeZstridrs   rt   rt   ru   copy_metadatah  s    zSoundFile.copy_metadata)r`   NNNNNT)r_   rV   FNN)r_   N)Nr   r_   rV   FNN)N)8r   r   r   r   r   r   r   r   rd   rf   rm   rn   ro   rp   r   r   r   r  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rc   r   r   rz   r   r|   r   r   r   r   r  r%  r   r   r   r   r   r   r   r   rb   r<  rt   rt   rt   ru   ra   $  s           
m


)    
^
#!5      
\
	$3			ra   r   c                 C   s   | dkrt | |ddS )z+Raise LibsndfileError if there is an error.r   r  N)r   )r   r  rt   rt   ru   r   |  s    r   c                 C   s  t | }|dkr0t| }|dkrLtd| nt|ttfsLtd|z|t|  O }W n" t	k
r   t
d|Y nX |dkrd}nt|ttfstd|z|t|  O }W n" t	k
r   t
d|Y nX td}||_d	|_t|tjkrt
d
|S )z8Return numeric ID for given format|subtype|endian combo.Nz)No default subtype for major format {0!r}zInvalid subtype: {0!r}zUnknown subtype: {0!r}rQ   zInvalid endian-ness: {0!r}zUnknown endian-ness: {0!r}SF_INFO*r   z1Invalid combination of format, subtype and endian)r   r   r   rn   r  r  str	_subtypesr   r,  r   _endiansr   r   rm   r   Zsf_format_checkZSF_FALSE)rn   ro   rp   resultr   rt   rt   ru   r     s:    
r   c                 C   s   t | ttfstd| t| }|ds>t| t|krLtd| t|	ddkrftdd|krvt
j}nd|krt
j}nt
j}|S )z=Check if mode is valid and return its integer representation.zInvalid mode: {0!r}zxrwb+Zxrwr   z&mode must contain exactly one of 'xrw'r   r`   )r  r  r>  r   rn   r   
differencer   r   intersectionr   ZSFM_RDWRSFM_READr  )r   Zmode_setr   rt   rt   ru   r     s    r   c           	      C   s   |}|dkr*t | |}t|ttfs2tnt| td}d|ksP| dkr|dkr`t	d||_
|dkrvt	d||_t||||_n$tdd |||||fD rt	d	|S )
z*Check arguments and create SF_INFO struct.Nr=  r`   r   zsamplerate must be specifiedzchannels must be specifiedc                 s   s   | ]}|d k	V  qd S r   rt   )r   argrt   rt   ru   r     s     z&_create_info_struct.<locals>.<genexpr>z\Not allowed for existing files (except 'RAW'): samplerate, channels, format, subtype, endian)_get_format_from_filenamer  r  r>  r   r   r   r   r   r   rd   rm   r   rn   any)	re   r   rd   rm   rn   ro   rp   Zoriginal_formatr   rt   rt   ru   r     s.    

    
r   c                 C   st   d}t | d| } z(tj| d dd }|dd}W n tk
rL   Y nX | tkrpd|krptd		| |S )
a  Return a format string obtained from file (or file.name).

    If file already exists (= read mode), an empty string is returned on
    error.  If not, an exception is raised.
    The return type will always be str or unicode (even if
    file/file.name is a bytes object).

    r   r   r_   r   Nr]   r^   r`   zGNo format specified and unable to get format from file extension: {0!r})
r   r  r	  splitextr   	Exceptionr   _formatsr   rn   )re   r   rn   rt   rt   ru   rF    s    	rF  c                 C   s:   t ttfD ]*}| D ]\}}|| kr|    S qq
dS )z;Return the string representation of a given numeric format.zn/aN)rJ  r?  r@  r:  )
format_int
dictionarykvrt   rt   ru   r     s
    r   c                 C   sR   t d}| |_tt j||t d |j}t|j|rLt 	|
ddndfS )z6Return the ID and short description of a given format.zSF_FORMAT_INFO*ZSF_FORMAT_INFOr]   r^   r   )r   r   rn   r   r   r   r   r   r   r   r   )rK  format_flagr   r   rt   rt   ru   r     s    
r   c                 c   sD   t d}tt j| |t d t|d D ]}t||V  q.dS )z8Helper for available_formats() and available_subtypes().zint*rT   r   N)r   r   r   r   r   r   ranger   )Z
count_flagrO  r  rK  rt   rt   ru   r     s    
r   c                 C   sT   t | ttfstd| zt|   }W n" tk
rN   td| Y nX |S )z4Check if `format_str` is valid and return format ID.zInvalid format: {0!r}zUnknown format: {0!r})	r  r  r>  r   rn   rJ  r   r,  r   )
format_strrK  rt   rt   ru   r     s    r   c                 C   sN   |t jk}|t jk}tt| dt| dt| dp2|t| dpHt| dpH|gS )z>Check if file has all the necessary attributes for virtual IO.r   r   rz   rc   r  )r   rD  r  allr   )re   r   readonlyZ	writeonlyrt   rt   ru   r    s    

r  c                   @   s   e Zd ZdZdS )SoundFileErrorz-Base class for all soundfile-specific errors.Nr   r   r   r   rt   rt   rt   ru   rT    s   rT  c                   @   s   e Zd ZdZdS )r   zKsoundfile module runtime error.

    Errors that used to be `RuntimeError`.NrU  rt   rt   rt   ru   r      s   r   c                   @   s.   e Zd ZdZd
ddZedd Zdd Zd	S )r   zjlibsndfile errors.


    Attributes
    ----------
    code
        libsndfile internal error number.
    r   c                 C   s   t | || || _|| _d S r   )r   r   coder  )r   rV  r  rt   rt   ru   r   /  s    zLibsndfileError.__init__c                 C   s,   | j r$t| j }t|ddS dS dS )zRaw libsndfile error message.r]   r^   z'(Garbled error message from libsndfile)N)rV  r   Zsf_error_numberr   r   r   )r   Zerr_strrt   rt   ru   error_string4  s    zLibsndfileError.error_stringc                 C   s   | j | j S r   )r  rW  r   rt   rt   ru   __str__@  s    zLibsndfileError.__str__N)r   )r   r   r   r   r   r   rW  rX  rt   rt   rt   ru   r   &  s
   

r   )r_   r   NrV   FNNNNNNNT)NNNT)Nr   r_   r   NrV   FNNNNNNNT)F)N)NN)r   )Pr   __version__osr  sysr  r   r   r   ctypes.utilr   Z_find_libraryZ
_soundfiler   r   unicoder  	NameErrorr>  r   rJ  r?  r@  r   r&  r  rX   Z_machineZ_packaged_libnamerZ   Z_architecturer  Z_soundfile_datar	  dirname__file___pathr   Z
_full_pathZdlopenr   ImportErrorr   Z_libnameZ_explicit_libnameisdirZ_hbrew_pathr   Zsf_version_stringr   Z__libsndfile_version__
startswithr   rc   rz   r|   r   r   r   r   r   r   r   ra   r   r   r   r   rF  r   ZSFC_GET_FORMAT_INFOr   r   r   r  rI  rT  RuntimeErrorr   r   rt   rt   rt   ru   <module>   s  

&	
               
]  
8                  
;4


      ^
 
