• Non ci sono risultati.

Sound and FFT

N/A
N/A
Protected

Academic year: 2021

Condividi "Sound and FFT"

Copied!
6
0
0

Testo completo

(1)

Sound and FFT

Importiamo una serie di "utilities" che si useranno nel seguito:

In [8]:

import scipy

import numpy as np

from matplotlib import pyplot as plt from scipy.fftpack import fft, fftfreq

Definiamo le variabili che caratterizzano il nostro esercizio:

SAMPLE_RATE determines how many data points the signal uses to represent the sine wave per second. So if the signal had a sample rate of 10 Hz and was a five-second sine wave, then it would have 10 * 5 = 50 data points.

DURATION is the length of the generated sample.

In [33]:

SAMPLE_RATE = 44100 # Hertz DURATION = 5 # Seconds

Next, you define a function to generate a sine wave since you’ll use it multiple times later on. The function takes a frequency, freq, and then returns the x and y values that you’ll use to plot the wave.

In [34]:

# definisco la funzione che genera il segnale sinusoidale:

def generate_sine_wave(freq, sample_rate, duration):

x = np.linspace(0, duration, sample_rate * duration, endpoint=False) frequencies = x * freq

# 2pi because np.sin takes radians y = np.sin((2 * np.pi) * frequencies) return x, y

The x-coordinates of the sine wave are evenly spaced between 0 and DURATION, so the code uses NumPy’s linspace() to generate them. It takes a start value, an end value, and the number of samples to generate. Setting endpoint=False is important for the Fourier transform to work properly because it assumes a signal is periodic.

np.sin() calculates the values of the sine function at each of the x-coordinates. The result is multiplied by the frequency to make the sine wave oscillate at that frequency, and the product is multiplied by 2π to convert the input values to radians.

After you define the function, you use it to generate a two-hertz sine wave that lasts five seconds and plot it using Matplotlib. Your sine wave plot should look something like this:

(2)

In [44]:

# Generate a 2 hertz sine wave that lasts for 5 seconds x, y = generate_sine_wave(2, SAMPLE_RATE, DURATION) plt.plot(x, y)

plt.xlabel('time(s)') plt.show()

The x-axis represents time in seconds, and since there are two peaks for each second of time, you can see that the sine wave oscillates twice per second. This sine wave is too low a frequency to be audible, so in the next section, you’ll generate some higher-frequency sine waves, and you’ll see how to mix them.

Mixing Audio Signals in just two steps:

Adding the signals together Normalizing the result

Before you can mix the signals together, you need to generate them:

(Nota: che "," iniziale serve per mettere da parte il risultato del calcolo precedente scaricandolo nella

variabile "" (come avviene in un registro di memoria di calcolatrice). In questo caso viene usato per togliere di mezzo qualsiasi interferenza proveniente da valori precedentemente ottenuti.)

In [47]:

_, nice_tone = generate_sine_wave(400, SAMPLE_RATE, DURATION) _, noise_tone = generate_sine_wave(4000, SAMPLE_RATE, DURATION) _, noise_2=generate_sine_wave(7000, SAMPLE_RATE, DURATION)

noise_tone = noise_tone * 0.3 # regola l'ampiezza del noise noise_2 = noise_2*0.5

mixed_tone = nice_tone + noise_tone +noise_2 # somma segnale e rumore

(3)

noise_tone avra' invece una frequenza di 4000 Hz;

noise_2 avra' invece una frequenza di 7000 Hz;

mixed_tone conterra' ovviamente la somma dei due segnali precedenti.

Si noti che noise_tone e noise_2 vengono attenuati di un fattore rispettivamente di 0.3 e 0.5 prima di essere mescolati a produrre il negnale mixed_tone.

Il prossimo passo e' la normalizzazione, o scaling, del segnale. P.es. se lo vogliamo codificare in un formato a 16 bit avra' un range da -32768 a 32767:

In [55]:

normalized_tone = np.int16((mixed_tone / mixed_tone.max()) * 32767) plt.plot(normalized_tone[:1000])

plt.show()

In [51]:

len(normalized_tone)

Se volessimo ascoltare questo segnale audio dovremmo registrarlo in uno dei formati che un audio player puo' leggere. Dato che l'uso di interi a 16 bit e' lo standard per il formato .wav, useremo il metodo

wavfile.write di SciPy per registrarlo in un file:

In [56]:

from scipy.io.wavfile import write

# Remember SAMPLE_RATE = 44100 Hz is our playback rate write("mysinewave.wav", SAMPLE_RATE, normalized_tone)

Ora il prossimo passo che ci proponiamo e' di distinguere le tre componenti del suono ed eliminare la parte di rumore per ottenere un suono piu' pulito. A questo scopo useremo la trasformata di Fourier:

Out[51]:

220500

(4)

In [58]:

# Number of samples in normalized_tone N = SAMPLE_RATE * DURATION

yf = fft(normalized_tone) # calcolo la TdF del segnale

xf = fftfreq(N, 1 / SAMPLE_RATE) # frequenze centrali dei bin in cui la TdF # e' stata prima calcolata

plt.plot(xf, np.abs(yf)) # np.abs valuta sqrt(re^2+im^2) della trasforma ta

# complessa (che e' poi il Power Spectrum) plt.xlim([0,5000]) # per limitare l'estensione dell'asse x

plt.xlabel('Hz') plt.ylabel('Power')

#plt.xlim([0generate_sine_wave,5000]) # per limitare il range dell'asse X plt.show()

Lo spettro di potenza appare con due picchi simmetrici rispetto alla frequenza 0 (lo spettro di potenza della TdF e' sempre una funzione pari, ma le frequenze negative non hanno senso fisico). Le frequenze positive corrispondenti cadono esattamente ai valori delle frequenze con cui abbiamo costruito il segnale audio di prova: 400 Hz e 4000 Hz.

Notare che la linea blu del plot si estende sull'asse X fino alla frequenza ~22000 Hz (per l'esattezza 22050 Hz) che corrisponde esattamente alla meta' del SAMPLE_RATE=44100 Hz che abbiamo usato per generare il segnale. Questa e' la frequenza di Nyquist, cioe' la massima frequenza rivelabile da un campionamento a 44100 Hz.

Inversione

Passiamo ora a sfruttare l'invertibilita' della trasformata di Fourier. Questa proprieta' permette di ritornare dallo spazio delle frequenze a quello del segnale. Se pero' nello spazio di Fourier eliminiamo una data frequenza, anche nella ricostruzione del segnale non la ritroveremo. Siccome il rumore l'abbiamo aggiunto (e visto nello spettro di potenza) a 4000 Hz, andremo ora ad eliminare quella componente dallo spettro di Fourier.

1) individuiamo a quali indici del vettore delle ascisse corrisponde la frequenza di rumore:

(5)

# cerco gli indici dei punti in cui il vettore abs(yf) (spettro di potenza)

# supera un valore dato. Dallo spettro di potenza si vede che

# la frequenza di rumore corrisponde ai punti in cui np.abs(yf) > 0.5E9.

# Individuiamo gli indici in cui il vettore abs(yf) supera il valore dato iii=[i for i,v in enumerate(np.abs(yf)) if v > .5e9]

print('indici a cui la potenza > 0.5e9: ',iii) print('corrispondenti alle frequenze: ',xf[iii])

2) individuati gli indici corrispondenti alla frequenza di -4000 Hz e +4000 Hz (sono iii[1] ed iii[2]),

andiamo ad azzerare la trasformata di Fourier in quei punti che corrispondono alla frequenza di 4000 Hz che abbiamo aggiunto per simulare un rumore:

In [78]:

yf[iii[1]-2:iii[1]+3]=0

#yf[iii[2]-2:iii[2]+3]=0

#yf[iii[3]-2:iii[3]+3]=0 yf[iii[4]-2:iii[4]+3]=0 print(np.abs(yf[iii]))

In [79]:

plt.plot(xf, np.abs(yf))

#plt.xlim([0,5000]) plt.show()

3) adesso, dopo aver azzerato la frequenza del rumore, usiamo la trasformazione inversa di Fourier per ottenere il segnale "pulito":

indici a cui la potenza > 0.5e9: [2000, 20000, 35000, 185500, 20050 0, 218500]

corrispondenti alle frequenze: [ 400. 4000. 7000. -7000. -4000.

-400.]

[2.10041698e+09 0.00000000e+00 1.05021919e+09 1.05021919e+09 0.00000000e+00 2.10041698e+09]

(6)

In [80]:

from scipy.fftpack import ifft # importiamo la trasformata inversa new_sig = ifft(yf).real # separiamo la parte reale da plottare plt.plot(new_sig[:400]) # plot dei primio 400 punti

plt.show()

Warning:

La procedura illustrata qui e' utile per illustrare le potenzialita' della trasformata di Fourier, ma non e' quella piu' appropriata da usare nei casi reali. Infatti, i segnali reali non sono mai perfettamente monocromatici come in questo esempio e si devono utilizzare metodi piu' raffinati per tagliare opportunamente lo spettro di Fourier prima di antitrasformare. In questo campo gioca un ruolo essenziale l'utilizzo di filtri che, per essere efficaci, devono rispondere a precisi requisiti che qui non trattiamo.

In [ ]:

Riferimenti

Documenti correlati

Enrico Silva - diritti riservati - Non è permessa, fra l’altro, l’inclusione anche parziale in altre opere senza il consenso scritto dell’autore.. Esperimento

Chiari Deficit nelle abilità sociocomunicative verbali e non verbali; le difficoltà sociali sono evidenti anche in presenza di aiuto; l’iniziativa nelle interazioni sociali è

sempre più curioso e assetato di conoscenza riguardo a questo settore e da una fase di puro consumo si sta gradualmente evolvendo a una fase di vero e proprio culto del vino.

in particolare, finalizzate a:
 a) illustrare e favorire la conoscenza delle disposizioni normative, al.. normativo la rilevanza strategica della comunicazione, poco o niente

 dall’altra parte, in quanto titolare della proprietà o altro diritto reale sull’ex casa familiare, sarà tenuto a dichiararne il relativo reddito fondiario. Infatti, essendo

La sequenza archeologica Gli scavi archeologici effettuati in questa zona hanno interessato una superficie molto limitata 6 x 13 m densamente cosparsa di frammenti archeologici; qui

•  Generalmente genera uno spettro di dispersione più esteso verso le basse frequenze rispetto alle MASW. Preparazione all’Esame di Stato - Roma,

EUGL exhibits an electrical conductivity more than 4 orders of magnitude greater than that of the parent eumelanin compound. It may be speculated that this conductivity increment