1010from .config import load_config
1111
1212
13+ class _ProgressContext :
14+ def __init__ (self , pbar = False , total = 1 , callback = None , done = 0 , message = "Processing audio chunks" ):
15+ self .enabled = bool (pbar or callback )
16+ self .bar = None
17+ self .callback = callback
18+ self .done = done
19+ self .total = total
20+ self .message = message
21+ if not self .enabled :
22+ return
23+ self .bar = tqdm (total = total , desc = message , leave = False ) if pbar else None
24+ self .total = int (self .total or 1 )
25+ self .done = int (self .done or 0 )
26+ self .emit ()
27+
28+ def emit (self , done = None ):
29+ if not self .enabled :
30+ return
31+ if done is not None :
32+ self .done = int (done )
33+ if self .callback is None :
34+ return
35+ self .callback (min (self .done , self .total ), self .total , self .message )
36+
37+ def update (self , amount ):
38+ if not self .enabled :
39+ return
40+ amount = int (amount )
41+ if self .bar :
42+ self .bar .update (amount )
43+ self .done += amount
44+ self .emit ()
45+
46+ def close (self ):
47+ if not self .enabled :
48+ return
49+ if self .bar :
50+ self .bar .close ()
51+
1352def get_model_from_config (model_type , config_path , model_kwargs_override = None ):
1453 model_kwargs_override = model_kwargs_override or {}
1554 config = load_config (config_path )
@@ -247,7 +286,18 @@ def _add_weighted_chunk(result, counter, chunk, window, start, length):
247286 counter [..., start :start + length ] += window
248287
249288
250- def _run_complete_chunks (model , mix , windows , result , counter , chunk_size , step , batch_size , progress_bar , source_indices = None ):
289+ def _run_complete_chunks (
290+ model ,
291+ mix ,
292+ windows ,
293+ result ,
294+ counter ,
295+ chunk_size ,
296+ step ,
297+ batch_size ,
298+ progress ,
299+ source_indices = None ,
300+ ):
251301 n_chunks = _complete_chunk_count (mix .shape [1 ], chunk_size , step )
252302 if n_chunks == 0 :
253303 return 0
@@ -272,13 +322,25 @@ def _run_complete_chunks(model, mix, windows, result, counter, chunk_size, step,
272322 step ,
273323 start_offset = batch_start * step ,
274324 )
275- if progress_bar :
276- progress_bar .update (step * (batch_end - batch_start ))
325+ progress .update (step * (batch_end - batch_start ))
277326
278327 return n_complete
279328
280329
281- def _run_tail_chunks (model , mix , starts , windows , result , counter , chunk_size , step , batch_size , first_chunk , progress_bar , source_indices = None ):
330+ def _run_tail_chunks (
331+ model ,
332+ mix ,
333+ starts ,
334+ windows ,
335+ result ,
336+ counter ,
337+ chunk_size ,
338+ step ,
339+ batch_size ,
340+ first_chunk ,
341+ progress ,
342+ source_indices = None ,
343+ ):
282344 for batch_start in range (first_chunk , len (starts ), batch_size ):
283345 batch_indices = range (batch_start , min (batch_start + batch_size , len (starts )))
284346 batch = [(_extract_chunk (mix , starts [idx ], chunk_size ), idx ) for idx in batch_indices ]
@@ -288,8 +350,7 @@ def _run_tail_chunks(model, mix, starts, windows, result, counter, chunk_size, s
288350 start = starts [idx ]
289351 _add_weighted_chunk (result , counter , chunks [j ], windows [idx ], start , length )
290352
291- if progress_bar :
292- progress_bar .update (step * len (batch_data ))
353+ progress .update (step * len (batch_data ))
293354
294355
295356def _finalize_overlap (result , counter , length_init , border ):
@@ -449,7 +510,7 @@ def _can_demix_mlx_full(model, device):
449510 )
450511
451512
452- def demix_track_mlx_full (config , model , mix , device , pbar = False , source_indices = None ):
513+ def demix_track_mlx_full (config , model , mix , device , pbar = False , source_indices = None , progress_callback = None ):
453514 import mlx .core as mx
454515
455516 C = config .audio .chunk_size
@@ -463,7 +524,7 @@ def demix_track_mlx_full(config, model, mix, device, pbar=False, source_indices=
463524 starts , windows = _mlx_build_chunk_plan (mix .shape [1 ], C , step , fade_size )
464525 result = mx .zeros ((_source_count (config , source_indices ), mix .shape [0 ], mix .shape [1 ]), dtype = mx .float32 )
465526 counter = mx .zeros ((1 , 1 , mix .shape [1 ]), dtype = mx .float32 )
466- progress_bar = tqdm ( total = mix .shape [1 ], desc = "Processing audio chunks" , leave = False ) if pbar else None
527+ progress = _ProgressContext ( pbar , mix .shape [1 ], progress_callback )
467528
468529 for batch_start in range (0 , len (starts ), batch_size ):
469530 batch_indices = range (batch_start , min (batch_start + batch_size , len (starts )))
@@ -473,18 +534,17 @@ def demix_track_mlx_full(config, model, mix, device, pbar=False, source_indices=
473534 for j , ((_ , length ), idx ) in enumerate (batch ):
474535 result , counter = _mlx_add_weighted_chunk (result , counter , chunks [j ], windows [idx ], starts [idx ], length )
475536 mx .eval (result , counter )
476- if progress_bar :
477- progress_bar .update (step * len (batch ))
537+ progress .update (step * len (batch ))
478538
479- if progress_bar :
480- progress_bar . close ( )
539+ progress . close ()
540+ progress . emit ( mix . shape [ 1 ] )
481541 return _sources_to_dict (config , _mlx_finalize_overlap (result , counter , length_init , border ), source_indices )
482542
483543
484544demix_track_mlx_roformer = demix_track_mlx_full
485545
486546
487- def demix_track (config , model , mix , device , pbar = False , source_indices = None ):
547+ def demix_track (config , model , mix , device , pbar = False , source_indices = None , progress_callback = None ):
488548 C = config .audio .chunk_size
489549 source_indices = _normalize_source_indices (config , source_indices )
490550 step = _get_inference_step (config , C )
@@ -501,32 +561,51 @@ def demix_track(config, model, mix, device, pbar=False, source_indices=None):
501561 with _autocast (device , config .training .get ('use_amp' , True )):
502562 with torch .inference_mode ():
503563 result , counter = _init_overlap_buffers (config , mix , device , use_complete_fast_path , source_indices )
504- progress_bar = tqdm ( total = mix .shape [1 ], desc = "Processing audio chunks" , leave = False ) if pbar else None
564+ progress = _ProgressContext ( pbar , mix .shape [1 ], progress_callback )
505565
506566 with _model_source_context (model , source_indices ):
507567 complete_chunks = 0
508568 if use_complete_fast_path :
509569 complete_chunks = _run_complete_chunks (
510- model , mix_device , chunk_windows , result , counter , C , step , batch_size , progress_bar , source_indices
570+ model ,
571+ mix_device ,
572+ chunk_windows ,
573+ result ,
574+ counter ,
575+ C ,
576+ step ,
577+ batch_size ,
578+ progress ,
579+ source_indices ,
511580 )
512581
513582 _run_tail_chunks (
514- model , mix_device , chunk_starts , chunk_windows , result , counter , C , step , batch_size ,
515- complete_chunks , progress_bar , source_indices
583+ model ,
584+ mix_device ,
585+ chunk_starts ,
586+ chunk_windows ,
587+ result ,
588+ counter ,
589+ C ,
590+ step ,
591+ batch_size ,
592+ complete_chunks ,
593+ progress ,
594+ source_indices ,
516595 )
596+ progress .emit (mix .shape [1 ])
517597
518598
519- if progress_bar :
520- progress_bar .close ()
599+ progress .close ()
521600
522601 estimated_sources = _finalize_overlap (result , counter , length_init , border )
523602
524603 return _sources_to_dict (config , estimated_sources , source_indices )
525604
526605
527- def demix_track_demucs (config , model , mix , device , pbar = False , source_indices = None ):
606+ def demix_track_demucs (config , model , mix , device , pbar = False , source_indices = None , progress_callback = None ):
528607 if _can_demix_mlx_full (model , device ):
529- return demix_track_mlx_full (config , model , mix .cpu ().numpy (), device , pbar = pbar , source_indices = source_indices )
608+ return demix_track_mlx_full (config , model , mix .cpu ().numpy (), device , pbar = pbar , source_indices = source_indices , progress_callback = progress_callback )
530609
531610 source_indices = _normalize_source_indices (config , source_indices )
532611 source_names = _source_names (config )
@@ -543,7 +622,7 @@ def demix_track_demucs(config, model, mix, device, pbar=False, source_indices=No
543622 i = 0
544623 batch_data = []
545624 batch_locations = []
546- progress_bar = tqdm ( total = mix .shape [1 ], desc = "Processing audio chunks" , leave = False ) if pbar else None
625+ progress = _ProgressContext ( pbar , mix .shape [1 ], progress_callback )
547626
548627 while i < mix .shape [1 ]:
549628 part = mix [:, i :i + C ].to (device )
@@ -563,11 +642,12 @@ def demix_track_demucs(config, model, mix, device, pbar=False, source_indices=No
563642 counter [..., start :start + l ] += 1.
564643 batch_data , batch_locations = [], []
565644
566- if progress_bar :
567- progress_bar .update (step )
645+ if progress .bar :
646+ progress .bar .update (step )
647+ progress .emit (min (i , mix .shape [1 ]))
568648
569- if progress_bar :
570- progress_bar . close ( )
649+ progress . close ()
650+ progress . emit ( mix . shape [ 1 ] )
571651
572652 estimated_sources = (result / counter ).cpu ().numpy ()
573653 np .nan_to_num (estimated_sources , copy = False , nan = 0.0 )
@@ -576,13 +656,15 @@ def demix_track_demucs(config, model, mix, device, pbar=False, source_indices=No
576656 return estimated_sources
577657 return _sources_to_dict (config , estimated_sources , source_indices )
578658
579- def demix (config , model , mix : NDArray , device , pbar = False , model_type : str = None , source_indices = None ) -> Dict [str , NDArray ]:
659+ def demix (config , model , mix : NDArray , device , pbar = False , model_type : str = None , source_indices = None , progress_callback = None ) -> Dict [str , NDArray ]:
580660 if _can_demix_mlx_full (model , device ):
581- return demix_track_mlx_full (config , model , mix , device , pbar = pbar , source_indices = source_indices )
661+ return demix_track_mlx_full (config , model , mix , device , pbar = pbar , source_indices = source_indices , progress_callback = progress_callback )
582662 mix = torch .tensor (mix , dtype = torch .float32 )
583663 if model_type in {'demucs' , 'tasnet' , 'legacy_demucs' , 'legacy_tasnet' }:
584664 from .modules .legacy_demucs import apply_legacy_model
585665
666+ progress = _ProgressContext (callback = progress_callback )
667+ progress .emit (0 )
586668 with _autocast (device , config .training .get ('use_amp' , True )):
587669 with torch .inference_mode ():
588670 estimates = apply_legacy_model (
@@ -593,7 +675,8 @@ def demix(config, model, mix: NDArray, device, pbar=False, model_type: str = Non
593675 overlap = float (config .inference .get ('overlap' , 0.25 )),
594676 progress = pbar ,
595677 ).cpu ().numpy ()
678+ progress .emit (1 )
596679 return dict (zip (config .training .instruments , estimates ))
597680 if model_type == 'htdemucs' :
598- return demix_track_demucs (config , model , mix , device , pbar = pbar , source_indices = source_indices )
599- return demix_track (config , model , mix , device , pbar = pbar , source_indices = source_indices )
681+ return demix_track_demucs (config , model , mix , device , pbar = pbar , source_indices = source_indices , progress_callback = progress_callback )
682+ return demix_track (config , model , mix , device , pbar = pbar , source_indices = source_indices , progress_callback = progress_callback )
0 commit comments