#NEWLINE# def retarget( songs , duration , music_labels = None , out_labels = None , out_penalty = None , volume = None , volume_breakpoints = None , springs = None , constraints = None , min_beats = None , max_beats = None , fade_in_len = 3.0 , fade_out_len = 5.0 , **kwargs ) : #NEWLINE# #INDENT# 'Retarget a song to a duration given input and output labels on\n    the music.\n\n    Suppose you like one section of a song, say, the guitar solo, and\n    you want to create a three minute long version of the solo.\n    Suppose the guitar solo occurs from the 150 second mark to the 200\n    second mark in the original song.\n\n    You can set the label the guitar solo with \'solo\' and the rest of\n    the song with \'other\' by crafting the ``music_labels`` input\n    function. And you can set the ``out_labels`` function to give you\n    nothing but solo::\n\n        def labels(t):\n            if 150 < t < 200:\n                return \'solo\'\n            return \'other\'\n\n        def target(t): return \'solo\'\n\n        song = Song("sweet-rock-song.wav")\n\n        composition, info = retarget(song, 180,\n            music_labels=labels, out_labels=target)\n\n        composition.export(filename="super-long-solo")\n\n    You can achieve much more complicated retargetings by adjusting\n    the ``music_labels``, `out_labels` and ``out_penalty`` functions,\n    but this should give you a basic sense of how to use the\n    ``retarget`` function.\n\n    :param song: Song to retarget\n    :type song: :py:class:`radiotool.composer.Song`\n    :param duration: Duration of retargeted song (in seconds)\n    :type duration: float\n    :param music_labels: A function that takes a time (in seconds) and\n        returns the label (str) of the input music at that time\n    :type music_labels: function\n    :param out_labels: A function that takes a time (in seconds) and\n        returns the desired label (str) of the output music at that\n        time\n    :type out_labels: function\n    :param out_penalty: A function that takes a time (in seconds) and\n        returns the penalty for not matching the correct output label\n        at that time (default is 1.0)\n    :type out_penalty: function\n    :returns: Composition of retargeted song, and dictionary of\n        information about the retargeting\n    :rtype: (:py:class:`radiotool.composer.Composition`, dict)\n    ' #NEWLINE# if isinstance ( info , Track ) : #NEWLINE# #INDENT# songs = [ songs ] #NEWLINE# #UNINDENT# multi_songs = ( len ( songs ) > 1 ) #NEWLINE# analyses = [ s . analysis for s in songs ] #NEWLINE# beat_lengths = [ a [ BEAT_DUR_KEY ] for a in analyses ] #NEWLINE# beats = [ a [ 'beats' ] for a in analyses ] #NEWLINE# beat_length = np . mean ( beat_lengths ) #NEWLINE# logging . info ( 'Beat lengths of songs: {} (mean: {})' . format ( beat_lengths , beat_length ) ) #NEWLINE# if ( out_labels is not None ) : #NEWLINE# #INDENT# target = [ out_labels ( i ) for i in np . arange ( 0 , duration , beat_length ) ] #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# target = [ '' for i in np . arange ( 0 , duration , beat_length ) ] #NEWLINE# #UNINDENT# if ( music_labels is not None ) : #NEWLINE# #INDENT# if ( not multi_songs ) : #NEWLINE# #INDENT# music_labels = [ music_labels ] #NEWLINE# music_labels = [ item for sublist in music_labels for item in sublist ] #NEWLINE# #UNINDENT# if ( len ( music_labels ) != len ( songs ) ) : #NEWLINE# #INDENT# raise ArgumentException ( 'Did not specify {} sets of music labels' . format ( len ( songs ) ) ) #NEWLINE# #UNINDENT# start = [ [ music_labels [ i ] ( j ) for j in b ] for ( i , b ) in enumerate ( beats ) ] #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# start = [ [ '' for i in b ] for b in beats ] #NEWLINE# #UNINDENT# if ( out_penalty is not None ) : #NEWLINE# #INDENT# pen = np . array ( [ out_penalty ( i ) for i in np . arange ( 0 , duration , beat_length ) ] ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# pen = np . array ( [ 1 for i in np . arange ( 0 , duration , beat_length ) ] ) #NEWLINE# #UNINDENT# in_vas = kwargs . pop ( 'music_va' , None ) #NEWLINE# if ( in_vas is not None ) : #NEWLINE# #INDENT# if ( not multi_songs ) : #NEWLINE# #INDENT# in_vas = [ in_vas ] #NEWLINE# in_vas = [ item for sublist in in_vas for item in sublist ] #NEWLINE# #UNINDENT# if ( len ( in_vas ) != len ( songs ) ) : #NEWLINE# #INDENT# raise ArgumentException ( 'Did not specify {} sets of v/a labels' . format ( len ( songs ) ) ) #NEWLINE# #UNINDENT# for ( i , in_va ) in enumerate ( in_vas ) : #NEWLINE# #INDENT# if callable ( in_va ) : #NEWLINE# #INDENT# in_va = np . array ( [ in_va ( j ) for j in beats [ i ] ] ) #NEWLINE# #UNINDENT# in_vas [ i ] = in_va #NEWLINE# #UNINDENT# #UNINDENT# target_va = kwargs . pop ( 'out_va' , None ) #NEWLINE# if callable ( target_va ) : #NEWLINE# #INDENT# target_va = np . array ( [ target_va ( i ) for i in np . arange ( 0 , duration , beat_length ) ] ) #NEWLINE# #UNINDENT# if ( constraints is None ) : #NEWLINE# #INDENT# min_pause_len = 20.0 #NEWLINE# max_pause_len = 35.0 #NEWLINE# min_pause_beats = int ( np . ceil ( ( min_pause_len / beat_length ) ) ) #NEWLINE# max_pause_beats = int ( np . floor ( ( max_pause_len / beat_length ) ) ) #NEWLINE# constraints = [ ( rt_constraints . PauseConstraint ( min_pause_beats , max_pause_beats , to_penalty = 1.4 , between_penalty = 0.05 , unit = 'beats' ) , rt_constraints . PauseEntryVAChangeConstraint ( target_va , 0.005 ) , rt_constraints . PauseExitVAChangeConstraint ( target_va , 0.005 ) , rt_constraints . TimbrePitchConstraint ( context = 0 , timbre_weight = 1.5 , chroma_weight = 1.5 ) , rt_constraints . EnergyConstraint ( penalty = 0.5 ) , rt_constraints . MinimumLoopConstraint ( 8 ) , rt_constraints . ValenceArousalConstraint ( in_va , target_va , ( pen * 0.125 ) ) , rt_constraints . NoveltyVAConstraint ( in_va , target_va , pen ) ) for in_va in in_vas ] #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# max_pause_beats = 0 #NEWLINE# if ( len ( constraints ) > 0 ) : #NEWLINE# #INDENT# if isinstance ( constraints [ 0 ] , rt_constraints . Constraint ) : #NEWLINE# #INDENT# constraints = [ constraints ] #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# pipelines = [ rt_constraints . ConstraintPipeline ( constraints = c_set ) for c_set in constraints ] #NEWLINE# trans_costs = [ ] #NEWLINE# penalties = [ ] #NEWLINE# all_beat_names = [ ] #NEWLINE# for ( i , song ) in enumerate ( songs ) : #NEWLINE# #INDENT# ( trans_cost , penalty , bn ) = pipelines [ i ] . apply ( song , len ( target ) ) #NEWLINE# trans_costs . append ( trans_cost ) #NEWLINE# penalties . append ( penalty ) #NEWLINE# all_beat_names . append ( bn ) #NEWLINE# #UNINDENT# logging . info ( 'Combining tables' ) #NEWLINE# total_music_beats = int ( np . sum ( [ len ( b ) for b in beats ] ) ) #NEWLINE# total_beats = ( total_music_beats + max_pause_beats ) #NEWLINE# trans_cost = ( np . ones ( ( total_beats , total_beats ) ) * np . inf ) #NEWLINE# sizes = [ len ( b ) for b in beats ] #NEWLINE# idx = 0 #NEWLINE# for ( i , size ) in enumerate ( sizes ) : #NEWLINE# #INDENT# trans_cost [ idx : ( idx + size ) , idx : ( idx + size ) ] = trans_costs [ i ] [ : size , : size ] #NEWLINE# idx += size #NEWLINE# #UNINDENT# trans_cost [ : total_music_beats , total_music_beats : ] = np . vstack ( [ tc [ : len ( beats [ i ] ) , len ( beats [ i ] ) : ] for ( i , tc ) in enumerate ( trans_costs ) ] ) #NEWLINE# trans_cost [ total_music_beats : , : total_music_beats ] = np . hstack ( [ tc [ len ( beats [ i ] ) : , : len ( beats [ i ] ) ] for ( i , tc ) in enumerate ( trans_costs ) ] ) #NEWLINE# trans_cost [ total_music_beats : , total_music_beats : ] = trans_costs [ 0 ] [ len ( beats [ 0 ] ) : , len ( beats [ 0 ] ) : ] #NEWLINE# penalty = np . empty ( ( total_beats , penalties [ 0 ] . shape [ 1 ] ) ) #NEWLINE# penalty [ : total_music_beats , : ] = np . vstack ( [ p [ : len ( beats [ i ] ) , : ] for ( i , p ) in enumerate ( penalties ) ] ) #NEWLINE# penalty [ total_music_beats : , : ] = penalties [ 0 ] [ len ( beats [ 0 ] ) : , : ] #NEWLINE# logging . info ( 'Building cost table' ) #NEWLINE# first_pause = total_music_beats #NEWLINE# if ( min_beats is None ) : #NEWLINE# #INDENT# min_beats = 0 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( min_beats is 'default' ) : #NEWLINE# #INDENT# min_beats = int ( ( 20.0 / beat_length ) ) #NEWLINE# #UNINDENT# #UNINDENT# if ( max_beats is None ) : #NEWLINE# #INDENT# max_beats = ( - 1 ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( max_beats is 'default' ) : #NEWLINE# #INDENT# max_beats = int ( ( 90.0 / beat_length ) ) #NEWLINE# max_beats = min ( max_beats , penalty . shape [ 1 ] ) #NEWLINE# #UNINDENT# #UNINDENT# tc2 = np . nan_to_num ( trans_cost ) #NEWLINE# pen2 = np . nan_to_num ( penalty ) #NEWLINE# beat_names = [ ] #NEWLINE# for ( i , bn ) in enumerate ( all_beat_names ) : #NEWLINE# #INDENT# for b in bn : #NEWLINE# #INDENT# if ( not str ( b ) . startswith ( 'p' ) ) : #NEWLINE# #INDENT# beat_names . append ( ( i , float ( b ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# beat_names . extend ( [ ( 'p' , i ) for i in xrange ( max_pause_beats ) ] ) #NEWLINE# result_labels = [ ] #NEWLINE# logging . info ( 'Running optimization (full backtrace, memory efficient)' ) #NEWLINE# logging . info ( ( '\twith min_beats(%d) and max_beats(%d) and first_pause(%d)' % ( min_beats , max_beats , first_pause ) ) ) #NEWLINE# song_starts = [ 0 ] #NEWLINE# for song in songs : #NEWLINE# #INDENT# song_starts . append ( ( song_starts [ ( - 1 ) ] + len ( song . analysis [ 'beats' ] ) ) ) #NEWLINE# #UNINDENT# song_ends = np . array ( song_starts [ 1 : ] , dtype = np . int32 ) #NEWLINE# song_starts = np . array ( song_starts [ : ( - 1 ) ] , dtype = np . int32 ) #NEWLINE# t1 = time . clock ( ) #NEWLINE# ( path_i , path_cost ) = build_table_full_backtrace ( tc2 , pen2 , song_starts , song_ends , first_pause = first_pause , max_beats = max_beats , min_beats = min_beats ) #NEWLINE# t2 = time . clock ( ) #NEWLINE# logging . info ( 'Built table (full backtrace) in {} seconds' . format ( ( t2 - t1 ) ) ) #NEWLINE# path = [ ] #NEWLINE# if ( max_beats == ( - 1 ) ) : #NEWLINE# #INDENT# max_beats = ( min_beats + 1 ) #NEWLINE# #UNINDENT# first_pause_full = ( max_beats * first_pause ) #NEWLINE# n_beats = first_pause #NEWLINE# for i in path_i : #NEWLINE# #INDENT# if ( i >= first_pause_full ) : #NEWLINE# #INDENT# path . append ( ( 'p' , ( i - first_pause_full ) ) ) #NEWLINE# result_labels . append ( None ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# path . append ( beat_names [ ( i % n_beats ) ] ) #NEWLINE# song_i = path [ ( - 1 ) ] [ 0 ] #NEWLINE# beat_name = path [ ( - 1 ) ] [ 1 ] #NEWLINE# result_labels . append ( start [ song_i ] [ np . where ( ( np . array ( beats [ song_i ] ) == beat_name ) ) [ 0 ] [ 0 ] ] ) #NEWLINE# #UNINDENT# #UNINDENT# logging . info ( 'Generating audio' ) #NEWLINE# ( comp , cf_locations , result_full_labels , cost_labels , contracted , result_volume ) = _generate_audio ( songs , beats , path , path_cost , start , volume = volume , volume_breakpoints = volume_breakpoints , springs = springs , fade_in_len = fade_in_len , fade_out_len = fade_out_len ) #NEWLINE# info = { #NEWLINE# #INDENT# 'beat_length' : beat_length , #NEWLINE# 'contracted' : contracted , #NEWLINE# 'cost' : ( np . sum ( path_cost ) / len ( path ) ) , #NEWLINE# 'path' : path , #NEWLINE# 'path_i' : path_i , #NEWLINE# 'target_labels' : target , #NEWLINE# 'result_labels' : result_labels , #NEWLINE# 'result_full_labels' : result_full_labels , #NEWLINE# 'result_volume' : result_volume , #NEWLINE# 'transitions' : [ Label ( 'crossfade' , loc ) for loc in cf_locations ] , #NEWLINE# 'path_cost' : cost_labels , #NEWLINE# #UNINDENT# } #NEWLINE# return ( comp , info )