03-fft-morphing.py - Performs the spectral morphing 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 spectral morphing of two sounds, by multiplying the
magnitudes, and adding the phases of both sounds.

For a simpler and more efficient process, see the Phase Vocoder
implementation of the spectral morphing: `PVMorph`.

.. code-block:: python

    from pyo import *
    
    s = Server(duplex=0).boot()
    
    # First source
    snd1 = SfPlayer("../snds/baseballmajeur_m.aif", loop=True, mul=0.3).mix(2)
    # Second source
    snd2 = FM(carrier=[75, 100, 125, 150], ratio=[0.999, 0.5005], index=20, mul=0.2).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 magnitudes and phases of input sounds.
    pol1 = CarToPol(fin1["real"], fin1["imag"])
    pol2 = CarToPol(fin2["real"], fin2["imag"])
    
    # Times magnitudes and adds phases
    mag = pol1["mag"] * pol2["mag"] * 200
    pha = pol1["ang"] + pol2["ang"]
    
    # Converts back polar coordinates to cartesian coordinates.
    car = PolToCar(mag, pha)
    
    # Converts the new real and imag parts into a time domain signal.
    fout = IFFT(car["real"], car["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 = size
        fin2.size = size
        fout.size = size
    
    
    s.gui(locals())

