def get_loops(fileobj, output_temp, inter=8.0, trans=2.0): track = LocalAudioFile(fileobj.name) tracks = [track, track, track] # 3 of em! valid = [] # compute resampled and normalized matrices for track in tracks: track.resampled = resample_features(track, rate='beats') track.resampled['matrix'] = timbre_whiten(track.resampled['matrix']) # remove tracks that are too small if is_valid(track, inter, trans): valid.append(track) # for compatibility, we make mono tracks stereo track = make_stereo(track) tracks = valid if len(tracks) < 1: return [] # Initial transition. Should contain 2 instructions: fadein, and playback. start = initialize(tracks[0], inter, trans) # Middle transitions. Should each contain 2 instructions: crossmatch, playback. middle = [] [middle.extend(make_transition(t1, t2, inter, trans)) for (t1, t2) in tuples(tracks)] # Last chunk. Should contain 1 instruction: fadeout. end = terminate(tracks[-1], FADE_OUT) actions = start + middle + end # output_temp = tempfile.NamedTemporaryFile(mode="w+b", suffix=".mp3") render(actions, output_temp.name, False) # Do it again new_one = audio.LocalAudioFile(output_temp.name) analysis = json.loads(urllib.urlopen(new_one.analysis.pyechonest_track.analysis_url).read()) return (output_temp.name, analysis)
def do_work(audio_files, options): inter = float(options.inter) trans = float(options.transition) order = bool(options.order) equal = bool(options.equalize) verbose = bool(options.verbose) # Get pyechonest/remix objects analyze = lambda x : LocalAudioFile(x, verbose=verbose) tracks = map(analyze, audio_files) # decide on an initial order for those tracks if order == True: if verbose: print "Ordering tracks..." tracks = order_tracks(tracks) if equal == True: equalize_tracks(tracks) if verbose: print for track in tracks: print "Vol = %.0f%%\t%s" % (track.gain*100.0, track.analysis.pyechonest_track.title) print valid = [] # compute resampled and normalized matrices for track in tracks: if verbose: print "Resampling features for", track.analysis.pyechonest_track.title track.resampled = resample_features(track, rate='beats') track.resampled['matrix'] = timbre_whiten(track.resampled['matrix']) # remove tracks that are too small if is_valid(track, inter, trans): valid.append(track) # for compatibility, we make mono tracks stereo track = make_stereo(track) tracks = valid if len(tracks) < 1: return [] # Initial transition. Should contain 2 instructions: fadein, and playback. if verbose: print "Computing transitions..." start = initialize(tracks[0], inter, trans) # Middle transitions. Should each contain 2 instructions: crossmatch, playback. middle = [] [middle.extend(make_transition(t1, t2, inter, trans)) for (t1, t2) in tuples(tracks)] # Last chunk. Should contain 1 instruction: fadeout. end = terminate(tracks[-1], FADE_OUT) return start + middle + end
def cutnote(audioData, length): beatlength = (audioData.sampleRate * 60 / tempo) #in samples i = beatlength / length data = audioData.data[0:i] if len(data) < i: if audioData.numChannels == 2: shape = (i - len(data), 2) else: shape = (i - len(data), ) data = numpy.append(data, numpy.zeros(shape, dtype=numpy.int16), 0) r = audio.AudioData(ndarray=data, numChannels=audioData.numChannels, sampleRate=audioData.sampleRate) return make_stereo(r) if (r.numChannels == 1) else r
def cutnote(audioData, length): beatlength = (audioData.sampleRate * 60 / tempo) #in samples i = beatlength/length data = audioData.data[0:i] if len(data) < i: if audioData.numChannels == 2: shape = (i - len(data),2) else: shape = (i - len(data),) data = numpy.append(data, numpy.zeros(shape, dtype=numpy.int16), 0) r = audio.AudioData( ndarray=data, numChannels=audioData.numChannels, sampleRate = audioData.sampleRate ) return make_stereo(r) if (r.numChannels == 1) else r
def get_loops(fileobj, output_temp, inter=8.0, trans=2.0): track = LocalAudioFile(fileobj.name) tracks = [track, track, track] # 3 of em! valid = [] # compute resampled and normalized matrices for track in tracks: track.resampled = resample_features(track, rate='beats') track.resampled['matrix'] = timbre_whiten(track.resampled['matrix']) # remove tracks that are too small if is_valid(track, inter, trans): valid.append(track) # for compatibility, we make mono tracks stereo track = make_stereo(track) tracks = valid if len(tracks) < 1: return [] # Initial transition. Should contain 2 instructions: fadein, and playback. start = initialize(tracks[0], inter, trans) # Middle transitions. Should each contain 2 instructions: crossmatch, playback. middle = [] [ middle.extend(make_transition(t1, t2, inter, trans)) for (t1, t2) in tuples(tracks) ] # Last chunk. Should contain 1 instruction: fadeout. end = terminate(tracks[-1], FADE_OUT) actions = start + middle + end # output_temp = tempfile.NamedTemporaryFile(mode="w+b", suffix=".mp3") render(actions, output_temp.name, False) # Do it again new_one = audio.LocalAudioFile(output_temp.name) analysis = json.loads( urllib.urlopen(new_one.analysis.pyechonest_track.analysis_url).read()) return (output_temp.name, analysis)
def remix(self): """ Remixing happens here. Take your input file from self.infile and write your remix to self.outfile. If necessary, self.tempfile can be used for temp files. """ self.log("Listening to beatbox track...", 30) self.original = audio.LocalAudioFile(self.infile) self.tag['tempo'] = self.original.analysis.tempo bad = [] for i, segment in enumerate(self.original.analysis.segments): segment.encode("seg%s.mp3" % i) loudnesses = [x.timbre[0] for i, x in enumerate(self.original.analysis.segments) if i not in bad] brightnesses = [x.timbre[1] for i, x in enumerate(self.original.analysis.segments) if i not in bad] flatnesses = [x.timbre[2] for i, x in enumerate(self.original.analysis.segments) if i not in bad] attacks = [x.timbre[3] for i, x in enumerate(self.original.analysis.segments) if i not in bad] timbre5 = [x.timbre[4] for i, x in enumerate(self.original.analysis.segments) if i not in bad] timbre6 = [x.timbre[5] for i, x in enumerate(self.original.analysis.segments) if i not in bad] timbre7 = [x.timbre[6] for i, x in enumerate(self.original.analysis.segments) if i not in bad] timbre8 = [x.timbre[7] for i, x in enumerate(self.original.analysis.segments) if i not in bad] timbre9 = [x.timbre[8] for i, x in enumerate(self.original.analysis.segments) if i not in bad] timbre10 = [x.timbre[9] for i, x in enumerate(self.original.analysis.segments) if i not in bad] timbre11 = [x.timbre[10] for i, x in enumerate(self.original.analysis.segments) if i not in bad] timbre12 = [x.timbre[11] for i, x in enumerate(self.original.analysis.segments) if i not in bad] print "21: %s" % self.original.analysis.segments[21].timbre print "MINS" print "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" % ('loud','bright','flat','attack','t5','t6','t7','t8','t9','t10','t11','t12') print "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" % (avg(loudnesses),avg(brightnesses),avg(flatnesses),avg(attacks),avg(timbre5),avg(timbre6),avg(timbre7),avg(timbre8),avg(timbre9),avg(timbre10),avg(timbre11),avg(timbre12)) print print "MAXS" print "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" % ('loud','bright','flat','attack','t5','t6','t7','t8','t9','t10','t11','t12') print "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" % (stddev(loudnesses),stddev(brightnesses),stddev(flatnesses),stddev(attacks),stddev(timbre5),stddev(timbre6),stddev(timbre7),stddev(timbre8),stddev(timbre9),stddev(timbre10),stddev(timbre11),stddev(timbre12)) self.log("Sorting kicks and snares...", 10) kicks = self.original.analysis.segments.that(are_kicks) snares = self.original.analysis.segments.that(are_snares) hats = self.original.analysis.segments.that(are_hats) # Time to replace self.log("Replacing beats...", 20) hat_sample = audio.AudioData(self.sample_path + self.template['hats'], sampleRate=44100, numChannels=2, verbose=False) kick_sample = audio.AudioData(self.sample_path + self.template['kick'], sampleRate=44100, numChannels=2, verbose=False) snare_sample = audio.AudioData(self.sample_path + self.template['snare'], sampleRate=44100, numChannels=2, verbose=False) if self.original.numChannels == 1: self.original = make_stereo(self.original) empty = audio.AudioData(ndarray=numpy.zeros(((self.original.sampleRate * self.original.analysis.duration), 2), dtype=numpy.int16), numChannels=2, sampleRate=44100) last = 0 for segment in kicks: if last + len(kick_sample.data) > segment.start: truncated = kick_sample.data if len(truncated) > len(empty.data[self.original.sampleRate*segment.start:self.original.sampleRate*segment.start + len(kick_sample.data)]): truncated = truncated[:len(empty.data[self.original.sampleRate*segment.start:self.original.sampleRate*segment.start + len(kick_sample.data)])] empty.data[self.original.sampleRate*segment.start:self.original.sampleRate*segment.start + len(kick_sample.data)] += truncated last = segment.start last = 0 for segment in snares: if last + len(snare_sample.data) > segment.start: truncated = snare_sample.data if len(truncated) > len(empty.data[self.original.sampleRate*segment.start:self.original.sampleRate*segment.start + len(snare_sample.data)]): truncated = truncated[:len(empty.data[self.original.sampleRate*segment.start:self.original.sampleRate*segment.start + len(snare_sample.data)])] empty.data[self.original.sampleRate*segment.start:self.original.sampleRate*segment.start + len(snare_sample.data)] += truncated last = segment.start for segment in hats: if last + len(hat_sample.data) > segment.start: truncated = hat_sample.data if len(truncated) > len(empty.data[self.original.sampleRate*segment.start:self.original.sampleRate*segment.start + len(hat_sample.data)]): truncated = truncated[:len(empty.data[self.original.sampleRate*segment.start:self.original.sampleRate*segment.start + len(hat_sample.data)])] empty.data[self.original.sampleRate*segment.start:self.original.sampleRate*segment.start + len(hat_sample.data)] += truncated last = segment.start self.log("Mastering...", 20) audio.mix(empty, self.original, 0.8).encode(self.outfile) self.updateTags(' (Beatbox Machine remix)') return self.outfile
def mashComponents(localAudioFiles, loudnessMarkers): instSegments = localAudioFiles[0].analysis.segments# This is the base track vocalSegments = localAudioFiles[1].analysis.segments# This is the overlay track instBeats = localAudioFiles[0].analysis.beats[loudnessMarkers[0][0]: loudnessMarkers[0][1]] vocalBeats = localAudioFiles[1].analysis.beats[loudnessMarkers[1][0]: loudnessMarkers[1][1]] pitches = meanPitches(instSegments,instBeats) timbre = meanTimbre(instSegments,instBeats) sections = localAudioFiles[1].analysis.sections #This is the new lead vocal layer sections = sections.that(selection.are_contained_by_range( vocalBeats[0].start, vocalBeats[-1].start+vocalBeats[-1].duration)) if(len(sections)==0):sections = localAudioFiles[1].analysis.sections[2:-2] pyplot.figure(0,(16,9)) image = numpy.array(pitches) image = numpy.concatenate((image,numpy.array(timbre)),axis = 1) image = numpy.concatenate((image,numpy.array(meanLoudness(instSegments,instBeats))), axis = 1) """ Now image contains chromatic, timbral, and loudness information""" sectBeats = getSectBeats(sections[0]) # get beats that comprise a specific section template = numpy.array(meanPitches(vocalSegments,sectBeats)) template = numpy.concatenate((template,numpy.array( meanTimbre(vocalSegments,sectBeats))),axis=1) template = numpy.concatenate((template,numpy.array( meanLoudness(vocalSegments,sectBeats))),axis = 1) im = feature.match_template(image,template,pad_input=True) maxValues = [] #tuples of x coord, y coord, correlation, and section len(in secs) ij = numpy.unravel_index(numpy.argmax(im), im.shape) x, y = ij[::-1] maxValues.append((numpy.argmax(im),x,y,sections[0].duration)) for i in range(len(sections)-1): sectBeats = getSectBeats(sections[i+1]) template = numpy.array(meanPitches(vocalSegments,sectBeats)) template = numpy.concatenate((template,numpy.array( meanTimbre(vocalSegments,sectBeats))), axis=1) template = numpy.concatenate((template,numpy.array( meanLoudness(vocalSegments,sectBeats))),axis = 1) match = feature.match_template(image,template,pad_input=True) ij = numpy.unravel_index(numpy.argmax(match), match.shape) x, y = ij[::-1] maxValues.append((numpy.argmax(match), TEMPLATE_WIDTH*i+x,y,sections[i+1].duration)) im = numpy.concatenate((im,match),axis = 1) maxValues.sort() maxValues.reverse() try: count = 0 while(maxValues[count][3] < 10.0): # choose a section longer than 10 secs count += 1 x = maxValues[count][1] y = maxValues[count][2] except: print "exception in mashComponents..." ij = numpy.unravel_index(numpy.argmax(im), im.shape) x, y = ij[::-1] pyplot.imshow(im, cmap = pyplot.get_cmap('gray'), aspect = 'auto') pyplot.plot(x,y,'o',markeredgecolor='r',markerfacecolor='none',markersize=15) pyplot.show() sectionBeats = getSectBeats(sections[x/TEMPLATE_WIDTH]) print "len(sectionBeats): ", len(sectionBeats) print "len(instBeats): ", len(instBeats) print "y: ", y y = instBeats[y].absolute_context()[0] instBeats = localAudioFiles[0].analysis.beats matchingBeats = instBeats[(y-len(sectionBeats)/2):(y+len(sectionBeats)/2)] print"len(matchingBeats): ", len(matchingBeats) matchingBeats = matchingBeats[-len(sectionBeats):] print"len(matchingBeats): ", len(matchingBeats) """ Check to make sure lengths of beat lists are equal... """ if len(matchingBeats) != len(sectionBeats): print "len(matchingBeats) != len(sectionBeats). For now, I will just truncate..." print "len(matchingBeats): ", len(matchingBeats) print "len(sectionBeats): ", len(sectionBeats) if len(matchingBeats) > len(sectionBeats):matchingBeats = matchingBeats[ :len(sectionBeats)] else: sectionBeats = sectionBeats[:len(matchingBeats)] """ I have to make sure sectionBeats and matchingBeats are similarly aligned within their group, aka bar of four beats. I will add a beat to the beginning of matchingBeats until that condition is met. I re-initialize instBeats and vocalBeats, because now I want to include the areas outside of those marked off by AutomaticDJ for fade ins and fade outs.""" vocalBeats = localAudioFiles[1].analysis.beats while(matchingBeats[0].local_context()[0] != sectionBeats[0].local_context()[0]): matchingBeats.insert(0,instBeats[matchingBeats[0].absolute_context()[0]-1]) sectionBeats.append(vocalBeats[sectionBeats[-1].absolute_context()[0]+1]) """ Check to make sure lengths of beat lists are equal... """ if len(matchingBeats) != len(sectionBeats): print "len(matchingBeats) != len(sectionBeats) at the second checkpoint." print "This should not be the case. The while loop must not be adding beats" print "to both lists equally." print "len(matchingBeats): ", len(matchingBeats) print "len(sectionBeats): ", len(sectionBeats) sys.exit() """ Next, I will use the beats around the designated beats above to transition into and out of the mashup. """ XLEN = 4 # number of beats in crossmatch if(matchingBeats[0].absolute_context()[0] < XLEN or len(instBeats) - matchingBeats[-1].absolute_context()[0] - 1 < XLEN or sectionBeats[0].absolute_context()[0] < XLEN or len(vocalBeats) - sectionBeats[-1].absolute_context()[0] - 1 < XLEN): XLEN -= 1 BUFFERLEN = 12 # number of beats before and after crossmatches while(matchingBeats[0].absolute_context()[0] < BUFFERLEN+XLEN or len(instBeats) - matchingBeats[-1].absolute_context()[0] - 1 < BUFFERLEN+XLEN or sectionBeats[0].absolute_context()[0] < BUFFERLEN+XLEN or len(vocalBeats) - sectionBeats[-1].absolute_context()[0] - 1 < BUFFERLEN+XLEN): BUFFERLEN -= 1 try: """ These are the 4 beats before matchingBeats. These are the four beats of the instrumental track that preclude the mashed section. """ b4beatsI = instBeats[matchingBeats[0].absolute_context()[0]-XLEN: matchingBeats[0].absolute_context()[0]] """ These are the 4 beats after matchingBeats. These are the four beats of the instrumental track that follow the mashed section. """ afterbeatsI = instBeats[matchingBeats[-1].absolute_context()[0]+1: matchingBeats[-1].absolute_context()[0]+1+XLEN] if(len(b4beatsI) != len(afterbeatsI)): print "The lengths of b4beatsI and afterbeatsI are not equal." """ These are the 16 beats before the 4-beat crossmatch into matchingBeats. """ preBufferBeats = instBeats[matchingBeats[0].absolute_context()[0]-BUFFERLEN-XLEN: matchingBeats[0].absolute_context()[0]-XLEN] """ These are the 16 beats before the 4-beat crossmatch into matchingBeats. """ postBufferBeats = instBeats[matchingBeats[-1].absolute_context()[0]+1+XLEN: matchingBeats[-1].absolute_context()[0]+1+XLEN+BUFFERLEN] if(len(preBufferBeats) != len(postBufferBeats)): print "The lengths of preBufferBeats and postBufferBeats are not equal." print "len(preBufferBeats): ", len(preBufferBeats) print "len(postBufferBeats): ", len(postBufferBeats) print matchingBeats[-1].absolute_context()[0] print len(instBeats) sys.exit() """ These are the 4 beats before matchingBeats. These are the four beats of the new vocal track that preclude the mashed section. """ b4beatsV = vocalBeats[sectionBeats[0].absolute_context()[0]-XLEN: sectionBeats[0].absolute_context()[0]] """ These are the 4 beats after matchingBeats. These are the four beats of the new vocal track that follow the mashed section. """ afterbeatsV = vocalBeats[sectionBeats[-1].absolute_context()[0]+1: sectionBeats[-1].absolute_context()[0]+1+XLEN] if(len(b4beatsV) != len(afterbeatsV)): print "The lengths of b4beatsI and afterbeatsI are not equal." sys.exit() except: print "exception in 4 beat try block." sys.exit() """ vocData: An AudioData object for the new vocal data that will be overlaid. instData: An AudioData object for the base instrumental track. originalVocData: An AudioData object of the original vocal to accompany the new one. vocalMix: An AudioData of both vocal tracks mixed together, in order to keep the overall vocal loudness approximately constant. mix: An AudioData of the instrumental track and combined vocals mixed together. """ vocData = audio.getpieces(localAudioFiles[3],b4beatsV+sectionBeats+afterbeatsV) instData = audio.getpieces(localAudioFiles[2],b4beatsI+matchingBeats+afterbeatsI) if instData.data.shape[0] >= vocData.data.shape[0]: mix = audio.megamix([instData, vocData]) else: mix = audio.megamix([vocData, instData]) # the longer data set has to go first. mix.encode('mix.mp3') vocData.encode('vocData.mp3') """ Now, make a similar mix for before the mashed sections...""" instData = audio.getpieces(localAudioFiles[2], preBufferBeats + b4beatsI) vocData = audio.getpieces(localAudioFiles[4], preBufferBeats + b4beatsI) premix = audio.megamix([instData, vocData]) """ ...and another mix for after the mashed sections.""" instData = audio.getpieces(localAudioFiles[2], afterbeatsI + postBufferBeats) vocData = audio.getpieces(localAudioFiles[4], afterbeatsI + postBufferBeats) postmix = audio.megamix([instData, vocData]) """ Now, I have three AudioData objects, mix, premix, and postmix, that overlap by four beats. I will build Crossmatch objects from the overlapping regions, and three Playback objects for the areas that are not in transition. """ action.make_stereo(premix) action.make_stereo(mix) action.make_stereo(postmix) preBuffdur = sum([p.duration for p in preBufferBeats]) # duration of preBufferBeats playback1 = action.Playback(premix,0.0,preBuffdur) b4dur = sum([p.duration for p in b4beatsI]) # duration of b4beatsI crossfade1 = action.Crossfade((premix,mix),(preBuffdur,0.0),b4dur) abdur = sum([p.duration for p in afterbeatsI]) playback2 = action.Playback(mix,b4dur,mix.duration - b4dur - abdur) crossfade2 = action.Crossfade((mix,postmix),(mix.duration - abdur,0.0),abdur) playback3 = action.Playback(postmix,abdur,sum([p.duration for p in postBufferBeats])) action.render([playback1,crossfade1,playback2,crossfade2,playback3], 'mashup.mp3')