This example illustrates how BarBitURythme can be used to
That encoding will later be used to train BarBitURythme statistical models and generate sequences of similar style.
We set up the python machinery that will be used. Since barbiturythme is not in our system's python package repositories (sys.path), we add it.
In [1]:
import os, sys
sys.path.append( '/'.join(os.getcwd().split('/')[:-1]) + '/barbiturythme' )
In [2]:
import numpy as np
import subprocess
import barbiturythme
from barbiturythme import bbur_gene
We choose the data folder/files location and name and initialize a bbur_gene.bbur_io class to read and write to data files.
In [3]:
io = bbur_gene.bbur_io()
io.data_folder_name = '4bars_4beats_4subs_3bands'
io.data_file_name = 'hh_00'
io.n_freq_int = 3
Then the class barbiturythme.BarBit will be used to read .wav files and encode (some of) their content into machine adapted data.
In [4]:
bb = barbiturythme.BarBit()
bb.read( '/home/freinque/tracks/atlanta_trap.wav' )
We set up the parameters of the standard spectral analysis procedure. Roughly speaking, we will
In [5]:
bb.window_size = 1024*2
bb.hop_size = 512
bb.set_freq_bounds([[20,120],[4000,6000],[13000,14000]])
bb.smooth_windows = [1,10,1]
start_time = 10
duration = 15
bb.calc_odf( start_time, start_time + duration )
We plot the increase levels in each interval
In [6]:
bb.plot_odf()
We adjust the levels at which we consider that each instrument is played and use bb.calc_onsets() to determine at which steps each instrument is played.
In [7]:
bb.min_thresholds = [0.3,0.5,0.2]
bb.median_windows = [5,9,13]
bb.peak_sizes = [0.05,1,0.02]
bb.calc_onsets()
We plot the results. If they don't make us happy (i.e. what we hear and see coincide), we can reexecute the above cells with different paramenters.
In [8]:
bb.plot_onsets()
At this point, our BarBit doesn't know what is the tempo of our track so it can't really find its bars (i.e. measures) or multi-bar structures (e.g. choruses, etc.). If you know it for sure, just set bb.bpm to it.
Otherwise, bbur_gene.bpm_finder() provides a decent (although very simple) way of calculating it. Here, we use the onsets (i.e. moments when hit) of the snare and multiply the result by 2 since it is played every two beats.
In [9]:
bpmf = bbur_gene.bpm_finder()
bpmf.gcd = bb.hop_size
bpmf.sampling_rate = bb.sampling_rate
bpmf.set_onsets( bb.onsets[1] )
In [10]:
bpmf.calc_bpms()
In [11]:
bb.bpm = 2.*bpmf.bpms[3]
bb.bpm
Out[11]:
We set the set the parameters of the bar encoding.
In [12]:
bb.subs_per_beat = 4
bb.beats_per_bar = 4
bb.n = 4
bb.encode_onsets() then does what its name says.
In [13]:
bb.encode_onsets()
The result is a bunch of 4bars (concatenated sequence made of 4 bars) in integer (bb.n_bars_int) and binary (bb.n_bars_bin) forms. For instance
In [14]:
bb.n_bars_bin[0][0]
Out[14]:
where the third element being [1,0,1] means that at the third time subdivision, the fisrt and third (kick and hihat) intruments are played, the the fourth element [0,0,1] means that at the fourth time subdivision, the third (hihat) intrument is played, etc. The integer form looks like
In [15]:
bb.n_bars_int[0][0]
Out[15]:
where 5 stands for 12**0 + 021 + 1*22, etc.
bb doesn't know where exactly to set the 'time 0' moment. We help a bit, but this could be mostly automated. subdiv_shift is our preferred time shift.
In [16]:
subdiv_shift = int(( bb.sampling_rate*60.0/(bb.bpm*bb.hop_size) ) / bb.subs_per_beat) #time shift, in subdivs
observations = np.array( bb.n_bars_int[57*subdiv_shift][:] )
In [17]:
print observations[:]
And we add de desired 4bars to the data file.
In [18]:
io.append_data( [observations[1]] )
In [ ]: