Saturday 15 February 2014

Sython - sound from Python

A quick note that SFPL has been replaced with Python! 

All the processors are the same but the syntax is simply adding new classes and methods to Python via the Jython Java port.   As of just now - I have even gotten the Do (thing Execute/Future) semantics for multi-threading running

Whilst SF will never be 'main stream' I hope that it being based on Python will make it more approachable. It also opens up the possibility of very much more complex synthesis and processing options.

Note: how easy it is to perform processing in parallel:

sf_do(saturateNode_)

I will discuss closures and do semantics in the next post.

Here is an example of Sython:

import math
import random

execfile("patches/python/concurrent.py")

def fixSize(signal):
    mag=sf.MaxValue(signal)
    return sf.NumericVolume(signal,1.0/mag)
 
def fixSizeSat(signal):
     return fixSize(sf.Saturate(fixSize(signal)))
    
def saturatedNode(pitch,a,d,s,r,v):
    def saturateNode_():
        l=a+d+s+r
        signal1=sf.SineWave(l,pitch)
        signal2=sf.SineWave(l,2*pitch*1.003)
        signal3=sf.SineWave(l,3*pitch*1.005)
        envelope= sf.NumericShape(
                 (0,0),
                 (a,1),
                 (a+d,0.75),
                 (a+d+s,0.25),
                 (a+d+s+r,0)
        )
        sat=(20-pitch/1000)
        if sat<1:
            sat=1
            
        def doSat(sigIn):
            temp=sf.NumericVolume(sf.Multiply(sigIn,envelope),sat)
            return sf.Normalise(sf.Clean(sf.Saturate(temp)))
        
        signal=sf.Mix(
            doSat(signal1),
            sf.DB_6(doSat(signal2)),
            sf.DB_15(doSat(signal3))
        )
        signal=fixSize(signal)
        hf=sf.Clip(sf.NumericVolume(signal,3))
    
        r1=fixSizeSat(sf.RBJPeaking(hf,pitch*1.3,0.5,75))
        r2=fixSizeSat(sf.RBJPeaking(hf,pitch*2.1,0.5,75))
        r3=fixSizeSat(sf.RBJPeaking(hf,pitch*2.9,0.5,75))
    
        signal=sf.Mix(
            sf.DB_6(signal),
            sf.DB_1(r1),
            sf.DB_4(r2),
            sf.DB_6(r3)
        )
        signal=sf.Clean(sf.NumericVolume(signal,v))
        envelope= sf.NumericShape(
                 (0,1),
                 (a+d+s+r-125,1),
                 (a+d+s+r,0)
        )
        print "Returing from do task"   
        return sf.Multiply(envelope,signal)
    return sf_do(saturateNode_)

all=[sf.Silence(100)]

for x in range(12, 32):
    signal=saturatedNode(math.pow(2,x*0.325),125,500,1000,2500,1)
    print "All:" + all.__str__() + " , " + "Signal: " + signal.__str__()
    all.append(signal)

all=sf.Concatenate(all)
random.seed(0.128)
all=sf.Normalise(all)
sf.WriteFile32((all,all),"temp/temp.wav")
shutdownConcurrnt()

The above produces this waveform:


No comments:

Post a Comment