SHARE
TWEET

autotracker.py

kill0u Dec 20th, 2012 178 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python --
  2. # -*- coding: utf-8 -*-
  3. #
  4. #    Autotracker-C - the even more ultimate audio experience
  5. #    (C) Ben "GreaseMonkey" Russell, 2010
  6. #
  7. #    This program is free software: you can redistribute it and/or modify
  8. #    it under the terms of the GNU General Public License as published by
  9. #    the Free Software Foundation, either version 3 of the License, or
  10. #    (at your option) any later version.
  11. #
  12. #    This program is distributed in the hope that it will be useful,
  13. #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. #    GNU General Public License for more details.
  16. #
  17. #    You should have received a copy of the GNU General Public License
  18. #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19.  
  20. import sys, struct, random
  21. import math
  22.  
  23. # we'll do major as our base this time
  24. # if random.random() < 0.4: # minor
  25.         # BASE_SCALE = [ 0, 2, 3, 5, 7, 8, 10 ]
  26.         # BASE_ISCALE = [ 0, 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6 ]
  27. # else: # major
  28. BASE_SCALE = [ 0, 2, 4, 5, 7, 9, 11 ]
  29. BASE_ISCALE = [ 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6 ]
  30. BASE_ICHORDS = [[] for i in xrange(12)]
  31. BASE_IBASS = [[] for i in xrange(12)]
  32. for i in [0,3,4,5]:
  33.         for j in xrange(3):
  34.                 BASE_IBASS[BASE_SCALE[(i+j*2)%7]].append(BASE_SCALE[i])
  35. for i in xrange(6):
  36.         for j in xrange(3):
  37.                 BASE_ICHORDS[BASE_SCALE[(i+j*2)%7]].append(BASE_SCALE[i])
  38.  
  39. # strategies we can use
  40. STRAT_CHORUS = 1
  41. STRAT_VERSE = 2
  42. STRAT_PRECHORUS = 3
  43. STRAT_INTERLUDE = 4 # minor <-> major pretty much
  44. STRAT_INTRO = 5 # must be done after doing the chorus
  45. STRAT_OUTRO = 6
  46.  
  47. STRAT_FLAGS_RELATE = 0x100 # attempt to relate to reference
  48. STRAT_FLAGS_START = 0x200 # start with base note
  49. STRAT_FLAGS_END = 0x400 # end with base note and cadence
  50. STRAT_FLAGS_TRANSITION = 0x800 # aim for base note after end and cadence
  51. STRAT_FLAGS_COPY = 0x1000 # just copy the pattern data
  52. STRAT_FLAGS_COMPOTRANSPOSE = 0x2000 # DON'T DO ANYTHING ELSE
  53. STRAT_FLAGS_FADEOUT = 0x4000
  54.  
  55. # stages are 16 rows long
  56. # there are 4 stages per 64-row pattern
  57. # stretches are 1 64-row pattern long
  58.  
  59. def relnote(n, a):
  60.         kn = BASE_ISCALE[(n+120)%12] + (n/12)*7
  61.         kn += a
  62.         return BASE_SCALE[(kn+70)%7] + (kn/7)*12
  63.  
  64. def nearinate(ln, n):
  65.         if n >= 12:
  66.                 if abs(n-12-ln) < abs(n-ln):
  67.                         return n-12
  68.                 else:
  69.                         return n
  70.         else:
  71.                 if abs(n+12-ln) < abs(n-ln):
  72.                         return n+12
  73.                 else:
  74.                         return n
  75.        
  76. class Depender:
  77.         def __init__(self, sng, parent):
  78.                 self.parent = parent
  79.                 self.sng = sng
  80.                 if parent:
  81.                         parent.add_dep(self)
  82.                 self.deps = []
  83.        
  84.         # add dependency
  85.         def add_dep(self, dep):
  86.                 self.deps.append(dep)
  87.        
  88.         # delegate stuff to your children
  89.         def delegate(self):
  90.                 for d in self.deps:
  91.                         d.delegate()
  92.                         d.depend()
  93.        
  94.         # delegate spice to your children
  95.         # this does the actual pattern writing
  96.         def delegate_spice(self, pat, stage):
  97.                 for d in self.deps:
  98.                         d.delegate_spice(pat, stage)
  99.                
  100.                 self.spice(pat, stage)
  101.        
  102.         ###################################
  103.         # v OVERRIDE THESE METHODS HERE v #
  104.         ###################################
  105.        
  106.         # make your mind up on the matter
  107.         def initiate(self):
  108.                 pass
  109.        
  110.         # make children repeat strat
  111.         def repeat(self):
  112.                 pass
  113.        
  114.         # depend on parent decision
  115.         def depend(self):
  116.                 pass
  117.        
  118.         # make your piece awesome
  119.         def spice(self, pat, stage):
  120.                 pass
  121.  
  122. class LeadInstrument(Depender):
  123.         def __init__(self, sng, parent):
  124.                 Depender.__init__(self, sng, parent)
  125.                 self.ch = sng.alloc(1, True)
  126.                 self.last_note = 0
  127.                 self.steal_note = False
  128.        
  129.         def spice(self, pat, stage):
  130.                 n1 = self.sng.lead_data[stage]
  131.                 n2 = self.sng.lead_data[stage+1] if stage+1 < len(self.sng.lead_data) else n1
  132.                 base = (stage&3)*16
  133.                 if (pat.strat&255) == STRAT_OUTRO:
  134.                         if (pat.strat & STRAT_FLAGS_START) and base == 0:
  135.                                 pat.data[base][self.ch][0] = 254 # note cut
  136.                        
  137.                         return
  138.                 elif (pat.strat&255) == STRAT_INTRO:
  139.                         return
  140.                
  141.                 if not self.steal_note:
  142.                         pat.data[base][self.ch][0] = n1+60
  143.                         pat.data[base][self.ch][1] = 1
  144.                
  145.                 last_steal = self.steal_note
  146.                
  147.                 self.steal_note = random.random() < 0.6
  148.                
  149.                 #print n1,n2
  150.                
  151.                 stealstep = random.randint(1,2)
  152.                 if pat.strat & STRAT_FLAGS_END and (stage & 3) == 3:
  153.                         self.steal_note = False
  154.                 else:
  155.                         noteseq = []
  156.                        
  157.                         r = random.randint(1,1)
  158.                         if r == 1: # steping two notes just before n2
  159.                                 # pick either one for equal
  160.                                 if n2 > n1 or (n2 == n1 and random.random() < 0.5):
  161.                                         noteseq.append(relnote(n2,-2))
  162.                                         noteseq.append(relnote(n2,-1))
  163.                                 else:
  164.                                         noteseq.append(relnote(n2,2))
  165.                                         noteseq.append(relnote(n2,1))
  166.                
  167.                         beatseq = []
  168.                         lbs = 2
  169.                         tgt = 8-len(noteseq)
  170.                         if last_steal:
  171.                                 tgt -= stealstep
  172.                        
  173.                         for i in xrange(len(noteseq)):
  174.                                 lbs = random.randint(lbs,tgt)
  175.                                 tgt += 1
  176.                                 beatseq.append(2*lbs)
  177.                        
  178.                         for i in xrange(len(noteseq)):
  179.                                 pat.data[base+beatseq[i]][self.ch][0] = noteseq[i]+60
  180.                                 pat.data[base+beatseq[i]][self.ch][1] = 1
  181.                
  182.                 if self.steal_note:
  183.                        
  184.                         pat.data[base+16-stealstep*2][self.ch][0] = n2+60
  185.                         pat.data[base+16-stealstep*2][self.ch][1] = 1
  186.                
  187.        
  188.         def initiate(self):
  189.                 note = 0
  190.                
  191.                 if (self.sng.strat&255) == STRAT_INTERLUDE:
  192.                         note = BASE_SCALE[4] if (self.sng.strat & STRAT_FLAGS_END) and self.sng.stretch_pos == 3 else BASE_SCALE[5]
  193.                 elif (self.sng.strat&255) == STRAT_PRECHORUS:
  194.                         note = BASE_SCALE[4] if (self.sng.strat & STRAT_FLAGS_END) and self.sng.stretch_pos == 3 else BASE_SCALE[1]
  195.                
  196.                 if (self.sng.strat & STRAT_FLAGS_START) and self.sng.stretch_pos == 0:
  197.                         self.last_note = 0
  198.                         pass
  199.                 elif (self.sng.strat & STRAT_FLAGS_END) and self.sng.stretch_pos == 3:
  200.                         pass
  201.                 elif (self.sng.strat & STRAT_FLAGS_RELATE) and self.sng.ref != -1:
  202.                         note = random.choice(BASE_ICHORDS[(self.sng.bass_data[self.sng.ref*4+self.sng.stretch_pos]+120)%12])
  203.                 else:
  204.                         note = random.choice(BASE_SCALE[:-1]) # don't use 7 here
  205.                
  206.                 note = nearinate(self.last_note,note)
  207.                
  208.                 self.sng.lead_data.append(note)
  209.                 self.last_note = note
  210.                 self.delegate()
  211.  
  212. class BassInstrument(Depender):
  213.         def __init__(self, sng, parent):
  214.                 Depender.__init__(self, sng, parent)
  215.                 self.ch = sng.alloc(1, True)
  216.                 self.last_note = 0
  217.        
  218.         def spice(self, pat, stage):
  219.                 n = self.sng.bass_data[stage]
  220.                 base = (stage&3)*16
  221.                
  222.                 for i in xrange(0,16,2):
  223.                         pat.data[base+i][self.ch][0] = n+60
  224.                         pat.data[base+i][self.ch][1] = 2
  225.        
  226.         def depend(self):
  227.                 note = 0
  228.                
  229.                 if (self.sng.strat&255) == STRAT_INTERLUDE:
  230.                         note = BASE_SCALE[4] if (self.sng.strat & STRAT_FLAGS_END) and self.sng.stretch_pos == 3 else BASE_SCALE[5]
  231.                 elif (self.sng.strat&255) == STRAT_PRECHORUS:
  232.                         note = BASE_SCALE[4] if (self.sng.strat & STRAT_FLAGS_END) and self.sng.stretch_pos == 3 else BASE_SCALE[1]
  233.                
  234.                 if (self.sng.strat & STRAT_FLAGS_START) and self.sng.stretch_pos == 0:
  235.                         pass
  236.                 elif (self.sng.strat & STRAT_FLAGS_END) and self.sng.stretch_pos == 3:
  237.                         pass
  238.                 elif (self.sng.strat & STRAT_FLAGS_RELATE):
  239.                         note = self.sng.bass_data[self.sng.ref*4+self.sng.stretch_pos]
  240.                 else:
  241.                         note = random.choice(BASE_IBASS[self.sng.lead_data[-1]%12])
  242.                
  243.                 if (self.sng.strat&255) == STRAT_PRECHORUS and note == 0:
  244.                         note = BASE_SCALE[5]
  245.                
  246.                 note = nearinate(12,note+12)-12
  247.                 self.sng.bass_data.append(note)
  248.                 self.last_note = note
  249.        
  250.         def initiate(self):
  251.                 raise Exception("BassInstrument not meant to initiate")
  252.  
  253. class DrumInstrument(Depender):
  254.         def __init__(self, sng, parent):
  255.                 Depender.__init__(self, sng, parent)
  256.                 self.ch = sng.alloc(3, False)
  257.                 self.skip_kick = False
  258.        
  259.         def spice(self, pat, stage):
  260.                 rbase = (stage&3)*16
  261.                
  262.                 note = 60
  263.                
  264.                 for q in xrange(2):
  265.                         base = rbase + q*8
  266.                         prekick = (random.random() < 0.5)
  267.                        
  268.                         if not self.skip_kick:
  269.                                 pat.data[base][self.ch+1][0] = note
  270.                                 pat.data[base][self.ch+1][1] = 4
  271.                        
  272.                         if prekick:
  273.                                 pat.data[base+2][self.ch+1][0] = note
  274.                                 pat.data[base+2][self.ch+1][1] = 4
  275.                        
  276.                         pat.data[base+4][self.ch+2][0] = note
  277.                         pat.data[base+4][self.ch+2][1] = 5
  278.                        
  279.                         for i in xrange(0,8,2):
  280.                                 pat.data[base+i][self.ch][0] = note
  281.                                 pat.data[base+i][self.ch][1] = 3
  282.                                 if i%4 == 2:
  283.                                         pat.data[base+i][self.ch][2] = 30
  284.                        
  285.                         if (pat.strat & STRAT_FLAGS_START) and base == 0:
  286.                                 prekick = False
  287.                         elif (pat.strat & STRAT_FLAGS_END) and base == 56:
  288.                                 self.skip_kick = False
  289.                                 for i in xrange(2,8,2):
  290.                                         pat.data[base+i][self.ch+2][0] = note
  291.                                         pat.data[base+i][self.ch+2][1] = 5
  292.                         elif (pat.strat & STRAT_FLAGS_RELATE): # blatant copy
  293.                                 opat = self.sng.refpat(pat.ref)
  294.                                 for i in xrange(8):
  295.                                         for j in xrange(3):
  296.                                                 pat.data[base+i][self.ch+j] = opat.data[base+i][self.ch+j][:]
  297.                                 continue
  298.                        
  299.                         self.skip_kick = (random.random() < 0.4)
  300.                        
  301.                         if self.skip_kick:
  302.                                 pat.data[base+6][self.ch+1][0] = note
  303.                                 pat.data[base+6][self.ch+1][1] = 4
  304.        
  305.         def depend(self):
  306.                 # drums only happen in spice
  307.                 pass
  308.        
  309.         def initiate(self):
  310.                 raise Exception("DrumInstrument not meant to initiate")
  311.  
  312. class ChordInstrument(Depender):
  313.         def __init__(self, sng, parent):
  314.                 Depender.__init__(self, sng, parent)
  315.                 self.ch = sng.alloc(3, True)
  316.                 self.last_note = None
  317.        
  318.         def spice(self, pat, stage):
  319.                 nb = (self.sng.bass_data[stage]+120)%12
  320.                 n1 = (self.sng.chord_data[stage]+120)%12
  321.                 n2 = (relnote(n1,2)+120)%12
  322.                 n3 = (relnote(n1,4)+120)%12
  323.                 base = (stage&3)*16
  324.                
  325.                 if base == 0:
  326.                         self.last_note = None
  327.                
  328.                 if n1 != self.last_note:
  329.                         pat.data[base][self.ch][0] = nb+60
  330.                         pat.data[base][self.ch][1] = 6
  331.                        
  332.                         if n2 == nb:
  333.                                 pat.data[base][self.ch][0] = n2+60
  334.                                 pat.data[base][self.ch][1] = 6
  335.                                 pat.data[base][self.ch+1][0] = n3+60
  336.                                 pat.data[base][self.ch+1][1] = 6
  337.                                 pat.data[base][self.ch+2][0] = n1+60+12
  338.                                 pat.data[base][self.ch+2][1] = 6
  339.                         elif n3 == nb:
  340.                                 pat.data[base][self.ch][0] = n3+60
  341.                                 pat.data[base][self.ch][1] = 6
  342.                                 pat.data[base][self.ch+1][0] = n1+60+12
  343.                                 pat.data[base][self.ch+1][1] = 6
  344.                                 pat.data[base][self.ch+2][0] = n2+60+12
  345.                                 pat.data[base][self.ch+2][1] = 6
  346.                         else:
  347.                                 pat.data[base][self.ch][0] = n1+60
  348.                                 pat.data[base][self.ch][1] = 6
  349.                                 pat.data[base][self.ch+1][0] = n2+60
  350.                                 pat.data[base][self.ch+1][1] = 6
  351.                                 pat.data[base][self.ch+2][0] = n3+60
  352.                                 pat.data[base][self.ch+2][1] = 6
  353.                
  354.                 self.last_note = n1
  355.        
  356.         def depend(self):
  357.                 note = 0
  358.                
  359.                 if (self.sng.strat&255) == STRAT_INTERLUDE:
  360.                         note = 7 if (self.sng.strat & STRAT_FLAGS_END) and self.sng.stretch_pos == 3 else 9
  361.                 elif (self.sng.strat&255) == STRAT_PRECHORUS:
  362.                         note = 7 if (self.sng.strat & STRAT_FLAGS_END) and self.sng.stretch_pos == 3 else 2
  363.                
  364.                 if (self.sng.strat & STRAT_FLAGS_START) and self.sng.stretch_pos == 0:
  365.                         pass
  366.                 elif (self.sng.strat & STRAT_FLAGS_END) and self.sng.stretch_pos == 3:
  367.                         pass
  368.                 elif (self.sng.strat & STRAT_FLAGS_RELATE):
  369.                         note = self.sng.chord_data[self.sng.ref*4+self.sng.stretch_pos]
  370.                 else:
  371.                         note = random.choice(BASE_ICHORDS[self.sng.bass_data[-1]%12])
  372.                
  373.                 if (self.sng.strat&255) == STRAT_PRECHORUS and note == 0:
  374.                         note = 9
  375.                
  376.                 note = nearinate(12,note+12)-12
  377.                
  378.                 self.sng.chord_data.append(note)
  379.        
  380.         def initiate(self):
  381.                 raise Exception("ChordInstrument not meant to initiate")
  382.  
  383. class FadeoutEffect(Depender):
  384.         def __init__(self, sng, parent):
  385.                 Depender.__init__(self, sng, parent)
  386.                 self.ch = sng.alloc(1, False)
  387.                 self.fade_len = 0
  388.        
  389.         def spice(self, pat, stage):
  390.                 base = (stage&3)*16
  391.                 if (pat.strat&255) == STRAT_INTRO and (pat.strat & STRAT_FLAGS_START) and (stage&3) == 0:
  392.                         pat.data[0][self.ch][3] = 22
  393.                         pat.data[0][self.ch][4] = 0x80
  394.                 elif (pat.strat&255) == STRAT_OUTRO:
  395.                         for i in xrange(0,16,self.sng.stretch_len/2):
  396.                                 pat.data[base+i][self.ch][3] = 23
  397.                                 pat.data[base+i][self.ch][4] = 0xF1
  398.        
  399.         def depend(self):
  400.                 if (self.sng.strat&255) == STRAT_OUTRO:
  401.                         self.fade_len = self.sng.stretch_len
  402.                
  403.        
  404.         def initiate(self):
  405.                 raise Exception("FadeoutEffect not meant to initiate")
  406.  
  407. class SwingEffect(Depender):
  408.         def __init__(self, sng, parent):
  409.                 Depender.__init__(self, sng, parent)
  410.                 self.ch = sng.alloc(1, False)
  411.                 self.fade_len = 0
  412.                 self.swing_str = random.randint(-1,2)
  413.                 if self.swing_str <= 0:
  414.                         self.swing_str = 0
  415.        
  416.         def spice(self, pat, stage):
  417.                 base = (stage&3)*16
  418.                 if self.swing_str == 1:
  419.                         for i in xrange(0,16,4):
  420.                                 pat.data[base+i][self.ch][3] = 1
  421.                                 pat.data[base+i][self.ch][4] = 5
  422.                                 pat.data[base+i+2][self.ch][3] = 1
  423.                                 pat.data[base+i+2][self.ch][4] = 3
  424.                 elif self.swing_str == 2:
  425.                         for i in xrange(0,16,4):
  426.                                 pat.data[base+i][self.ch][3] = 1
  427.                                 pat.data[base+i][self.ch][4] = 6
  428.                                 pat.data[base+i+2][self.ch][3] = 1
  429.                                 pat.data[base+i+2][self.ch][4] = 3
  430.        
  431.         def depend(self):
  432.                 pass
  433.        
  434.         def initiate(self):
  435.                 raise Exception("SwingEffect not meant to initiate")
  436.  
  437. class Pattern:
  438.         def __init__(self, rows, strat, ref):
  439.                 self.rows = rows
  440.                 self.strat = strat
  441.                 self.ref = ref
  442.                 self.data = [[[-1,-1,-1,-1,0] for i in xrange(64)] for i in xrange(rows)]
  443.        
  444.         def save(self, fp):
  445.                 # don't bother packing well, you'll need to add your samples in -GM
  446.                 odat = []
  447.                
  448.                 for l in self.data:
  449.                         for ch in xrange(64):
  450.                                 m = 0x00
  451.                                
  452.                                 if l[ch][0] != -1:
  453.                                         m |= 0x01
  454.                                 if l[ch][1] != -1:
  455.                                         m |= 0x02
  456.                                 if l[ch][2] != -1:
  457.                                         m |= 0x04
  458.                                 if l[ch][3] != -1:
  459.                                         m |= 0x08
  460.                                
  461.                                 odat.append(0x80|(ch+1))
  462.                                 odat.append(m)
  463.                                 if m & 0x01:
  464.                                         odat.append(l[ch][0])
  465.                                 if m & 0x02:
  466.                                         odat.append(l[ch][1])
  467.                                 if m & 0x04:
  468.                                         odat.append(l[ch][2])
  469.                                 if m & 0x08:
  470.                                         odat.append(l[ch][3])
  471.                                         odat.append(l[ch][4])
  472.                         odat.append(0)
  473.                
  474.                 fp.write(struct.pack("<HHI",len(odat),self.rows,0))
  475.                 fp.write(''.join(chr(v) for v in odat))
  476.  
  477. class Song:
  478.         def __init__(self):
  479.                 self.orders = []
  480.                 self.samples = self.gen_samples()
  481.                 self.patterns = []
  482.                 self.pat_chorus = []
  483.                 self.pat_chorus_base = 0
  484.                 self.pat_chorus_ord = 0
  485.                 self.chnbase = 0
  486.                 self.chn_tonal = [False for i in xrange(64)]
  487.                
  488.                 self.lead_data = []
  489.                 self.beat_data = []
  490.                 self.bass_data = []
  491.                 self.chord_data = []
  492.                
  493.                 self.key = random.randint(-6,6) # 0 == (major ? C : Am)
  494.                 self.mode = 0 # 0 == major, -3 = minor
  495.                 self.strat = 0
  496.                 self.ref = 0
  497.                
  498.                 self.stretch_len = 0
  499.                 self.stretch_pos = 0
  500.                
  501.                 # OK, let's rock
  502.                 lead = LeadInstrument(self, None)
  503.                 bass = BassInstrument(self, lead)
  504.                 drum = DrumInstrument(self, lead)
  505.                 chords = ChordInstrument(self, bass)
  506.                 fx_fadeout = FadeoutEffect(self, lead)
  507.                 fx_swing = SwingEffect(self, lead)
  508.                 self.root = lead
  509.                
  510.                 self.epictronise()
  511.        
  512.         def fakesin(self,v):
  513.                 v = v % math.pi*2
  514.                 return -0.5 if v < math.pi else 0.5
  515.        
  516.         def saw(self,v,d):
  517.                 return ((float(v)/float(d)) % 1.0)*2.0-1.0
  518.        
  519.         def gen_samples(self):
  520.                 l = []
  521.                
  522.                 # sample 1: lead: square
  523.                 l.append(([(-60 if i%256 < 128 else 60)+(-60 if i%255 < 128 else 60) for i in xrange(256*255)],8363*8,True))
  524.                
  525.                 # sample 2: bass: sawtooth
  526.                 l.append(([(((i%64)-32)*180*(i**2))/(64*((64*50)**2)) for i in xrange(64*50)][::-1],8363,True))
  527.                
  528.                 # sample 3: hihat
  529.                 q = []
  530.                 for i in xrange(650):
  531.                         q = [(random.randint(-1,1)*120*i*i)/(650*650)] + q
  532.                 l.append((q,8134*4,False))
  533.                
  534.                 # sample 4: kick
  535.                 q = []
  536.                 for i in xrange(4000):
  537.                         q = [int(120*self.fakesin(i*i*i*math.pi*2.0*4/(4000.0**3)))] + q
  538.                 l.append((q,8134*4,False))
  539.                
  540.                 # sample 5: snare
  541.                 q = []
  542.                 for i in xrange(650*4):
  543.                         q = [(random.randint(-1,1)*120*i*i)/(650*650*4*4)] + q
  544.                 l.append((q,8134*2,False))
  545.                
  546.                 # sample 6: chord: hypersaw
  547.                 # NOTE: this is not a proper hypersaw as it doesn't distort enough.
  548.                 #q = []
  549.                 #for i in xrange(8363*16):
  550.                 #       q.append(int(15*(
  551.                 #               self.saw(i*2048+12345,8363*16)*4
  552.                 #               + self.saw(i*1024+67890,8363*16)*2
  553.                 #               + self.saw(i*512+2467,8363*16)*1
  554.                 #               + self.saw(i*4096+5437,8363*16)*1
  555.                 #       )))
  556.                 # decided to change the waveform.
  557.                 # it's now a triangle wave.
  558.                 q = [((i-32)*120)/64 for i in xrange(64)]
  559.                 l.append((q+q[::-1],8363*4,True))
  560.                
  561.                 return l
  562.        
  563.         def refpat(self, ref):
  564.                 return self.patterns[self.orders[ref]]
  565.        
  566.         def gen_pat(self, strat, ref = -1):
  567.                 p = Pattern(64, strat, ref)
  568.                
  569.                 self.strat = strat
  570.                 self.ref = ref
  571.                
  572.                 for i in xrange(4):
  573.                         self.stretch_pos = i
  574.                         self.root.initiate()
  575.                
  576.                 self.orders.append(len(self.patterns))
  577.                 self.patterns.append(p)
  578.                 if (strat&255) == STRAT_CHORUS and len(self.pat_chorus) < self.stretch_len:
  579.                         self.pat_chorus.append(p)
  580.        
  581.         def gen_pat_round(self, strat):
  582.                 choref = self.pat_chorus_ord
  583.                 if (strat&255) == STRAT_CHORUS:
  584.                         if self.pat_chorus and not (strat & STRAT_FLAGS_COPY):
  585.                                 print "rep", self.pat_chorus_base, self.pat_chorus_ord, len(self.orders)
  586.                                
  587.                                 # just tweak the orderlist and sync the song data
  588.                                 for i in xrange(len(self.pat_chorus)):
  589.                                         self.orders.append(self.pat_chorus_base+i)
  590.                                         for j in xrange(4):
  591.                                                 for q in [self.lead_data, self.chord_data, self.bass_data, self.beat_data]:
  592.                                                         if q:
  593.                                                                 q.append(q[(self.pat_chorus_ord+i)*4+j])
  594.                                 return
  595.                         else:
  596.                                 self.pat_chorus = []
  597.                                 self.pat_chorus_ord = len(self.orders)
  598.                                 self.pat_chorus_base = len(self.patterns)
  599.                
  600.                 for i in xrange(self.stretch_len):
  601.                         ts = strat
  602.                         ref = -1
  603.                        
  604.                         if i == 0:
  605.                                 ts |= STRAT_FLAGS_START
  606.                         else:
  607.                                 k = i
  608.                                 ref = 1
  609.                                 while k and not k&1:
  610.                                         ref <<= 1
  611.                                         k >>= 1
  612.                                
  613.                                 ref = len(self.orders)-ref
  614.                                
  615.                                 ts |= STRAT_FLAGS_RELATE
  616.                        
  617.                         if strat & STRAT_FLAGS_COMPOTRANSPOSE:
  618.                                 if (strat&255) == STRAT_CHORUS:
  619.                                         ref = choref+i
  620.                                 elif (strat&255) == STRAT_OUTRO:
  621.                                         ref = len(self.orders)-self.stretch_len
  622.                        
  623.                         if (strat&255) == STRAT_OUTRO:
  624.                                 ref = len(self.orders)-1
  625.                                 ts |= STRAT_FLAGS_RELATE
  626.                         elif i == self.stretch_len-1:
  627.                                 ts |= STRAT_FLAGS_END
  628.                        
  629.                         self.gen_pat(ts, ref)
  630.        
  631.         def epictronise(self):
  632.                 self.strat_list = [
  633.                         STRAT_INTRO,
  634.                         STRAT_CHORUS,
  635.                         STRAT_VERSE, STRAT_PRECHORUS, STRAT_CHORUS,
  636.                         STRAT_VERSE, STRAT_PRECHORUS, STRAT_INTERLUDE, STRAT_CHORUS,
  637.                         STRAT_CHORUS|STRAT_FLAGS_COPY|STRAT_FLAGS_COMPOTRANSPOSE,
  638.                         STRAT_VERSE, STRAT_PRECHORUS, STRAT_CHORUS,
  639.                         STRAT_CHORUS|STRAT_FLAGS_COPY|STRAT_FLAGS_COMPOTRANSPOSE,
  640.                         STRAT_OUTRO
  641.                 ]
  642.                
  643.                 for strat in self.strat_list:
  644.                         self.stretch_len = random.choice([2,4])
  645.                         if (strat&255) == STRAT_INTRO:
  646.                                 self.stretch_len = 2
  647.                         elif (strat&255) == STRAT_CHORUS:
  648.                                 self.stretch_len = 2
  649.                         elif (strat&255) == STRAT_OUTRO:
  650.                                 self.stretch_len = 4
  651.                        
  652.                        
  653.                         self.curpat = None
  654.                        
  655.                         self.gen_pat_round(strat)
  656.                
  657.                 l = []
  658.                 for i in xrange(len(self.orders)):
  659.                         if self.orders[i] in l:
  660.                                 continue
  661.                        
  662.                         l.append(self.orders[i])
  663.                         for j in xrange(4):
  664.                                 self.root.delegate_spice(self.refpat(i), i*4+j)
  665.                
  666.                 last_was_transpose = False
  667.                 for p in self.patterns:
  668.                         for r in xrange(p.rows):
  669.                                 for ch in xrange(64):
  670.                                         if self.chn_tonal[ch] and p.data[r][ch][0] != -1 and p.data[r][ch][0] < 120:
  671.                                                 p.data[r][ch][0] += self.key
  672.                        
  673.                         if p.strat & STRAT_FLAGS_COPY:
  674.                                 op = self.refpat(p.ref)
  675.                                 for r in xrange(p.rows):
  676.                                         for ch in xrange(64):
  677.                                                 p.data[r][ch] = op.data[r][ch][:]
  678.                        
  679.                         if p.strat & STRAT_FLAGS_COMPOTRANSPOSE:
  680.                                 for r in xrange(p.rows):
  681.                                         for ch in xrange(64):
  682.                                                 if self.chn_tonal[ch] and p.data[r][ch][0] != -1 and p.data[r][ch][0] < 120:
  683.                                                         p.data[r][ch][0] += 2
  684.                                
  685.                                 if not last_was_transpose:
  686.                                         self.key += 2
  687.                                
  688.                                 last_was_transpose = True
  689.                         else:
  690.                                 last_was_transpose = False
  691.        
  692.         def alloc(self, count, tonal):
  693.                 b = self.chnbase
  694.                 self.chnbase += count
  695.                 for i in xrange(b,self.chnbase,1):
  696.                         self.chn_tonal[i] = tonal
  697.                 return b
  698.        
  699.         def save(self, fname):
  700.                 fp = open(fname, "wb")
  701.                 fp.write("IMPM AutoTracker C Module :D \x00")
  702.                 fp.write(struct.pack("<HHHHH",0x1004,len(self.orders)+1,0,len(self.samples),len(self.patterns)))
  703.                 fp.write(struct.pack("<HHHH",0x0216,0x0200,0x0019,0x0000))
  704.                 fp.write(struct.pack("<BBBBBB",128,48,4,125,128,0))
  705.                 fp.write(struct.pack("<HII",0,0,0))
  706.                 fp.write("\x20"*64)
  707.                 fp.write("\x40"*64)
  708.                 fp.write(''.join(chr(v) for v in self.orders)+"\xFF")
  709.                 patroot = fp.tell()
  710.                 fp.write("\x00"*4*(len(self.samples)+len(self.patterns)))
  711.                
  712.                 # do it ChibiTracker-style
  713.                 for dat,frq,lpd in self.samples:
  714.                         t = fp.tell()
  715.                         fp.write("IMPSAUTOTRACKERC\x00")
  716.                         fp.write(struct.pack("<BBB",64,0x11 if lpd else 0x01,64))
  717.                         fp.write("Autotracker C sample     \x00")
  718.                         fp.write(struct.pack("<BB",0x01,0x00))
  719.                         fp.write(struct.pack("<IIIIIII",len(dat),0,len(dat),frq,0,0,t+0x50))
  720.                         fp.write(struct.pack("<BBBB",0x00,0x00,0x00,0x00))
  721.                         fp.write(''.join(chr(255&v) for v in dat))
  722.                         nt = fp.tell()
  723.                         fp.seek(patroot)
  724.                         fp.write(struct.pack("<I",t))
  725.                         patroot = fp.tell()
  726.                         fp.seek(nt)
  727.                
  728.                 for p in self.patterns:
  729.                         t = fp.tell()
  730.                         p.save(fp)
  731.                         nt = fp.tell()
  732.                         fp.seek(patroot)
  733.                         fp.write(struct.pack("<I",t))
  734.                         patroot = fp.tell()
  735.                         fp.seek(nt)
  736.                
  737.                 fp.close()
  738.  
  739. Song().save("dump-c.it" if len(sys.argv) < 2 else sys.argv[1])
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top