Gráficos

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...)
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...)
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
function specgram(x; 
    overlap=0.5, 
    window=hamming(div(length(x), 16)), 
    nfft=length(window), 
    rest...)
  
  window isa Integer && (window = rect(window))
  overlap isa AbstractFloat && (overlap = round(Int, length(window) * overlap))
    
  return stft(x; overlap=overlap, window=window, nfft=nfft)
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)",
      kws...)
    mat = specgram(x; kws...)
  
    fmax = fs
    if onesided
      mat = mat[1:div(size(mat, 1) + 2, 2), :]
      fmax = fs/2
    end
  
  times = range(0; length=size(mat, 2), stop=length(x)/fs) # aprox
  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
0.4s
Julia
specplot (generic function with 3 methods)

sr = 100
x = sin.(range(0; step=0.01, length=1000));
# time segments in seconds
tsegs = [ (0.1, 1.3), (2.35, 5.5), (6.55, 9), (9, 9.9) ]
1.0s
Julia
4-element Array{Tuple{Real,Real},1}: (0.1, 1.3) (2.35, 5.5) (6.55, 9) (9, 9.9)
# in samples. 
  # Sólo redondea al (tiempo * sr), pero encargándome de que 
  # no de menos que 1 ni más que length(x)
nsegs = [ clamp.(round.(Int, sr .* ts), 1, length(x)) for ts in tsegs ]
0.6s
Julia
4-element Array{Tuple{Int64,Int64},1}: (10, 130) (235, 550) (655, 900) (900, 990)
# a vector holding the 4 vectors of samples
xsegs = [ x[n0:ne] for (n0, ne) in nsegs ]
# a vector holding the 4 vectors of indices
nss   = [ n0:ne for (n0, ne) in nsegs ]
# a vector holding the 4 vectors of time stamps
tss   = nss ./ sr
# make 4 plots
pls = [ 
        plot(ts, xseg;
          legend=true, label=string(ts[1]) * " s to " * string(ts[2]) * " s"
      ) 
      for (ts, xseg) in zip(tss, xsegs) ]
# and plot them in a 2 by 2 matrix
plot(pls...; layout = (2, 2), title = "Las 4 cosas")
1.1s
Julia
plot(sin, 0, 4π; 
  label="SENO", 
  legend=true, 
  xticks=[0, 0.12, π, 3.9, 2π], 
  yticks=[-5, -0.2, 0.2, 2],
  xlabel="SOY EL TIEMPO (hr)", 
  ylabel="hehe",
  legendtitle="etiquetas",
  title="GRRR"
)
plot!(cos, 0, 4π; 
  label="COSENO",
  xlims=(0.1, 4.4),
  ylims=(-5.3, 2.4)
)
0.7s
Julia
ts = range(0; step=0.01, length=10000)
specplot(sin.(2π .* ts .^2) .+ 0.01 .* rand(length(ts));
  clims=(-10, 5)
)
1.6s
Julia
Runtimes (1)