""" Implementation of Audio Effects Chain Manipulation for the task 'Mixing Style Transfer' """ from glob import glob import os import sys currentdir = os.path.dirname(os.path.realpath(__file__)) sys.path.append(currentdir) sys.path.append(os.path.dirname(currentdir)) from common_audioeffects import * from common_dataprocessing import create_dataset # create augmentation effects chain according to targeted effects with their applying probability def create_effects_augmentation_chain(effects, \ ir_dir_path=None, \ sample_rate=44100, \ shuffle=False, \ parallel=False, \ parallel_weight_factor=None): ''' Args: effects (list of tuples or string) : First tuple element is string denoting the target effects. Second tuple element is probability of applying current effects. ir_dir_path (string) : directory path that contains directories of impulse responses organized according to RT60 sample_rate (int) : using sampling rate shuffle (boolean) : shuffle FXs inside current FX chain parallel (boolean) : compute parallel FX computation (alpha * input + (1-alpha) * manipulated output) parallel_weight_factor : the value of alpha for parallel FX computation. default=None : random value in between (0.0, 0.5) ''' fx_list = [] apply_prob = [] for cur_fx in effects: # store probability to apply current effects. default is to set as 100% if isinstance(cur_fx, tuple): apply_prob.append(cur_fx[1]) cur_fx = cur_fx[0] else: apply_prob.append(1) # processors of each audio effects if isinstance(cur_fx, AugmentationChain) or isinstance(cur_fx, Processor): fx_list.append(cur_fx) elif cur_fx.lower()=='gain': fx_list.append(Gain()) elif 'eq' in cur_fx.lower(): fx_list.append(Equaliser(n_channels=2, sample_rate=sample_rate)) elif 'comp' in cur_fx.lower(): fx_list.append(Compressor(sample_rate=sample_rate)) elif 'expand' in cur_fx.lower(): fx_list.append(Expander(sample_rate=sample_rate)) elif 'pan' in cur_fx.lower(): fx_list.append(Panner()) elif 'image'in cur_fx.lower(): fx_list.append(MidSideImager()) elif 'algorithmic' in cur_fx.lower(): fx_list.append(AlgorithmicReverb(sample_rate=sample_rate)) elif 'reverb' in cur_fx.lower(): # apply algorithmic reverberation if ir_dir_path is not defined if ir_dir_path==None: fx_list.append(AlgorithmicReverb(sample_rate=sample_rate)) # apply convolution reverberation else: IR_paths = glob(f"{ir_dir_path}*/RT60_avg/[!0-]*") IR_list = [] IR_dict = {} for IR_path in IR_paths: cur_rt = IR_path.split('/')[-1] if cur_rt not in IR_dict: IR_dict[cur_rt] = [] IR_dict[cur_rt].extend(create_dataset(path=IR_path, \ accepted_sampling_rates=[sample_rate], \ sources=['impulse_response'], \ mapped_sources={}, load_to_memory=True, debug=False)[0]) long_ir_list = [] for cur_rt in IR_dict: cur_rt_len = int(cur_rt.split('-')[0]) if cur_rt_len < 3000: IR_list.append(IR_dict[cur_rt]) else: long_ir_list.extend(IR_dict[cur_rt]) IR_list.append(long_ir_list) fx_list.append(ConvolutionalReverb(IR_list, sample_rate)) else: raise ValueError(f"make sure the target effects are in the Augment FX chain : received fx called {cur_fx}") aug_chain_in = [] for cur_i, cur_fx in enumerate(fx_list): normalize = False if isinstance(cur_fx, AugmentationChain) or cur_fx.name=='Gain' else True aug_chain_in.append((cur_fx, apply_prob[cur_i], normalize)) return AugmentationChain(fxs=aug_chain_in, shuffle=shuffle, parallel=parallel, parallel_weight_factor=parallel_weight_factor) # create audio FX-chain according to input instrument def create_inst_effects_augmentation_chain(inst, \ apply_prob_dict, \ ir_dir_path=None, \ algorithmic=False, \ sample_rate=44100): ''' Args: inst (string) : FXmanipulator for target instrument. Current version only distinguishes 'drums' for applying reverberation apply_prob_dict (dictionary of (FX name, probability)) : applying proababilities for each FX ir_dir_path (string) : directory path that contains directories of impulse responses organized according to RT60 algorithmic (boolean) : rather to use algorithmic reverberation (True) or convolution reverberation (False) sample_rate (int) : using sampling rate ''' reverb_type = 'algorithmic' if algorithmic else 'reverb' eq_comp_rand = create_effects_augmentation_chain([('eq', apply_prob_dict['eq']), ('comp', apply_prob_dict['comp'])], \ ir_dir_path=ir_dir_path, \ sample_rate=sample_rate, \ shuffle=True) pan_image_rand = create_effects_augmentation_chain([('pan', apply_prob_dict['pan']), ('imager', apply_prob_dict['imager'])], \ ir_dir_path=ir_dir_path, \ sample_rate=sample_rate, \ shuffle=True) if inst=='drums': # apply reverberation to low frequency with little probability low_pass_eq_params = ParameterList() low_pass_eq_params.add(Parameter('high_shelf_gain', -50.0, 'float', minimum=-50.0, maximum=-50.0)) low_pass_eq_params.add(Parameter('high_shelf_freq', 100.0, 'float', minimum=100.0, maximum=100.0)) low_pass_eq = Equaliser(n_channels=2, \ sample_rate=sample_rate, \ bands=['high_shelf'], \ parameters=low_pass_eq_params) reverb_parallel_low = create_effects_augmentation_chain([low_pass_eq, (reverb_type, apply_prob_dict['reverb']*0.01)], \ ir_dir_path=ir_dir_path, \ sample_rate=sample_rate, \ parallel=True, \ parallel_weight_factor=0.8) # high pass eq for drums reverberation high_pass_eq_params = ParameterList() high_pass_eq_params.add(Parameter('low_shelf_gain', -50.0, 'float', minimum=-50.0, maximum=-50.0)) high_pass_eq_params.add(Parameter('low_shelf_freq', 100.0, 'float', minimum=100.0, maximum=100.0)) high_pass_eq = Equaliser(n_channels=2, \ sample_rate=sample_rate, \ bands=['low_shelf'], \ parameters=high_pass_eq_params) reverb_parallel_high = create_effects_augmentation_chain([high_pass_eq, (reverb_type, apply_prob_dict['reverb'])], \ ir_dir_path=ir_dir_path, \ sample_rate=sample_rate, \ parallel=True, \ parallel_weight_factor=0.6) reverb_parallel = create_effects_augmentation_chain([reverb_parallel_low, reverb_parallel_high], \ ir_dir_path=ir_dir_path, \ sample_rate=sample_rate) else: reverb_parallel = create_effects_augmentation_chain([(reverb_type, apply_prob_dict['reverb'])], \ ir_dir_path=ir_dir_path, \ sample_rate=sample_rate, \ parallel=True) # full effects chain effects_chain = create_effects_augmentation_chain([eq_comp_rand, \ pan_image_rand, \ reverb_parallel, \ ('gain', apply_prob_dict['gain'])], \ ir_dir_path=ir_dir_path, \ sample_rate=sample_rate) return effects_chain