Ejercicios para entrar en calor

Código auxiliar

# Cargo paquetitos
using DSP, FFTW
# Y armo un par de funciones auxiliares
stem(args...; kwargs...) = sticks(args...; 
  																marker=:circle, 
  																leg=false, 
  																kwargs...)
# Delta
d(n) = n == 0 ? 1. : 0. 
# Escalón
u(n) = n >= 0 ? 1. : 0. 
using Plots
# 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
cshift

1) Conv de señales de soporte acotado generales

Suponé que representamos a uan señal discreta de soporte acotado arbitraria como una tupla `(x, n)` donde `n` es el inicio del soporte

x1 = (1:10, -6)
stem(range(x1[2]; length=length(x1[1])), x1[1])
function conv_ext((x, nx), (h, nh))
  ny = nx + nh
  y  = conv_v2(x, h)
  
  return y, ny
end
function conv_v2(x, h)
  ny = length(x) + length(h) - 1
  x_ext = padright(x, ny)
  h_ext = padright(h, ny)
  
  y = conv_circ(x_ext, h_ext)
  
  return y
end
# Adelantando un poco el ej 3)
function conv_circ(x, y)
  @assert length(x) == length(y)
  
  out = ifft( fft(x) .* fft(y) )
  return out
end
function conv_v3(x, h)
  nx = length(x); nh = length(h);
  ny = nx + nh - 1
  
  return [
    sum(x[k + 1] * h[n - k + 1] for k in max(0, n - nh + 1):min(n, nx - 1))
    for n in 0:ny-1
  ]
end
conv_v3 (generic function with 1 method)
function mkfun(x)
  function xd(n)
    (n < 0 || n >= length(x)) && return 0.
  
    return x[n + 1]
  end
  return xd
end
mkfun (generic function with 1 method)
function conv_v4(x, h)
  xd = mkfun(x); hd = mkfun(h)
  ny = length(x) + length(h) - 1
  
  return [
    sum(xd(k) * hd(n - k) for k in 0:ny)
    
    for n in 0:ny-1
  ]
end
conv_v4 (generic function with 1 method)
x = [1.0, 0.0, 1.0]
h = [2.0, 3.0]
conv_v4(x, h)
4-element Array{Float64,1}: 2.0 3.0 2.0 3.0

2) Función que calcula los coeficientes de la

serie de Fourier

"""
  serie(x)
Toma un vector con los valores de [x(0), x(1), ..., x(N-1)] del primer
período de la señal N-periódica y devuelve [a_0, a_1, ..., a_{N-1}]
"""
function serie(x)
  return fft(x) ./ length(x)
end
function serie_v2(x)
  nx = length(x)
  
  return [
      1/nx * sum(x[n + 1] * exp(-im*2π*k/nx*n) for n in 0 : nx - 1)
    for k in 0 : nx - 1
  ]
end
Shift+Enter to run

3) Función que calcule la convolución circular usando la DFT

function conv_circ(x, y)
  @assert length(x) == length(y)
  
  out = ifft( fft(x) .* fft(y) )
  return out
end
conv_circ (generic function with 1 method)
x = [1., 2., 3.4]
y = [5., 22.3, 5]
3-element Array{Float64,1}: 5.0 22.3 5.0
conv_circ(x, [0, 1, 0])
3-element Array{Complex{Float64},1}: 3.4+0.0im 1.0+0.0im 2.0+0.0im

Bonus points para el que devuelva un vector de números reales cuando las entradas son ambas reales

4) Función que tome una función y grafique su espectro

Recibe por parámetro el ancho de banda `bw` de la señal continua, y el soporte `duracion` y su tiempo inicial `t0` (default 0)

Asume que la señal es real.

El gráfico es sólo del módulo y sólo de frecuencias positivas.

El eje horizontal, en Hz.

function plotspec(xc; bw, duracion, t0=0)
  
  xc
end
Shift+Enter to run

5) Espectrograma

Robá código del notebook de espectrograma.

Para agarrar confianza, jugá un poco hasta estar cómodo con los parámetros del espectrograma. Podés armar señales y/o subir wavs tuyos, como se ve en el notebook de espectrograma.

Armá espectrogramas que muestren claramente el efecto del ancho de ventana (en la resolución en tiempo y frecuencia), y del tipo de ventana (en la resolución en frecuencia y los lóbulos secundarios).

Runtimes (1)