o
    i                     @   s   d dl Z d dlmZ d dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZ d dlmZmZ 		dded	ejd
ededef
ddZdd ZdejdejfddZdededed
efddZdS )    N)tqdm)LogisticRegression)make_pipeline)FunctionTransformerStandardScaler      ?   reference_clip	oww_model
model_name	thresholdNc                 K   s  t t}t|D ]X}t| tkrtjj	| \}}	n| }	|dkr,|	t
jddd }	d}
td|	jd |
 |
D ]'}|j|	|||
  fi |}|| |kr`|j|j| }|| | q9q	t|| dkrz|| t
d|j| df t
|| S )a8  
    Processes input audio files (16-bit, 16-khz single-channel WAV files) and gets the openWakeWord
    audio features that produce a prediction from the specified model greater than the threshold value.


    Args:
        reference_clip (str): The target audio file to get features from
        oww_model (openwakeword.Model): The openWakeWord model object used to get predictions
        model_name (str): The name of the model to get predictions from (should correspond to
                          a python dictionary key in the oww_model.models attribute)
        threshold (float): The minimum score from the model required to capture the associated features
        N (int): How many times to run feature extraction for a given clip, adding some slight variation
                 in the starting position each time to ensure that the features are not identical

    Returns:
        ndarray: A numpy array of shape N x M x L, where N is the number of examples, M is the number
                 of frames in the window, and L is the audio feature/embedding dimension.
       r   i   N`   )collectionsdefaultdictlistrangetypestrscipyioZwavfilereadnprandomrandintshapeZpredictZpreprocessorZget_featuresZmodel_inputsappendlenemptyvstack)r	   r
   r   r   r   kwargsZpositive_data_srZdatZ	step_sizeiZpredictionsfeatures r&   \/home/kim/smarthome/.venv/lib/python3.10/site-packages/openwakeword/custom_verifier_model.pyget_reference_clip_features   s,   
r(   c                 C   s   dd | D S )Nc                 S   s   g | ]}|  qS r&   )flatten.0r$   r&   r&   r'   
<listcomp>Z   s    z$flatten_features.<locals>.<listcomp>r&   )xr&   r&   r'   flatten_featuresY   s   r.   r%   labelsc                 C   s0   t dddd}tttt |}|| | |S )a  
    Train a logistic regression binary classifier model on the provided features and labels

    Args:
        features (ndarray): A N x M numpy array, where N is the number of examples and M
                             is the number of features
        labels (ndarray): A 1D numpy array where each value corresponds to the label of the Nth
                           example in the `features` argument

    Returns:
        The trained scikit-learn logistic regression model
    r   i  gMbP?)Zrandom_stateZmax_iterC)r   r   r   r.   r   fit)r%   r/   ZclfZpipeliner&   r&   r'   train_verifier_model]   s   r2   positive_reference_clipsnegative_reference_clipsoutput_pathc                    s  t j r!tjdd gi|t j d t jjd  ntjdi |t	 fddt
| ddD }|jd dkrEtdt	 fd	dt
|d
dD }td tt	||ftdg|jd  dg|jd   }td t|t|d dS )a  
    Trains a voice-specific custom verifier model on examples of wake word/phrase speech and other speech
    from a single user.

    Args:
        positive_reference_clips (str): The path to a directory containing single-channel 16khz, 16-bit WAV files
                                        of the target wake word/phrase.
        negative_reference_clips (str): The path to a directory containing single-channel 16khz, 16-bit WAV files
                                        of miscellaneous speech not containing the target wake word/phrase.
        output_path (str): The location to save the trained verifier model (as a scikit-learn .joblib file)
        model_name (str): The name or path of the trained openWakeWord model that the verifier model will be
                          based on. If only a name, it must be one of the pre-trained models included in the
                          openWakeWord release.
        kwargs: Any other keyword arguments to pass to the openWakeWord model initialization

    Returns:
        None
    Zwakeword_modelsr   c                    s   g | ]
}t | d dqS )   )r   r(   r*   r   Zowwr&   r'   r,      s    z)train_custom_verifier.<locals>.<listcomp>z#Processing positive reference clips)ZdesczThe positive features were created! Make sure that the positive reference clips contain the appropriate audio for the desired modelc              	      s   g | ]}t | d ddqS )g        r   )r   r   r8   r*   r9   r&   r'   r,      s    z#Processing negative reference clipsz%Training and saving verifier model...r   zDone!wbNr&   )ospathexistsopenwakewordModelsplitextsplitsepr   r    r   r   
ValueErrorprintr2   arraypickledumpopen)r3   r4   r5   r   r!   Zpositive_featuresZnegative_featuresZlr_modelr&   r9   r'   train_custom_verifierr   s6    

$rI   )r   r   )r;   r   r   r>   numpyr   r   rF   Zsklearn.linear_modelr   Zsklearn.pipeliner   Zsklearn.preprocessingr   r   r   r?   floatintr(   r.   Zndarrayr2   rI   r&   r&   r&   r'   <module>   sD   
;