APPUNTI PER LINGUAGGIO DI SCRIPTING Nyquist (versione 3, formato SAL) Il manuale completo del linguaggio Nyquist si trova alla URL: http://www.cs.cmu.edu/~rbd/doc/nyquist/nyquistman.pdf La variabile s è l'audio/selezione corrente Per ottenere le modifiche sul suono occorre premettere le istruzioni con "return" ===================================================================== Cambiare l'offset di una Track in Audacity in Nyquist SAL return s + 0.5 ===================================================================== Cambiare ampiezza di una Track in Audacity in Nyquist SAL Nyquist "scale" function: scale(number, sound) Moltiplica l'ampiezza del suono ("sound") per il numero dato ("number"): 0.5 dimezza l'ampiezza, 2 la raddoppia. Es.: return scale(0.5, s) ===================================================================== Generazione di un tono sinusoidale Il comando hzosc(f) produce un'onda seno di frequenza f, come comando "Genera Tono ...". Es.: hzosc (1000) produce un'onda seno di 1kHz. Generazione di un'onda quadra o a impulsi Il comando osc-pulse(f,dc) produce un'onda quadra, o a impulso, più in generale, di frequenza f con ciclo di lavoro (o duty cycle) dc. Il ciclo di lavoro, cioè la proporzione di tempo che l'onda sta nella parte positiva, assume valori da -1 a +1: a 0, la proporzione positivo/negativo è 50/50; scendendo verso -1 aumenta la proporzione nella parte negativa; salendo verso +1, aumenta la proporzione della parte positiva. Es.: osc-pulse(1000,0) produce un'onda quadra di 1kHz con duty cycle 50/50. ===================================================================== Moltiplicazione di un segnale con un segnale (tono) portante generato Portante seno return s * hzosc(1000) N.B. Con return s * hzosc(19000), difficilmente si riesce a udire. Portante onda quadra Es.: return s * osc-pulse(19000, 0) moltiplica l'audio attuale per un'onda quadra portante di 19kHz, con un ciclo 50/50. ===================================================================== Piece-wise Approximations (Approssimazioni piece-wise, a intervalli) Sono approssimazioni di funzioni definite su intervalli. La più semplice delle approssimazioni piece-wise in Nyquist è pwl(): prende in input un elenco di punti (breakpoints), assundo il primo punto in (0, 0) e valore finale a 0. Tutti i valori, sia t sia l, sono in percentuale. pwl(t1, l1, t2, l2, ... tn) return s * pwl(0.2, 1.0, 0.4, 0.5, 0.7, 0.5, 1.0) Crea un inviluppo lineare a intervalli con breakpoint (0, 0), (t1, l1), (t2, l2), ... (tn, 0). I tempi sono sempre relativi a 0; non sono le durate di ogni singolo segmento di inviluppo. Variante pwlv(l1, t2, l2, t3, t3, ... tn, ln) Crea un inviluppo lineare a intervalli con breakpoint (0, l1), (t2, l2), … with (tn, ln). return s * pwlv(0, 0.2, 1.0, 0.4, 0.5, 0.7, 0.5, 1.0, 0.0) ===================================================================== Modulazione di frequenza (FM) La modulazione di frequenza è una tecnica che consente di modificare la frequenza di una onda (detta portante) sinusoidale con un’altra onda (detta modulante). fmosc (pitch modulator table phase) Restituisce un suono che è una tabella (table) oscillata al tono (pitch) più la modulazione (modulator) partendo dalla fase indicata (phase). La modulazione (modulator) è espressa in Hz: ad esempio, una sinusoide con ampiezza 1.0 (sarebbe 2.0 da picco a gola) causerà una deviazione di +/- 1Hz nel suono. Ci si può ridurre a due parametri: il tono (pitch) e il modulante (modulator). return fmosc (a4, pwl(1.0)) ; tono (onda seno) di metà audio di quello selezionato Infatti, pwl con un solo tempo (quello finale) lascia il valore dell’ampiezza inalterato. E’ un’oscillazione fasulla, cioè è un oscillatore FM senza modulazione di input: risultato, un tono sinusoidale stabile. La durata della modulazione determina la durata del tono generato (quando finisce il segnale di modulazione, anche l’oscillatore si ferma). ======= return fmosc (a4, pwlv(0.0, 0.7, step-to-hz(a4))) Esempio più interessante: la funzione modulante è una rampa da 0 Hz a A4 (440 Hz). La pwlv (piece-wise linear function) si comporta così: 1. Primo breakpoint a (0.0, 0.0); 2. Secondo e terzo parametro (0.7 e step-to-hz(a4), rispettivamente) sono tempo e valore del secondo e ultimo breakpoint; Fa uno sweep (rapido cambiamento) di frequenza di un’ottava; pwlv passa da 0 a 440 Hz, quando viene aggiunta alla frequenza fondamentale di 440 Hz, quindi finisce per raddoppiare la frequenza (sweep di un’ottava). step-to-hz traduce una nota in hertz (a4 —> 440 Hz) ======= La stessa idea si può applicare a un’onda portante non sinusoidale, memorizzata in una tabella. La funzione list(s, 0, nil) converte il suono s in una tabella (i campioni di una forma d’onda), restituita dalla funzione list. Ricordando che fmosc() ha 4 parametri, fmosc (pitch modulator table phase) usiamo ora gli altri due, la tabella a cui si applica l’oscillazione (pitch più modulator). Quindi, return fmosc (c0, pwl(1.0), list(s, 0, nil), 0.0) modula il segnale s secondo il pitch minimo c0 (un do a circa 16 Hz), senza alcuna ulteriore modulazione; la lettura della tabella di s avverrà due volte in senso proporzionale (come se fosse 2 elevato al numero di ottava). return fmosc (cs0, pwlv(0.0, 1.0, step-to-hz(cs0)), list(s, 0, nil), 0.0) In questo caso invece, la modulazione (cioè la lettura della tabella aumenta fino alla velocità di un’ottava superiore a quella di partenza (cs è do#). ======= L’oscillazione di una tabella, un elenco di numeri che fungono da singolo periodo, si realizza con la funzione osc() osc(pitch [, duration, table, phase ]) osc() restituisce un suono che è la tabella table (se assente, una sinusoide), oscillata alla nota pitch (esempio, c4) per una certa durata duration (se assente, 1 secondo), partendo con una certa fase phase (se assente, 0 gradi). Quindi, solo pitch è il parametro necessario. lfo(freq [, duration, table, phase ]) Come osc() sopra, ma la frequenza freq è espressa in Hz, e non come una nota. Restituisce una tabella table oscillata a una certa frequenza freq per una certa durata duration, cominciando con una certa fase phase. Un effetto di vibrato si ottiene inserendo l’oscillazione come modulante. return fmosc (0, lfo(6.0), list(s, 0, nil), 0.0)