#! /usr/bin/env python

# This little python script searches in the directories passed to it on the command line (NOT recursively) for mp3 files
# and uses sox to extract random chunks of random length and concatenate them together, with crossfading, creating
# a sort of audio collage from your audio files (which remain untouched!). The default output is 'collage.mp3'
# Please bear with the code, it's full of non-elegant solutions - I'm a python newbie
# sox is a great tool with many effects with which it would be possible to create a crazier collage


#max length in seconds of the audio chunks that will make up the collage. (Percieved length will be smaller due
#to crossfades
max = 14 
##WARNING## *all* input files have to be longer than max

import os
import commands
import random
import sys

#let's make a working directory 

tmp = 'audiocollagetemporaryfolder/'
os.system('mkdir -p {0}'.format(tmp))

def duration(x):
	"""Returns duration of an mp3 in seconds, ignoring warnings in the ouput"""
	
	os.system('touch {0}soxiout'.format(tmp))
	os.system('soxi -D "{0}" >> {1}soxiout'.format(x,tmp))
	f = open('{0}soxiout'.format(tmp),'r')
	g = f.readline()
	while g != '':
		dura = g[:-2]
		h = f.readline()
		if h == '':
			break
		else: 
			g = h
	return int(float(g))
	os.system('rm -f {0}soxiout'.format(tmp))
	


#ask for the output file:
print ''
print ''
out = raw_input('output file (it *WILL* overwrite existing files) - default is collage.mp3: ')

if out == '':
	out = 'collage.mp3'

#first thing get the directories in which to search mp3s
#print sys.argv
#print ''
#print len(sys.argv)
directories = []
for i in range(1,len(sys.argv)):
	directories.append(sys.argv[i])

#then put all the files in these directories in a list

files = []
for i in directories:
	tmplist = os.listdir('{0}'.format(i))
	for h in tmplist:
		files.append(i + '/' + h)
	
#next make a new list with only mp3 files

mp3 = []
for i in files:
	if i[-3:] == 'mp3':
		mp3.append(i)

#on to the fun stuff: one by one, trim the audio files and save them to audiocollagetemporaryfolder/[number].wav

i = 0
while mp3 != []:
	a = random.choice(mp3)		#randomly select an mp3, then take away that item from the mp3 list
	c = mp3[0:mp3.index(a)]		
	c.extend(mp3[mp3.index(a) + 1:])
	mp3 = c
	dura = duration(a);	
	td = [dura, random.randint(0,dura - max), random.randint(7,max)] #td stands for trim data - storing in it info needed for sox

	#resampling is needed because the splice effect (used afterwards) wants files with same sample rate
	cmd = 'sox  "{0}" {1}{2}.wav rate 44.1k trim {3} {4}'.format(a,tmp,i,td[1],td[2]) 

	print 'trimming ', a
	print ' '  
	os.system(cmd)
	i = i + 1

#now using sox's splice effect we'll concatenate with crossfading first 0.wav and 1.wav, writing the result
#on 1.wav, then 1.wav and 2.wav writing on 2.wav... and so on

print '-'*20
print 'attaching all the chunks together'

j = 0
while j < i - 1:
	arg = '{0}{1}.wav'.format(tmp,j)
	dur = duration(arg)
	cmd = 'sox {0}{1}.wav {0}{2}.wav {0}a.wav splice -q {3},{4}'.format(tmp,j,j+1,dur,random.randint(1,2))
	print cmd
	os.system(cmd)
	os.system('rm -f {0}{1}.wav'.format(tmp,j+1))
	os.system('mv {0}a.wav {0}{1}.wav'.format(tmp, j+1))
	j = j + 1


#final conversion to output file, adding fade in, out and removing working directory

print '-'*20
print 'exporting to the selected output file/type'

cmd = 'sox {0}{1}.wav {2} fade t 2 0'.format(tmp,j - 1,out)
print cmd
os.system(cmd)


print 'removing temporary files'
os.system('rm -rf {0}'.format(tmp))

print 'Done'


