o
    rriH*                     @   s  d Z ddlm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ZddlmZ ddlmZ dd	lmZ dd
lmZmZ ejeeef ZG dd dejZG dd dZdd Z					d!dejeef dejejef dededededededej e dejfdd Z!dS )"z
Code to apply a model to a mix. It will handle chunking with overlaps and
inteprolation between chunks, as well as the "shift trick".
    )ThreadPoolExecutorN)nn)
functional   )Demucs)HDemucs)HTDemucs)center_trimDummyPoolExecutorc                       sh   e Zd Z		ddeje dejejeje   deje f fddZe	defdd	Z
d
d Z  ZS )BagOfModelsNmodelsweightssegmentc                    s   t    t|dksJ |d  |D ]!}|j jksJ |j jks%J |j jks-J |dur4||_q j| _ j| _ j| _t|| _	|du rU fdd|D }nt|t|ks_J |D ]}t|t jksnJ qa|| _
dS )a  
        Represents a bag of models with specific weights.
        You should call `apply_model` rather than calling directly the forward here for
        optimal performance.

        Args:
            models (list[nn.Module]): list of Demucs/HDemucs models.
            weights (list[list[float]]): list of weights. If None, assumed to
                be all ones, otherwise it should be a list of N list (N number of models),
                each containing S floats (S number of sources).
            segment (None or float): overrides the `segment` attribute of each model
                (this is performed inplace, be careful is you reuse the models passed).
        r   Nc                    s   g | ]
}d d  j D qS )c                 S   s   g | ]}d qS )      ? .0_r   r   @/home/ubuntu/.local/lib/python3.10/site-packages/demucs/apply.py
<listcomp><   s    z3BagOfModels.__init__.<locals>.<listcomp>.<listcomp>)sourcesr   firstr   r   r   <   s    z(BagOfModels.__init__.<locals>.<listcomp>)super__init__lenr   
samplerateaudio_channelsr   r   
ModuleListr   r   )selfr   r   r   otherweight	__class__r   r   r      s(   

zBagOfModels.__init__returnc                 C   s2   t d}| jD ]}t|trt|t |j}q|S )Ninf)floatr   
isinstancer   minr   )r   max_allowed_segmentmodelr   r   r   r)   C   s   

zBagOfModels.max_allowed_segmentc                 C   s   t d)NzCall `apply_model` on this.)NotImplementedError)r   xr   r   r   forwardK   s   zBagOfModels.forward)NN)__name__
__module____qualname__tpListModelOptionalr&   r   propertyr)   r-   __classcell__r   r   r"   r   r      s    'r   c                   @   s*   e Zd Zd	ddZedd Zdd ZdS )
TensorChunkr   Nc                 C   s   |j d }|dksJ ||k sJ |d u r|| }nt|| |}t|tr1|j| _||j | _n|| _|| _|| _|j| _d S )Nr   )shaper(   r'   r7   tensoroffsetlengthdevice)r   r:   r;   r<   total_lengthr   r   r   r   P   s   


zTensorChunk.__init__c                 C   s   t | jj}| j|d< |S )Nr8   )listr:   r9   r<   )r   r9   r   r   r   r9   c   s   
zTensorChunk.shapec                 C   s   || j  }| jjd }|dksJ | j|d  }|| }td|}t||}|| }|| }	t| jd||f ||	f}
|
jd |ksFJ |
S )Nr8   r      .)r<   r:   r9   r;   maxr(   Fpad)r   target_lengthdeltar>   startendcorrect_startcorrect_endpad_left	pad_rightoutr   r   r   paddedi   s   


zTensorChunk.padded)r   N)r.   r/   r0   r   r5   r9   rM   r   r   r   r   r7   O   s
    

r7   c                 C   s&   t | tr| S t | tjsJ t| S )N)r'   r7   thTensor)tensor_or_chunkr   r   r   tensor_chunk|   s   
rQ   T      ?r   Fr*   mixshiftssplitoverlaptransition_powerprogressnum_workersr   r$   c           )   	   C   s  |du r|j }nt |}|
du r"|dkr|jdkrt|}
nt }
|||||||
|	d}t| trd}dgt| j }t	| j
| jD ]H\}}tt| j }|| t||fi |}|| t|D ]\}}|dd|ddddf  |9  < ||  |7  < qg||7 }~qCt|tjsJ t|jd D ]}|dd|ddddf  ||   < q|S | | |   |dksJ d|j\}}}|r*d|d< td	| j }t|}t|tsJ ||d
|  }d}t|D ]'}td|}t|||| | }t| |fi |}||d|| df 7 }q|| }t|tjs(J |S |r,d|d< tj|t| j|||j d}tj||j d}|	du rO| j}	|	durY|	dks[J t| j|	 }td| | }td||} tt || j d}!t!tj"d|d
 d |dtj"||d
  dd|dg}"t|"|ksJ |"|"#  | }"g }#| D ]}t|||}$|
j$t| |$fi |}%|#%|%|f ||7 }q|rt&j&|#|!ddd}#|#D ]:\}%}|%' }&|&jd }'|d||| f  |"d|' |& |j 7  < ||||   |"d|' |j 7  < q|( dksJ || }t|tjs*J |S t| t)r?|	dur?t|	| j }(nt*| drK| +|}(n|}(t|}t|tsYJ ||(|}t,  | |}W d   n	1 suw   Y  t|tjsJ t-||S )a  
    Apply model to a given mixture.

    Args:
        shifts (int): if > 0, will shift in time `mix` by a random amount between 0 and 0.5 sec
            and apply the oppositve shift to the output. This is repeated `shifts` time and
            all predictions are averaged. This effectively makes the model time equivariant
            and improves SDR by up to 0.2 points.
        split (bool): if True, the input will be broken down in 8 seconds extracts
            and predictions will be performed individually on each and concatenated.
            Useful for model with large memory footprint like Tasnet.
        progress (bool): if True, show a progress bar (requires split=True)
        device (torch.device, str, or None): if provided, device on which to
            execute the computation, otherwise `mix.device` is assumed.
            When `device` is different from `mix.device`, only local computations will
            be on `device`, while the entire tracks will be stored on `mix.device`.
        num_workers (int): if non zero, device is 'cpu', how many threads to
            use in parallel.
        segment (float or None): override the model segment parameter.
    Nr   cpu)rT   rU   rV   rW   rX   r=   poolr   g        r   z-transition_power < 1 leads to weird behavior.rT   g      ?r@   .FrU   )r=   z.2fr8   x   seconds)
unit_scalencolsunitvalid_length).r=   rN   typer   r
   r'   r   r   r   zipr   r   nextiter
parameterstoapply_model	enumeraterO   ranger9   evalintr   rQ   r7   rM   randomrandintzerosr   r&   formatcatarangerA   submitappendtqdmresultr(   r   hasattrra   no_gradr	   ))r*   rS   rT   rU   rV   rW   rX   r=   rY   r   r[   kwargs	estimatestotals	sub_modelmodel_weightsoriginal_model_devicerL   kinst_weightbatchchannelsr<   	max_shift
padded_mixr   r;   shiftedshifted_out
sum_weightsegment_lengthstrideoffsetsscaler!   futureschunkfuture	chunk_outchunk_lengthra   r   r   r   rh      s   




$*


,


rh   )	r   TrR   r   FNr   NN)"__doc__concurrent.futuresr   rm   typingr1   torchrN   r   torch.nnr   rB   ru   demucsr   hdemucsr   htdemucsr   utilsr	   r
   Unionr3   Moduler   r7   rQ   rO   rl   boolr&   r4   rh   r   r   r   r   <module>   sP   4-
