Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- """
- Song generation using 'Fractal Wurfelspiel' technique as described in
- https://plus.maths.org/content/os/issue55/features/kormann/index
- and Fractal Motion / Midpoint Displacement, as described in
- http://www.tursiops.cc/fm/#midpt
- The generated song is a string in MML format.
- Author: a5kin
- """
- import math, random
- class FractalSong:
- def __init__(self, structure='00010011', notes=["o2e", "o2g", "o2a", "o2a+", "o2b", "o3d", "o3e", "o3g", "o3a", "o3a+", "o3b", "o4d", "o4e", ]):
- self.pattern = structure
- self.structure = [int(c) for c in structure]
- self.items = 2
- self.rhythm = ""
- self.bars = []
- self.notes = notes
- self.melody = [None for i in range(len(self.notes))]
- self.song = "l16"
- def iterate(self):
- struct1 = [p for p in self.structure]
- struct2 = [p + self.items for p in self.structure]
- self.structure[:] = []
- for i in range(len(self.pattern)):
- ii = i % (len(self.pattern) // 2)
- if self.pattern[i] == '0':
- self.structure += struct1[ii*self.items:(ii+1)*self.items]
- else:
- self.structure += struct2[ii*self.items:(ii+1)*self.items]
- self.items *= 2
- def build_melody(self, x1, x2, v1, v2):
- if x2 - x1 <= 0:
- return
- self.melody[x1] = v1
- self.melody[x2] = v2
- if x2 - x1 <= 1:
- return
- xc = (x1 + x2) // 2
- vc = max(0, min(len(self.notes) - 1, (v1 + v2) // 2 + random.randint(-2, 4)))
- self.build_melody(x1, xc, v1, vc)
- self.build_melody(xc, x2, vc, v2)
- def generate(self, iters, mask = 0b1111, mandatory=0b0000):
- # build rhythm
- for i in range(iters):
- self.iterate()
- num = random.randint(0, 15)
- num |= mandatory
- num &= mask
- for i in range(self.items):
- num = num ^ 2 ** random.randint(0, 3)
- if i % 2 == 0 and num < 8:
- num += 8 # make sure each bar starts with note
- num |= mandatory
- bar = bin(num)[2:].zfill(4).replace("0", " ").replace("1", "X")
- self.bars.append(bar)
- num &= mask
- for i in self.structure:
- self.rhythm += self.bars[i] + "|"
- # build melody
- self.iterate()
- self.iterate()
- self.melody = [None for i in range(len(self.structure)*4)]
- self.build_melody(0, len(self.structure)*4 - 1, 0, 0)
- self.rhythm = self.rhythm.replace("|", "")
- for i in range(len(self.rhythm)):
- bar_num = self.structure[i // 4] * 4 + i % 2
- note = self.notes[self.melody[bar_num]] if self.rhythm[i] == "X" else "r"
- self.song += note
- if __name__ == "__main__":
- fs = FractalSong("00010011", ["o2e", "o2g", "o2a", "o2a+", "o2b", "o3d", "o3e", "o3g", "o3a", "o3a+", "o3b", "o4d", "o4e", ])
- fs.generate(5)
- print fs.song
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement