Skip to content

Instantly share code, notes, and snippets.

@foodini
Created November 3, 2023 18:47
Show Gist options
  • Save foodini/cd980105e0b919379f451d79ff100ddf to your computer and use it in GitHub Desktop.
Save foodini/cd980105e0b919379f451d79ff100ddf to your computer and use it in GitHub Desktop.
A brief python program to convert IQ's Pirates music to my Shadertoy tracker.
#!/usr/bin/env python3
from collections import defaultdict
import re
chan1 = '''
// F2
x = t; b = 0.0;
D(36)D(2)D(2)D(20)D(2)D(16)D(6)D(2)D(226)
y += instrument( 174.0, tint*(t-x) );
// G2
x = t; b = 0.0;
D(53)D(208)
y += instrument( 195.0, tint*(t-x) );
// A2
x = t; b = 0.0;
D(34)D(2)D(2)D(2)D(1)D(7)D(2)D(2)D(2)D(1)D(3)D(8)D(2)D(8)D(2)D(4)D(2)D(2)D(2)D(1)
D(31)D(2)D(4)D(138)D(46)D(2)
y += instrument( 220.0, tint*(t-x) );
// A#2
x = t; b = 0.0;
D(42)D(2)D(2)D(14)D(2)D(2)D(1)D(25)D(2)D(16)D(2)D(2)
y += instrument( 233.0, tint*(t-x) );
// B2
x = t; b = 0.0;
D(125)
y += instrument( 246.0, tint*(t-x) );
// C3
x = t; b = 0.0;
D(35)D(6)D(7)D(2)D(3)D(1)D(5)D(7)D(2)D(2)D(1)D(1)D(2)D(3)D(6)D(199)D(2)D(2)D(2)D(1)
y += instrument( 261.0, tint*(t-x) );
// C#3
x = t; b = 0.0;
D(120)D(2)D(4)D(132)D(1)D(5)D(42)D(2)
y += instrument( 277.0, tint*(t-x) );
// D3
x = t; b = 0.0;
D(0)D(2)D(1)D(2)D(1)D(2)D(1)D(1)D(1)D(1)D(2)D(1)D(2)D(1)D(2)D(1)D(1)D(1)D(1)D(2)
D(1)D(2)D(1)D(2)D(1)D(3)D(2)D(2)D(2)D(2)D(2)D(1)D(5)D(3)D(5)D(2)D(2)D(12)D(2)D(6)
D(2)D(2)D(2)D(2)D(2)D(1)D(1)D(2)D(5)D(3)D(2)D(2)D(2)D(3)D(3)D(6)D(1)D(136)D(9)D(2)
D(2)D(2)D(1)D(17)D(2)D(2)D(2)D(1)D(11)
y += instrument( 293.0, tint*(t-x) );
// E3
x = t; b = 0.0;
D(41)D(7)D(2)D(15)D(7)D(2)D(27)D(6)D(13)D(2)D(4)D(132)D(1)D(23)D(2)D(2)D(2)D(18)D(4)
y += instrument( 329.0, tint*(t-x) );
// F3
x = t; b = 0.0;
D(42)D(2)D(2)D(20)D(2)D(2)D(19)D(11)D(2)D(6)D(2)D(4)D(5)D(5)D(8)D(2)D(2)D(20)D(2)D(16)
D(6)D(2)D(82)D(4)D(2)D(2)D(2)D(2)D(1)D(12)D(5)D(2)D(2)D(2)D(1)D(7)
y += instrument( 349.0, tint*(t-x) );
// G3
x = t; b = 0.0;
D(47)D(24)D(19)D(2)D(2)D(2)D(2)D(3)D(11)D(37)D(120)D(13)D(2)D(2)D(2)D(18)
y += instrument( 391.0, tint*(t-x) );
// A3
x = t; b = 0.0;
D(95)D(5)D(2)D(12)D(16)D(2)D(2)D(2)D(1)D(7)D(2)D(2)D(2)D(1)D(3)D(8)D(2)D(8)D(2)D(4)
D(2)D(2)D(2)D(1)D(31)D(2)D(4)D(2)D(2)D(12)D(1)D(1)D(30)D(2)D(2)D(3)D(12)D(5)D(2)D(2)
D(3)
y += instrument( 440.0, tint*(t-x) );
// A#3
x = t; b = 0.0;
D(96)D(2)D(40)D(2)D(2)D(14)D(2)D(2)D(1)D(25)D(2)D(16)D(2)D(2)D(24)D(18)D(1)D(1)D(24)D(24)
y += instrument( 466.0, tint*(t-x) );
// C4
x = t; b = 0.0;
D(131)D(6)D(7)D(2)D(3)D(1)D(5)D(7)D(2)D(2)D(1)D(1)D(2)D(3)D(6)D(47)D(2)
y += instrument( 523.0, tint*(t-x) );
// C#4
x = t; b = 0.0;
D(216)D(2)D(3)
y += instrument( 554.0, tint*(t-x) );
// D4
x = t; b = 0.0;
D(132)D(2)D(2)D(2)D(2)D(2)D(1)D(5)D(3)D(5)D(2)D(2)D(12)D(2)D(6)D(2)D(2)D(2)D(2)D(2)
D(1)D(1)D(2)D(5)D(3)D(2)D(2)D(2)D(3)D(3)D(6)D(2)D(2)D(4)D(4)D(2)D(5)D(7)D(5)
y += instrument( 587.0, tint*(t-x) );
// E4
x = t; b = 0.0;
D(137)D(7)D(2)D(15)D(7)D(2)D(27)D(6)D(13)D(2)D(8)
y += instrument( 659.0, tint*(t-x) );
// F4
x = t; b = 0.0;
D(138)D(2)D(2)D(20)D(2)D(2)D(19)D(11)D(2)D(6)D(2)D(4)D(5)D(13)D(2)D(1)D(4)D(3)
y += instrument( 698.0, tint*(t-x) );
// G4
x = t; b = 0.0;
D(143)D(24)D(19)D(2)D(2)D(2)D(2)D(3)D(11)D(24)D(14)D(4)
y += instrument( 783.0, tint*(t-x) );
// A4
x = t; b = 0.0;
D(191)D(5)D(2)D(12)D(24)
y += instrument( 880.0, tint*(t-x) );
// A#4
x = t; b = 0.0;
D(192)D(2)D(52)
y += instrument( 932.0, tint*(t-x) );
// C5
x = t; b = 0.0;
y += instrument( 1046.0, tint*(t-x) );
'''
chan2 = '''
// D0
x = t; b = 0.0;
D(24)D(6)D(3)
y += instrument( 36.0, tint*(t-x) );
// F0
x = t; b = 0.0;
D(66)D(2)D(1)D(2)D(91)D(2)D(1)D(2)
y += instrument( 43.0, tint*(t-x) );
// G0
x = t; b = 0.0;
D(96)D(2)D(1)D(2)D(91)D(2)D(1)D(2)D(49)D(2)D(1)D(2)D(1)D(2)D(1)D(2)
y += instrument( 48.0, tint*(t-x) );
// A0
x = t; b = 0.0;
D(48)D(2)D(1)D(2)D(22)D(2)D(43)D(2)D(1)D(2)D(1)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(22)D(2)
D(43)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(1)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(1)D(2)D(1)D(2)
D(37)D(2)D(1)D(2)
y += instrument( 55.0, tint*(t-x) );
// A#0
x = t; b = 0.0;
D(42)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(25)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(25)D(2)D(1)D(2)
D(13)D(2)D(1)D(2)D(25)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(23)
y += instrument( 58.0, tint*(t-x) );
// C1
x = t; b = 0.0;
D(41)D(31)D(2)D(63)D(31)D(2)D(56)D(2)D(2)D(52)D(2)D(1)D(2)
y += instrument( 65.0, tint*(t-x) );
// D1
x = t; b = 0.0;
D(24)D(6)D(3)D(3)D(2)D(1)D(15)D(2)D(1)D(2)D(19)D(2)D(1)D(2)D(1)D(2)D(1)D(2)D(13)D(2)
D(1)D(2)D(7)D(2)D(1)D(2)D(13)D(2)D(1)D(15)D(2)D(1)D(2)D(19)D(2)D(1)D(2)D(1)D(2)D(1)
D(2)D(13)D(2)D(1)D(2)D(7)D(2)D(1)D(2)D(7)D(2)D(46)D(2)D(1)D(2)D(1)D(2)D(1)D(1)D(1)
D(13)D(2)D(1)D(2)D(1)D(2)D(1)D(1)D(1)D(7)
y += instrument( 73.0, tint*(t-x) );
// F1
x = t; b = 0.0;
D(66)D(2)D(1)D(2)D(91)D(2)D(1)D(2)D(121)D(2)D(1)D(1)D(1)
y += instrument( 87.0, tint*(t-x) );
// G1
x = t; b = 0.0;
D(96)D(2)D(1)D(2)D(91)D(2)D(1)D(2)D(49)D(2)D(1)D(2)D(1)D(2)D(1)D(2)
y += instrument( 97.0, tint*(t-x) );
// A1
x = t; b = 0.0;
D(48)D(2)D(1)D(2)D(22)D(2)D(43)D(2)D(1)D(2)D(1)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(22)D(2)
D(43)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(1)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(1)D(2)D(1)D(2)
D(37)D(2)D(1)D(2)
y += instrument( 110.0, tint*(t-x) );
// A#1
x = t; b = 0.0;
D(42)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(25)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(25)D(2)D(1)D(2)
D(13)D(2)D(1)D(2)D(25)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(23)
y += instrument( 116.0, tint*(t-x) );
// C2
x = t; b = 0.0;
D(41)D(31)D(2)D(63)D(31)D(2)D(56)D(2)D(2)D(52)D(2)D(1)D(2)
y += instrument( 130.0, tint*(t-x) );
// D2
x = t; b = 0.0;
D(36)D(2)D(1)D(15)D(2)D(1)D(2)D(19)D(2)D(1)D(2)D(1)D(2)D(1)D(2)D(13)D(2)D(1)D(2)D(7)
D(2)D(1)D(2)D(13)D(2)D(1)D(15)D(2)D(1)D(2)D(19)D(2)D(1)D(2)D(1)D(2)D(1)D(2)D(13)D(2)
D(1)D(2)D(7)D(2)D(1)D(2)D(7)D(2)D(46)D(2)D(1)D(2)D(1)D(2)D(1)D(1)D(1)D(13)D(2)D(1)
D(2)D(1)D(2)D(1)D(1)D(1)D(7)
y += instrument( 146.0, tint*(t-x) );
// F2
x = t; b = 0.0;
D(288)D(2)D(1)D(1)D(1)
'''
pitches = defaultdict(lambda: [[],[]])
channel_count = [0, 0]
for channel_id, channel in enumerate([chan1, chan2]):
for line in channel.splitlines():
match = re.search(r'// ([A-G]#?[0-9])', line)
if match:
pitch = re.sub('#', 's', match.groups()[0])
position = 0
match = re.search(r'D\(\d\)', line)
if match:
notes = re.split('[^0-9+]', line)
for delta in notes:
if delta:
position += int(delta)
pitches[position][channel_id].append(pitch)
if len(pitches[position][channel_id]) > channel_count[channel_id]:
channel_count[channel_id] = len(pitches[position][channel_id])
last_key = 0
for key in sorted(pitches.keys()):
print(key, pitches[key])
last_key = int(key)
print('channel_count:', channel_count)
num_measures = (last_key + 11) // 12
num_measures += 3
num_rows = num_measures * 12
print(f'code_rows: {last_key}, num_measures*12: {num_measures*12}')
print()
print(f'const int num_tracks = 6;')
print(f'const int beats_per_measure = 4;')
print(f'const int rows_per_beat = 3;')
print(f'const int num_measures = {num_measures};')
print(f'const int num_rows = num_tracks * beats_per_measure * rows_per_beat * num_measures;')
print(f'const uint instruments[] = uint[](IQ, IQ, IQ, IQ, IQ, IQ);')
print(f'const vec2 left = vec2(0.7, 0.3);')
print(f'const vec2 right = vec2(0.3, 0.7);')
print(f'const vec2 balances[] = vec2[](left, left, left, right, right, right);')
print(f'const uint tracks[] = uint[] (');
for row_id in range(num_rows):
print(' ', end='')
for channel_id in range(2):
for pitch in pitches[row_id][channel_id]:
print('%3s, ' % pitch, end='')
for _ in range(3-len(pitches[row_id][channel_id])):
print(' NO, ', end='')
measure = row_id // 12
beat = (row_id % 12) // 3
row = (row_id % 12) % 3
print(f' // Row{row_id}, Measure{measure}, Beat{beat}.{row}')
print(');')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment