예제 #1
0
 def __init__(self,
              samplerate,
              numVoices          = 16
              ):
     
     numOscillators = SynthParameters.NUM_OSCILLATORS
     
     # Assemble voices
     self.voices = []
     for _ in range(numVoices):
         oscillators     = []
         volumeEnvelopes = []
         filters         = []
         filterEnvelopes = []
         for _ in range(numOscillators):
             oscillators.append(Oscillator(samplerate=samplerate))
             volumeEnvelopes.append(ADSR())
             filters.append(Filter())
             filterEnvelopes.append(ADSR())
         self.voices.append(Voice(oscillators, volumeEnvelopes, filters, filterEnvelopes))
 
     self.LFO = Oscillator(Waveform.SINE, 1, samplerate=samplerate)
     self.LFOToVolume = 0.0
     self.LFOToFilter = 0.0
예제 #2
0
class Synth(object):
    
    def __init__(self,
                 samplerate,
                 numVoices          = 16
                 ):
        
        numOscillators = SynthParameters.NUM_OSCILLATORS
        
        # Assemble voices
        self.voices = []
        for _ in range(numVoices):
            oscillators     = []
            volumeEnvelopes = []
            filters         = []
            filterEnvelopes = []
            for _ in range(numOscillators):
                oscillators.append(Oscillator(samplerate=samplerate))
                volumeEnvelopes.append(ADSR())
                filters.append(Filter())
                filterEnvelopes.append(ADSR())
            self.voices.append(Voice(oscillators, volumeEnvelopes, filters, filterEnvelopes))
    
        self.LFO = Oscillator(Waveform.SINE, 1, samplerate=samplerate)
        self.LFOToVolume = 0.0
        self.LFOToFilter = 0.0
    
    def noteOn(self,
               midiNote):
        # find free voice
        voice = self._getFreeVoice()
        
        # check if voice found
        if voice != None:
            
            """
            print "Voice Id: " + str(voice.id)
            print "isActive() " + str(voice.isActive())
            """
            
            voice.reset()
            voice.midiNote = midiNote
            for volumeEnvelope in voice.volumeEnvelopes:
                volumeEnvelope.noteOn()
            for filterEnvelope in voice.filterEnvelopes:
                filterEnvelope.noteOn()
        
    def noteOff(self,
                midiNote):
        # find correct voice (with correct note)
        voice = None
        
        for v in self.voices:
            if v.midiNote == midiNote and v.isPressed():
                voice = v
                break

        if voice != None:
            
            """
            print "Voice Id: " + str(voice.id)
            print "isActive() " + str(voice.isActive())
            """
            
            for volumeEnvelope in voice.volumeEnvelopes:
                volumeEnvelope.noteOff()
            for filterEnvelope in voice.filterEnvelopes:
                filterEnvelope.noteOff()
    

    
    def getSample(self):
        
        sample = 0.0
        
        # get LFO sample to only advance once
        lfoSample = self.LFO.getSample()
        
        # loop over active voices
        for voice in [voice for voice in self.voices if voice.isActive]:
            # broadcast filter LFO to all voices
            voice.filterLFOMod = clip(lfoSample * self.LFOToFilter, 
                                           -1.0, 
                                           1.0)
            sample += voice.getSample()
            
        
        sample /= len(self.voices) / 4.0
            
        sample *= (lfoSample * self.LFOToVolume + 1.0) * 0.5
        
        # TODO: implement module for effects. Limit here by hand
        sample = clip(sample, -1.0, 1.0)
        
        return sample
        
    def setParameter(self,
                     parameter,
                     value):
        
        if parameter == SynthParameters.OSC_ALL_WAVEFORM:
            setter = partial(self._setParameterOscAllWaveform, value)
        elif parameter == SynthParameters.OSC_1_WAVEFORM:
            setter = partial(self._setParameterOsc1Waveform, value)
        elif parameter == SynthParameters.OSC_2_WAVEFORM:
            setter = partial(self._setParameterOsc2Waveform, value)
        elif parameter == SynthParameters.OSC_3_WAVEFORM:
            setter = partial(self._setParameterOsc3Waveform, value)
        
        elif parameter == SynthParameters.OSC_ALL_GAIN:
            setter = partial(self._setParameterOscAllGain, value)
        elif parameter == SynthParameters.OSC_1_GAIN:
            setter = partial(self._setParameterOsc1Gain, value)
        elif parameter == SynthParameters.OSC_2_GAIN:
            setter = partial(self._setParameterOsc2Gain, value)
        elif parameter == SynthParameters.OSC_3_GAIN:
            setter = partial(self._setParameterOsc3Gain, value)
        
        elif parameter == SynthParameters.OSC_ALL_DETUNE:
            setter = partial(self._setParameterOscAllDetune, value)
        elif parameter == SynthParameters.OSC_1_DETUNE:
            setter = partial(self._setParameterOsc1Detune, value)
        elif parameter == SynthParameters.OSC_2_DETUNE:
            setter = partial(self._setParameterOsc2Detune, value)
        elif parameter == SynthParameters.OSC_3_DETUNE:
            setter = partial(self._setParameterOsc3Detune, value)
        
        elif parameter == SynthParameters.OSC_ALL_CUTOFF:
            setter = partial(self._setParameterOscAllCutoff, value)
        elif parameter == SynthParameters.OSC_ALL_RESONANCE:
            setter = partial(self._setParameterOscAllResonance, value)
        
        elif parameter == SynthParameters.OSC_ALL_FILTER_ENVELOPE_AMOUNT:
            setter = partial(self._setParameterOscAllFilterEnvelopeAmount, value)
        elif parameter == SynthParameters.OSC_ALL_FILTER_ENEVELOPE_ATTACK:
            setter = partial(self._setParameterOscAllFilterEnvelopeAttack, value)
        elif parameter == SynthParameters.OSC_ALL_FILTER_ENEVELOPE_DECAY:
            setter = partial(self._setParameterOscAllFilterEnvelopeDecay, value)
        elif parameter == SynthParameters.OSC_ALL_FILTER_ENEVELOPE_SUSTAIN:
            setter = partial(self._setParameterOscAllFilterEnvelopeSustain, value)
        elif parameter == SynthParameters.OSC_ALL_FILTER_ENEVELOPE_RELEASE:
            setter = partial(self._setParameterOscAllFilterEnvelopeRelease, value)
                
        elif parameter == SynthParameters.OSC_ALL_VOLUME_ENEVELOPE_ATTACK:
            setter = partial(self._setParameterOscAllVolumeEnvelopeAttack, value)
        elif parameter == SynthParameters.OSC_1_VOLUME_ENEVELOPE_ATTACK:
            setter = partial(self._setParameterOsc1VolumeEnvelopeAttack, value)
        elif parameter == SynthParameters.OSC_2_VOLUME_ENEVELOPE_ATTACK:
            setter = partial(self._setParameterOsc2VolumeEnvelopeAttack, value)
        elif parameter == SynthParameters.OSC_3_VOLUME_ENEVELOPE_ATTACK:
            setter = partial(self._setParameterOsc3VolumeEnvelopeAttack, value)
            
        elif parameter == SynthParameters.OSC_ALL_VOLUME_ENEVELOPE_DECAY:
            setter = partial(self._setParameterOscAllVolumeEnvelopeDecay, value)
        elif parameter == SynthParameters.OSC_1_VOLUME_ENEVELOPE_DECAY:
            setter = partial(self._setParameterOsc1VolumeEnvelopeDecay, value)
        elif parameter == SynthParameters.OSC_2_VOLUME_ENEVELOPE_DECAY:
            setter = partial(self._setParameterOsc2VolumeEnvelopeDecay, value)
        elif parameter == SynthParameters.OSC_3_VOLUME_ENEVELOPE_DECAY:
            setter = partial(self._setParameterOsc3VolumeEnvelopeDecay, value)
            
        elif parameter == SynthParameters.OSC_ALL_VOLUME_ENEVELOPE_SUSTAIN:
            setter = partial(self._setParameterOscAllVolumeEnvelopeSustain, value)
            
        elif parameter == SynthParameters.OSC_ALL_VOLUME_ENEVELOPE_RELEASE:
            setter = partial(self._setParameterOscAllVolumeEnvelopeRelease, value)
        elif parameter == SynthParameters.OSC_1_VOLUME_ENEVELOPE_RELEASE:
            setter = partial(self._setParameterOsc1VolumeEnvelopeRelease, value)
        elif parameter == SynthParameters.OSC_2_VOLUME_ENEVELOPE_RELEASE:
            setter = partial(self._setParameterOsc2VolumeEnvelopeRelease, value)
        elif parameter == SynthParameters.OSC_3_VOLUME_ENEVELOPE_RELEASE:
            setter = partial(self._setParameterOsc3VolumeEnvelopeRelease, value)
            
        
        
        # Local parameters (local to Synth)
        elif parameter == SynthParameters.LFO_FREQUENCY:
            self.LFO.frequency = clip(value, 0.0001, float("inf"))
            return
        elif parameter == SynthParameters.LFO_TO_VOLUME:
            self.LFOToVolume = clip(value, -1.0, 1.0)
            return
        elif parameter == SynthParameters.LFO_TO_FILTER:
            self.LFOToFilter = clip(value, -1.0, 1.0)
            return
        
        # Parameter not implemented
        else:
            return
            
        for voice in self.voices:
            setter(voice)
    
    def _getFreeVoice(self):
        voice = None
        for v in self.voices:
            if not v.isActive():
                voice = v
                break
        return voice    
        
        # return next((voice for voice in self.voices if not voice.isActive()), None)
    
    """
    Parameter setter functions
    """
    
    # Oscillator
    
    def _setParameterOscAllWaveform(self,
                                 value,
                                 voice):
        for oscillator in voice.oscillators:
            oscillator.waveform = value
    
    def _setParameterOsc1Waveform(self,
                                 value,
                                 voice):
        voice.oscillators[0].waveform = value
    
    def _setParameterOsc2Waveform(self,
                                 value,
                                 voice):
        voice.oscillators[1].waveform = value
        
    def _setParameterOsc3Waveform(self,
                                 value,
                                 voice):
        voice.oscillators[2].waveform = value
    
    def _setParameterOscAllGain(self,
                                 value,
                                 voice):
        for oscillator in voice.oscillators:
            oscillator.gain = clip(value, 0.0, 1.0)
    
    def _setParameterOsc1Gain(self,
                                 value,
                                 voice):
        voice.oscillators[0].gain = clip(value, 0.0, 1.0)
        
    def _setParameterOsc2Gain(self,
                                 value,
                                 voice):
        voice.oscillators[1].gain = clip(value, 0.0, 1.0)
        
    def _setParameterOsc3Gain(self,
                                 value,
                                 voice):
        voice.oscillators[2].gain = clip(value, 0.0, 1.0)
    
    def _setParameterOscAllDetune(self,
                                 value,
                                 voice):
        for oscillator in voice.oscillators:
            oscillator.detune = value
    
    def _setParameterOsc1Detune(self,
                                 value,
                                 voice):
        voice.oscillators[0].detune = value
    
    def _setParameterOsc2Detune(self,
                                 value,
                                 voice):
        voice.oscillators[1].detune = value
    
    def _setParameterOsc3Detune(self,
                                 value,
                                 voice):
        voice.oscillators[2].detune = value
    
    # Volume envelope
    
    def _setParameterOscAllVolumeEnvelopeAttack(self,
                                          value,
                                          voice):
        for volumeEnvelope in voice.volumeEnvelopes:
            volumeEnvelope.stageValue[Stage.ATTACK] = clip(value, 0.01, float("inf"))
            
    def _setParameterOsc1VolumeEnvelopeAttack(self,
                                          value,
                                          voice):
        voice.volumeEnvelopes[0].stageValue[Stage.ATTACK] = clip(value, 0.01, float("inf"))
        
    def _setParameterOsc2VolumeEnvelopeAttack(self,
                                          value,
                                          voice):
        voice.volumeEnvelopes[1].stageValue[Stage.ATTACK] = clip(value, 0.01, float("inf"))
        
    def _setParameterOsc3VolumeEnvelopeAttack(self,
                                          value,
                                          voice):
        voice.volumeEnvelopes[2].stageValue[Stage.ATTACK] = clip(value, 0.01, float("inf"))
        
    def _setParameterOscAllVolumeEnvelopeDecay(self,
                                         value,
                                         voice):
        for volumeEnvelope in voice.volumeEnvelopes:
            volumeEnvelope.stageValue[Stage.DECAY] = clip(value, 0.01, float("inf"))
            
    def _setParameterOsc1VolumeEnvelopeDecay(self,
                                         value,
                                         voice):
        voice.volumeEnvelopes[0].stageValue[Stage.DECAY] = clip(value, 0.01, float("inf"))
        
    def _setParameterOsc2VolumeEnvelopeDecay(self,
                                         value,
                                         voice):
        voice.volumeEnvelopes[1].stageValue[Stage.DECAY] = clip(value, 0.01, float("inf"))
        
    def _setParameterOsc3VolumeEnvelopeDecay(self,
                                         value,
                                         voice):
        voice.volumeEnvelopes[2].stageValue[Stage.DECAY] = clip(value, 0.01, float("inf"))
        
    def _setParameterOscAllVolumeEnvelopeSustain(self,
                                           value,
                                           voice):
        for volumeEnvelope in voice.volumeEnvelopes:
            volumeEnvelope.stageValue[Stage.SUSTAIN] = clip(value, 0.0, 1.0)
        
    def _setParameterOscAllVolumeEnvelopeRelease(self,
                                           value,
                                           voice):
        for volumeEnvelope in voice.volumeEnvelopes:
            volumeEnvelope.stageValue[Stage.RELEASE] = clip(value, 0.01, float("inf"))
    
    def _setParameterOsc1VolumeEnvelopeRelease(self,
                                           value,
                                           voice):
        voice.volumeEnvelopes[0].stageValue[Stage.RELEASE] = clip(value, 0.01, float("inf"))
            
    def _setParameterOsc2VolumeEnvelopeRelease(self,
                                           value,
                                           voice):
        voice.volumeEnvelopes[1].stageValue[Stage.RELEASE] = clip(value, 0.01, float("inf"))
            
    def _setParameterOsc3VolumeEnvelopeRelease(self,
                                           value,
                                           voice):
        voice.volumeEnvelopes[2].stageValue[Stage.RELEASE] = clip(value, 0.01, float("inf"))
    
    # Filter envelope
    
    def _setParameterOscAllFilterEnvelopeAttack(self,
                                          value,
                                          voice):
        for filterEnvelope in voice.filterEnvelopes:
            filterEnvelope.stageValue[Stage.ATTACK] = clip(value, 0.01, float("inf"))
        
    def _setParameterOscAllFilterEnvelopeDecay(self,
                                         value,
                                         voice):
        for filterEnvelope in voice.filterEnvelopes:
            filterEnvelope.stageValue[Stage.DECAY] = clip(value, 0.01, float("inf"))
        
    def _setParameterOscAllFilterEnvelopeSustain(self,
                                           value,
                                           voice):
        for filterEnvelope in voice.filterEnvelopes:
            filterEnvelope.stageValue[Stage.SUSTAIN] = clip(value, 0.0, 1.0)
        
    def _setParameterOscAllFilterEnvelopeRelease(self,
                                           value,
                                           voice):
        for filterEnvelope in voice.filterEnvelopes:
            filterEnvelope.stageValue[Stage.RELEASE] = clip(value, 0.01, float("inf"))
    
    def _setParameterOscAllFilterEnvelopeAmount(self,
                                          value,
                                          voice):
        for filterEnvelopeAmount in voice.filterEnvelopesAmounts:
            filterEnvelopeAmount = clip(value, -1.0, 1.0)
    
    # Filter
    
    def _setParameterOscAllCutoff(self,
                            value,
                            voice):
        for filter in voice.filters:
            filter.cutoff = clip(value, 0.0, 0.999)
    
    def _setParameterOscAllResonance(self,
                               value,
                               voice):
        for filter in voice.filters:
            filter.resonance = clip(value, 0.0, 1.0)