La danzabilidad es una medida de que tan bailable puede ser una cancion respecto a una musica bailable de su genero o a cualquier otra musica bailable. Utilizamos el analisis de detrendimiento de fluctuacion con un metodo de regresion que utiliza un algoritmo de descenso de gradiente basado en una funcion de atencion. El proposito es analizar si una pieza sonora se desvia mucho de una tendencia tomada como bailable y en base al desvio se computa cuanto movimiento que se pueda correlacionar puede haber en la pieza analizada.
El algoritmo de danzabilidad que proponemos utiliza el metodo de descenso de gradiente con funciones de atencion para calcular la tendencia mientras que definimos como targets para calcular la tendencia tendencias presentes en canciones bailables. Esto mejora la estimacion en canciones donde la duracion del tono es mas larga, en lentos de piano, en canciones de reggaeton, en piezas de musica electronica, en piezas de rock.
El primer paso antes de calcular la danzabilidad como tal es computar onsets percusivos en una cancion utilizando el contenido de alta frecuencia. De esta forma se espera que se utilizen partes donde hayan repiques de bateria o tonos similares para saber donde estan los onsets.
In [5]:
#importamos las funciones en el modulo de algoritmos MIR
from apicultor.utils.algorithms import *
#importamos soundfile de las dependencias de apicultor
from soundfile import read
tags_dir = 'bajo'
#abrimos nuestro sonido de RedPanal
audio, fs = read('710.ogg')
#lo convertimos a mono para poder analizar
audio = mono_stereo(audio)
#llamamos a la clase MIR para obtener nuestros onsets
retrieve = MIR(audio, fs)
#aplicamos un filtro para remover el ruido hasta 40 Hz
retrieve.signal = retrieve.IIR(retrieve.signal, 40, 'highpass')
#importamos nuestra funcion para obtener los onsets
from apicultor.sonification.Sonification import hfc_onsets
#calculamos el contenido de frecuencia alta en todos los frames
hfcs = []
for frame in retrieve.FrameGenerator():
retrieve.window()
retrieve.Spectrum()
hfcs.append(retrieve.hfc())
hfcs /= max(hfcs)
#filtramos y seleccionamos los frames con optimo contenido
fir = firwin(11, 1.0 / 8, window = "hamming")
retrieve.filtered = np.convolve(hfcs, fir, mode="same")
retrieve.climb_hills()
retrieve.hfcs = np.array([i for i, x in enumerate(retrieve.Filtered) if x > 0]) * retrieve.N
Nosotros partiremos de la base de que teniendo un onset percusivo de una cancion se puede saber la danzabilidad del resto de la musica ya que si una parte es muy bailable tiene que ser probable que el resto lo sea debido a los procesos a largo plazo. Es por esto que utilizaremos los ocho segundos siguientes de hallar el primer onset de la pieza musical analizada para calcular la danzabilidad de la cancion. En este ejemplo la cancion es una pista de bajo por lo cual no se hara ninguna asociacion con una media especifica de un genero sino que la media sera tomada aleatoriamente.
In [ ]:
#danceability
if tag_dir == 'electronic':
meany = np.loadtxt('means/y1.txt') #one more time
if tag_dir == 'pop':
meany = np.loadtxt('means/y2.txt') #you should be dancing
if tag_dir == 'rock':
meany = np.loadtxt('means/y3.txt') #sultans of swing
if tag_dir == 'mapuche':
meany = np.loadtxt('means/y4.txt') #mapuche dance
if tag_dir == 'reggaeton':
meany = np.loadtxt('means/y5.txt') #despacito
if tag_dir != 'reggaeton' and tag_dir != 'electronic' and tag_dir != 'pop' and tag_dir != 'rock' and tag_dir != 'mapuche':
meany = random.choice(['y1.txt','y2.txt','y3.txt','y4.txt','y5.txt'])
meany = np.loadtxt('means/'+meany)
print("DANZABILIDAD DE LA CANCION: ")
print(danceability(retrieve.signal[retrieve.hfcs[0]:retrieve.hfcs[0]+(retrieve.fs*8)], meany, retrieve.fs))