import sys,os,shutil,numpy,progressbar
abspeed=0.02
bgdir='/home/nyk/fasnacht/'
def empty_directory(d):
for f in os.listdir(d):
os.unlink('%s/%s' % (d.rstrip('/'),f))
commands=['','Portamento Up','Portamento Down','TonePortamento','Vibrato','ToneP + VolSlide','Vibra + VolSlide','Tremolo','* NOT USED *','SampleOffset','VolumeSlide','PositionJump','Set Volume','PatternBreak','Misc. Cmds','Set Speed']
def get_pattern(data,p,speed,fps):
samples,notes,effects,lastchan={},{},{},{}
tots=0
last_speed=speed
for i in range(64):
tots+=abspeed*speed
frame=int(tots*fps)
for chan in range(4):
note=''
for byte in range(4):
v=ord(data[1084+p*1024+i*16+chan*4+byte])
b=bin(v)[2:]
note+=(8-len(b))*'0'+b
sample=int(note[:4]+note[16:20],2)
note_period=int(note[4:16],2)
effect_command=int(note[20:24],2)
effect_data=int(note[24:],2)
if effect_command==15: speed=effect_data
if not sample and lastchan.has_key(chan): sample=lastchan[chan]
lastchan[chan]=sample
if speed!=last_speed:
tots-=abspeed*last_speed
tots+=abspeed*speed
frame=int(tots*fps)
last_speed=speed
samples[frame]=samples.get(frame,[])+[sample]
notes[frame]=notes.get(frame,[])+[note_period]
effects[frame]=effects.get(frame,[])+[effect_command]
samplist,notelist,efflist=[],[],[]
for i in range(max(samples.keys())):
if samples.has_key(i):
samplist.append(samples[i])
notelist.append(notes[i])
efflist.append(effects[i])
else:
samplist.append([])
notelist.append([])
efflist.append([])
return samplist,notelist,efflist,speed
def mod_lists(fn,fps=25.0):
data=open(fn).read()
for i in range(20):
if data[i]==0: break
song_name=data[:i]
song_length=ord(data[950])
patterns=map(lambda x: ord(data[952+x]),range(song_length))
num_pat=max(patterns)+1
ident=data[1080:1084]
assert ident=='M.K.'
print 'Song Name = "%s", Length = %d, Patterns = %d' % (song_name,song_length,num_pat)
sample_list,note_list,effect_list=[],[],[]
speed=6
for i,p in enumerate(patterns):
s,n,e,speed=get_pattern(data,p,speed,fps)
sample_list+=s
note_list+=n
effect_list+=e
len_tot=float(len(sample_list))/fps
len_min=len_tot/60
len_s=len_tot % 60
print 'Speed = %d, length = %d:%02d (%d frames)' % (speed,len_min,len_s,len(sample_list))
return sample_list,note_list,effect_list
flat=lambda z : reduce(lambda x,y:list(x)+list(y),z,[])
def exe(c):
print c
os.system(c)
fn=sys.argv[1]
used_channel=int(sys.argv[2])
odir='/tmp/' + str(used_channel) + os.path.basename(fn).split('.')[0]
if os.path.isdir(odir): empty_directory(odir)
else: os.mkdir(odir)
sample_list,note_list,effect_list=mod_lists(fn)
used_samples=filter(int,sorted(list(set(flat(sample_list)))))
used_notes=sorted(list(set(flat(note_list))))
used_effects=sorted(list(set(flat(effect_list))))
sampnotes={}
for u in used_samples:
sampnotes[u]=[]
for s,n in zip(flat(sample_list),flat(note_list)):
if s==u and n not in sampnotes[u]: sampnotes[u].append(n)
bgfiles=sorted(os.listdir(bgdir))
print 'Images:',len(bgfiles)
inps=[]
for i,(s,n,e) in enumerate(zip(sample_list,note_list,effect_list)):
npl=[]
for chan,(si,ni,ei) in enumerate(zip(s,n,e)):
if si: npl.append(float(sampnotes[si].index(ni))/float(len(sampnotes[si])))
else: npl.append(0)
if len(npl): mean=npl[used_channel]
else: mean=0
inps.append(mean)
avg_inp=float(sum(inps))/float(len(inps))
ffakt=float(len(inps))/float(len(bgfiles))
print 'Average intensity = %2.2f, Frame factor = %2.2f' % (avg_inp,ffakt)
pos=0.0
pbar = progressbar.ProgressBar().start()
for n,i in enumerate(inps):
pos+=(i/avg_inp)/ffakt
if pos>=len(bgfiles): pos=len(bgfiles)-1
shutil.copy(bgdir+bgfiles[int(pos)],'%s/image%05d.jpg' % (odir,n))
percent_complete=int(float(n)/float(len(inps))*100)
pbar.update(percent_complete)
pbar.finish()
afn='/tmp/'+str(used_channel)+fn.lower().replace('mod','avi')
afn2=str(used_channel)+fn.lower().replace('mod','avi')
wfn='/tmp/'+fn.lower().replace('mod','wav')
mfn='/tmp/'+fn.lower().replace('mod','mp3')
assert fn!=afn2
exe('mencoder mf://%s/*.jpg -ovc x264 -x264encopts crf=20 -o %s -mf fps=25' % (odir,afn) )
if not os.path.isfile(wfn): exe('timidity %s -Ow -o %s' % (fn,wfn))
if not os.path.isfile(mfn): exe('lame %s %s' % (wfn,mfn))
if os.path.isfile(afn2): os.unlink(afn2)
exe('ffmpeg -i %s -i %s -vcodec copy %s -acodec copy -newaudio' % (afn,mfn,afn2))