Trabajo Práctico Especial de Señales y Sistemas

Identificación de canciones mediante huellas digitales acústicas

Código auxiliar

# Cargo paquetitos
using DSP, FFTW, Statistics, WAV
function wavread_mono(file)
  x, sr = wavread(file)
  return mean(x; dims=2)[:], sr
end
# Y armo un par de funciones auxiliares
stem(args...; kwargs...) = sticks(args...; 
  																marker=:circle, 
  																leg=false, 
  																kwargs...)
stem!(args...; kwargs...) = sticks!(args...; 
  																marker=:circle, 
  																leg=false, 
  																kwargs...)
zeropolegain(pr) = DSP.ZeroPoleGain(pr)
zeropolegain(z, p, g) = DSP.ZeroPoleGain(z, p, g)
polynomialratio(zpg) = DSP.PolynomialRatio(zpg)
function polynomialratio(b, a)
  n = max(length(a), length(b))
  return DSP.PolynomialRatio(padright(b, n), padright(a, n))
end
getpoles(zpg) = DSP.ZeroPoleGain(zpg).p
getzeros(zpg) = DSP.ZeroPoleGain(zpg).z
getgain(zpg) = DSP.ZeroPoleGain(zpg).k
getnumcoefs(pr) = trimlastzeros!(reverse(DSP.PolynomialRatio(pr).b.coeffs))
getdencoefs(pr) = trimlastzeros!(reverse(DSP.PolynomialRatio(pr).a.coeffs))
function trimlastzeros!(a)
  !iszero(a[end]) && return a
  pop!(a)
  return trimlastzeros!(a)
end
DSP.filt(zpg::DSP.ZeroPoleGain, r...; kwargs...) = filt(polynomialratio(zpg), r...; kwargs...)
function zplane(zs, ps; kwargs...)
	scatter(real.(zs), imag.(zs);
		  marker = (:black, :circle), label="Cero", kwargs...)
	scatter!( real.(ps), imag.(ps);
	  	marker = (:red, :xcross), label="Polo", kwargs...)  
  ts = range(0,stop=2pi;length=100)
  plot!(cos.(ts), sin.(ts); aspect_ratio = 1, kwargs...)
end
zplane(pr::DSP.PolynomialRatio; kwargs...) = zplane(DSP.ZeroPoleGain(pr); kwargs...)
# Delta
d(n) = n == 0 ? 1. : 0. 
# Escalón
u(n) = n >= 0 ? 1. : 0. 
using Plots
Plots.default(:legend, false)
# Pad vector with zeros on the right until its length is `n`
padright(x, n) = copyto!(zeros(eltype(x), n), x)
"""
Función módulo pero con offset (opcional)
Manda a `t` al intervalo [from, from+length)
sumándole o restándole algún múltiplo de `len`
"""
cshift(t, len, from=0) = mod(t - from, len) + from
	# Espectrograma
	using IterTools
	function stft(x; overlap, window, nfft, rest...)
	  nwin = length(window)
	  @assert overlap < nwin
	  res = [ fft(padright(xseg .* window, nfft))
		for xseg in partition(x, nwin, nwin - overlap)]
	  return [ res[i][j] for j in 1:nfft, i in eachindex(res)]
	end
	specplot(x::AbstractMatrix; kwargs...) = 
		@error "You are entering a Matrix (2D Array). I need a Vector (1D Array)."
	function specplot(x::AbstractVector;
		  fs=1,
		  onesided=false,
		  xaxis="Tiempo (s)",
		  yaxis="Frecuencia (Hz)",
		  window=hamming(div(length(x), 16)),
		  overlap=0.5,
		  nfft=length(window),
		  kws...)
		window isa Integer && (window = rect(window))
		overlap isa AbstractFloat && (overlap = round(Int, length(window) * overlap))
		mat = stft(x; overlap=overlap, window=window, nfft=nfft)
		fmax = fs
		if onesided
		  mat = mat[1:div(size(mat, 1) + 2, 2), :]
		  fmax = fs/2
		end
	  toffset = length(window) / 2fs
	  times = range(toffset; length=size(mat, 2), stop=length(x)/fs - toffset)
	  freqs = range(0; length=size(mat, 1), stop=fmax)
		# Reubico las frecuencias negativas arriba de todo
	  if !onesided
		freqs = cshift.(freqs, fs, -fs/2)
		ord   = sortperm(freqs)
		mat   = mat[ord, :]
		freqs = freqs[ord]
	  end
		return heatmap(times, freqs, log.(abs.(mat) .+ eps());
			  xaxis=xaxis, yaxis=yaxis,
			  seriescolor=:bluesreds, legend=true, kws...)
	 return times, freqs, mat
	end
	function specplot(x :: AbstractVector{<:AbstractFloat}; kws...)
		return specplot(convert.(Complex, x); onesided=true, kws...)
	end
Julia

Canciones a procesar

El audio corto con el que deben hacer los primeros ejercicios:

Pink.ogg
138.25 KB

Otras 40 canciones en `ogg`, estéreo, a 44100 Hz

songs = [
Aerosmith - Crazy.ogg
,
Bon Jovi - Bed Of Roses.ogg
,
Meat Loaf - I'd Do Anything For Love (But I Won't Do That).ogg
,
Keith Sweat - Twisted.ogg
,
Mariah Carey - Hero.ogg
,
Big Mountain - Baby I Love Your Way(1994).ogg
,
Bon Jovi - Always.ogg
,
Coolio - Gangsta's Paradise (feat. L.V.).ogg
,
Eric Clapton - My Father's Eyes.ogg
,
Guns N' Roses - Don't Cry.ogg
,
Aerosmith - I Don't Want to Miss a Thing.ogg
,
Lou Bega - Mambo No. 5 (A Little Bit of...).ogg
,
Eric Clapton - Wonderful Tonight.ogg
,
Bryan Adams - Please Forgive Me.ogg
,
Bryan Adams - (Everything I Do) I Do It For You - Live in Canada.ogg
,
Alanis Morissette - Head Over Feet.ogg
,
Alanis Morissette - You Oughta Know.ogg
,
4 Non Blondes - What's Up.ogg
,
Metallica - Enter Sandman.ogg
,
'Filthy Rich' Since I.ogg
,
Christopher Cross - Ride Like The Wind.ogg
,
Eric Clapton - Tears In Heaven.ogg
,
Green Day - Basket Case.ogg
,
Aqua - Barbie Girl.ogg
,
En Vogue - Don't Let Go (Love).ogg
,
Extreme - More Than Words.ogg
,
Cher - Believe.ogg
,
Alanis Morissette - Ironic.ogg
,
Mark Morrison - Return Of The Mack.ogg
,
Mariah Carey - Without You.ogg
,
Mariah Carey - Always Be My Baby.ogg
,
Bloodhound Gang - The Bad Touch.ogg
,
Goo Goo Dolls - Iris.ogg
,
Dr. Dre ft. Snoop Dogg, Kurupt, Nate Dogg - The Next Episode.ogg
,
Britney Spears - ...Baby One More Time.ogg
,
Hootie & The Blowfish - Let Her Cry.ogg
,
Brandy & Monica - The Boy Is Mine.ogg
,
Fugees - Killing Me Softly With His Song.ogg
,
Blur - Song 2-SSbBvKaM6sk.ogg
];
0.1s
Julia
Aerosmith - Crazy.ogg
4.93 MB
Bon Jovi - Bed Of Roses.ogg
5.31 MB
Meat Loaf - I'd Do Anything For Love (But I Won't Do That).ogg
6.26 MB
Keith Sweat - Twisted.ogg
3.79 MB
Mariah Carey - Hero.ogg
3.32 MB
Big Mountain - Baby I Love Your Way(1994).ogg
3.51 MB
Bon Jovi - Always.ogg
5.02 MB
Coolio - Gangsta's Paradise (feat. L.V.).ogg
3.59 MB
Eric Clapton - My Father's Eyes.ogg
6.86 MB
Guns N' Roses - Don't Cry.ogg
4.01 MB
Aerosmith - I Don't Want to Miss a Thing.ogg
3.85 MB
Lou Bega - Mambo No. 5 (A Little Bit of...).ogg
2.94 MB
Eric Clapton - Wonderful Tonight.ogg
4.76 MB
Bryan Adams - Please Forgive Me.ogg
4.40 MB
Bryan Adams - (Everything I Do) I Do It For You - Live in Canada.ogg
5.19 MB
Alanis Morissette - Head Over Feet.ogg
3.61 MB
Alanis Morissette - You Oughta Know.ogg
3.36 MB
4 Non Blondes - What's Up.ogg
4.14 MB
Metallica - Enter Sandman.ogg
4.50 MB
'Filthy Rich' Since I.ogg
3.43 MB
Christopher Cross - Ride Like The Wind.ogg
3.69 MB
Eric Clapton - Tears In Heaven.ogg
3.46 MB
Green Day - Basket Case.ogg
2.55 MB
Aqua - Barbie Girl.ogg
2.78 MB
En Vogue - Don't Let Go (Love).ogg
3.70 MB
Extreme - More Than Words.ogg
3.28 MB
Cher - Believe.ogg
3.21 MB
Alanis Morissette - Ironic.ogg
3.40 MB
Mark Morrison - Return Of The Mack.ogg
2.91 MB
Mariah Carey - Without You.ogg
3.26 MB
Mariah Carey - Always Be My Baby.ogg
3.44 MB
Bloodhound Gang - The Bad Touch.ogg
3.10 MB
Goo Goo Dolls - Iris.ogg
3.00 MB
Dr. Dre ft. Snoop Dogg, Kurupt, Nate Dogg - The Next Episode.ogg
2.73 MB
Britney Spears - ...Baby One More Time.ogg
3.10 MB
Hootie & The Blowfish - Let Her Cry.ogg
3.49 MB
Brandy & Monica - The Boy Is Mine.ogg
3.33 MB
Fugees - Killing Me Softly With His Song.ogg
3.15 MB
Blur - Song 2-SSbBvKaM6sk.ogg
1.54 MB
# Cargo paquetitos
using DSP, FFTW, Statistics, WAV
function wavread_mono(file)
  x, sr = wavread(file)
  return mean(x; dims=2)[:], sr
end
# Y armo un par de funciones auxiliares
stem(args...; kwargs...) = sticks(args...; 
  																marker=:circle, 
  																leg=false, 
  																kwargs...)
stem!(args...; kwargs...) = sticks!(args...; 
  																marker=:circle, 
  																leg=false, 
  																kwargs...)
zeropolegain(pr) = DSP.ZeroPoleGain(pr)
zeropolegain(z, p, g) = DSP.ZeroPoleGain(z, p, g)
polynomialratio(zpg) = DSP.PolynomialRatio(zpg)
function polynomialratio(b, a)
  n = max(length(a), length(b))
  return DSP.PolynomialRatio(padright(b, n), padright(a, n))
end
getpoles(zpg) = DSP.ZeroPoleGain(zpg).p
getzeros(zpg) = DSP.ZeroPoleGain(zpg).z
getgain(zpg) = DSP.ZeroPoleGain(zpg).k
getnumcoefs(pr) = trimlastzeros!(reverse(DSP.PolynomialRatio(pr).b.coeffs))
getdencoefs(pr) = trimlastzeros!(reverse(DSP.PolynomialRatio(pr).a.coeffs))
function trimlastzeros!(a)
  !iszero(a[end]) && return a
  pop!(a)
  return trimlastzeros!(a)
end
DSP.filt(zpg::DSP.ZeroPoleGain, r...; kwargs...) = filt(polynomialratio(zpg), r...; kwargs...)
function zplane(zs, ps; kwargs...)
	scatter(real.(zs), imag.(zs);
		  marker = (:black, :circle), label="Cero", kwargs...)
	scatter!( real.(ps), imag.(ps);
	  	marker = (:red, :xcross), label="Polo", kwargs...)  
  ts = range(0,stop=2pi;length=100)
  plot!(cos.(ts), sin.(ts); aspect_ratio = 1, kwargs...)
end
function zplane(zs, ps; kwargs...)
	scatter(real.(zs), imag.(zs);
		  marker = (:black, :circle), label="Cero", kwargs...)
	scatter!( real.(ps), imag.(ps);
	  	marker = (:red, :xcross), label="Polo", kwargs...)  
  ts = range(0,stop=2pi;length=100)
  plot!(cos.(ts), sin.(ts); aspect_ratio = 1, kwargs...)
end
zplane(pr::DSP.PolynomialRatio; kwargs...) = zplane(DSP.ZeroPoleGain(pr); kwargs...)
# Delta
d(n) = n == 0 ? 1. : 0. 
# Escalón
u(n) = n >= 0 ? 1. : 0. 
using Plots
Plots.default(:legend, false)
# Pad vector with zeros on the right until its length is `n`
padright(x, n) = copyto!(zeros(eltype(x), n), x)
"""
Función módulo pero con offset (opcional)
Manda a `t` al intervalo [from, from+length)
sumándole o restándole algún múltiplo de `len`
"""
cshift(t, len, from=0) = mod(t - from, len) + from
# Espectrograma
using IterTools
function stft(x; overlap, window, nfft, rest...)
  nwin = length(window)
  @assert overlap < nwin
  res = [ fft(padright(xseg .* window, nfft)) 
    for xseg in partition(x, nwin, nwin - overlap)]
  
  return [ res[i][j] for j in 1:nfft, i in eachindex(res)]
end
specplot(x::AbstractMatrix; kwargs...) = @error "You are entering a Matrix (2D Array). I need a Vector (1D Array)."
function specplot(x::AbstractVector; 
      fs=1, 
      onesided=false, 
      xaxis="Tiempo (s)", 
      yaxis="Frecuencia (Hz)",
      window=hamming(div(length(x), 16)),
      overlap=0.5,
      nfft=length(window),
      kws...)
    window isa Integer && (window = rect(window))
    overlap isa AbstractFloat && (overlap = round(Int, length(window) * overlap))
    
    mat = stft(x; overlap=overlap, window=window, nfft=nfft)
    fmax = fs
    if onesided
      mat = mat[1:div(size(mat, 1) + 2, 2), :]
      fmax = fs/2
    end
  
  toffset = length(window) / 2sr
  times = range(toffset; length=size(mat, 2), stop=length(x)/fs - toffset)
  freqs = range(0; length=size(mat, 1), stop=fmax)
  
	# Reubico las frecuencias negativas arriba de todo
  if !onesided
    freqs = cshift.(freqs, fs, -fs/2)
    ord   = sortperm(freqs)
    mat   = mat[ord, :]
    freqs = freqs[ord]
  end
	return heatmap(times, freqs, log.(abs.(mat) .+ eps()); 
          xaxis=xaxis, yaxis=yaxis,
          seriescolor=:bluesreds, legend=true, kws...)
 return times, freqs, mat 
end
function specplot(x :: AbstractVector{<:AbstractFloat}; kws...)
    return specplot(convert.(Complex, x); onesided=true, kws...)
end
33.4s
Julia
specplot (generic function with 3 methods)
Julia

Introducción

Imaginen la siguiente situación: se encuentran en un bar, tomando su trago favorito, inmersos en esa interesante conversación cuando de repente . . . “pará, pará, ¿qué es eso que suena?”. Entre el ruido general alcanzan a distinguir esa canción que no escuchaban en tanto tiempo, que habían obsesivamente intentado encontrar pero que, a pesar de ello, nunca llegaron a dar siquiera con el nombre del intérprete. Su corazón se estremece . . . Ahora que la tienen ahí, sonando nuevamente, la situación es bien diferente a la de hace algunos años: toman su teléfono celular, abren alguna de las aplicaciones de reconocimiento de audio que tienen y, en cuestión de segundos, aparece la información completa del tema, la banda, ¡e incluso se atreve a sugerir artistas similares!

Si el protagonista de esta ficción fuera estudiante de Señales y Sistemas, no debería extrañarnos que surjan en él varios interrogantes: ¿cómo hizo el programa para reconocer la canción escuchando sólo 10 segundos?, ¿cómo puede funcionar con el ruido de un bar de fondo? y ¿cómo pudee ser que además identifique tan rápido a seta banda que nadie conoce?

Resulta que todo este proceso se basa en reconocer huellas digitales acústicas, una técnica robusta y eficiente que puede entenderse en términos de Señales y Sistemas.

Reconocimiento mediante huellas digitales acústicas

El reconocimiento de audio mediante huellas digitales acústicas es una técnica que busca identificar una pieza de audio, contrastando la información contenida en dicha pieza contra la almacenada en una base de datos de pistas conocidas. Esta técnica comienza a desarrollarse desde el año 2000, pero es durante la última década que tomé mayor impulso, siendo posible hoy en día encontrar una variedad de aplicaciones para smartphones capaces de identificar casi cualquier pieza de audio en segundos [4].

Existen varias formas dea bordar el problema del reconocimiento, pero todas persiguen la misma finalidad:

  • Simplicidad computacional: el reconocimiento debe realizarse en forma rápida.

  • Eficiencia en el uso de memoria y buena capacidad de discriminación: existen aproximadamente 100 millones de canciones grabadas [1].

  • Robustez ante degradaciones: ruido de fondo, degradación por compresión digital del audio, ecualización por respuesta en frecuencia no plana del lugar y/o parlantes, etc.

  • Granularidad: capacidad de reconocimiento utilizando sólo un segmento del audio.

  • Alta tasa de aciertos, baja tasa de falsos positivos y de rechazos.

El procedimiento básico consiste en analizar el segmento de audio buscando extraer características particulares en el esapcio tiempo-frecuencia (es decir, en su espectrograma) que sirvan para identificarlo luego. Una característica podría ser, por ejemplo, la potencia que posean las diferentes bandas de frecuencias. Al conjunto de estas características se las denomina huella digital acústica.

Analogía entre una huella digital tradicional y una huella digital acústica.

Este procedimiento de extracción de huellas se utiliza tanto para confeccionar la base de datos de canciones conocidas como para posteriormente reconocer segmentos de audio que se desean identificar consultando la base de datos.

La elección de las características es la base del funcionamiento del método. Deben ser lo suficientemente específicas como para identificar a cada canción unívocamente pero a la vez ocupar poca memoria para permitir realizar la búsqueda en forma rápida y eficiente. También deberán ser relativamente inmunes ante ruidos y distorsiones del audio de manera de lograr un sistema de reconocimiento robusto.

Diferentes características han sido propuestas con el fin de lograr estas especificaciones. Algunos ejemplos que se extraen del dominio tiempo-frecuencia son los MFCC [4] (Mel-Frequency Cepstrum Coefficients, comúnmente utilizados para la representación del habla), SFM [1] (Spectral Flatness Measure, una estimación de cuánto se aproxima una banda espectral a ser un tono o ruido), la ubicación de los picos de potencia del espectrograma (la base del algoritmo de Shazam [9, 8]), la energía de las bandas [6], etc. Además del espectrograma, otras técnicas se han utilizados como wavelets y algoritmos de visión [2], algoritmos de machine learning [3], y meta-características [7], útiles en grabaciones muy distorsionadas.

En este trabajo desarrollaremos una implementación simple que utiliza como características el signo de la diferencia de energía entre bandas [5].

Cabe destacar que esta característica sólo sirve para reconocer las mismas versiones de las canciones que se almacenan en la base de datos: es decir, no está diseñada para reconocer versiones en vivo o interpretaciones diferentes a la original.

Descripción del sistema de reconocimiento

El sistema de reconocimiento consta de dos bloques principales:

  1. El algoritmo para extraer las huellas digitales acústicas.

  2. La base de datos que almacena las huellas acústicas de las canciones conocidas y permite realizar búsquedas a partir de la huella acústica de una canción desconocida.

El algoritmo para extraer las huellas acústicas toma como entrada el archivo con el audio, lo pre-procesa, extrae las características, y entrega como resultado la huella acústica.

Esquema del algoritmo para extraer la huella digital acústica.

La base de datos guardará las huellas acústicas de las canciones conocidas. Tiene además un sistema de búsqueda (en inglés query) tal que al realizar un query con una huella acústica dada nos devuelve la canción – más probable – a la cual correseponde.

El esquema del sistema completo se presenta a continuación:

Esquema representando la generación de la base de datos de huellas acústicas y la consulta.

Observe que el algoritmo de extracción de huellas se utiliza tanto en la creación de la base de datos de canciones conocidas como para el reconocimiento de audios desconocidos.

Algoritmo de extracción de huellas digitales acústicas

El algoritmo de extracción de huellas acústicas tiene como finalidad extraer características a partir del espectrograma del audio. Primeramente, se acondiciona el audio con un pre-procesamiento. Luego se realiza un espectrograma del audio pre-procesado y finalmente se extraen las características para cada intervalo de tiempo.

1. Pre-procesamiento del audio

Se comienza convirtiendo el audio, que suele ser estar en estéreo, a un audio monocanal, promediando los canales.

Luego, se reduce su frecuencia de muestreo, aprovechando que son las frecuencias bajas las que contienen la información más útil para la extracción de características. En general, el audio está muestreado a 44100 Hz (calidad de CD), pero para este algoritmo de reconocimiento basta con tenerlo muestreado a 1/8 de su frecuencia original, 5512.5 Hz. Esto permite trabajar con menos muestras, aliviando la carga computacional.

Para realizar los siguientes ejercicios, utilice el archivo Pink.ogg.

Ejercicio 1)

Cargue la pista de audio. Verifique que la variable cargada es una matriz con 2 columnas, cada una correspondiendo a un canal de audio. Promedie los canales utilizando al función mean para tener 1 solo canal y grafique una porción de la señal resultante. Verifique que el audio resultante sea similar al original escuchándolo.

Julia
Ejercicio 2)

Mediante la función fft, realice un análisis espectral de la señal mostrando la densidad espectral de potencia (PSD) en función de la frecuencia en Hz. Verifique que la mayor PSD se concentra en las bajas frecuencias. Utilice escala logarítmica para mostrar el resultado.

La PSD, inline_formula not implemented, la puede estimar como inline_formula not implemented, donde inline_formula not implemented es la duración del segmento temporal que usa para la estimación, o mejor aún, dividiendo al audio en segmentos, realizando la estimación anterior con cada uno, y finalmente promediándolas.

Julia
Ejercicio 3)

Mediante la función fft, obtenga el espectro de una ventana rectangular y una de Hamming de igual duración y grafique su potencia en escala logarítmica en un mismo gráfico para compararlos. ¿Cuál es la resolución en frecuencia de cada ventana? Al realizar un espectrogama, ¿qué ventaja tiene utilizar la ventana de Hamming frente a la rectangular?

Julia
Ejercicio 4)

Implemente un sistema para reducir la frecuencia de muestreo del audio, de 44100 Hz a 5512.5 Hz. Muestre un diagrama en bloques y justifique su diseño. Diseñe el filtro pasabajos mediante el método de ventaneo explicando y justificando las decisiones, de forma tal que su retardo sea menor a 1 ms. Graficar un diagrama de polos y ceros, respuesta en frecuencia (módulo y fase), respuesta al impulso, y retardo de grupo.

Julia
Ejercicio 5)

Realice un espectrograma de la señal original y la filtrada y verifique los efectos del filtrado. Indique el tipo y longitud de ventana utilizada.

Julia

Espectrograma

Los parámetros con los que se realice el espectrograma tienen una influencia directa sobre la extracción de las características. La elección de la ventana (tipo y longitud) es el parámetro principal, ya que debería lograr una resolución razonable tanto en tiempo como en frecuencia que permita distinguir las características espectrales y temporales con claridad.

Ejercicio 6)

Realice un espectrograma de la señal sub-muestreada y muestre una imagen (con zoom) de alguna región donde se vean las características espectrales de la señal dada la ventana utilizada. Muestre y justifique cómo cambia la visualización de las características con 3 diferentes longitudes de ventana y comente qué longitud utilizará en el algoritmo. Realice las comparaciones con ventana rectangular y de Hamming.

Julia

Extracción de características

La función provista stft permite obtener la matriz inline_formula not implemented con las sucesivas DFT de los segmentos de la señal ventaneados -- lo que se grafica en un espectrograma.

Estas DFT nos devuelven muestras del espectro en frecuencias equiespaciadas en escala lineal – junto con los vectores de tiempos y frecuencias correspondientes a cada columna y fila.

A partir de esto, necesitaremos la energía en bandas de frecuencia equiespaciadas en escala logarítmica (esto es similar a la escala psicoacústica Bark) debido a que así funciona el oído humano, que es un buen reconocedor de canciones – la relación entre frecuencias y posición de resonancia de la membrana basilar es aproximadamente logarítmica.

Debemos obtener una matriz de energías inline_formula not implemented, cuyas columnas, al igual que las de inline_formula not implemented, representan características espectrales del n-ésimo segmento de señal ventaneado (frame inline_formula not implemented). Para todo inline_formula not implemented, el elemento inline_formula not implemented de nuestra nueva matriz debe contener la energía total de todos los coeficientes de inline_formula not implemented asociados a frecuencias que caen dentro de la inline_formula not implemented-ésima banda de frecuencia.

Ejercicio 7)

Divida al espectrograma en 21 bandas de frecuencias, equiespaciadas en escala logarítmica (es decir, el cociente entre frecuencias de bandas consecutivas debe ser constante). La frecuencia inferior de la primera banda debe ser 300 Hz y la superior de la última, 2 kHz. La función logspace le puede ser de ayuda.

Obtenga la inline_formula not implemented.

Julia

Finalmente, las características se obtienen mediante una función que opera sobre inline_formula not implemented según:

En palabras, inline_formula not implemented es 1 si la diferencia de energía entre las bandas m y m+1 para el frame actual n es mayor a la del frame anterior n-1. Experimentalmente, se verficó que estas características son robustas ante varios tipos de procesamientos y distorsiones del audio[5].

Ejercicio 8)

Implemente el algoritmo de extracción de características, calculando la huella. Debido al efecto borde, inline_formula not implemented debería resultar una matriz de 20 filas.

Ejecute el algoritmo sobre un segmento de audio y muestre una imagen de la huella digital acústica obtenida.

Julia

Confección de la base de datos

En principio, la base de datos simplemente debe

  • Guardar, para cada frame,

    • las características obtenidas,

    • un identificador de la canción de la cual provino,

    • el número de frame dentro de la canción.

  • Permitir buscar el identificador de canción y el número de frame a partir de una característica, o informar si la característica buscada no se encuentra en la base de datos.

Así, cuando se desea identificar una música desconocida, se calculan las características de cada frame, se obtienen los identificadores de la base, y se opera con ellos de algún modo razonable para devolver la (o las) canciones más probables.

Ahora bien, es importante que este tipo de algoritmos escalen a bases de datos grandes y funcione rápido; para eso, es crucial que la la base de datos aproveche bien el espacio en memoria y permita una búsqueda eficiente. Por esto, se le proveen funciones que implementan una versión sencilla de una base de datos que cumple con estas características, que deberán ser entendidos.

Para confeccionar la base de datos, se utilizará la función generar_DB. Esta función requiere que el alumno haya definido otra una función que, dado un archivo de audio como entrada, lo pre-procese, analice y extraiga su huella digital acústica en forma automática.

Ejercicio 9)

Encapsule su algoritmo de extracción de huellas acústicas en una función llamada generar_huella que reciba como entrada el path del archivo de audio y devuelva su huella digital acústica.

Julia
Ejercicio 10)

Observe que la cantidad de elementos a guardar en la base de datos se incrementa conforme la longitud de las ventanas del espectrograma inicial disminuye, o el solapamiento entre ventanas se incrementa. Determine el solapamiento entre ventanas del espectrograma para obtener una densidad de aproximadamente 25 elementos por segundo y utilice este valor para el ejercicio siguiente.

Julia
Ejercicio 11)

Ejecute la función generar_DB para confeccionar la base de datos completa de su lista de canciones. Utilice al menos 40 canciones para llenar la base de datos.

Julia

Test del algoritmo

En esta etapa final, pondremos a prueba la eficacia del algoritmo completo de reconocimiento. El procedimiento consistirá en obtener el porcentaje de aciertos del método al reconocer segmentos de audio, los cuales serán sometidos a distintas distorsiones.

Para esto se suministra la función query_DB, la cual recibe como entradas la base de datos y la huella acústica del segmento de audio a reconocer, y devuelve el IDs de la canción que mejor coincide con la huella. Para entender cómo opera esta función, lea el Apéndice y el código.

Ejercicio 12)

Evalúe la tasa de aciertos del algoritmo identificando segmentos de duración inline_formula not implemented con tiempo inicial elegido al azar de canciones elegidas al azar (vea la función rand). Las canciones deberán ser las mismas que utilizó para confeccionar la base de datos. Realice la evaluación para 50 segmentos con duración inline_formula not implemented entre 5, 10 y 20 segundos cada vez (150 evaluaciones en total) obteniendo la tasa de aciertos en cada caso.

Julia
Ejercicio 13)

Repita el ejercicio 12 sumando ruido a los segmentos de audio. Utilice la función randn para generar las muestras de ruido. Evalúe tasa de aciertos para SNR 0dB, 10dB y 20dB, mostrando sus resultados en una tabla para 9 combinaciones de longitud temporal y ruido.

Julia
Ejercicio 14) (OPTATIVO)

Reproduzca y grabe un segmento de alguna de las canciones e intente reconocerla con su algoritmo. Puede utilizar dispositivos como el micrófono de su PC, su teléfono celular, una radio, etc. Comente los resultados obtenidos así como las condiciones de ruido de fondo y los dispositivos utilizados. (Recuerde que su función recibe audios a 44100 Hz.)

Julia
Ejercicio 15) (OPTATIVO; SÓLO PARA LOS MÁS ENTUSIASTAS)

Repita el ejercicio 12 para T=10 solamente, afectando los segmentos con otro tipos de distorsiones elegidas entre las siguientes:

  • Saturación

  • Cuantización

  • Cambio de velocidad

  • Ecualización

Si elige saturación y/o cuantización, muestre el efecto que ocasiona sobre el audio mediante un espectrograma. Justifique si estas distorsiones pueden considerarse o no sistemas LTI.

Julia
Ejercicio 16) (OPTATIVO; SÓLO PARA LOS MÁS OBSESIVOS)

Verifique cómo cambia la tasa de aciertos cuando:

  • cambia el solapamiento

  • incrementa el solapamiento sólo al momento de identificar pero no al armar la base de datos

  • cambia la longitud de la ventana manteniendo la tasa de frames por segundo

  • cambia el algoritmo de extracción de características por algún otro que se le ocurra

Julia

Apéndice

La estructura de la base de datos

La base de datos es un vector de inline_formula not implemented elementos, cada uno de los cuales es un vector de tamaño dinámico. Para cada frame de la huella acústica, se genera un valor a guardar en estos vectores de tamaño dinámico. El índice en el que se guarda cada valor se obtiene pasando a decimal el número binario conformado por las características del frame en cuestión. Note que la cantidad de elementos del vector de la base, inline_formula not implemented se debe a que cada frame de la huella acústica posee 20 elementos binarios.

Cada valor a guardar es un objeto de tipo FrameID, que consiste de un entero de 32 bits sin signo, que determina el número de frame, y un entero de 16 bits sin signo que guarda el índice de la canción. Observe que el máximo número de canciones distintas que se podrán almacenar en esta tabla es inline_formula not implemented. Obserbe también que múltiples FrameIDs de distintos frames pueden requerir ser guardados en la misma posición por tener la misma huella; por esto, cada elemento es un vector que puede crecer según se requiera.

Esta implementación puede ser optimizada pero es un balance razonable entre eficiencia y simpleza, suficiente para este trabajo.

La búsqueda de la canción más probable

La búsqueda en la base de datos parte de una huella acústica de entrada y devuelve el ID de la canción más probable a la cual corresponde como salida.

Para cada frame de la huella se obtiene el índice del vector de la base de datos que debe consultarse, pasando la característica de cada frame de binario a decimal, del modo inverso que cuando se almacenan elementos en la base, y se extraen todos los elementos almacenados en esa posición. Cada uno de estos elementos posee el ID de la canción a la cual corresponde y el número del frame que le correspondía originalmente.

Una forma sencilla de decidir a qué canción corresponde la huella podría ser elegir, de todos los elementos que se extrajeron, el ID que aparezca el mayor número de veces.

Un refinamiento al criterio anterior es, dado que para cada ID se dispone del número de frame del cual se extrajo, quedarse con la mayor cantidad de ID dentro de un intervalo de frames igual a la longitud de la huella que se está consultando. Esto es lo que está implementado en la función query_DB.

Por ejemplo, supongamos que se realiza un query a la base de datos con una huella que posee una longitud de 5 frames y se obtienen los siguientes 7 elementos:

Bajo el primer criterio se declararía ganador al ID 7 dado que aparece mayor cantidad de veces, pero bajo el segundo criterio se decide por el ID 3, debido a que en el intervalo de 5 frames que tiene la huella de entrada el ID 7 aparece como máximo 2 veces y el ID 3 aparece 3 veces.

Bibliografía

Runtimes (1)