Python custom generator of object not efficient
Your ifs structure is needlessly complicated. They only set r1 and r2 based on simple rules (r1 [resp. r2] is 0.1 if SB1.fq [resp. SB2.fq] is lower than 100 and 0.2 otherwise) and compute upper1 and upper2 using the same formula. So you can use the simpler:

r1 = 0.1 if SB1.fq &lt;= 100 else 0.2
r2 = 0.1 if SB2.fq &lt;= 100 else 0.2
upper1 = (1 + r1) * SB1.fq + frequency_step
upper2 = (1 + r2) * SB2.fq + frequency_step


You can also use min to make these values not go over upper_frequency. But this is still some redundancies, especially given the fact that, later, you use r1 &amp; SB1 and r2 &amp; SB2 in the same kind of pattern in your ranges. So better extract out a function:

def frequency_range(SB, step, higher_frequency):
    r = 0.1 if SB.fq &lt;= 100 else 0.2
    high = (1 + r) * SB.fq + step
    low = (1 - r) * SB.fq
    return range(int(low), int(min(high, higher_frequency)))


And the main function is now:

def duo_SBs_to_test(SB1, SB2, frequency_step=1, shift_step=50, max_shift=20000, permutations=True):
    max_phases = max(sum(SB1.phases), sum(SB2.phases))
    upper_frequency = frequency_step + 1/(2 * max_phases) * 1000000

    parameters = itertools.product(
            range(0, max_shift + shift_step, shift_step),
            frequency_range(SB1, frequency_step, upper_frequency),
            frequency_range(SB2, frequency_step, upper_frequency))

    for s, f1, f2 in parameters:
        yield Signal(f1, SB1.phase), Signal(f2, SB2.phase), s
        if permutations:
            yield Signal(f2, SB2.phase), Signal(f1, SB1.phase), s


Now the only little change that I can think of that could improve performances is to avoid testing permutations at each iteration. So you could perform two "radicaly" different iterations depending on the value of permutations:

def duo_SBs_to_test(SB1, SB2, frequency_step=1, shift_step=50, max_shift=20000, permutations=True):
    max_phases = max(sum(SB1.phases), sum(SB2.phases))
    upper_frequency = frequency_step + 1/(2 * max_phases) * 1000000

    parameters = itertools.product(
            range(0, max_shift + shift_step, shift_step),
            frequency_range(SB1, frequency_step, upper_frequency),
            frequency_range(SB2, frequency_step, upper_frequency))

    if permutations:
        for s, f1, f2 in parameters:
            yield Signal(f1, SB1.phase), Signal(f2, SB2.phase), s
            yield Signal(f2, SB2.phase), Signal(f1, SB1.phase), s
    else:
        for s, f1, f2 in parameters:
            yield Signal(f1, SB1.phase), Signal(f2, SB2.phase), s




Now, as regard to your next step, you’re basically just reinventing filter. Just use that instead:

def compute(SB1, SB2, frequency_step = 1, shift_step = 50, max_shift = 20000, permutations = True):
    return list(filter(condition, duo_SBs_to_test(SB1, SB2, frequency_step, shift_step, max_shift, permutations))


And if that compute function is called in a for loop, you can also remove the need to convert it to a list.