Ultimate Crash Server FoxDot python custom functions

Find here some python functions, sometimes useful, to boost Foxdot. You can also see our tutorial on how to create new Foxdot function.

@@@ Loop Pattern Generator @@@

>> PBin(number)

@loop_pattern_method
def PBin(number):
    """ convert a number to a binary list Pattern """
    return [int(i) for i in str(bin(number)[2:])]
    
example :
d1 >> play("x", amp=PBin(21456))

>> PTime()

@loop_pattern_method
def PTime():
    """ Generate a pattern from the local machine time """
    return [int(t) for t in str(Clock.get_time_at_beat(int(Clock.now()))) if t != '.']
    
example :
b1 >> blip(PTime(), dur=1/2)

>> PTimebin()

@loop_pattern_method
def PTimebin():
    """ Generate a pattern of actual time converted to binary """
    return PBin(int(Clock.get_time_at_beat(int(Clock.now()))))

example :
b1 >> blip(PTime(), dur=1/4, amp=PTimebin())

@@@ Global Functions @@@

>> lininf(start, finish, duration)

def lininf(start=0, finish=1, time=32):
    ''' linvar from start to finish but stay at finish after time '''
    return linvar([start,finish],[time,inf], start=now)

def expinf(start=0, finish=1, time=32):
    ''' expvar from start to finish but stay at finish after time '''
    return expvar([start,finish],[time,inf], start=now)


example :
b1 >> blip(lininf(0,7,32), dur=1/2, amp=lininf())
Clock.bpm = expinf(42,220,32)

>> linbpm(targetBpm, duration)

def linbpm(endBpm=170, durBpm=128):
    ''' use with Clock.bpm = linbpm(220, 12) to change from current bpm to target bpm in x beats'''
    Clock.bpm = linvar([Clock.bpm,endBpm],[durBpm,inf], start=now)

example :
Clock.bpm = linbpm(220,32)

>> masterAll(args, value)

def masterAll(args = "dur", value=1):
	""" change all active players args, restore with all previous value """
	global valueDict
	if args != "reset":
		for p in Clock.playing:
			if p in valueDict:
				if args in valueDict[p]:
					pass
				else:
					try:
						valueDict[p][args] = p.__getitem__(args)
					except:
						valueDict[p][args] = 0
			else:
				valueDict[p] = {}
				try:
					valueDict[p][args] = p.__getitem__(args)
				except:
					valueDict[p][args] = 0
			p.__setattr__(args, value)
	else:
		for k,v in valueDict.items():
			for l, w in v.items():
				try:
					k.__setattr__(l, w)
				except:
					pass
		valueDict = {}


example :

d1 >> play("x-", dur=PDur(5,8))
b2 >> blip([0,2,4,2] , dur=PDur(3,8))

masterAll("dur", 1)  ## set all dur to 1
masterAll("reset")  ## reset to previous values

@@@ Random Generator @@@

>> PGauss(mean, deviation)

class PGauss(RandomGenerator):
	''' Returns random floating point values using Gaussian distribution '''
	def __init__(self, mean=0, deviation=1, **kwargs):
		RandomGenerator.__init__(self, **kwargs)
		self.args = (mean, deviation)
		self.mean = mean
		self.deviation = deviation
		self.init_random(**kwargs)
	def func(self, index):
		if isinstance(self.mean, float):
			return gauss(self.mean, self.deviation)
		elif isinstance(self.mean, int):
			return int(round(gauss(self.mean, self.deviation)))


example :
b2 >> dbass(PGauss(0,2), dur=PDur(5,8))

>> PCoin(low, high, proba)

class PCoin(RandomGenerator):
	''' Choose between 2 values with probability, eg : PCoin(0.25,2,0.2)'''
	def __init__(self, low=0, high=1, proba=0.5, **kwargs):
		RandomGenerator.__init__(self, **kwargs)
		self.init_random(**kwargs)
		self.low = low
		self.high = high
		self.proba = proba
	def func(self, index):
		return choices([self.low, self.high], [1-self.proba, self.proba])[0]

example :
b2 >> dbass(PGauss(0,2), dur=PDur(5,8), amp=PCoin(0,1,0.8))

>> PChar(case, alpha)

class PChar(RandomGenerator):
	''' Generate characters randomly, PChar(case, alpha)
	case = 0 , only lowercase
	case = 1 , only uppercase
	case = 2 , lower case and uppercase
	alpha = 0, only alpha
	alpha = 1, only nonalpha
	alpha = 2, alpha + nonalpha'''
	def __init__(self, case=2, alpha=2, **kwargs):
		RandomGenerator.__init__(self, **kwargs)
		self.init_random(**kwargs)
		self.case = case
		self.alpha = alpha
	def func(self, index):
		if self.alpha == 0:
			charList = alpha
		elif self.alpha == 1:
			charList = ''.join([x for x in nonalpha.keys()])
		else:
			charList = ''.join([x for x in nonalpha.keys()]) + alpha
		if self.case == 0:
			char = choice(charList)
		elif self.case == 1:
			char = choice(charList).upper()
		else:
			char = choice([choice(charList), choice(charList).upper()])
		return char

example :
d2 >> play(PChar(2,2), dur=PDur(3,8))

@@@ Pattern Method @@@

>> norm(mult) // mod

@PatternMethod
def norm(self, mult=1):
    """ Returns the pattern with all values between 0 and 1*mult """
    pos = self - min(self)
    return (pos / max(pos))*mult

example :
print(P[0,2,4,3].norm(2)) -> P[0,1,2,1.5]

>> clamp(min, max)

@PatternMethod
def clamp(self, mini, maxi):
    """ Returns the pattern with all values clamped to min - max"""
    return self.transform(lambda n: max( min(maxi, n), mini))

example :
print(P[0,2,4,6,8,10,125].clamp(5,10)) -> P[5, 5, 5, 6, 8, 10, 10]

>> lmap(min, max)

@PatternMethod
def lmap(self, oMin, oMax):
    """ Retruns the pattern mapped to min and max values """
    return ((self - min(self)) / (max(self)-min(self)) * (oMax - oMin) + oMin)

example :
print(P[0,2,4,6,8].lmap(200,8000)) -> P[200, 2150, 4100, 6050, 8000]

>> add(num)

@PatternMethod
def add(self, value):
    ''' pattern method add, so you can use with <sometimes>'''
    return self + value


example :
b1 >> blip([0,2,4,2], dur=1/2).sometimes("add", 2)

>> rnd(number)

For this method, you need to edit the FoxDot\lib\Patterns\Main.py file and add at the end of the GeneratorPattern class

def rnd(self, base=2):
    """ Round up the generator random value to nearest base value"""
    return self.transform(lambda value: round(base * round(float(value) / base),3))

example :
print(PWhite(0,1).rnd(0.25)[:8]) -> P[0.5, 0.0, 0.75, 0.25, 0.75, 0.5, 0.75, 0.5]
d1 >> play("x", dur=PWhite(0,0.9).rnd(0.25) + 0.25)

@@@ Player Method @@@

>> gtr(strings)

@player_method
def gtr(self, strings=1):
    ''' for guitar players, play notes like tabs'''
    self.root = Pattern(strings).submap({0:-10, 1:-8, 2:-3, 3:2, 4:7, 5:11, 6:16})
    self.scale = Scale.chromatic
    return self

example :
g1 >> dbass(P[7,7,10,7,5,[3,P+[3,5,3]],2], dur=P[1.5,0.5,0.75,0.75,0.5,2,2]).gtr(2) ## the 2nd string A