yading@9: #!/usr/bin/env python yading@9: # encoding: utf-8 yading@9: yading@9: """ yading@9: Created by Yading Song on 2013-04-21 for Music Hack Day in Paris yading@9: Copyright (c) 2013 . All rights reserved. yading@9: """ yading@9: yading@12: #import soundcloud yading@12: #import musixmatch yading@12: #import musixmatch.ws yading@12: yading@12: import json yading@9: import os,sys,optparse,signal,time,math yading@9: import cherrypy as cp yading@10: import numpy yading@10: import sys yading@10: sys.path.append('/usr/local/lib/python2.7/site-packages') yading@9: from cherrypy.lib import static yading@9: import subprocess as sp yading@9: from subprocess import Popen as spopen yading@9: yading@10: import time yading@10: import random yading@9: """"*********************************************************************************""" yading@9: yading@9: from xml.dom import minidom yading@9: import urllib2 #call url function yading@9: import os yading@9: import sys yading@9: import cPickle yading@9: yading@9: import pyechonest # import echonest API yading@9: from pyechonest import artist, catalog, config, playlist # How it works instead of pyechonest yading@9: yading@10: from echonest.remix import audio, modify yading@9: yading@10: # echonest API for pitch shifting yading@10: config.ECHO_NEST_API_KEY="SFXNKMTRAZ3ULHK6U " yading@10: yading@12: # musiXmatch API key yading@12: apikey = '8496dd1c715c69a74ef9fcde1716cf4a' yading@10: yading@10: yading@10: # 7 digital API key yading@10: DIGITAL7_API_KEY = '7dbpa63h3y3d' yading@10: yading@10: yading@10: usage = """ yading@10: Usage: yading@10: python beatshift.py yading@10: Exampel: yading@10: python beatshift.py CryMeARiver.mp3 CryMeAShifty.mp3 yading@10: """ yading@9: yading@9: yading@9: yading@9: # this is just a parser for command line options for the server. yading@9: op = optparse.OptionParser() yading@9: op.add_option('-u', '--user', action="store", dest="USER", default="devel", type="str") yading@9: options, args = op.parse_args() yading@9: CONFIG_FILE = "%(USER)s.cfg" %options.__dict__ yading@9: yading@9: if not os.path.isfile(CONFIG_FILE) : yading@9: print >> sys.stderr, "Config file not found: %s" %CONFIG_FILE yading@9: sys.exit(-1) yading@9: yading@9: # This is the server side of the actual Web-application yading@9: class ServerExample: yading@9: yading@9: def __init__(self): yading@9: self.inputs = [] yading@9: yading@9: def index(self): yading@9: return "" yading@9: yading@10: yading@9: @cp.expose yading@9: def receiveinput(self, userinput): yading@10: # type in the title of the song you like yading@10: print "\n\n >>>The user entered the text: %(userinput)s\n\n" %locals() yading@9: yading@12: #lyrics = musixmatch.ws.track.lyrics.get('Baby',apikey=apikey) yading@11: yading@12: html_head = ''' BrutalizeMe

Results

''' yading@11: yading@12: content = '''

You have chosen %s music

''' %userinput yading@12: html_tail = '''

Back
''' yading@10: audio_url = "" yading@10: yading@12: #(tracktitle, trackid) = get_trackid_from_text_search(userinput,'Justin Bieber') yading@13: (tracktitle, trackid) = get_trackid_from_text_search(userinput,'') yading@13: yading@10: audio_url = get_preview_from_trackid(trackid) yading@10: yading@12: content = content + '''

''' % audio_url + ''' %s ''' % userinput yading@9: yading@10: file_name = tracktitle + u'.mp3' yading@10: file_name = file_name.replace(u'/', u' ') yading@10: yading@10: #file_name = t.title + u'.mp3' yading@10: # download_path = os.path.join(file_path, file_name) yading@10: yading@12: file_name = "Baby.mp3" yading@10: # download the song in the same path folder yading@10: path_name = './' + file_name yading@10: mp3 = download_file(audio_url, path_name) yading@10: yading@13: os.system('ffmpeg -i Baby.mp3 -ac 1 Baby.wav') yading@12: os.system('./sonic-annotator-0.7-osx-x86_64/sonic-annotator -d vamp:mtg-melodia:melodia:melody Baby.wav -w csv --csv-one-file baby.txt --csv-separator " " ') yading@13: yading@10: yading@10: print "Pitch Shifting Done" yading@10: yading@10: os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"step1('Baby.wav');exit;\" ") yading@10: #os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"step1('Baby.wav');exit;\" ") yading@10: print "Melody" yading@10: yading@10: os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"step2('Baby.wav');exit;\" ") yading@10: #os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"step2('Baby_ps12.wav');exit;\" ") yading@10: print "Instrument" yading@10: #os.system('/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r "mcc -m filename.m;exit;"') yading@9: yading@10: print "Done STEP 1" yading@12: yading@12: # light version yading@10: pitchshifting5('melody.wav','melody_ps5.wav') yading@13: print "pitch shifting 5" yading@12: # heaven version yading@10: pitchshifting12('melody.wav','melody_ps12.wav') yading@9: yading@10: yading@10: os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"step3('melody_ps5.wav');exit;\"") yading@12: os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"step3_heavy('melody_ps12.wav');exit;\"") yading@10: print "Step 3" yading@12: yading@12: os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"fix_offset('melody.wav','ysbaby_voice_light.wav');exit;\"") yading@12: os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"fix_offset('melody.wav','ysbaby_voice_heavy.wav');exit;\"") yading@12: yading@10: os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"final_mix('ysbaby_voice_light.wav','instrumental.wav');exit;\"") yading@12: os.system("/Applications/MATLAB_R2012b.app/bin/matlab -nojvm -nosplash -nodisplay -r \"final_mix_heavy('ysbaby_voice_heavy.wav','instrumental.wav');exit;\"") yading@12: yading@10: lightaudio_url = 'light_' + tracktitle yading@10: midaudio_url = 'mid_' + tracktitle yading@10: heavyaudio_url = 'heavy_' + tracktitle yading@10: yading@12: content = content + '''

''' + ''' Light Version

''' yading@12: content = content + '''

''' + ''' Heavy Version ''' yading@10: #content = content + '''

''' % heavyaudio_url + ''' Heaven Version ''' yading@10: yading@9: return html_head, content, html_tail yading@9: yading@9: @cp.expose yading@9: def testpage(self): yading@9: return " You have accessed the test page " yading@9: yading@10: def pitchshifting5(input_filename, output_filename): yading@10: soundtouch = modify.Modify() yading@10: audiofile = audio.LocalAudioFile(input_filename) yading@10: beats = audiofile.analysis.beats yading@10: out_shape = (len(audiofile.data),) yading@10: out_data = audio.AudioData(shape=out_shape, numChannels=1, sampleRate=44100) yading@10: yading@10: for i, beat in enumerate(beats): yading@10: data = audiofile[beat].data yading@10: number = beat.local_context()[0] % 12 yading@10: #new_beat = soundtouch.shiftPitchSemiTones(audiofile[beat], number*-1) yading@10: new_beat = soundtouch.shiftPitchSemiTones(audiofile[beat], -5) yading@10: out_data.append(new_beat) yading@10: yading@10: out_data.encode(output_filename) yading@10: yading@10: yading@10: def pitchshifting12(input_filename, output_filename): yading@10: soundtouch = modify.Modify() yading@10: audiofile = audio.LocalAudioFile(input_filename) yading@10: beats = audiofile.analysis.beats yading@10: out_shape = (len(audiofile.data),) yading@10: out_data = audio.AudioData(shape=out_shape, numChannels=1, sampleRate=44100) yading@10: yading@10: for i, beat in enumerate(beats): yading@10: data = audiofile[beat].data yading@10: number = beat.local_context()[0] % 12 yading@10: #new_beat = soundtouch.shiftPitchSemiTones(audiofile[beat], number*-1) yading@12: new_beat = soundtouch.shiftPitchSemiTones(audiofile[beat], -12) yading@10: out_data.append(new_beat) yading@10: yading@10: out_data.encode(output_filename) yading@10: yading@10: yading@9: def url_call(url): yading@9: """ yading@10: ***This method is from get_preview_url.py by Thierry Bertin-Mahieux*** yading@10: Do a simple request to the 7digital API yading@10: We assume we don't do intense querying, this function is not robust yading@10: Return the answer as na xml document yading@10: """ yading@9: stream = urllib2.urlopen(url) yading@9: xmldoc = minidom.parse(stream).documentElement yading@9: stream.close() yading@9: return xmldoc yading@9: yading@10: yading@10: def download_file(file_url, file_name): yading@10: # open the url yading@10: mp3file = urllib2.urlopen(file_url) yading@10: yading@10: # open the local file for writing yading@10: local_file = open(file_name, "wb") yading@10: # write to file yading@10: local_file.write(mp3file.read()) yading@10: local_file.close() yading@10: yading@9: """"*********************************************************************************""" yading@9: yading@10: def get_trackid_from_text_search(title,artistname=''): yading@10: """ yading@10: ***This method is from get_preview_url.py by Thierry Bertin-Mahieux*** yading@10: Search for an artist + title using 7digital search API yading@10: Return None if there is a problem, or tuple (title,trackid) yading@10: """ yading@10: url = 'http://api.7digital.com/1.2/track/search?' yading@10: url += 'oauth_consumer_key='+DIGITAL7_API_KEY yading@10: query = title yading@10: if artistname != '': yading@10: query = artistname + ' ' + query yading@10: query = urllib2.quote(query) yading@10: url += '&q='+query yading@10: xmldoc = url_call(url) yading@10: status = xmldoc.getAttribute('status') yading@10: if status != 'ok': yading@10: return None yading@10: resultelem = xmldoc.getElementsByTagName('searchResult') yading@10: if len(resultelem) == 0: yading@10: return None yading@10: track = resultelem[0].getElementsByTagName('track')[0] yading@10: tracktitle = track.getElementsByTagName('title')[0].firstChild.data yading@10: trackid = int(track.getAttribute('id')) yading@10: return (tracktitle,trackid) yading@10: yading@10: yading@9: def get_preview_from_trackid(trackid): yading@9: """ yading@9: ***This method is from get_preview_url.py by Thierry Bertin-Mahieux*** yading@9: Ask for the preview to a particular track, get the XML answer yading@9: After calling the API with a given track id, yading@9: we get an XML response that looks like: yading@9: yading@9: yading@9: yading@9: http://previews.7digital.com/clips/34/6804688.clip.mp3 yading@9: yading@9: yading@9: yading@9: We parse it for the URL that we return, or '' if a problem yading@9: """ yading@9: url = 'http://api.7digital.com/1.2/track/preview?redirect=false' yading@9: url += '&trackid='+str(trackid) yading@9: url += '&oauth_consumer_key='+DIGITAL7_API_KEY yading@9: xmldoc = url_call(url) yading@9: status = xmldoc.getAttribute('status') yading@9: if status != 'ok': yading@9: return '' yading@9: urlelem = xmldoc.getElementsByTagName('url')[0] yading@9: preview = urlelem.firstChild.nodeValue yading@9: return preview yading@9: yading@9: yading@9: yading@9: """"*********************************************************************************""" yading@9: yading@9: yading@9: def getProcessPids(port,kill=False): yading@9: '''Get the pid of the offending Python process given a port after an unsuccessful restart.''' yading@9: print "Running lsof -i :"+str(port)," ...\n\n" yading@9: command = "lsof -i :"+str(port) yading@9: w = spopen(command,stdout=sp.PIPE,stderr=sp.PIPE,shell=True) yading@9: se = w.stderr.readlines() yading@9: result = w.stdout.readlines() yading@9: exitcode = w.wait() yading@9: if not result : yading@9: print "getProcessPid:: Unable to obtain process pid. (lsof returned nothing. exitcode: %s)" %str(exitcode) yading@9: return False yading@9: import pprint yading@9: pprint.pprint(result) yading@9: yading@9: # get heading: yading@9: ix = None yading@9: head = result[0].upper() yading@9: if 'PID' in head: yading@9: head = filter(lambda x: x != str(), head.split(' ')) yading@9: head = map(lambda x: x.strip().replace(' ',''), head) yading@9: if 'PID' in head : ix = head.index('PID') yading@9: # get process pid yading@9: pids = [] yading@9: for line in result : yading@9: if 'python' in line.lower() : yading@9: line = filter(lambda x: x != str(), line.split(' ')) yading@9: line = map(lambda x: x.strip().replace(' ',''), line) yading@9: try : yading@9: if ix : yading@9: pids.append(int(line[ix])) yading@9: else: yading@9: numbers = filter(lambda x: x.isdigit(), line) yading@9: pids.append(int(numbers[0])) yading@9: except: yading@9: print 'Error parsing lsof results.' yading@9: return False yading@9: print 'Pids found: ',pids yading@9: # kill if specified yading@9: if kill : yading@9: pids_killed = [] yading@9: import signal yading@9: for pid in pids: yading@9: print 'Killing process: ',pid yading@9: try : yading@9: os.kill(pid,signal.SIGKILL) yading@9: pids_killed.append(pid) yading@9: except : yading@9: print 'Failed: ',pid yading@9: if pids_killed : yading@9: print 'Processes killed:',pids_killed,' Waiting 10 seconds...' yading@9: import time yading@9: time.sleep(10) yading@9: return True yading@9: return False yading@9: yading@9: yading@9: def main(argv=None): yading@9: yading@9: # Configure and start yading@9: yading@9: yading@9: cp.config.update(CONFIG_FILE) yading@9: cp.config.update({'tools.staticdir.root': os.getcwd()}) yading@10: cp.tree.mount(ServerExample(),script_name="/MusicHackParis",config=CONFIG_FILE) yading@9: port = int(cp.server.socket_port) yading@9: ip = cp.server.socket_host yading@9: print "Trying to bind: %(ip)s:%(port)s" %locals() yading@9: getProcessPids(port,kill=True) yading@9: cp.quickstart() yading@9: yading@9: if __name__ == "__main__": yading@9: main()