


import os
from dataclasses import dataclass, field
from io import BytesIO
from typing import TYPE_CHECKING, Any, ClassVar, Dict, Optional, Union

import numpy as np
import pyarrow as pa

from .. import config
from ..download.streaming_download_manager import xopen, xsplitext
from ..table import array_cast
from ..utils.py_utils import no_op_if_value_is_null, string_to_dict


if TYPE_CHECKING:
    from .features import FeatureType


__snake_case							,	__snake_case							,	__snake_case   							=						False, False, False



@dataclass
class 	__lowerCamelCase			:
       _lowercase											=     None
       _lowercase											=     True
       _lowercase											=     True
       _lowercase											=     None
       # Automatically constructed
       _lowercase											=     "dict"
       _lowercase											=     pa.struct({"""bytes""": pa.binary(), """path""": pa.string()}						)
       _lowercase											=     field(default="""Audio"""				,      init=_a				,      repr=_a						)







       def __call__(			self: Optional[int]					):






            '''simple docstring'''




            return self.pa_type







       def 		snake_case_	(			self: Tuple,A_: Union[str, bytes, dict]					):






            '''simple docstring'''




            try:
                 import soundfile as sf  # soundfile is a dependency of librosa, needed to decode audio files.
            except ImportError as err:
                 raise ImportError('To support encoding audio data, please install \'soundfile\'.'					) from err
            if isinstance(A_,A_					):
                 return {"bytes": None, "path": value}
            elif isinstance(A_,A_					):
                 return {"bytes": value, "path": None}
            elif "array" in value:
                 # convert the audio array to wav bytes
                 __UpperCamelCase =			BytesIO()
                 sf.write(A_,value['array'],value['sampling_rate'],format='wav'					)
                 return {"bytes": buffer.getvalue(), "path": None}
            elif value.get('path'					) is not None and os.path.isfile(value['path']					):
                 # we set "bytes": None to not duplicate the data if they're already available locally
                 if value["path"].endswith('pcm'					):
                      # "PCM" only has raw audio bytes
                      if value.get('sampling_rate'					) is None:
                           # At least, If you want to convert "PCM-byte" to "WAV-byte", you have to know sampling rate
                           raise KeyError('To use PCM files, please specify a \'sampling_rate\' in Audio object'					)
                      if value.get('bytes'					):
                           # If we already had PCM-byte, we don`t have to make "read file, make bytes" (just use it!)
                           __UpperCamelCase =			np.frombuffer(value['bytes'],dtype=np.intaa					).astype(np.floataa					) / 3_2767
                      else:
                           __UpperCamelCase =			np.memmap(value['path'],dtype='h',mode='r'					).astype(np.floataa					) / 3_2767

                      __UpperCamelCase =			BytesIO(bytes()					)
                      sf.write(A_,A_,value['sampling_rate'],format='wav'					)
                      return {"bytes": buffer.getvalue(), "path": None}
                 else:
                      return {"bytes": None, "path": value.get('path'					)}
            elif value.get('bytes'					) is not None or value.get('path'					) is not None:
                 # store the audio bytes, and path is used to infer the audio format using the file extension
                 return {"bytes": value.get('bytes'					), "path": value.get('path'					)}
            else:
                 raise ValueError(
                     F'''An audio sample should have one of \'path\' or \'bytes\' but they are missing or None in {value}.'''					)







       def 		snake_case_	(			self: List[Any],A_: dict,A_: Optional[Dict[str, Union[str, bool, None]]] = None					):






            '''simple docstring'''




            if not self.decode:
                 raise RuntimeError('Decoding is disabled for this feature. Please use Audio(decode=True) instead.'					)

            __UpperCamelCase,    __UpperCamelCase =			(value['path'], BytesIO(value['bytes']					)) if value['bytes'] is not None else (value['path'], None)
            if path is None and file is None:
                 raise ValueError(F'''An audio sample should have one of \'path\' or \'bytes\' but both are None in {value}.'''					)

            try:
                 import librosa
                 import soundfile as sf
            except ImportError as err:
                 raise ImportError('To support decoding audio files, please install \'librosa\' and \'soundfile\'.'					) from err

            __UpperCamelCase =			xsplitext(A_					)[1][1:].lower() if path is not None else None
            if not config.IS_OPUS_SUPPORTED and audio_format == "opus":
                 raise RuntimeError(
                     'Decoding \'opus\' files requires system library \'libsndfile\'>=1.0.31, '
                     'You can try to update `soundfile` python library: `pip install "soundfile>=0.12.1"`. '					)
            elif not config.IS_MP3_SUPPORTED and audio_format == "mp3":
                 raise RuntimeError(
                     'Decoding \'mp3\' files requires system library \'libsndfile\'>=1.1.0, '
                     'You can try to update `soundfile` python library: `pip install "soundfile>=0.12.1"`. '					)

            if file is None:
                 __UpperCamelCase =			token_per_repo_id or {}
                 __UpperCamelCase =			path.split('::'					)[-1]
                 try:
                      __UpperCamelCase =			string_to_dict(A_,config.HUB_DATASETS_URL					)['repo_id']
                      __UpperCamelCase =			token_per_repo_id[repo_id]
                 except (ValueError, KeyError):
                      __UpperCamelCase =			None

                 with xopen(A_,'rb',use_auth_token=A_					) as f:
                      __UpperCamelCase,    __UpperCamelCase =			sf.read(A_					)

            else:
                 __UpperCamelCase,    __UpperCamelCase =			sf.read(A_					)

            __UpperCamelCase =			array.T
            if self.mono:
                 __UpperCamelCase =			librosa.to_mono(A_					)
            if self.sampling_rate and self.sampling_rate != sampling_rate:
                 __UpperCamelCase =			librosa.resample(A_,orig_sr=A_,target_sr=self.sampling_rate					)
                 __UpperCamelCase =			self.sampling_rate

            return {"path": path, "array": array, "sampling_rate": sampling_rate}







       def 		snake_case_	(			self: List[Any]					):






            '''simple docstring'''




            from .features import Value

            if self.decode:
                 raise ValueError('Cannot flatten a decoded Audio feature.'					)
            return {
                "bytes": Value('binary'					),
                "path": Value('string'					),
            }







       def 		snake_case_	(			self: str,A_: Union[pa.StringArray, pa.StructArray]					):






            '''simple docstring'''




            if pa.types.is_string(storage.type					):
                 __UpperCamelCase =			pa.array([None] * len(A_					),type=pa.binary()					)
                 __UpperCamelCase =			pa.StructArray.from_arrays([bytes_array, storage],['bytes', 'path'],mask=storage.is_null()					)
            elif pa.types.is_binary(storage.type					):
                 __UpperCamelCase =			pa.array([None] * len(A_					),type=pa.string()					)
                 __UpperCamelCase =			pa.StructArray.from_arrays([storage, path_array],['bytes', 'path'],mask=storage.is_null()					)
            elif pa.types.is_struct(storage.type					) and storage.type.get_all_field_indices('array'					):
                 __UpperCamelCase =			pa.array([Audio().encode_example(A_					) if x is not None else None for x in storage.to_pylist()]					)
            elif pa.types.is_struct(storage.type					):
                 if storage.type.get_field_index('bytes'					) >= 0:
                      __UpperCamelCase =			storage.field('bytes'					)
                 else:
                      __UpperCamelCase =			pa.array([None] * len(A_					),type=pa.binary()					)
                 if storage.type.get_field_index('path'					) >= 0:
                      __UpperCamelCase =			storage.field('path'					)
                 else:
                      __UpperCamelCase =			pa.array([None] * len(A_					),type=pa.string()					)
                 __UpperCamelCase =			pa.StructArray.from_arrays([bytes_array, path_array],['bytes', 'path'],mask=storage.is_null()					)
            return array_cast(A_,self.pa_type					)







       def 		snake_case_	(			self: Optional[Any],A_: pa.StructArray					):






            '''simple docstring'''




            @no_op_if_value_is_null
            def path_to_bytes(A_: Union[str, Any]					):
                 with xopen(A_,'rb'					) as f:
                      __UpperCamelCase =			f.read()
                 return bytes_

            __UpperCamelCase =			pa.array(
                [
                    (path_to_bytes(x['path']					) if x['bytes'] is None else x['bytes']) if x is not None else None
                    for x in storage.to_pylist()
                ],type=pa.binary(),)
            __UpperCamelCase =			pa.array(
                [os.path.basename(A_					) if path is not None else None for path in storage.field('path'					).to_pylist()],type=pa.string(),)
            __UpperCamelCase =			pa.StructArray.from_arrays([bytes_array, path_array],['bytes', 'path'],mask=bytes_array.is_null()					)
            return array_cast(A_,self.pa_type					)






'''simple docstring'''



from collections.abc import Generator
from math import sin



def      UpperCAmelCase__   (      UpperCAmelCase_       :							bytes				)	->						bytes:
     if len(UpperCAmelCase_				) != 32:
          raise ValueError('Input must be of length 32'				)

     __lowerCamelCase  :      Dict														=						B''
     for i in [3, 2, 1, 0]:
          little_endian += string_aa[8 * i : 8 * i + 8]
     return little_endian



def      UpperCAmelCase__   (      UpperCAmelCase_       :							int				)	->						bytes:
     if i < 0:
          raise ValueError('Input must be non-negative'				)

     __lowerCamelCase  :      Union[str, Any]														=						format(UpperCAmelCase_ ,       '08x'				)[-8:]
     __lowerCamelCase  :      str														=						B''
     for i in [3, 2, 1, 0]:
          little_endian_hex += hex_rep[2 * i : 2 * i + 2].encode('utf-8'				)
     return little_endian_hex



def      UpperCAmelCase__   (      UpperCAmelCase_       :							bytes				)	->						bytes:
     __lowerCamelCase  :      Optional[Any]														=						B''
     for char in message:
          bit_string += format(UpperCAmelCase_ ,       '08b'				).encode('utf-8'				)
     __lowerCamelCase  :      List[str]														=						format(len(UpperCAmelCase_				) ,       '064b'				).encode('utf-8'				)

     # Pad bit_string to a multiple of 512 chars
     bit_string += b"1"
     while len(UpperCAmelCase_				) % 5_12 != 4_48:
          bit_string += b"0"
     bit_string += to_little_endian(start_len[32:]				) + to_little_endian(start_len[:32]				)

     return bit_string



def      UpperCAmelCase__   (      UpperCAmelCase_       :							bytes				)	->						Generator[list[int], None, None]:
     if len(UpperCAmelCase_				) % 5_12 != 0:
          raise ValueError('Input must have length that\'s a multiple of 512'				)

     for pos in range(0 ,       len(UpperCAmelCase_				) ,       5_12				):
          __lowerCamelCase  :      Any														=						bit_string[pos : pos + 5_12]
          __lowerCamelCase  :      Optional[int]														=						[]
          for i in range(0 ,       5_12 ,       32				):
               block_words.append(int(to_little_endian(block[i : i + 32]				) ,       2				)				)
          yield block_words



def      UpperCAmelCase__   (      UpperCAmelCase_       :							int				)	->						int:
     if i < 0:
          raise ValueError('Input must be non-negative'				)

     __lowerCamelCase  :      List[Any]														=						format(UpperCAmelCase_ ,       '032b'				)
     __lowerCamelCase  :      Optional[int]														=						''
     for c in i_str:
          new_str += "1" if c == "0" else "0"
     return int(UpperCAmelCase_ ,       2				)



def      UpperCAmelCase__   (      UpperCAmelCase_       :							int ,       UpperCAmelCase_       :							int				)	->						int:
     return (a + b) % 2**32



def      UpperCAmelCase__   (      UpperCAmelCase_       :							int ,       UpperCAmelCase_       :							int				)	->						int:
     if i < 0:
          raise ValueError('Input must be non-negative'				)
     if shift < 0:
          raise ValueError('Shift must be non-negative'				)
     return ((i << shift) ^ (i >> (32 - shift))) % 2**32



def      UpperCAmelCase__   (      UpperCAmelCase_       :							bytes				)	->						bytes:
     __lowerCamelCase  :      Optional[Any]														=						preprocess(UpperCAmelCase_				)

     __lowerCamelCase  :      Union[str, Any]														=						[int(2**32 * abs(sin(i + 1				)				)				) for i in range(64				)]

     # Starting states
     __lowerCamelCase  :      Dict														=						0x67_45_23_01
     __lowerCamelCase  :      Union[str, Any]														=						0xef_cd_ab_89
     __lowerCamelCase  :      Optional[Any]														=						0x98_ba_dc_fe
     __lowerCamelCase  :      Union[str, Any]														=						0x10_32_54_76

     __lowerCamelCase  :      List[str]														=						[
         7,
         12,
         17,
         22,
         7,
         12,
         17,
         22,
         7,
         12,
         17,
         22,
         7,
         12,
         17,
         22,
         5,
         9,
         14,
         20,
         5,
         9,
         14,
         20,
         5,
         9,
         14,
         20,
         5,
         9,
         14,
         20,
         4,
         11,
         16,
         23,
         4,
         11,
         16,
         23,
         4,
         11,
         16,
         23,
         4,
         11,
         16,
         23,
         6,
         10,
         15,
         21,
         6,
         10,
         15,
         21,
         6,
         10,
         15,
         21,
         6,
         10,
         15,
         21,
     ]

     # Process bit string in chunks, each with 16 32-char words
     for block_words in get_block_words(UpperCAmelCase_				):
          __lowerCamelCase  :      Dict														=						aa
          __lowerCamelCase  :      Tuple														=						ba
          __lowerCamelCase  :      List[Any]														=						ca
          __lowerCamelCase  :      Dict														=						da

          # Hash current chunk
          for i in range(64				):
               if i <= 15:
                    # f = (b & c) | (not_32(b) & d)     # Alternate definition for f
                    __lowerCamelCase  :      List[str]														=						d ^ (b & (c ^ d))
                    __lowerCamelCase  :      Optional[int]														=						i
               elif i <= 31:
                    # f = (d & b) | (not_32(d) & c)     # Alternate definition for f
                    __lowerCamelCase  :      Optional[int]														=						c ^ (d & (b ^ c))
                    __lowerCamelCase  :      Tuple														=						(5 * i + 1) % 16
               elif i <= 47:
                    __lowerCamelCase  :      str														=						b ^ c ^ d
                    __lowerCamelCase  :      Any														=						(3 * i + 5) % 16
               else:
                    __lowerCamelCase  :      Union[str, Any]														=						c ^ (b | not_aa(UpperCAmelCase_				))
                    __lowerCamelCase  :      int														=						(7 * i) % 16
               __lowerCamelCase  :      Optional[int]														=						(f + a + added_consts[i] + block_words[g]) % 2**32
               __lowerCamelCase  :      Optional[Any]														=						d
               __lowerCamelCase  :      Tuple														=						c
               __lowerCamelCase  :      Optional[int]														=						b
               __lowerCamelCase  :      List[str]														=						sum_aa(UpperCAmelCase_ ,       left_rotate_aa(UpperCAmelCase_ ,       shift_amounts[i]				)				)

          # Add hashed chunk to running total
          __lowerCamelCase  :      int														=						sum_aa(UpperCAmelCase_ ,       UpperCAmelCase_				)
          __lowerCamelCase  :      str														=						sum_aa(UpperCAmelCase_ ,       UpperCAmelCase_				)
          __lowerCamelCase  :      List[Any]														=						sum_aa(UpperCAmelCase_ ,       UpperCAmelCase_				)
          __lowerCamelCase  :      List[str]														=						sum_aa(UpperCAmelCase_ ,       UpperCAmelCase_				)

     __lowerCamelCase  :      Dict														=						reformat_hex(UpperCAmelCase_				) + reformat_hex(UpperCAmelCase_				) + reformat_hex(UpperCAmelCase_				) + reformat_hex(UpperCAmelCase_				)
     return digest


if __name__ == "__main__":
      import doctest

      doctest.testmod()






