02-fft-cross-synth.py - Performs the cross-synthesis of two sounds.
============================================================================================================================================


The FFT object analyses an input signal and converts it into the
spectral domain. Three audio signals are sent out of the object,
the real part, from bin 0 (DC) to bin size/2 (Nyquist frequency),
the imaginary part, from bin 0 to bin size/2-1, and the bin number,
an increasing count from 0 to size-1.

This script performs the cross-synthesis of two sounds, by applying the
amplitude of each bin of a sound to the frequency of each bin of a second sound.

For a simpler and more efficient process, see the Phase Vocoder
implementations of the spectral cross synthesis: `PVCross` and `PVMult`.

.. code-block:: python

    from pyo import *
    
    s = Server(duplex=0).boot()
    
    # First source, providing the amplitude envelope (usually with lot of dynamics and variations).
    snd1 = SfPlayer("../snds/baseballmajeur_m.aif", loop=True).mix(2)
    # Second source, the spectral content (usually a rich frequency spectrum with few dynamic variations).
    snd2 = FM(carrier=[75, 100, 125, 150], ratio=[0.999, 0.5005], index=20, mul=0.4).mix(2)
    
    # FFT size in samples
    size = 1024
    # Number of overlaps
    olaps = 4
    
    # Converts the source signals into their spectral representation.
    fin1 = FFT(snd1, size=size, overlaps=olaps)
    fin2 = FFT(snd2, size=size, overlaps=olaps)
    
    # Gets the bin magnitude of the first sound.
    mag = Sqrt(fin1["real"] * fin1["real"] + fin1["imag"] * fin1["imag"], mul=10)
    # Scales `real` and `imag` parts of the second sound by the magnitude of the first one.
    real = fin2["real"] * mag
    imag = fin2["imag"] * mag
    
    # Converts the new real and imag parts into a time domain signal.
    fout = IFFT(real, imag, size=size, overlaps=olaps).mix(2).out()
    
    
    # Change of FFT size must be done on all FFT and IFFT objects at the same time!
    def setSize(x):
        fin1.size = x
        fin2.size = x
        fout.size = x
    
    
    s.gui(locals())

