PageRenderTime 83ms CodeModel.GetById 40ms app.highlight 9ms RepoModel.GetById 31ms app.codeStats 0ms

/examples/step/step-by-section.py

http://echo-nest-remix.googlecode.com/
Python | 101 lines | 75 code | 4 blank | 22 comment | 1 complexity | 24a070e2bfb1ac550ff21e6f931ed25b MD5 | raw file
  1#!/usr/bin/env python
  2# encoding: utf=8
  3
  4"""
  5step-by-section.py
  6
  7For each bar, take one of the nearest (in timbre) beats 
  8to the last beat, chosen from all of the beats that fall
  9on the one in this section. Repeat for all the twos, etc.
 10
 11This version divides things by section, retaining the 
 12structure and approximate length of the original. The 
 13variation parameter, (_v_) means there's a roughly 
 14one in _v_ chance that the actual next beat is chosen. A 
 15musical M-x dissociated-press.
 16
 17Originally by Adam Lindsay, 2009-03-10.
 18"""
 19import random
 20
 21import echonest.audio as audio
 22from echonest.sorting import *
 23from echonest.selection import *
 24
 25usage = """
 26Usage:
 27    python step-by-section.py inputFilename outputFilename [variation]
 28
 29variation is the number of near candidates chosen from. [default=4]
 30
 31Example:
 32    python step-by-section.py Discipline.mp3 Displicine.mp3 6
 33"""
 34def main(infile, outfile, choices=4):
 35    audiofile = audio.LocalAudioFile(infile)
 36    meter = audiofile.analysis.time_signature['value']
 37    fade_in = audiofile.analysis.end_of_fade_in
 38    fade_out = audiofile.analysis.start_of_fade_out
 39    sections = audiofile.analysis.sections.that(overlap_range(fade_in, fade_out))
 40    outchunks = audio.AudioQuantumList()
 41
 42    for section in sections:
 43        print str(section) + ":"
 44        beats = audiofile.analysis.beats.that(are_contained_by(section))
 45        segments = audiofile.analysis.segments.that(overlap(section))
 46        num_bars = len(section.children())
 47        
 48        print "\t", len(beats), "beats,", len(segments), "segments"
 49        if len(beats) < meter:
 50            continue
 51        
 52        b = []
 53        segstarts = []
 54        for m in range(meter):
 55            b.append(beats.that(are_beat_number(m)))
 56            segstarts.append(segments.that(overlap_starts_of(b[m])))
 57        
 58        if not b:
 59            continue
 60        elif not b[0]:
 61            continue
 62        
 63        now = b[0][0]
 64        
 65        for x in range(0, num_bars * meter):
 66            beat = x % meter
 67            next_beat = (x + 1) % meter
 68            now_end_segment = segments.that(contain_point(now.end))[0]
 69            next_candidates = segstarts[next_beat].ordered_by(timbre_distance_from(now_end_segment))
 70            if not next_candidates:
 71                continue
 72            next_choice = next_candidates[random.randrange(min(choices, len(next_candidates)))]
 73            next = b[next_beat].that(start_during(next_choice))[0]
 74            outchunks.append(now)
 75            print "\t" + now.context_string()
 76            now = next
 77    
 78    out = audio.getpieces(audiofile, outchunks)
 79    out.encode(outfile)
 80    
 81    
 82def are_beat_number(beat):
 83    def fun(x):        
 84        if x.local_context()[0] == beat:
 85            return x
 86    return fun
 87
 88#
 89if __name__ == '__main__':
 90    import sys
 91    try:
 92        inputFilename = sys.argv[1]
 93        outputFilename = sys.argv[2]
 94        if len(sys.argv) > 3:
 95            variation = int(sys.argv[3])
 96        else:
 97            variation = 4
 98    except:
 99        print usage
100        sys.exit(-1)
101    main(inputFilename, outputFilename, variation)