import random
class Module(BaseModule):
    """
    "Pulsar synthesis module"
    
    Description

    This module implements the classic pulsar synthesis.

    Sliders

        # Base Frequency : 
            Base pitch of the synthesis
        # Pulsar Width : 
            Amount of silence added to one period
        # Detune Factor : 
            Amount of jitter applied to the pitch
        # Detune Speed : 
            Speed of the jitter applied to the pitch
    
    Graph Only
    
        # Overall Amplitude : 
            The amplitude curve applied on the total duration of the performance

    Popups & Toggles
    
        # Wave Shape : 
            Shape used for the synthesis
        # Custom Wave : 
            Define a custom wave shape by entering amplitude values
        # Window Type : 
            Pulsar envelope

    """
    def __init__(self):
        BaseModule.__init__(self)
        self.customtable = self.custom_value
        self.wavetable = HarmTable(size=8192)
        self.wind = WinTable(type=self.wtype_index, size=8192)
        self.rnd1 = Randi(min=1-self.detune, max=1+self.detune, freq=self.detunesp)
        self.rnd2 = Randi(min=1-self.detune, max=1+self.detune, freq=self.detunesp)
        self.polyfreqs = self.polyphony_spread
        self.ply1 = [self.bfreq*i*self.rnd1 for i in self.polyfreqs]
        self.ply2 = [self.bfreq*i*self.rnd2 for i in self.polyfreqs]
        self.ply3 = [self.bfreq*i for i in self.polyfreqs for j in range(self.nchnls)]
        self.pfreqs = self.ply3+self.ply1+self.ply2
        self.pul = Pulsar(self.wavetable, self.wind, freq=self.pfreqs, frac=self.width, 
                          phase=0, interp=4, mul=0.1*self.polyphony_scaling*self.env)
        self.out = Mix(self.pul, voices=self.nchnls)

        #INIT
        self.wavedict = {'Sine':[1], 'Sawtooth':[1, 0.5, 0.333, 0.25, 0.2, 0.167, 0.143, 0.111, 0.1], 'Square':[1, 0, 0.333, 0, 0.2, 0, 0.143, 0, 0.111],
                            'Complex1':[1, 0, 0, 0, 0.3, 0, 0, 0, 0.2, 0, 0, 0.05], 'Complex2':[1, 0, 0, 0.3, 0, 0, 0.2, 0, 0, 0, 0, 0.1, 0, 0, 0.05, 0, 0, 0.02],
                            'Complex3':[1, 0, 0, 0.2, 0, 0.1, 0, 0, 0, 0.3, 0, 0.1, 0, 0, 0.05, 0, 0, 0.1, 0, 0.05, 0, 0, 0, 0.05, 0, 0, 0.02],
                            'Custom':self.customtable}

        self.shape(self.shape_index, self.shape_value)

    def shape(self, index, value):
        self.wavetable.replace(self.wavedict[value])

    def custom(self, value):
        self.wavedict['Custom'] = value

    def wtype(self, index, value):
        self.wind.type = index

Interface = [   cgraph(name="env", label="Overall Amplitude", func=[(0,1),(1,1)], col="blue"),
                cslider(name="bfreq", label="Base Frequency", min=0.1, max=1000, init=100, rel="log", unit="Hz", col="blue"),
                cslider(name="width", label="Pulsar Width", min=0.01, max=1, init=0.5, rel="lin", unit="x", col="green4"),
                cslider(name="detune", label="Detune Factor", min=0.0001, max=0.999, init=0.005, rel="log", unit="x", col="red"),
                cslider(name="detunesp", label="Detune Speed", min=0.0001, max=100, init=0.3, rel="log", unit="Hz", col="red"),
                cpopup(name="wtype", label="Window Type", init="Tuckey", col="orange4", value=["Rectangular", "Hamming", "Hanning", 
                            "Bartlett", "Blackman 3", "Blackman 4", "Blackman 7", "Tuckey", "Sine"]),
                cpopup(name="shape", label="Wave Shape", init="Sine", col="green", value=["Sine","Sawtooth","Square","Complex1", "Complex2", "Complex3", "Custom"]),
                cgen(name="custom", label="Custom Wave", init=[1,0,0.5,0.3,0,0,0.2,0,0.1,0,0.09,0,0.05], popup=("shape", 6), col="green2"),
                cpoly()
          ]

