PageRenderTime 425ms CodeModel.GetById 221ms app.highlight 12ms RepoModel.GetById 189ms app.codeStats 1ms

/examples/capsule/capsule.py

http://echo-nest-remix.googlecode.com/
Python | 112 lines | 67 code | 20 blank | 25 comment | 20 complexity | e28319cf13ef732ccfc5f204747daaed MD5 | raw file
  1#!/usr/bin/env python
  2# encoding: utf=8
  3
  4"""
  5capsule.py
  6
  7accepts songs on the commandline, order them, beatmatch them, and output an audio file
  8
  9Created by Tristan Jehan and Jason Sundram.
 10"""
 11
 12import os
 13import sys
 14from optparse import OptionParser
 15
 16from echonest.action import render, make_stereo
 17from echonest.audio import LocalAudioFile
 18from pyechonest import util
 19
 20from capsule_support import order_tracks, equalize_tracks, resample_features, timbre_whiten, initialize, make_transition, terminate, FADE_OUT, display_actions, is_valid
 21from utils import tuples
 22
 23def do_work(audio_files, options):
 24
 25    inter = float(options.inter)
 26    trans = float(options.transition)
 27    order = bool(options.order)
 28    equal = bool(options.equalize)
 29    verbose = bool(options.verbose)
 30    
 31    # Get pyechonest/remix objects
 32    analyze = lambda x : LocalAudioFile(x, verbose=verbose)
 33    tracks = map(analyze, audio_files)
 34    
 35    # decide on an initial order for those tracks
 36    if order == True:
 37        if verbose: print "Ordering tracks..."
 38        tracks = order_tracks(tracks)
 39    
 40    if equal == True:
 41        equalize_tracks(tracks)
 42        if verbose:
 43            print
 44            for track in tracks:
 45                print "Vol = %.0f%%\t%s" % (track.gain*100.0, track.analysis.pyechonest_track.title)
 46            print
 47    
 48    valid = []
 49    # compute resampled and normalized matrices
 50    for track in tracks:
 51        if verbose: print "Resampling features for", track.analysis.pyechonest_track.title
 52        track.resampled = resample_features(track, rate='beats')
 53        track.resampled['matrix'] = timbre_whiten(track.resampled['matrix'])
 54        # remove tracks that are too small
 55        if is_valid(track, inter, trans):
 56            valid.append(track)
 57        # for compatibility, we make mono tracks stereo
 58        track = make_stereo(track)
 59    tracks = valid
 60    
 61    if len(tracks) < 1: return []
 62    # Initial transition. Should contain 2 instructions: fadein, and playback.
 63    if verbose: print "Computing transitions..."
 64    start = initialize(tracks[0], inter, trans)
 65    
 66    # Middle transitions. Should each contain 2 instructions: crossmatch, playback.
 67    middle = []
 68    [middle.extend(make_transition(t1, t2, inter, trans)) for (t1, t2) in tuples(tracks)]
 69    
 70    # Last chunk. Should contain 1 instruction: fadeout.
 71    end = terminate(tracks[-1], FADE_OUT)
 72    
 73    return start + middle + end
 74
 75def get_options(warn=False):
 76    usage = "usage: %s [options] <list of mp3s>" % sys.argv[0]
 77    parser = OptionParser(usage=usage)
 78    parser.add_option("-t", "--transition", default=8, help="transition (in seconds) default=8")
 79    parser.add_option("-i", "--inter", default=8, help="section that's not transitioning (in seconds) default=8")
 80    parser.add_option("-o", "--order", action="store_true", help="automatically order tracks")
 81    parser.add_option("-e", "--equalize", action="store_true", help="automatically adjust volumes")
 82    parser.add_option("-v", "--verbose", action="store_true", help="show results on screen")        
 83    parser.add_option("-p", "--pdb", default=True, help="dummy; here for not crashing when using nose")
 84    
 85    (options, args) = parser.parse_args()
 86    if warn and len(args) < 2: 
 87        parser.print_help()
 88    return (options, args)
 89    
 90def main():
 91    options, args = get_options(warn=True);
 92    actions = do_work(args, options)
 93    verbose = bool(options.verbose)
 94    
 95    if verbose:
 96        display_actions(actions)
 97        print "Output Duration = %.3f sec" % sum(act.duration for act in actions)
 98    
 99        print "Rendering..."
100    # Send to renderer
101    render(actions, 'capsule.mp3', verbose)
102    return 1
103    
104if __name__ == "__main__":
105    main()
106    # for profiling, do this:
107    #import cProfile
108    #cProfile.run('main()', 'capsule_prof')
109    # then in ipython:
110    #import pstats
111    #p = pstats.Stats('capsule_prof')
112    #p.sort_stats('cumulative').print_stats(30)