class Module(BaseModule):
    """
    "Phase vocoder buffer with bin independent speed playback"

    Description

    This module pre-analyses the input sound and keeps the
    phase vocoder frames in a buffer for the playback. User
    has control on playback position independently for every 
    frequency bin.
    
    Sliders
    
        # Low Bin Speed : 
            Lowest bin speed factor
        # High Bin Speed : 
            Highest bin speed factor

        * For random distribution, these values are the 
          minimum and the maximum of the distribution.

    Graph Only
    
        # Overall Amplitude : 
            The amplitude curve applied on the total duration of the performance
            
    Popups & Toggles

        # Reset : 
            Reset pointer positions to the beginning of the buffer.
        # Speed Distribution : 
            Speed distribution algorithm.
        # FFT Size : 
            Size, in samples, of the FFT
        # FFT Envelope : 
            Windowing shape of the FFT
        # FFT Overlaps : 
            Number of FFT overlaping analysis
        # Polyphony Voices : 
            Number of voices played simultaneously (polyphony), 
            only available at initialization time
        # Polyphony Spread : 
            Pitch variation between voices (chorus), 
            only available at initialization time

    """
    def __init__(self):
        BaseModule.__init__(self)
        self.snd = self.addSampler("snd")
        snddur = self.getSamplerDur("snd")
        self.server.startoffset = snddur

        size = int(self.fftsize_value)
        olaps = int(self.overlaps_value)
        wintype = self.wtype_index
        mode = self.mode_index

        self.fin = PVAnal(self.snd, size=size, overlaps=olaps, wintype=wintype)
        self.buf = PVBufLoops(self.fin, self.low, self.high, mode, length=snddur)
        self.fout = PVSynth(self.buf, wintype=wintype, mul=self.env)

        self.fade = SigTo(value=1, time=.05, init=1)
        self.out = Sig(self.fout, mul=self.fade)

    def reset(self, value):
        if value:
            self.buf.reset()

    def mode(self, index, value):
        self.buf.mode = index

    def wtype(self, index, value):
        self.fin.wintype = index
        self.fout.wintype = index

Interface = [   csampler(name="snd"), 
                cgraph(name="env", label="Overall Amplitude", func=[(0,1),(1,1)], col="blue"),
                cslider(name="low", label="Low Bin Speed", min=0, max=2, init=0.9, rel="lin", unit="x", col="green1"),
                cslider(name="high", label="High Bin Speed", min=0, max=2, init=1.1, rel="lin", unit="x", col="green2"),
                cbutton(name="reset", label="Reset", col="blue2"),
                cpopup(name="mode", label="Speed Distribution", init="Linear", col="blue2",
                        value=["Linear", "Exponential", "Logarithmic", "Random", "Rand Exp Min", "Rand Exp Max", "Rand Bi-Exp"]),
                cpopup(name="fftsize", label="FFT Size", init="1024", rate="i", value=["16", "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192"], col="red"),
                cpopup(name="wtype", label="FFT Envelope", init="Hanning", col="red", value=["Rectangular", "Hamming", "Hanning", "Bartlett",
                            "Blackman 3", "Blackman 4", "Blackman 7", "Tuckey", "Sine"]),
                cpopup(name="overlaps", label="FFT Overlaps", rate="i", init="4", col="red", value=["1", "2", "4", "8", "16"]),
                cpoly()
          ]

