INTRODUCTION |
Dès qu’un rayon lumineux parvient à l’œil ou qu’un son atteint l’oreille, il en découle un signal qui peut être interprété comme une fonction du temps y(t). Lorsqu’il s’agit d’une lumière monochromatique ou d’un son pur, cette fonction sera une oscillation sinusoïdale d’amplitude A et de fréquence f, donnée par l’expression [plus.. Si l’origine du temps ne correspond pas au début de l’oscillation, il faut encore rajouter un décalage de phase]:
|
SPECTRE D’UN SON, HARMONIQUES |
Les composantes de fréquences sinusoïdales déterminent le timbre sonore d’une voix ou d’un instrument de musique. Un son purement périodique est constitué de la fondamentale et de ses harmoniques dont les fréquences sont des multiples entiers de la fondamentale. Si l’on représente graphiquement l’amplitude de chacune des différentes composantes de fréquences du son, on obtient son spectre que l’on peut déterminer. Un appareil permettant de déterminer le spectre d’un son est appelé analyseur de spectre. TigerJython est capable de déterminer le spectre d’un son à l’aide d’un célèbre algorithme appelé transformation de Fourier rapide (FFT = Fast Fourier Transform). Pour effectuer une transformation de Fourier rapide, on passe à la fonction fft(samples, n) une liste contenant les valeurs échantillonnées à intervalles de temps réguliers. Le paramètre n permet d’indiquer que l’on ne prend que les n premières valeurs de la liste pour effectuer la FFT. La fonction fft retourne une liste de nombres représentant l’amplitude de chacune desn/2 composantes de fréquences (normalisées) du son analysé. Chaque nombre ainsi obtenu par la fonction fft représente une fréquence présente dans le spectre du son analysé. La différence de fréquence entre chaque composante retournée est de r = fs / n, où fs est la fréquence d’échantillonnage. La grandeur r est appelée résolution du spectre. Ces n/2 valeurs de retour espacées d’une différence de fréquence r couvrent la plage de fréquence entre 0 et n/2*r = fs/2, ou, pour faire simple : La FFT permet de déterminer le spectre compris entre 0 et fs/2 pour une fréquence d’échantillonnage de fs. Pour prendre un exemple concret, l’échantillonnage à 44100 Hz d’un CD audio permet de couvrir une plage de fréquence de 0 à 22050 Hz, ce qui correspond à l’ensemble de la page de fréquence audibles par l’oreille humaine.
from soundsystem import * from gpanel import * def showSpectrum(text): makeGPanel(-2000, 22000, -0.2, 1.2) drawGrid(0, 20000, 0, 1.0, 10, 5, "blue") title(text) lineWidth(2) r = fs / n # Resolution f = 0 for i in range(n // 2): line(f, 0, f, a[i]) f += r fs = 40000 # Sampling frequency n = 10000 # Number of samples samples = getWavMono("wav/doublesine.wav") openMonoPlayer(samples, fs) play() a = fft(samples, n) showSpectrum("Audio Spectrum") |
MEMENTO |
Comme vous pouvez l’imaginer et l’entendre, le spectre contient deux composantes de fréquences différentes : 500 Hz et 1.5 kHz présentant un rapport d’amplitude de 1 pour 1/2. L’analyseur de spectre révèle également quelques autres composantes de fréquences perturbatrices. La fréquence 0 correspond à une composante de signal constante (offset). On dispose à présent d’un analyseur de spectre permettant d’examiner les fondamentales et les harmoniques de divers instruments de musiques, de voix humaines ou animales. On trouve un enregistrement de flûte ("wav/flute.wav") et de hautbois ("wav/oboe.wav") tout prêts dans la distribution de TigerJython et l’on voit immédiatement qu’ils présentent des caractéristiques sonores très différentes. |
SPECTRES DE FONCTIONS QUELCONQUES |
D’après le théorème de Fourier, toute fonction périodique de fréquence f peut être représentée comme une superposition de fonctions sinusoïdales de fréquences f, 2*f, 3*f, etc. (Séries de Fourier).
from soundsystem import * from gpanel import * def showSpectrum(text): makeGPanel(-2000, 22000, -0.2, 1.2) drawGrid(0, 20000, 0, 1.0, 10, 5, "blue") title(text) lineWidth(2) r = fs / n # Resolution f = 0 for i in range(n // 2): line(f, 0, f, a[i]) f += r n = 10000 fs = 40000 # Sampling frequency f = 1000 # Signal frequency samples = [0] * 120000 # sampled data for 3 s t = 0 dt = 1 / fs # sampling period for i in range(120000): samples[i] = square(1000, f, t) t += dt openMonoPlayer(samples, 40000) play() a = fft(samples, n) showSpectrum("Spectrum Square Wave") |
MEMENTO |
L’expérience montre que le spectre d’une fonction rectangulaire est constitué des multiples impairs de la fréquence fondamentale et que les amplitudes de ces composantes de fréquences sont les termes de la suite 1, 1/3, 1/5, 1/7, etc. Il n’est cependant pas possible de déterminer par l’expérience que les composantes spectrales s’étendent à l’infini d’un point de vue théorique. |
SONOGRAMME |
La transformation de Fourier rapide est un outil idéal pour enregistrer le comportement spectral d’un son variant dans le temps tel qu’un mot parlé. Bien entendu, le signal n’est dans ce cas plus périodique mais on peut faire l’hypothèse qu’il est périodique par morceaux. C’est la raison pour laquelle l’algorithme FFT est souvent utilisé, à intervalles réguliers de 2.5 ms, sur de courts blocs de signaux de 100 ms par exemple. On obtient de ce fait un nouveau spectre toutes les 2.5 ms qui peut être représenté par des bandes verticales colorées dans un sonogramme.
from soundsystem import * from gpanel import * def toColor(z): w = int(450 + 300 * z) c = X11Color.wavelengthToColor(w) return c def drawSonogram(): makeGPanel(0, 190, 0, 1000) title("Sonogramm of 'Harris'") lineWidth(4) # Analyse blocks every 50 samples for k in range(191): a = fft(samples[k * 50:], n) for i in range(n // 2): setColor(toColor(a[i])) point(k, i) fs = 20000 # Sampling freq->spectrum 0..10 kHz n = 2000 # Size of block for analyser samples = getWavMono("wav/harris.wav") openMonoPlayer(samples, fs) play() drawSonogram() |
MEMENTO |
Le sonogramme produit présente sur l’axe vertical les fréquences entre 0 et 10 kHz et, horizontalement, l’évolution temporelle du spectre de 0 à 190 * 50 / 20000 = 0.475 s. Pour effectuer la conversion entre les valeurs numériques et les couleurs, on utilise la fonction X11Color.wavelengthToColor() qui permet de convertir des longueurs d’onde du spectre visible compris entre 380 et 780 nm en une couleur affichable à l’écran. À la fin du mot, lorsque le « s » sifflant est prononcé, les hautes composantes spectrales sont clairement visibles, alors que les fondamentales sont complètement absentes. |
SPECTRE DE LA LUMIÈRE |
La lumière peut également être décomposée de manière spectrale pour déterminer la longueur d’onde de ses différentes composantes. Les longueurs d’onde du spectre visible s’étendent entre 380 nm et 780 nm. Il est fort probable que vous connaissiez déjà l’analyseur de spectre pour la lumière, à savoir le prisme. Celui-ci fonctionne en réfractant davantage les longueurs d’ondes bleues (380 nm) que les rouges (780 nm), selon la loi de la réfraction. Le programme suivant simule la transition d’un rayon lumineux blanc provenant du vide et pénétrant dans le verre en montrant le chemin emprunté par les différentes couleurs au moyen d’un agrandissement. from gpanel import * # K5 glass B = 1.5220 C = 4590 # nanometer^2 # Cauchy equation for refracting index def n(wavelength): return B + C / (wavelength * wavelength) makeGPanel(-1, 1, -1, 1) title("Refracting at the K5 glass") bgColor("black") setColor("white") line(-1, 0, 1, 0) lineWidth(4) line(-1, 1, 0, 0) lineWidth(1) sineAlpha = 0.707 for i in range(51): wavelength = 380 + 8 * i setColor(X11Color.wavelengthToColor(wavelength)) sineBeta = sineAlpha / n(wavelength) x = (sineBeta - 0.45) * 100 - 0.5 # magnification line(0, 0, x, -1) |
MEMENTO |
Afin d’obtenir un beau graphique, la lumière est davantage réfractée que dans la réalité. |
EXERCISES |
|