| |
La tecnica
di "table look-up" è diventata il metodo più
comune per generare segnali audio periodici con mezzi digitali. Essa
permette un compromesso tra i requisiti di un suono di alta qualità
e il desiderio di ottenere dei risultati con la maggiore efficienza
possibile. Uno dei grossi vantaggi del "table look-up" sta
nella composizione della tabella stessa.
Si possono infatti generare tabelle che rappresentano qualsiasi combinazione
di parziali in qualsiasi proporzione di ampiezza si desideri; naturalmente,
ciò conduce a sperimentare combinazioni di parziali che non esistono,
o magari non possono affatto esistere, negli strumenti acustici tradizionali;
oppure combinazioni che possono essere difficili da realizzare con sintetizzatori
analogici, ed impossibili da controllare in modi musicalmente interessanti
con questo tipo di strumenti, a meno che non si tratti di apparecchi
dotati di sistemi digitali di controllo.
Rivediamo brevemente come lavora il "table look-up". Vogliamo
produrre un'onda di suono che è di natura periodica, cioè
ripetitiva o ciclica. Innanzitutto ci occorre che il calcolatore generi
una serie di numeri per rappresentare un ciclo di quest'onda; poi bisogna
far ripetere continuamente al calcolatore questa serie ad una determinata
velocità (cicli al secondo, o frequenza) in modo da far convertire
dal nostro convertitore DAC (da digitale ad analogico) questi cicli
di numeri in un segnale audio di quella particolare frequenza. Se questa
serie di numeri è costituita dai valori derivati da una funzione
circolare di seno oppure di coseno, otterremo un tono sinusoidale dal
calcolatore. Ora, secondo una teoria molto usata, ogni funzione periodica
complessa può essere scomposta in una somma di funzioni di seno
e coseno. Per il musicista ciò significa che dovremmo essere
capaci di costruire qualsiasi suono esistente o anche finora non esistente,
addizionando tra loro gli appropriati toni sinusoidali alle appropriate
frequenze ed ampiezze.
Così,
per un tono che si approssima ad un'onda di rampa noi potremmo chiamare
simultaneamente 10 toni sinusoidali, con frequenze 1, 2, 3, 4, ... 9,
10 volte la frequenza fondamentale, e ampiezze 1/1, 1/4, 1/9, 1/16,
... 1/81, 1/100 dell'ampiezza della frequenza più bassa. Se dobbiamo
calcolare il valore di seno per ogni armonica in quest'onda ad ogni
campione, abbiamo in mano una procedura computazionale enormemente lunga.
Ma tenete presente che abbiamo a che fare con cicli di numeri; così,
invece di ripetere inutilmente gli stessi calcoli per ogni ciclo, noi
calcoliamo il valore di seno per un ciclo di un'onda di seno prototipo
che contiene già la somma delle 10 armoniche alle ampiezze volute;
immagazziniamo questi valori nella memoria del calcolatore sotto forma
di una tabella indirizzabile (ciascun valore è immagazzinato
in una locazione unica nella memoria del calcolatore e ci si può
riferire ad esso mediante l'indirizzo associato con quella locazione);
poi semplicemente programmiamo il calcolatore ad emettere i valori della
tabella alla frequenza che desideriamo. Questa frequenza determina le
successioni di indirizzi a cui il calcolatore deve andare per ottenere
la serie di valori dalla tabella dell'onda di seno.
Ciascun punto particolare nella tabella di seno è chiamato fase,
poiché questi valori sono derivati da cicli che si riferiscono
alla funzione circolare di seno. Il fattore che dice al calcolatore
quale fase dell'onda di seno consultare per ciascun suono è chiamato
sampling increment ("incremento di campionamento", abbreviato
SI) ed è in relazione con la frequenza del segnale in base alla
seguente equazione:
dove F = frequenza, TL = misura o numero di punti nella tabella, e SR
= "sampling rate", ossia numero di campioni da calcolare per
un secondo di suono.
Il corretto indirizzo di tabella o fase (PHS) viene calcolato per ogni
campione aggiungendo ripetutamente il sampling increment alla fase,
secondo l'equazione:
PHS = PHS + SI
Questa equazione viene eseguita una volta per ciascun campione. Quando
PHS diviene maggiore di
TL allora esso viene aggiustato facendo:
PHS = PHS - TL
Se la nostra frequenza è un do centrale (261 Hz), il corretto
sampling increment per una tabella con 512 full word, a 10.000 campioni
al secondo è:

Poiché la tabella ha solo numeri interi per indirizzi, ne risulta
una certa imprecisione; per ogni campione successivo, il calcolatore
guarderà alla seguente serie di locazioni: 0, 13, 26, 40, 53,
66, 80, 83, 106, 120 ... e andrà a prendere valori a queste locazioni
(i valori di seno desiderati), da mandare, alla fine, al convertitore.
Quanto maggiore è la dimensione della tabella, tanto minore sarà
la precisione della serie di fasi; ed anche, quanto maggiore è
la misura della tabella, tanto più memoria ci vuole, e questo
può divenire un problema costoso.
La dimensione
della tabella con 512 locazioni è un buon compromesso tra i requisiti
di un segnale audio pulito ed il mantenimento entro limiti ragionevoli
della memoria richiesta. Potete aumentare significativamente la precisione
ed anche ridurre la richiesta di memoria aggiungendo una procedura di
interpolazione che tiene conto della parte frazionaria di ogni sampling
increment: ma, come sempre, quel che si risparmia da una parte si spende
dall'altra: il table lock-up con interpolazione è almeno del
50% più lento del processo normale, il che significa che il tempo
di calcolo viene aumentato notevolmente.
Usi della procedura di table look-up
Chiaramente, l'uso fondamentale del table look-up consiste nel generare
un segnale audio; si crea una tabella di onda di seno scrivendo un programma
che chiamiamo in azione ad un certo momento durante l'esecuzione, e
si dà a questa tabella un indirizzo di riferimento (ad esempio
il numero 3) che dice al programma di table look-up di guardare la nostra
terza tabella ogni volta che occorre generare un'onda di seno.
Si devono osservare le convenzioni nel linguaggio di programmazione
che si sta usando, che consentono al programma di table look-up di trovare
la tabella di seno precedentemente generata In molti linguaggi, si dichiara
semplicemente all'inizio di entrambi i programmi che una particolare
area della memoria sarà designata dallo stesso nome in ciascuno
di essi: chiamiamola semplicemente F (come Funzione) e, come in Fortran,
scriveremo qualcosa come:
(table look-up) (funzione generatrice della tabella di seno)
Subroutine Tab Subroutine Sine Common F (512) Common F (512) etc...
etc... dove la parola COMMON
(comune) dice al calcolatore che l'area di memoria F, con 512 locazioni,
è la stessa per entrambi i programmi (o "subroutines").
Per motivi di convenienza, il processo di table look-up come generatore
di segnale è stata tradizionalmente chiamata subroutine di oscillatore,
poiché dà un risultato audio che è
identico ad un oscillatore analogico ideale; ma che oscillatore!
E' infinitamente più facile da controllare, ha una precisione
totale, non può dare distorsione, a meno che non gli facciate
produrre numeri più grandi della capacità del vostro calcolatore,
e per mezzo di procedure computazionali complesse può fare cose
che sarebbero impensabili con un oscillatore analogico qualsiasi.
Proprio come un oscillatore di un sintetizzatore analogico standard
può controllare vari parametri di altri oscillatori, o filtri
o inviluppi (mi riferisco al concetto analogico di controllo di voltaggio),
così l'oscillatore digitale può fare esattamente le stesse
cose, ma meglio e con molto maggior precisione. Tuttavia, bisogna dare
al programma di oscillatore valori dei dati che siano l'equivalente
dei voltaggi di controllo nel sistema analogico; e bisogna essere in
grado di disegnare una tabella di valori che corrisponda proporzionalmente
all'aumento o alla diminuzione nel tempo dei valori di controllo prescelti.
Per esempio, se vogliamo generare un glissando, dobbiamo riuscire a
far sì che la frequenza (input alla nostra subroutine di oscillatore
che genera il tono di seno) si elevi o scenda in un periodo di tempo
richiesto.
Con la otteniamo solo un glissando che cresce; con lb solo uno che cala;
con 1c una crescita seguita da diminuzione. Il grafico 1 c rappresenta
la situazione più conveniente, perché possiamo ottenere
anche il glissando crescente leggendo solo la prima metà della
funzione e quello diminuente leggendo solo la seconda metà. Se
questa tabella viene letta da una subroutine di oscillatore, possiamo
aggiustare il SI a seconda di quanto veloce vogliamo che sia il glissando.
Supponiamo di volere un intero ciclo di glissando su e giù (grafico
1 c) in un tempo di 3 secondi; 1 ciclo in 3 secondi significa .3333
cicli per secondo. Il Sampling Increment è calcolato come:

Un altro
tipico uso della subroutine di oscillatore è quello di generare
inviluppi di ampiezza, esattamente nello stesso modo in cui un generatore
di inviluppo analogico modella le caratteristiche di ampiezza nel tempo
di un suono. Qui l'oscillatore è usato per modellare il livello
audio istantaneo; i valori nella tabella che voi create sono proporzionali
al livello di voltaggio, cioè l'ampiezza del segnale a qualsiasi
momento dato. Il punto è che siamo liberi di disegnare qualsiasi
forma di inviluppo vogliamo e poi di manipolarla in qualsiasi maniera
ci piaccia.
Naturalmente queste qualità dipendono dalla velocità con
cui l'oscillatore di inviluppo legge queste tabelle come controlli di
ampiezza, il che, ancora una volta, si ottiene calcolando il SI.
Se, ad esempio, vogliamo 27 attacchi (cicli, in questo caso) in 4 secondi
e mezzo, scriviamo:
lasciando
al calcolatore il problema di calcolare quanti cicli al secondo sono
necessari per ottenere 27 attacchi in 4.5 secondi. Otterremo una serie
piuttosto veloce di attacchi che renderà 2a e 2c simili tra loro,
mentre 2b comincerà a sembrare come della musica suonata a rovescio
con un registratore.
|
|