Mauro Graziani
Tecniche di Sintesi

Look-up Table

Descrizione

In informatica il termine look-up table (trad. letterale: tabella in cui guardare) designa una struttura dati concepita per sostituire un calcolo complesso con una operazione di consultazione molto più veloce e semplice.
Oggi ormai si usano le calcolatrici tascabili, magari inserite nel cellulare, ma un esempio di look-up table, tratto non dall'informatica, ma dalla matematica, è quello delle tavole dei logaritmi in cui si può cercare il valore di un logaritmo senza doverlo calcolare a mano.
Nella sintesi digitale del suono si devono calcolare molti numeri in pochissimo tempo. La quantità è determinata dalla frequenza di campionamento (il sampling rate o SR). Tipicamente l'SR minimo per coprire l'intera estensione audio del sistema percettivo umano è di 44100 campioni al secondo (standard CD audio). Il tempo, quindi, è molto ridotto ed è un valore.
Come abbiamo visto, per sintetizzare un suono è necessario definire un algoritmo che generi in forma numerica la forma d'onda di tale suono e le sue variazioni nel tempo. Questa operazione può richiedere molti calcoli e sebbene i computer attuali siano molto veloci, ogni risparmio di tempo significa poter fare calcoli più complessi e accurati migliorando la qualità timbrica del segnale oppure aumentando le possibilità polifoniche del sistema.
Una delle aree più critiche nel calcolo delle forme d'onda è quella trigonometrica. Calcolare il seno o il coseno di un numero può richiedere del tempo e considerando che molti segnali si possono generare mediante somme di sinusoidi, il tempo di calcolo aumenta. Di conseguenza, risulta conveniente costruire un equivalente delle tavole trigonometriche e pre-calcolare i valori di un ciclo della funzione audio (la forma d'onda) per non essere costretti a calcolarli in fase di esecuzione, sostituendo il calcolo con una semplice consultazione.

Ecco, quindi il look-up oscillator, ovvero l'oscillatore che, per generare un segnale audio, scandisce ciclicamente una forma d'onda memorizzata, come nello schema in figura. L'oscillatore legge la tabella contenente un ciclo della forma d'onda memorizzata (in questo caso una sinusoide) tornando a capo una volta raggiunta la fine.
look-up schema
Aggiungendo un inviluppo, lo schema è completo.
lookup + envelope
Si tratta delle tecnica più semplice e diretta e come tale, è quella con cui, generalmente, si inizia lo studio della sintesi del suono. È nota anche con altre denominazioni, tipo: onda memorizzata, tabellare e altre.

Di solito, lo studente si sofferma poco su questa tecnica, giusto il tempo di apprendere i rudimenti di Csound o Max/MSP, per poi passare rapidamente a sistemi più complessi e potenti, ma, a mio avviso, è un errore. Una forma d'onda memorizzata è alla base di molte altre tecniche di sintesi ed è utile conoscere a fondo le problematiche dell'oscillatore digitale prima di approfondire sistemi più complessi (gli studenti del Triennio di Musica Elettronica devono studiare la pagina sull'oscillatore digitale).

Inoltre, lavorare con uno strumento semplice come il classico oscillatore con inviluppo rende evidenti
  1. varie proprietà acustiche delle onde
  2. vari fenomeni legati alla sovrapposizione di onde;
  3. la differenza fra timbro e spettro.

Formalismo

Dal punto di vista formale, la sintesi per onda fissa è molto semplice. La tabella memorizzata deve contenere una serie di valori che rappresentano un ciclo dell'onda audio da produrre che, di solito, è calcolata mediante somma di armonici. La formula, quindi, è

(1)    T = A1 * sin(f) + A2 * sin(2f) + A3 * sin(3f) + A4 * sin(4f) + ... + An * sin(nf)

dove An rappresenta l'ampiezza dell'ennesima componente ed è un valore che viene fissato al momento della creazione della tabella e non può più essere cambiato, f è la fondamentale e nf è l'ennesima componente (e.g. 2f è la componente con frequenza doppia della fondamentale, cioè il primo armonico; 3f ha frequenza tripla ed è il secondo armonico, etc).
Naturalmente la funzione memorizzata può essere generata anche mediante altri algoritmi.
La funzione è poi riscalata ad 1 in modo da produrre un segnale di ampiezza unitaria a cui si assegna l'ampiezza finale desiderata con una semplice moltiplicazione. Una volta che la tabella è stata caricata in memoria, un oscillatore si limita a leggerla ciclicamente. Ovviamente, per ottenere un segnale usabile, un inviluppo di ampiezza è obbligatorio, per cui abbiamo

S = T * G(k)

dove S è il segnale, T è la (1) e G(k) è la funzione utilizzata come inviluppo di ampiezza.

Caratteristiche

Vantaggi

Facilità di comprensione e implementazione
Il che si traduce in semplicità di controllo e facilità d'uso.
Segnale complesso
Con un singolo oscillatore è possibile generare un segnale composto da un numero elevato di armoniche
Velocità di calcolo Un singolo look-up oscillator con inviluppo utilizza pochissime risorse dal punto di vista del calcolo.
Per leggere la tabella sono sufficienti una somma e un and logico (per questo la lunghezza della tabella, di solito, è una potenza di 2) a cui si aggiunge una moltiplicazione per l'inviluppo di ampiezza.
Quest'ultimo può essere di vari tipi, ma, in linea di massima, ogni campione richiede solo una somma o moltiplicazione e un test. Inoltre, in alcuni sistemi (e.g. Csound), l'inviluppo viaggia a frequenza più lenta.

Limiti

Spettro fisso
Il limite principale di questo tipo di sintesi è che lo spettro è fisso: non può variare nel corso della nota, mentre nei suoni reali questo avviene quasi sempre ed è sensibile soprattutto in quelli a evoluzione libera.
Non può nemmeno cambiare fra un nota e la successiva, a meno che non si predispongano più tabelle con forme d'onda diverse.
Massima correlazione fra le componenti
La correlazione fra le componenti è massima, ovvero, ogni variazione di ampiezza o frequenza (e.g. il vibrato) si ripercuote in egual percentuale e in modo sincrono su tutte le componenti. Se diminuisco l'ampiezza di 6 dB, tutte le componenti e tutte insieme caleranno di 6 dB. Se applico un vibrato, tutte vibreranno insieme e il vibrato avrà esattamente la stessa escursione in termini di intervallo.
Una correlazione del genere in natura non si dà. Ci sono sempre piccole deviazioni che, per quanto lievi, vengono registrate dal nostro sistema percettivo e concorrono a creare una sensazione di realtà. Al contrario, un suono in cui la correlazione fra le componenti è massima, viene percepito come meccanico e artificiale.
Impossibilità di variare lo spettro in funzione dell'ampiezza
Nei suoni reali, il contenuto spettrale varia in base all'ampiezza, cioè alla dinamica. In uno strumento, una nota eseguita fff avrà più armonici della stessa nota eseguita ppp.
Inoltre, nell'attacco dei suoni reali, le componenti non arrivano tutte insieme, così come, nel rilascio, non se vanno insieme.
Impossibilità di variare lo spettro in funzione della frequenza
Nei suoni reali, il contenuto spettrale varia in base alla frequenza fondamentale. Con un qualsiasi strumento acustico, è facile accorgersi che una nota alta contiene meno armonici rispetto a una nota bassa (se eseguite a dinamiche simili).
Ovviamente, si possono definire varie forme d'onda con diverso contenuto spettrale e programmare un meccanismo che seleziona la più adatta in base alla fondamentale, ma in questo caso il cambiamento avviene a gradini e può risultare sensibile (a meno di non interpolare fra forme d'onda diverse).
Limitazioni causate dal foldover
Diretta conseguenza di quanto visto visto sopra è il fatto che, a partire da una certa frequenza fondamentale, le componenti più alte generano inevitabilmente foldover.
Per esempio, con SR = 44100, la 10ma armonica eguaglia la frequenza di Nyquist a 2205 Hz, che corrisponde, all'incirca, al penultimo Do del pianoforte. La 20ma armonica lo eguaglia a 1102.5.
Quindi, volendo evitare il foldover, ogni funzione audio ha una sua frequenza massima di utilizzo pari a N/k, con N = SR/2 (frequenza di Nyquist) e k = numero d'ordine della componente più alta presente in tabella.
Ne consegue che, volendo utilizzare una fondamentale maggiore di questo valore, si è costretti a cambiare funzione audio.
Impossibilità di creare componenti inarmoniche o "quasi armoniche"
Visto che l'onda audio viene generata mediante la scansione ciclica di una tabella memorizzata, senza altri interventi, è chiaro che la suddetta onda è forzatamente periodica.
Di conseguenza è impossibile generare componenti inarmoniche. Anche se la tabella venisse riempita di numeri casuali, la ciclicità del meccanismo di lettura genererebbe inevitabilmente una forma d'onda periodica.
Esistono, tuttavia, alcuni "trucchi" per creare suoni che, pur essendo composti da armonici, sembrano inarmonici (vedi oltre), ma c'è un altro problema. Anche nei suoni con componenti armoniche, spesso la frequenza delle armoniche non è esattamente un multiplo della fondamentale, come la teoria vorrebbe. Ci sono piccolissime deviazioni, inferiori alla JND (just noticeable difference), che non vengono percepite come tali, ma creano un sottile gioco di battimenti che rendono il suono non meccanico, come invece viene spesso percepito un suono fisso come quello creato dalla look-up table.
Chiaramente, un po' di riverberazione a valle aiuta.

Implementazione

In Max/MSP

Dal punto di vista dell'algoritmo di sintesi, questo sistema è molto semplice. Il modulo è identico a quello della singola onda sinusoidale con l'unica differenza che in cycle~ si aggiunge come argomento il nome del buffer da cui leggere la forma d'onda che, ovviamente, deve esistere nella patch e contenere l'onda da leggere.

Nella figura sotto si vede la patch di base (lookup_base.maxpat), con spiegazione.
lookup base patch
La parte più a sinistra è il meccanismo di sintesi che, come già detto, è identico a quello della singola onda sinusoidale con l'unica differenza che in cycle~ si deve aggiungere un argomento che è il nome del buffer da cui leggere la forma d'onda. Notare che più cycle~ possono leggere dallo stesso buffer.

Al centro, in basso, c'è il buffer in cui caricare la forma d'onda (all'apertura della patch viene caricata una sinusoide).
L'oscillatore di MSP (cycle~) necessita di una tabella lunga esattamente 512 campioni + guard point (un 513mo campione, copia del primo per l'interpolazione), quindi il buffer è dimensionato a 513 samples. Il buffer ha i seguenti comandi:

Sulla destra c'è il programma di creazione della tabella che contiene un ciclo della forma d'onda. Il punto è che in Max non esiste alcun oggetto o programma per creare una tale tabella e scriverlo usando un liguaggio a flusso di dati di Max rasenta la follia, per cui l'ho fatto in javascript. In realtà, in Max 6, fra gli esempi, c'è un look-up oscillator completo scritto in java. Io, però, ho preferito scrivere un modulo javascript che calcola solo la forma d'onda e la carica in un buffer principalmente per ragioni didattiche: essendo il modulo di Max completamente in java (anche la parte di sintesi) risulta oscuro all'utente che non conosce la programmazione in java.
Il mio modulo è chiamato harmsum.js perché, al momento, calcola solo una forma d'onda composta da una somma di armonici sinusoidali, ognuno con la propria ampiezza (per gli utenti di Csound, imita la GEN 10).
Harmsum ha un solo inlet che riconosce i seguenti comandi:
Di conseguenza, se si desidera calcolare una tabella e inviarla immediatamente in output, si fa come in figura, cioè:
  1. si fa partire il calcolo della forma d'onda
  2. si aspetta il msg donetable in uscita dall'outlet 3
  3. all'arrivo del msg si manda un bang a harmsum
  4. si aspetta il msg doneout, sempre dall'outlet 3
  5. all'arrivo del msg si manda a cycle~ il msg "set nomebuffer" per forzare la lettura della nuova forma d'onda. Questo passaggio è necessario perché cycle~ legge la tabella solo una volta e non si aggiorna automaticamente.


Patch di esempio
La patch add16_harmsum serve agli studenti per creare una tabella, calcolarla e poi usarla in polifonia con una tastiera MIDI (è consigliata una master keyboard MIDI collegata via USB o MIDI).
Funziona come segue:
  1. accendere l'audio cliccando l'altoparlante; alzare il volume con il fader (eventuale driver audio può essere cambiato con il pulsante Driver)
  2. gli slider colorati regolano l'ampiezza della fondamentale (il primo slider nero) e dei successivi 15 armonici (16 componenti in totale). L'ampiezza può anche essere regolata muovendo il dumping factor o creata casualmente con il pulsante Random. In ogni caso è consigliabile che all'inizio lo studente metta a zero gli slider (click Zero) e inizi ad aggiungere armonici manualmente per rendersi conto dell'effetto.
    È possibile memorizzare la situazione corrente con Shift-Click su un preset e richiamarla con un click.
  3. l'altezza può essere cambiata con la tastiera virtuale. Qui il suono è continuo per valutare la sonorità.
  4. con il pulsante "Send to Synth" la forma d'onda viene calcolata e inviata al synth polifonico a destra (Play). A questo punto è necessario azzerare il volume del blocco Create Wave.
  5. Alzare il volume del Synth e suonare con una tastiera MIDI collegata al computer.
  6. Si può cambiare l'inviluppo di ampiezza (ADSR)
esempio look-up