U
    Z$d9                     @   sl   d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZG dd de	Z
dd Zdd ZdS )    Nc                   @   sJ   e Zd ZdZdd ZdddZdddZdd	d
ZdddZdddZ	dS )	AudioDataa  
    Creates a new ``AudioData`` instance, which represents mono audio data.

    The raw audio data is specified by ``frame_data``, which is a sequence of bytes representing audio samples. This is the frame data structure used by the PCM WAV format.

    The width of each sample, in bytes, is specified by ``sample_width``. Each group of ``sample_width`` bytes represents a single audio sample.

    The audio data is assumed to have a sample rate of ``sample_rate`` samples per second (Hertz).

    Usually, instances of this class are obtained from ``recognizer_instance.record`` or ``recognizer_instance.listen``, or in the callback for ``recognizer_instance.listen_in_background``, rather than instantiating them directly.
    c                 C   sT   |dkst d|d dkr2d|  kr0dks:n t d|| _|| _t|| _d S )Nr   z&Sample rate must be a positive integer      z.Sample width must be between 1 and 4 inclusive)AssertionError
frame_datasample_rateintsample_width)selfr   r   r	    r   </tmp/pip-unpacked-wheel-4babgm0a/speech_recognition/audio.py__init__   s    
 
zAudioData.__init__Nc                 C   s   |dks|dkst d|dks<||dkr.dn|ks<t d|dkrJd}nt|| j | j d }|dkrvt| j}nt|| j | j d }t| j|| | j| jS )ag  
        Returns a new ``AudioData`` instance, trimmed to a given time interval. In other words, an ``AudioData`` instance with the same audio data except starting at ``start_ms`` milliseconds in and ending ``end_ms`` milliseconds in.

        If not specified, ``start_ms`` defaults to the beginning of the audio, and ``end_ms`` defaults to the end.
        Nr   z*``start_ms`` must be a non-negative numberzI``end_ms`` must be a non-negative number greater or equal to ``start_ms``i  )r   r   r   r	   lenr   r   )r
   Zstart_msZend_msZ
start_byteZend_byter   r   r   get_segment"   s4    
zAudioData.get_segmentc              
      sT  |dks|dkst d|dksJ|d dkrBd|  kr@dksJn t d| j | jdkrht dd |dk	r| j|krt | jd| j|d\ }|dk	r8| j|kr8|dkr(t | jd ztd	dd W n< tjk
r   d		 fd
dt
dt dD  Y nX t | j| nt | j| |dkrPt dd  S )a)  
        Returns a byte string representing the raw frame data for the audio represented by the ``AudioData`` instance.

        If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is resampled to match.

        If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting audio is converted to match.

        Writing these bytes directly to a file results in a valid `RAW/PCM audio file <https://en.wikipedia.org/wiki/Raw_audio_format>`__.
        Nr   z4Sample rate to convert to must be a positive integerr   r   z<Sample width to convert to must be between 1 and 4 inclusivei       c                 3   s"   | ]} |d  |d  V  qdS )r   r   Nr   .0iraw_datar   r   	<genexpr>s   s   z)AudioData.get_raw_data.<locals>.<genexpr>   )r   r   r	   audioopZbiasr   ZratecvZlin2linerrorjoinranger   )r
   convert_rateconvert_width_r   r   r   get_raw_data@   s    
 

  
        
  zAudioData.get_raw_datac           	   	   C   s   |  ||}|dkr| jn|}|dkr,| jn|}t R}t|d}z4|| |	| |
d || | }W 5 |  X W 5 Q R X |S )a!  
        Returns a byte string representing the contents of a WAV file containing the audio represented by the ``AudioData`` instance.

        If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting audio is converted to match.

        If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is resampled to match.

        Writing these bytes directly to a file results in a valid `WAV file <https://en.wikipedia.org/wiki/WAV>`__.
        Nwbr   )r    r   r	   ioBytesIOwaveopenclosesetframeratesetsampwidthsetnchannelswriteframesgetvalue)	r
   r   r   r   r   r	   Zwav_fileZ
wav_writerwav_datar   r   r   get_wav_data   s    





zAudioData.get_wav_datac              	      s   |  || |dkr| jn|}|dkr,| jn|ttdrHt  n< d dd d fddtd t D   t	
 R}t|d}z4|| | |d |  | }W 5 |  X W 5 Q R X |S )	aB  
        Returns a byte string representing the contents of an AIFF-C file containing the audio represented by the ``AudioData`` instance.

        If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting audio is converted to match.

        If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is resampled to match.

        Writing these bytes directly to a file results in a valid `AIFF-C file <https://en.wikipedia.org/wiki/Audio_Interchange_File_Format>`__.
        Nbyteswapr   r   c                 3   s    | ]} | |d  V  qdS )r/   Nr   r   r   r	   r   r   r      s   z*AudioData.get_aiff_data.<locals>.<genexpr>r!   )r    r   r	   hasattrr   r.   r   r   r   r"   r#   aifcr%   r&   r'   r(   r)   r*   r+   )r
   r   r   r   Z	aiff_fileZaiff_writerZ	aiff_datar   r0   r   get_aiff_data   s.    
  





zAudioData.get_aiff_datac           	      C   s   |dks2|d dkr*d|  kr(dks2n t d| jdkrH|dkrHd}| ||}t }tjdkrt }| jtj	O  _tj
|_nd}tj|ddd	d
gtjtj|d}||\}}|S )a  
        Returns a byte string representing the contents of a FLAC file containing the audio represented by the ``AudioData`` instance.

        Note that 32-bit FLAC is not supported. If the audio data is 32-bit and ``convert_width`` is not specified, then the resulting FLAC will be a 24-bit FLAC.

        If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is resampled to match.

        If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting audio is converted to match.

        Writing these bytes directly to a file results in a valid `FLAC file <https://en.wikipedia.org/wiki/FLAC>`__.
        Nr   r   r   z<Sample width to convert to must be between 1 and 3 inclusiventz--stdoutz--totally-silentz--best-)stdinstdoutstartupinfo)r   r	   r-   get_flac_converterosname
subprocessZSTARTUPINFOZdwFlagsZSTARTF_USESHOWWINDOWZSW_HIDEZwShowWindowPopenPIPEcommunicate)	r
   r   r   r,   flac_converterZstartup_infoprocessZ	flac_datastderrr   r   r   get_flac_data   sN    
 
zAudioData.get_flac_data)NN)NN)NN)NN)NN)
__name__
__module____qualname____doc__r   r   r    r-   r3   rC   r   r   r   r   r      s   	

H

*r   c                  C   s8  t d} | dkrtjtjt}t t  }}|dkrV|dkrVtj	|d} nh|dkrv|dkrvtj	|d} nH|dkr|d	krtj	|d
} n(|dkr|dkrtj	|d} nt
dz^t| tjst| }t| |jtjB  dt krtjdkrt ntd W n t
k
r2   Y nX | S )zdReturns the absolute path of a FLAC converter executable, or raises an OSError if none can be found.ZflacNWindows>   AMD64i686i786x86_64x86zflac-win32.exeDarwinzflac-macLinux>   rM   rJ   rK   zflac-linux-x86>   rL   rI   zflac-linux-x86_64zFLAC conversion utility not available - consider installing the FLAC command line application by running `apt-get install flac` or your operating system's equivalent)r   r   sync)shutil_whichr:   pathdirnameabspath__file__platformsystemmachiner   OSErroraccessX_OKstatchmodst_modeS_IEXECsysversion_inforP   )r@   	base_pathrW   rX   	stat_infor   r   r   r9     s4    

"r9   c                 C   sR   t d}|t jjD ]4}t j|| }t j|rt |t jr|  S qdS )zDPython 2 compatibility: backport of ``shutil.which()`` from Python 3PATHN)	r:   getenvsplitrR   pathsepr   existsrZ   r[   )ZpgmrR   pr   r   r   rQ   7  s
    
rQ   )r2   r   r"   r:   rV   r\   r<   r`   r$   objectr   r9   rQ   r   r   r   r   <module>   s    z2