Psicoacustica

Por Jose R. Zapata

Invitame a un Cafe

import numpy as np
import IPython.display as ipd
import librosa, librosa.display
import matplotlib.pyplot as plt

Escala de Magnitud

A menudo, la amplitud original de una señal en el dominio de tiempo o de lafrecuencia no es perceptualmente relevante para los humanos como la amplitud convertida en otras unidades, Ej: usar una escala logarítmica.

Por ejemplo, consideremos un tono puro cuya amplitud aumenta de forma lineal. Definir la variable de tiempo:

T = 5.0      # duracion en segundos
sr = 22050   # Frecuencia de muestreo en Hz
t = np.linspace(0, T, int(T*sr), endpoint=False)

Crear una señal que su amplitud aumente linealmente

amplitude = np.linspace(0, 1, int(T*sr), endpoint=False) # Amplitud variable en el tiempo
x = amplitude*np.sin(2*np.pi*440*t) #Señal sinusoidal

ipd.Audio(x, rate=sr)

Grafica de la señal:

librosa.display.waveplot(x, sr=sr);

png

Ahora considere una señal cuya amplitud crece exponencialmente, es decir, el logaritmo de la amplitud es lineal:

amplitude = np.logspace(-2, 0, int(T*sr), endpoint=False, base=10.0)
x = amplitude*np.sin(2*np.pi*440*t)

ipd.Audio(x, rate=sr)
librosa.display.waveplot(x, sr=sr);

png

A pesar de que la amplitud crece exponencialmente, para nosotros, el aumento en el volumen parece más gradual. Este fenómeno es un ejemplo de la ley Weber-Fechner law (Wikipedia)que establece que la relación entre un estímulo y la percepción humana es logarítmica.

Percepcion de la amplitud segun la frecuencia

T = 4.0      # duracion en segundos
sr = 44100   # Frecuencia de muestreo en Hz
t = np.linspace(0, T, int(T*sr), endpoint=False)

100 Hz

# 100 Hz
x1 = np.sin(2*np.pi*100*t)
ipd.Audio(x1, rate=sr)

250 Hz

#250 hz
x2 = np.sin(2*np.pi*250*t)
ipd.Audio(x2, rate=sr)

400 Hz

#400 hz
x3 = np.sin(2*np.pi*400*t)
ipd.Audio(x3, rate=sr)

1000 Hz

#1000 hz
x4 = np.sin(2*np.pi*1000*t)
ipd.Audio(x4, rate=sr)

4000 Hz

#4000 hz
x5 = np.sin(2*np.pi*4000*t)
ipd.Audio(x5, rate=sr)

10000 Hz

#10000 hz
x6 = np.sin(2*np.pi*10000*t)
ipd.Audio(x6, rate=sr)

15000 Hz

#15000 hz
x7 = np.sin(2*np.pi*15000*t)
ipd.Audio(x7, rate=sr)

18000 Hz

#18000 hz
x8 = np.sin(2*np.pi*18000*t)
ipd.Audio(x8, rate=sr)

Graficas de las señales

plt.figure(figsize=(12,10))
for n in range(8):
    plt.subplot(4,2,n+1)
    plt.plot(eval('x'+str(n+1))[:1000])# graficar los primeros 1000 valores

png

Enmascaramiento Simultaneo

400 Hz

# Audio de 400 Hz
x1, sr1 = librosa.load('./Data/400Hz.wav',sr=None)
X1 = librosa.stft(x1)
Xdb1 = librosa.amplitude_to_db(abs(X1)) # convertir la amplitud a dB
plt.figure(figsize=(14, 5))
librosa.display.specshow(Xdb1, sr=sr1, x_axis='time', y_axis='hz');
ipd.Audio(x1,rate=sr1)

png

500 Hz

x2, sr2 = librosa.load('./Data/500Hz.wav',sr=None)
X2 = librosa.stft(x2)
Xdb2 = librosa.amplitude_to_db(abs(X2)) # convertir la amplitud a dB
plt.figure(figsize=(14, 5))
librosa.display.specshow(Xdb2, sr=sr2, x_axis='time', y_axis='hz');
ipd.Audio(x2,rate=sr2)

png

400 Hz + 500 Hz

x3, sr3 = librosa.load('./Data/400Hz+500Hz.wav',sr=None)
X3 = librosa.stft(x3)
Xdb3 = librosa.amplitude_to_db(abs(X3)) # convertir la amplitud a dB
plt.figure(figsize=(14, 5))
librosa.display.specshow(Xdb3, sr=sr3, x_axis='time', y_axis='hz');
ipd.Audio(x3,rate=sr3)

png

Audios finales

ipd.display(ipd.Audio(x1,rate=sr1)) #400 Hz
ipd.display(ipd.Audio(x2,rate=sr2)) #500 Hz
ipd.display(ipd.Audio(x3,rate=sr3)) #400 Hz + 500 Hz

Phd. Jose R. Zapata