Come Creare una Forma d'Onda dall'Audio: Python, Librerie e Metodi di Visualizzazione
Generare una visualizzazione di forma d'onda da un file audio è un compito fondamentale di elaborazione del segnale digitale. Che tu stia costruendo un lettore podcast, un editor audio o una visualizzazione dati, ecco tre approcci — da librerie one-liner a elaborazione del segnale grezzo.
Metodo 1: Librerie di Alto Livello (Consigliato — 5 Righe)
Python + Librosa + Matplotlib — gestisce decodifica, risampolaggio, stereo-in-mono, normalizzazione automaticamente.
import librosa import librosa.display import matplotlib.pyplot as plt # Carica audio (auto-risampa a 22050 Hz mono di default) y, sr = librosa.load("tuo_audio.wav") # o .mp3, .flac, .ogg # Traccia forma d'onda plt.figure(figsize=(14, 5)) librosa.display.waveshow(y, sr=sr, alpha=0.8) plt.title("Forma d'Onda (Ampiezza vs Tempo)") plt.xlabel("Tempo (secondi)") plt.ylabel("Ampiezza") plt.tight_layout() plt.savefig("forma_onda.png", dpi=150) plt.show() Installa: pip install librosa matplotlib numpy
Opzioni di Personalizzazione
librosa.load(..., sr=None)— mantieni frequenza di campionamento nativa.librosa.display.waveshow(..., max_points=50000)— downsample per file enormi.offset=30, duration=10— traccia segmento 10s partendo da 30s.- Stile:
color='cyan',linewidth=0.5, sfondo scuroplt.style.use('dark_background').
Metodo 2: Elaborazione Manuale (Comprendere il Segnale)
Python + wave + NumPy — nessuna libreria DSP, solo libreria standard + NumPy. Buono per imparare.
import wave import numpy as np import matplotlib.pyplot as plt # Apri file WAV con wave.open("tuo_audio.wav", "rb") as wf: n_channels = wf.getnchannels() sampwidth = wf.getsampwidth() # byte per campione (1, 2, 3, 4) framerate = wf.getframerate() n_frames = wf.getnframes() raw = wf.readframes(n_frames) # Converti byte in array NumPy dtype = {1: np.int8, 2: np.int16, 3: np.int32, 4: np.int32}[sampwidth] audio = np.frombuffer(raw, dtype=dtype) # Gestisci stereo: media canali in mono if n_channels == 2: audio = audio.reshape(-1, 2).mean(axis=1) # Normalizza in [-1, 1] audio = audio.astype(np.float32) / np.iinfo(dtype).max # Asse temporale time = np.arange(len(audio)) / framerate # Traccia plt.figure(figsize=(14, 5)) plt.plot(time, audio, linewidth=0.5, color='#00d4aa') plt.title("Forma d'Onda (Decodifica Manuale)") plt.xlabel("Tempo (s)") plt.ylabel("Ampiezza (normalizzata)") plt.grid(True, alpha=0.3) plt.tight_layout() plt.show() Passaggi Chiave Spiegati
wave.openlegge intestazioni RIFF/WAV.getsampwidthdetermina profondità bit → dtype corretto.frombufferinterpreta byte grezzi come interi.- Stereo → mono via media (preserva energia meglio del singolo canale).
- Normalizza per valore intero massimo per dtype (es. 32767 per int16).
- Vettore tempo: indice campione / frequenza campionamento.
Metodo 3: Avanzato — Spettrogramma (Frequenza vs Tempo)
La forma d'onda mostra l'ampiezza. Lo spettrogramma mostra contenuto di frequenza nel tempo — essenziale per l'analisi.
import librosa import librosa.display import matplotlib.pyplot as plt import numpy as np y, sr = librosa.load("tuo_audio.wav", sr=None) # Calcola Mel spectrogram (frequenze spaziate percettivamente) S = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128, fmax=8000) S_dB = librosa.power_to_db(S, ref=np.max) # Traccia plt.figure(figsize=(14, 6)) librosa.display.specshow(S_dB, sr=sr, x_axis='time', y_axis='mel', fmax=8000, cmap='magma') plt.colorbar(format='%+2.0f dB') plt.title('Mel Spectrogram') plt.tight_layout() plt.show() Altri Tipi di Spettrogramma
- STFT (Lineare):
librosa.stft→librosa.amplitude_to_db— spaziatura lineare frequenze. - CQT (Constant-Q):
librosa.cqt— frequenza logaritmica, migliore per musica. - Chromagram:
librosa.feature.chroma_stft— 12 classi di altezza (analisi armonia).
Alternativa Web / JavaScript
Per forma d'onda basata su browser (nessun backend):
<canvas id="waveform" width="800" height="200"></canvas> <script> const audioCtx = new AudioContext(); fetch('audio.mp3').then(r => r.arrayBuffer()) .then(buf => audioCtx.decodeAudioData(buf)) .then(buffer => { const data = buffer.getChannelData(0); // Float32Array [-1,1] const canvas = document.getElementById('waveform'); const ctx = canvas.getContext('2d'); const step = Math.ceil(data.length / canvas.width); ctx.fillStyle = '#00d4aa'; for (let x = 0; x < canvas.width; x++) { const start = x * step; const end = Math.min(start + step, data.length); let min = 1, max = -1; for (let i = start; i < end; i++) { min = Math.min(min, data[i]); max = Math.max(max, data[i]); } const yMin = (1 + min) * canvas.height / 2; const yMax = (1 + max) * canvas.height / 2; ctx.fillRect(x, yMin, 1, yMax - yMin); } }); </script> Usa Web Audio API decodeAudioData — funziona offline, nessun server necessario.
Scegli il Tuo Approccio
| Esigenza | Usa |
|---|---|
| Script veloce, analisi, ricerca | Librosa (Metodo 1) |
| Impara DSP, nessuna dipendenza, solo WAV | Manuale (Metodo 2) |
| Analisi frequenza, musica, parlato | Spettrogramma (Metodo 3) |
| Visualizzatore web in tempo reale | Web Audio API + Canvas |
| Produzione C++/Rust/Go | libsndfile + FFTW / kissfft / rustfft |
Per la maggior parte delle attività Python: Librosa. Gestisce i casi limite (risampolaggio, stereo, formati, normalizzazione) che ti mordono nel codice manuale.