def copy_elements(elements):
    """Returns a deep copy of a list of elements"""
    new_elements = []
    for e in elements:
        if isinstance(e, Gain):
            new_elements.append(Gain())
        elif isinstance(e, UnitDelay):
            new_elements.append(UnitDelay())
        elif isinstance(e, Delay):
            new_elements.append(Delay(e.length))
        elif isinstance(e, Split):
            chains = []
            for chain in e.elements:
                chains.append(copy_elements(chain))
            new_elements.append(Split(chains))
        elif isinstance(e, Feedback):
            fb_elements = copy_elements(e.elements)
            new_elements.append(Feedback(fb_elements))

    return new_elements
"""
Benchmark test for the speed of the parameter estimation iteration function
"""

import os,sys
sys.path.append(os.path.abspath('crossroads_scripts'))
from param_estimation import get_error_for_model, get_error_for_model_vst
from  gen_faust import Model, Split, Gain, UnitDelay
import numpy as np
import time

# Test model
model = Model()
model.elements.append(Split([[Gain(), Gain()], [UnitDelay(), Gain()], [Gain(0.2)]]))
name = 'test'

# Constants
plugin = 'bench'
orig_file = 'audio_files/drums.wav'
out_file = 'audio_files/bench.wav'
N = 50
params, bounds = model.get_params()

# Time loop
tick = time.time()
for _ in range(N):
    err = get_error_for_model(params, model, plugin, orig_file, out_file, 'audio_files/drums.wav')
    
time = time.time() - tick
time_per_iter = time / N
Exemple #3
0
    exit(1)


print('Test basic')
model1 = Model()
model1.elements.append(Gain())
model2 = Model()
model2.elements.append(UnitDelay())

target = Model()
target.elements.append(Gain())
test_success(model1, model2, target)

print('Test Comb Filter')
model1 = Model()
model1.elements.append(Split([[], [Delay(4), Gain()]]))
model1.elements.append(Gain())
model2 = Model()
model2.elements.append(Split([[], [Delay(5), Gain()]]))

target = Model()
target.elements.append(Split([[], [Delay(5), Gain()]]))
target.elements.append(Gain())
test_success(model1, model2, target, num=15)

print('Test FIR Filter')
model1 = Model()
model1.elements.append(
    Split([[UnitDelay(), Gain()], [Delay(2), Gain()], [Delay(3),
                                                       Gain()],
           [Delay(4), Gain()]]))
def get_evolved_structure(plugin, dry_file, wet_file, des_file, tol=1e-5):
    """
    Evolve a structure for an audio effect that processes the dry audio
    to sound like the desired audio
    """
    N_pop = 4
    N_gens = 10
    N_survive = 3

    res = os.system('mkdir {}'.format(plugin))
    if (res > 0):
        exit(res)

    # create initial model parents
    models = []

    model1 = Model()
    model1.elements.append(Gain())
    models.append(model1)

    model2 = Model()
    model2.elements.append(UnitDelay())
    models.append(model2)

    model3 = Model()
    model3.elements.append(Split([[Gain()], [UnitDelay(), Gain()]]))
    models.append(model3)

    # create initial generation
    models = create_generation(models, N_pop, N_survive)

    gen_num = 0
    converge = False
    elapsed = time.time()
    while gen_num < N_gens:
        # test current generation
        print('Testing generation: {}'.format(gen_num))
        for n in range(N_pop):
            print(models[n])

        pool = mp.Pool(mp.cpu_count())
        results = pool.starmap(
            compute_model_fitness,
            [(models[n], plugin + f'_{n}', dry_file,
              wet_file[:-4] + f'_{n}' + wet_file[-4:], des_file, tol)
             for n in range(N_pop)])
        pool.close()

        errors = np.zeros(N_pop)
        models = []
        for n in range(N_pop):
            errors[n] = results[n][0]
            models.append(results[n][1])

        # sort
        aridxs = np.argsort(errors)
        errors = errors[aridxs]
        models = [models[i] for i in aridxs]

        # reorganize to prefer smaller structures
        n_perfect = 0
        for n in range(N_survive):
            if errors[n] < 5.0e-07: n_perfect += 1

        if n_perfect > 1:
            n_params = []
            for n in range(n_perfect):
                params, _ = models[n].get_params()
                n_params.append(len(params))

            aridxs = np.argsort(n_params)
            errors[:n_perfect] = errors[:n_perfect][aridxs]
            models[:n_perfect] = [models[:n_perfect][i] for i in aridxs]

        # save surviving faust files and plugins for later analysis
        for n in range(N_survive):
            models[n].write_to_file(plugin + '.dsp')
            compile_plugin(plugin)
            os.system('cp -R faust_plugins/{} {}/gen{}_{}'.format(
                plugin, plugin, gen_num, n))
            os.system('cp faust_scripts/{}.dsp {}/gen{}_{}/'.format(
                plugin, plugin, gen_num, n))

        # Take survivors
        errors = errors[:N_survive]
        models = models[:N_survive]

        print('Surviving errors: {}'.format(errors))

        # check for correct answer
        if errors[0] <= tol:
            converge = True
            break

        # mutate off survivors
        if N_pop < 24:
            N_pop += 4
        create_generation(models, N_pop, N_survive)

        gen_num += 1

    if converge:
        print('Converged!')
    else:
        print('Not Converged')

    print('Best error: {}'.format(errors[0]))
    print('Time elapsed: {}'.format(time.time() - elapsed))

    # Save final faust script and plugin
    models[0].write_to_file(plugin + '.dsp')
    compile_plugin(plugin)
    test_plugin(plugin, dry_file, wet_file)
    os.system('cp -R faust_plugins/{} {}/gen_final'.format(plugin, plugin))
    os.system('cp faust_scripts/{}.dsp {}/gen_final/'.format(plugin, plugin))

    return models[0]
def get_mutated_model(parent1, parent2):
    """Create a new model by mutating existing models"""

    strategy = random.choice(
        mutation_strategies
    )  # choose strategy randomly (eventually maybe use weighting?)
    new_model = Model()

    print('Mutating with strategy: ' + strategy)

    if strategy == 'concat_series':  # create new model with parent1 in series with parent2
        if bool(random.getrandbits(1)):
            new_model.elements = copy_elements(
                parent1.elements) + copy_elements(parent2.elements)
        else:
            new_model.elements = copy_elements(
                parent2.elements) + copy_elements(parent1.elements)

    elif strategy == 'concat_parallel':  # create new model with parent1 in parallel with parent2
        new_model.elements.append(
            Split([
                copy_elements(parent1.elements),
                copy_elements(parent2.elements)
            ]))

    # create new model by adding new element to random location in parent
    elif strategy == 'add_gain':
        parent_to_add = random.choice([parent1, parent2])
        new_model.elements = copy_elements(parent_to_add.elements)
        add_element(new_model, Gain())

    elif strategy == 'add_delay':
        parent_to_add = random.choice([parent1, parent2])
        new_model.elements = copy_elements(parent_to_add.elements)
        add_element(new_model, UnitDelay())

    elif strategy == 'add_nl':
        parent_to_add = random.choice([parent1, parent2])
        new_model.elements = copy_elements(parent_to_add.elements)
        add_element(new_model, CubicNL())

    elif strategy == 'add_split':
        parent_to_add = random.choice([parent1, parent2])
        new_model.elements = copy_elements(parent_to_add.elements)
        add_element(new_model, Split([[Gain()], [UnitDelay(), Gain()]]))

    elif strategy == 'add_chain':  # add new chain to existing parallel structure in parent
        parent_to_add = random.choice([parent1, parent2])
        new_model.elements = copy_elements(parent_to_add.elements)

        split_idxs = []
        for i, e in enumerate(new_model.elements):
            if isinstance(e, Split):
                split_idxs.append(i)

        if split_idxs == []:
            print('No Splits to add to! Mutating again...')
            return get_mutated_model(parent1, parent2)

        split_idx = random.choice(split_idxs)
        new_model.elements[split_idx].elements.append([UnitDelay(), Gain()])

    else:
        print('Warning: unknown mutation strategy selected')
        new_model.elements.append(UnitDelay())

    new_model.trim_model()  # trim unnecessary or repetetive elements of model

    return new_model
modelTP = Model()
fb = FB2()
fb.pole_mag = pole_mag
fb.pole_angle = pole_angle
modelTP.elements.append(fb)
add_to_tests(modelTP, 'Two-pole-test', yTP, ys, names, models)

# Lowpass filter
b, a = adsp.design_LPF2(1000, 0.7071, fs)
yLPF = np.zeros(np.shape(x))
yLPF[:, 0] = signal.lfilter(b, a, x[:, 0])
yLPF[:, 1] = signal.lfilter(b, a, x[:, 1])

modelLPF = Model('DF2_Test')
modelLPF.elements.append(
    Feedback([Split([[Gain(a[1])], [UnitDelay(), Gain(a[2])]]),
              Gain(-1.0)]))
modelLPF.elements.append(
    Split([[Gain(b[0])], [UnitDelay(), Gain(b[1])],
           [UnitDelay(), UnitDelay(), Gain(b[2])]]))
add_to_tests(modelLPF, 'test_DF2', yLPF, ys, names, models)

for n in range(len(models)):
    print(f'Generating Faust for: {names[n]}')
    print(models[n])

    # Write to file and compile
    models[n].write_to_file(f'{names[n]}.dsp')
    compile_plugin(f'{names[n]}')

    # Test
model1 = Model()
model1.elements.append(Gain())
add_to_tests(model1, 'gain', y1, ys, names, models)

# Delay / Comb filter
delay_amt = 5  # samples
mix = -0.5
del_sig = np.zeros(np.shape(x))
N = len(x[:, 0])
del_sig[delay_amt:, 0] = x[:N - delay_amt, 0]
del_sig[delay_amt:, 1] = x[:N - delay_amt, 1]
y2 = 0.5 * (x + del_sig * mix)

model2 = Model()
model2.elements.append(Split([[], [Delay(5), Gain(0.9)]]))
model2.elements.append(Gain(-0.1))
add_to_tests(model2, 'delay', y2, ys, names, models)

# 4th-order FIR filter
b = [0.3, -0.4, 0.12, 0.2, -0.75]
y3 = np.zeros(np.shape(x))
y3[:, 0] = signal.lfilter(b, [1], x[:, 0])
y3[:, 1] = signal.lfilter(b, [1], x[:, 1])

model3 = Model()
model3.elements.append(
    Split([[Gain()], [UnitDelay(), Gain()], [Delay(2), Gain()],
           [Delay(3), Gain()], [Delay(4), Gain()]]))
add_to_tests(model3, 'FIR filter', y3, ys, names, models)