Skip to content

Instantly share code, notes, and snippets.

@lifthrasiir
Created August 15, 2011 13:45
Show Gist options
  • Save lifthrasiir/1146785 to your computer and use it in GitHub Desktop.
Save lifthrasiir/1146785 to your computer and use it in GitHub Desktop.
quick and dirty BMS-to-HTML5 converter
import sys, os, urllib
wavs = {}
lines = {}
linesln = {}
stretches = {}
bpm = 120.0
maxpos = 0
precision = 1 << 16
for l in open(sys.argv[1], 'r'):
if l.lower().startswith('#bpm '):
bpm = float(l[5:])
elif l.lower().startswith('#wav'):
id = l[4:6].lower()
path = l[7:].strip()
if os.path.exists(path):
wavs[id] = path
elif os.path.exists(path[:-4] + '.ogg'):
wavs[id] = path[:-4] + '.ogg'
elif os.path.exists(path[:-4] + '.mp3'):
wavs[id] = path[:-4] + '.mp3'
else:
if id in wavs: del wavs[id]
elif l.startswith('#') and l[1:4].isdigit():
pos = int(l[1:4], 10)
if pos > maxpos: maxpos = pos
kind = l[4:6].lower()
data = l[7:].strip()
if kind in ('01', '11', '12', '13', '14', '15', '16', '17', '18', '19'):
assert len(data) % 2 == 0
div = len(data) // 2
line = lines.setdefault(pos, {})
for i in xrange(div):
val = data[i*2:i*2+2].lower()
if val != '00':
line.setdefault(i * precision // div, []).append(val)
elif kind in ('51', '52', '53', '54', '55', '56', '57', '58', '59'):
assert len(data) % 2 == 0
div = len(data) // 2
line = linesln.setdefault(pos, {})
for i in xrange(div):
val = data[i*2:i*2+2].lower()
if val != '00':
line.setdefault(i * precision // div, []).append((val, kind))
elif kind == '02':
stretches[pos] = float(data)
elif kind in ('04', '06'):
continue
else:
print >>sys.stderr, 'unknown kind', kind
# eliminate linesln
active = set()
for pos in xrange(maxpos+1):
for k, v in linesln.get(pos, {}).items():
for i, kind in v:
if kind in active:
active.remove(kind)
else:
lines.setdefault(pos, {}).setdefault(k, []).append(i)
active.add(kind)
wavsorder = []
seenwavs = set()
for pos in xrange(maxpos+1):
for k, v in lines.get(pos, {}).items():
for i in v:
if i not in seenwavs:
seenwavs.add(i)
wavsorder.append(i)
limits = 9999
#limits = 200
moreoptions = ''
#moreoptions = 'controls'
print '<!doctype html>'
print '<div id=q></div>'
print '<button id=r disabled onclick="play();return false">Play</button><br/>'
print '<script>'
print 'var canplay = 0, mustplay = 0;'
print 'function t(x){document.getElementById("q").innerHTML=x}'
print 'function c(x){x.oncanplaythrough="";t("loaded: "+(++canplay)+"/"+mustplay);if(canplay==mustplay)document.getElementById("r").disabled=false}'
print 'function setup(w,x){var st=(+new Date)+x,z;setTimeout(function(){z=(+new Date)-st;t("playing: time="+x+" latency="+z);/*z/=1000;*/z=0;for(var i=0;i<w.length;++i)if(w[i]){w[i].currentTime=z;w[i].play()}},x)}'
print 't("loading...");'
a = 0
for k in wavsorder:
try:
v = wavs[k]
except KeyError:
continue
if a < limits:
print '++mustplay;</script><audio id=w{} src="{}" {} oncanplaythrough="c(this)"></audio><script>w{} = document.getElementById("w{}");'.format(k, urllib.quote(v), moreoptions, k, k)
else:
print 'w{} = null;'.format(k)
a += 1
print 'function play(){'
time = 0.0
for pos in xrange(maxpos+1):
stretch = stretches.get(pos, 1.0)
dur = 240.0 / bpm * stretch
base = time * 1000.0
mult = dur / float(precision) * 1000.0
for k, v in lines.get(pos, {}).items():
print 'setup([{}],{});'.format(','.join('w{}'.format(i) for i in v), int(base + mult * k))
time += dur
print '}</script>'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment