

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


lowerCAmelCase__, lowerCAmelCase__, lowerCAmelCase__       = False, False, False






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


 def __call__(						self		: List[str]    )    ->      List[Any]:
   return self.pa_type


 def _UpperCamelCase	(						self		: str			,						lowerCAmelCase__		: Union[str, bytes, dict]    )    ->      dict:
   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(lowerCAmelCase__			,						lowerCAmelCase__    ):
     return {"bytes": None, "path": value}
   elif isinstance(lowerCAmelCase__			,						lowerCAmelCase__    ):
     return {"bytes": value, "path": None}
   elif "array" in value:
     # convert the audio array to wav bytes
     UpperCAmelCase					      =  BytesIO()
     sf.write(lowerCAmelCase__			,						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_2_7_6_7
       else:
         UpperCAmelCase					      =  np.memmap(value["path"]			,						dtype="h"			,						mode="r"    ).astype(np.floataa    ) / 3_2_7_6_7

       UpperCAmelCase					      =  BytesIO(bytes()    )
       sf.write(lowerCAmelCase__			,						lowerCAmelCase__			,						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 _UpperCamelCase	(						self		: Any			,						lowerCAmelCase__		: dict			,						lowerCAmelCase__		: Optional[Dict[str, Union[str, bool, None]]] = None    )    ->      dict:
   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(lowerCAmelCase__    )[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(lowerCAmelCase__			,						config.HUB_DATASETS_URL    )["repo_id"]
       UpperCAmelCase					      =  token_per_repo_id[repo_id]
     except (ValueError, KeyError):
       UpperCAmelCase					      =  None

     with xopen(lowerCAmelCase__			,						"rb"			,						use_auth_token=lowerCAmelCase__    ) as f:
       UpperCAmelCase      ,	UpperCAmelCase					      =  sf.read(lowerCAmelCase__    )

   else:
     UpperCAmelCase      ,	UpperCAmelCase					      =  sf.read(lowerCAmelCase__    )

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

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


 def _UpperCamelCase	(						self		: Any    )    ->      Union["FeatureType", Dict[str, "FeatureType"]]:
   from .features import Value

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


 def _UpperCamelCase	(						self		: Dict			,						lowerCAmelCase__		: Union[pa.StringArray, pa.StructArray]    )    ->      pa.StructArray:
   if pa.types.is_string(storage.type    ):
     UpperCAmelCase					      =  pa.array([None] * len(lowerCAmelCase__    )			,						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(lowerCAmelCase__    )			,						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(lowerCAmelCase__    ) 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(lowerCAmelCase__    )			,						type=pa.binary()    )
     if storage.type.get_field_index("path"    ) >= 0:
       UpperCAmelCase					      =  storage.field("path"    )
     else:
       UpperCAmelCase					      =  pa.array([None] * len(lowerCAmelCase__    )			,						type=pa.string()    )
     UpperCAmelCase					      =  pa.StructArray.from_arrays([bytes_array, path_array]			,						["bytes", "path"]			,						mask=storage.is_null()    )
   return array_cast(lowerCAmelCase__			,						self.pa_type    )


 def _UpperCamelCase	(						self		: Dict			,						lowerCAmelCase__		: pa.StructArray    )    ->      pa.StructArray:

   @no_op_if_value_is_null
   def path_to_bytes(lowerCAmelCase__		: List[Any]    ):
     with xopen(lowerCAmelCase__			,						"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(lowerCAmelCase__    ) 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(lowerCAmelCase__			,						self.pa_type    )






from . import (
    albert,
    align,
    altclip,
    audio_spectrogram_transformer,
    auto,
    autoformer,
    bark,
    bart,
    barthez,
    bartpho,
    beit,
    bert,
    bert_generation,
    bert_japanese,
    bertweet,
    big_bird,
    bigbird_pegasus,
    biogpt,
    bit,
    blenderbot,
    blenderbot_small,
    blip,
    blip_a,
    bloom,
    bridgetower,
    byta,
    camembert,
    canine,
    chinese_clip,
    clap,
    clip,
    clipseg,
    codegen,
    conditional_detr,
    convbert,
    convnext,
    convnextva,
    cpm,
    cpmant,
    ctrl,
    cvt,
    dataavec,
    deberta,
    deberta_va,
    decision_transformer,
    deformable_detr,
    deit,
    deprecated,
    deta,
    detr,
    dialogpt,
    dinat,
    distilbert,
    dit,
    donut,
    dpr,
    dpt,
    efficientformer,
    efficientnet,
    electra,
    encodec,
    encoder_decoder,
    ernie,
    ernie_m,
    esm,
    falcon,
    flaubert,
    flava,
    fnet,
    focalnet,
    fsmt,
    funnel,
    git,
    glpn,
    gpta,
    gpt_bigcode,
    gpt_neo,
    gpt_neox,
    gpt_neox_japanese,
    gpt_swa,
    gptj,
    gptsan_japanese,
    graphormer,
    groupvit,
    herbert,
    hubert,
    ibert,
    imagegpt,
    informer,
    instructblip,
    jukebox,
    layoutlm,
    layoutlmva,
    layoutlmva,
    layoutxlm,
    led,
    levit,
    lilt,
    llama,
    longformer,
    longta,
    luke,
    lxmert,
    mam_aaa,
    marian,
    markuplm,
    maskaformer,
    maskformer,
    mbart,
    mbartaa,
    mega,
    megatron_bert,
    megatron_gpta,
    mgp_str,
    mluke,
    mobilebert,
    mobilenet_va,
    mobilenet_va,
    mobilevit,
    mobilevitva,
    mpnet,
    mra,
    mta,
    musicgen,
    mvp,
    nat,
    nezha,
    nllb,
    nllb_moe,
    nystromformer,
    oneformer,
    open_llama,
    openai,
    opt,
    owlvit,
    pegasus,
    pegasus_x,
    perceiver,
    phobert,
    pixastruct,
    plbart,
    poolformer,
    prophetnet,
    qdqbert,
    rag,
    realm,
    reformer,
    regnet,
    rembert,
    resnet,
    roberta,
    roberta_prelayernorm,
    roc_bert,
    roformer,
    rwkv,
    sam,
    segformer,
    sew,
    sew_d,
    speech_encoder_decoder,
    speech_to_text,
    speech_to_text_a,
    speechta,
    splinter,
    squeezebert,
    swiftformer,
    swin,
    swinasr,
    swinva,
    switch_transformers,
    ta,
    table_transformer,
    tapas,
    time_series_transformer,
    timesformer,
    timm_backbone,
    transfo_xl,
    trocr,
    tvlt,
    umta,
    unispeech,
    unispeech_sat,
    upernet,
    videomae,
    vilt,
    vision_encoder_decoder,
    vision_text_dual_encoder,
    visual_bert,
    vit,
    vit_hybrid,
    vit_mae,
    vit_msn,
    vivit,
    wavaveca,
    wavaveca_conformer,
    wavaveca_phoneme,
    wavaveca_with_lm,
    wavlm,
    whisper,
    x_clip,
    xglm,
    xlm,
    xlm_prophetnet,
    xlm_roberta,
    xlm_roberta_xl,
    xlnet,
    xmod,
    yolos,
    yoso,
)



