` DEGLI STUDI DI UDINE UNIVERSITA Facolt`a di Ingegneria Corso di Laurea Triennale in Elettronica
Tesi di Laurea
EFFETTI AUDIO SU SISTEMI A MICROPROCESSORE
Relatore: Prof. RINALDO ROBERTO
Laureando: STEFANO RONCO
Correlatore: Prof. PETRELLA ROBERTO
ANNO ACCADEMICO 2009-2010
A mia madre e mio padre Sara e Federica
Sommario In questa tesi verranno analizzati e sviluppati alcuni dei pi` u importanti e conosciuti effetti audio utilizzati per la creazione e la elaborazione di musica, voce e strumenti musicali. Lo studio verr`a sviluppato nel dominio digitale; la naturale prosecuzione di questo lavoro ci porter`a ad implementare su un microprocessore, un sistema digitale, gli effetti studiati cos`ı da poter poi anche verificare la buona riuscita o meno della ricostruzione dell’effetto desiderato. I linguaggi di programmazione utilizzati in questa tesi sono essenzialmente due: il linguaggio MATLAB per una prima fase di studio e sviluppo, il linguaggio C per la definitiva programmazione del microprocessore. Il microprocessore utilizzato appartiene alla famiglia “28x Delfino Floating-point Series”, del produttore TEXAS INSTRUMENTS. Questo processore `e pre-montato su una scheda; il tutto fa parte di un prodotto definito come TMDXDOCK28343 experiment kit. Non `e obbiettivo di questo studio lo sviluppo di una apparecchiatura per uso professionale ma bens`ı cercare di comprendere quale sia il modello fisico di un determinato effetto e come questo possa essere implementato in un sistema digitale quale un microprocessore.
v
vi
Sommario
Indice Sommario
v
Elenco delle figure
ix
Introduzione
xi
1 La Scheda di elaborazione 1.1 Caratteristiche tecniche . . . . . . . . . . . . . . . . . 1.2 Il processore . . . . . . . . . . . . . . . . . . . . . . . 1.3 Il sistema di sviluppo . . . . . . . . . . . . . . . . . . 1.3.1 Installazione del Code Composer Studio . . . 1.3.2 Installazione dei driver dell’emulatore . . . . . 1.3.3 Note preliminari . . . . . . . . . . . . . . . . 1.3.4 Avvio del programma Code Composer Studio 1.3.5 Esecuzione del programma . . . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
1 1 3 3 3 4 4 4 5
2 Filtri Digitali 2.1 Filtri FIR . . . . 2.2 Filtri IIR . . . . . 2.3 Filtri Parametrici 2.4 Filtri a Pettine .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
11 11 13 14 15
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
3 Effetti Audio 17 3.1 Il buffer circolare . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.2 Motivazione delle scelte . . . . . . . . . . . . . . . . . . . . . . . 18 4 Ritardo temporale 4.1 Delay . . . . . . . 4.1.1 Parametri 4.2 Slapback Eco . . 4.2.1 Parametri 4.3 Multi-tap Eco . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . vii
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
21 21 25 26 26 29
viii
INDICE 4.3.1
Parametri . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5 Modulazione della linea temporale 5.1 Chorus . . . . . . . . . . . . . . . 5.1.1 Parametri . . . . . . . . . 5.2 Flanger . . . . . . . . . . . . . . 5.2.1 Parametri . . . . . . . . . 5.3 Vibrato . . . . . . . . . . . . . . 5.3.1 Parametri . . . . . . . . . 5.4 Pitch Shifter . . . . . . . . . . . . 5.4.1 Parametri . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
33 33 36 39 41 43 44 46 48
6 Riverbero digitale 51 6.1 Parametri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 7 Variazione di Ampiezza 7.1 Distorsione . . . . . . 7.1.1 Parametri . . . 7.2 Tremolo . . . . . . . . 7.2.1 Parametri . . . 8 Processi sulla dinamica 8.1 Compressione . . . . . 8.1.1 Parametri . . . 8.2 Soppressore di rumore 8.2.1 Parametri . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
59 59 61 62 63
. . . .
65 65 69 71 73
Conclusioni
75
A Codice C per la programmazione del DSP
77
Bibliografia
89
Elenco delle figure 1.1 Diagramma Blocchi Funzionali 1.2 Simulazione . . . . . . . . . . 1.3 Menu Breakpoints. . . . . . . 1.4 Il Sistema di Sviluppo . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
2 5 6 7
2.1 2.2 2.3 2.4
Struttura di un filtro FIR . . . . . . . . . . . Struttura di un filtro IIR . . . . . . . . . . . . Risposta in frequenza di un filtro parametrico Risposta in frequenza di un filtro a pettine . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
12 13 14 15
3.1
Struttura del buffer Circolare . . . . . . . . . . . . . . . . . . . 18
4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10
Struttura fisica del Delay . . . . . Implementazione, Delay . . . . . Filtro nel tempo, Delay . . . . . . Filtro in frequenza, Delay . . . . Implementazione, Slapback Eco . Filtro nel tempo, Slapback Eco . Filtro in frequenza, Slapback Eco Implementazione, Multi-tap Eco . Filtro nel tempo, Multi-tap Eco . Filtro in frequenza, Multi-tap Eco
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
21 22 23 23 26 27 27 29 30 30
5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9
Implementazione, Chorus . . Filtro in frequenza, Chorus . Coefficienti, Chorus . . . . . Parametri ritardo, Chorus . Implementazione, Flanger . Filtro in frequenza, Flanger Coefficiente, Flanger . . . . Implementazione, Vibrato . Coefficiente, Vibrato . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
34 34 35 36 39 40 40 43 44
. . . . . . . . . ix
. . . .
. . . . . . . . .
. . . .
. . . . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
x
ELENCO DELLE FIGURE 5.10 Implementazione, Pitch Shifter . . . . . . . . . . . . . . . . . . 46 5.11 Coefficiente, Pitch Shifter . . . . . . . . . . . . . . . . . . . . . 47 5.12 Filtro Passa-basso, Pitch Shifter . . . . . . . . . . . . . . . . . . 47 6.1 6.2 6.3 6.4
Risposta Impulsiva, Riverbero Implementazione, Riverbero . Filtro FIR, Riverbero . . . . . Cella IIR, Riverbero . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
51 52 53 54
7.1 7.2 7.3 7.4
Implementazione, Distorsione Segnali nel tempo, Distorsione Implementazione, Tremolo . . Coefficiente, Tremolo . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
59 60 62 63
8.1 8.2 8.3 8.4 8.5 8.6
Implementazione, Compressore Comportamento, Compressore . Segnale di Uscita, Compressore Implementazione, Soppressore . Comportamento, Soppressore . Segnale nel tempo, Soppressore
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
66 67 68 71 72 72
A.1 Struttura del Programma
. . . . . . . . . . . . . . . . . . . . . 77
Introduzione Gli effetti musicali trovano la loro applicazione pratica sin dagli inizi degli anni ’60 con la comparsa sulla scena mondiale dei primi strumenti musicali elettrici e la nascita dei pi` u famosi gruppi rock. In quegli anni infatti gli artisti iniziarono a sperimentare ed utilizzare dispositivi capaci di alterare le normali procedure di registrazione e di riproduzione del flusso audio. I primi a sfruttare i risultati di queste sperimentazioni furono i Rolling Stone, Jimmy Page, Jeff Beck, Jimi Hendrix, per citarne alcuni; nei loro brani degli anni ’60 `e gi`a possibile infatti ascoltare i primi effetti di distorsione, vibrato, tremolo e wah wah. Con il passare degli anni se ne sono sviluppati e perfezionati altri come il flanger, il phaser, il chorus e il delay; potevano essere creati live dagli artisti durante gli spettacoli o aggiunti in fase di registrazione dai tecnici del suono; la loro creazione era comunque sempre un processo che prevedeva l’alterazione fisica del supporto di registrazione o l’alterazione dei dispositivi di lettura di tale supporto. Ad esempio il delay consiste nella riproduzione di due tracce audio uguali su due linee temporali diverse; il flanger `e lo spostamento continuo sul nastro magnetico della testina di lettura. Gi`a agli inizi degli anni ’70 vennero sviluppati i primi sistemi digitali per la registrazione di tracce audio, ancora sperimentali, ma che si dimostrarono subito particolarmente interessanti per le possibilit`a di sviluppo in campo musicale. Fu solo nel 1978 che si registr`o la prima canzone in digitale, una cover dei Rose Royce cantata dai MorrisseyMullen. Questo sistema di registrazione digitale necessitava di nuovi supporti di memorizzazione e l’anno dopo, frutto di una collaborazione tra Philips e Sony, nasce il primo Compact-Disk. Nel 1982 fu messo in commercio il primo compact-disk musicale, “The visitors”, un successo degli Abba. I dispositivi analogici, quali dischi in vinile e audio-cassette, continuarono per`o a svolgere il loro compito fino alla fine del secolo quando vennero definitivamente soppiantati. Dal ’78 ad oggi la tecnologia digitale si `e sviluppata con un trend esponenziale che l’ha portata ad invadere il mercato a discapito dei sistemi analogici. Questo non riguarda solamente il settore musicale, si pensi ad esempio ai personal computer, ai telefoni cellulari e agli impianti hi-fi. Il settore musicale non poteva che seguire lo standard che si staxi
xii
Introduzione
va creando, unendo cos`ı alla qualit`a digitale le enormi potenzialit`a che questo sistema offriva soprattutto nel settore della musica che tratta gli effetti audio. Ora si pu`o affermare con certezza che la maggior parte di questi viene oggi implementata con algoritmi al computer o con dispositivi dedicati (DSP). Le differenze tra le due metodologie sono evidenti e riguardano essenzialmente il flusso audio in ingresso e la catena di elaborazione del segnale. Nei sistemi analogici, il flusso audio `e, a meno di amplificazioni, esattamente quello che viene generato da un microfono, i processi mediante i quali il segnale viene alterato sono di natura analogica, prodotti da amplificatori valvolari prima e amplificatori operazionali o transistor dopo. Per i dispositivi digitali invece il flusso audio viene filtrato e campionato prima di essere elaborato da un processore ed al termine dell’elaborazione viene interpolato per renderlo nuovamente analogico, tale tipologia di segnale `e richiesta dai dispositivi di diffusione. La possibilit`a di scegliere tra due tecnologie porta con s`e intrinsecamente l’obbligo di una valutazione delle caratteristiche favorevoli o meno di ogni tecnica. Se l’introduzione di campionatori ed interpolatori pu`o generare nel segnale del rumore indesiderato, l’utilizzo di un solo componente programmabile per la produzione di effetti, ne permette la simultanea presenza senza doverne aumentare le dimensioni ed i costi. L’utilizzo della tecnologia analogica presenta un vantaggio in termini di qualit`a del suono ed alta fedelt`a a discapito per`o dei costi e delle dimensioni dei dispositivi. Valutando opportunamente tutti i parametri sar`a cura del progettista operare una scelta verso la metodologia che pi` u si adatta alle richieste dell’utilizzatore.
Come anticipato nel sommario, in questo progetto si `e deciso di utilizzare un sistema digitale per la creazione di un dispositivo capace di generare un insieme di effetti digitali utili per un uso domestico dello stesso anche se le prestazioni del supporto permetterebbero di ottenere una qualit`a superiore. L’accuratezza del convertitore analogico-digitale a 12 bit permette infatti di ottenere una buona qualit`a e la velocit`a di elaborazione ci consentirebbe il campionamento ad una frequenza di 44100 Hz, standard utilizzato dai Compact-disk audio comunemente in commercio. Si `e per`o deciso di utilizzare una frequenza inferiore, 22050 Hz, per evitare alcuni problemi legati alle dimensioni della memoria del dispositivo che verranno affrontati in seguito. Per semplicit`a si `e deciso di affrontare il problema su un solo canale audio; quindi questo dispositivo lavorer`a su tracce Mono e non Stereo. Nonostante questa risulti un’evidente limitazione pratica, `e interessante sapere che in futuro sar`a possibile applicare la tecnologia su tracce stereo, previa delle piccole modifiche al codice sorgente. Si `e deciso di affrontare lo studio solamente degli effetti pi` u conosciuti notando comunque che anche quelli pi` u particolari sono una semplice sovrapposizione
xiii e combinazione degli effetti base. Si possono suddividere in quattro grandi famiglie a seconda di come vengono realizzati: • Effetti generati da un ritardo temporale: delay, slapback eco, multi-tap eco. • Effetti generati dalla modulazione della linea temporale: chorus, flanger, vibrato, pitch shifter. • Effetti generati dalla variazione dell’ampiezza: distorsione, tremolo. • Effetti generati da processi sulla dinamica: soppressore di rumore, limitatore, compressore. La struttura di questa tesi prevede un primo capitolo, dove viene presentata la scheda utilizzata e il sistema di sviluppo, una piccola guida pratica per avvicinarsi al suo utilizzo; un secondo capitolo in cui sono spiegati i concetti alla base del funzionamento di principio di alcuni filtri digitali utilizzati. Nel terzo capitolo si effettua una introduzione dei vari effetti con approfondimenti sulle strutture utilizzate e un paragrafo che contiene le motivazioni delle scelte effettuate per le implementazioni. Nel successivo capitolo si concentrano tutti gli studi fatti sugli effetti creati con la struttura delay; per ognuno di essi si pu`o trovare una breve introduzione dove si cerca di capire anche il processo fisico che ne sta alla base, i grafici esplicativi e le strutture implementative seguite dal codice Matlab con cui `e stato simulato all’elaboratore. Nel quinto capitolo verranno invece affrontati gli effetti generati dalla modulazione della linea temporale; il sesto `e interamente dedicato allo studio del riverbero. Nel settimo affronteremo gli effetti legati alla variazione di ampiezza del segnale. L’ultimo dar`a una breve spiegazione delle strutture che attuano processi legati alla dinamica del segnale. A seguire vi sar`a un appendice nella quale `e riportato parte del codice necessario per la programmazione della scheda Texas.
xiv
Introduzione
Capitolo 1 La Scheda di elaborazione La scheda utilizzata per lo sviluppo di questa tesi `e la TMDXDOCK28343, un kit di sviluppo prodotto da TEXAS INSTRUMENTS che comprende due parti: la scheda, che include il processore e le periferiche di supporto ed una basetta per interfacciare la suddetta con qualunque periferica esterna, `e molto utile in fase di progettazione perch`e permette di eseguire l’operazione in modo pratico portando all’esterno comodi connettori e consente la realizzazione di piccoli circuiti negli appositi spazi in essa ricavati. La scheda risulta inoltre ideale per operazioni in virgola mobile ed `e studiata per applicazioni di controllo in tempo reale.
1.1
Caratteristiche tecniche
Le periferiche di nostro interesse integrate su questa scheda sono: • 6 canali DMA • 3 CPU-Timer da 32 bit • Fino a 9 moduli ePWM • Convertitore Analogico-Digitale (ADC) da 12 bit • Fino a 3 moduli di interfaccia per comunicazioni seriali • Fino a 2 moduli per l’interfaccia seriale delle periferiche • Ingressi e uscite digitali • Interfaccia esterna • Fino ad 88 GPIO pins programmabili singolarmente 1
2
La Scheda di elaborazione
Figura 1.1: Diagramma Blocchi Funzionali
1.2 Il processore
1.2
3
Il processore
Il processore montato su questa scheda si basa sull’architettura del precedente c28x MCUs al quale `e stata aggiunta una FPU (floating-point unit) in singola precisione a 32 bit, il tutto con una frequenza di clock di 200 Mhz. Il risultato `e un sistema ad alte prestazioni che per la sua efficienza rende superfluo un secondo core anche per le elaborazioni pi` u complesse. A questo poi si aggiunge un veloce sistema di risposta agli interupt che permette il salvataggio dei registri e la gestione di molti interupt asincroni con tempi di latenza davvero molto brevi. Lo strumento della pipeline a 8 livelli di profondit`a, con la possibilit`a di accesso alla memoria di pipeline, conferisce al dispositivo una gran velocit`a senza richiedere dispendio di risorse ed elevata velocit`a alle memorie.
1.3
Il sistema di sviluppo
La scheda utilizzata viene accompagnata da un software di sviluppo chiamato Code Composer Studio. E’ un programma sviluppato dalla casa produttrice, la Texas Instruments, quindi un programma studiato appositamente per i sistemi Texas. Nella programmazione il linguaggio utilizzato `e il C, un linguaggio ad alto livello che verr`a opportunamente convertito dal software di sviluppo nel linguaggio macchina della scheda di elaborazione. Per completare la programmazione della scheda `e necessario l’utilizzo di un emulatore. L’emulatore `e un dispositivo che permette di connettere la scheda di elaborazione al Pc, `e dotato di una porta usb adatta alla connessione al Pc ed una porta con un connettore a pettine adatta al DSP.
1.3.1
Installazione del Code Composer Studio
La suite di sviluppo viene installata aprendo il file setup.exe, a cui seguono le richieste di dove e di quali componenti installare. E’ consigliabile seguire le impostazioni tipiche. Al termine dell’installazione verr`a eseguito il programma Code Composer Studio Setup. All’avvio sar`a necessario selezionare il dispositivo che si `e deciso di utilizzare. E’ per`o possibile che non sia presente nella lista; per ovviare a questo problema bisogner`a in primo luogo aggiornare il CCS3, ed in seguito installare il software contenuto nel cd allegato all’emulatore. In questa tesi `e stato scelto il sistema C28343 con emulatore BlackHawk: selezioneremo quindi la voce Blackhawk USB2000 - C28343 Controller. Al termine di questa procedura verr`a chiuso il programma e verr`a avviato il Code Composer Studio.
4
1.3.2
La Scheda di elaborazione
Installazione dei driver dell’emulatore
Per la programmazione e la simulazione su Pc della scheda `e necessario utilizzare un emulatore. Come tutte le periferiche, anche questa va opportunamente installata sul pc attraverso il cd allegato. Il dispositivo a disposizione per questo progetto `e il Blackhawk USB2000. E’ importante installare correttamente questo software perch`e altrimenti il CCS3 non sar`a in grado di trovare i file necessari all’avvio del sistema per il DSP in nostro possesso.
1.3.3
Note preliminari
Trattandosi di un micro-controllore il programmatore dovr`a andare a definire tutti i parametri delle periferiche interne, dalla frequenza di clock all’uso o meno dei vari convertitori, quindi inizializzare tutti i registri di sistema. Queste operazioni risultano estremamente complesse per una persona che si avvicina per la prima volta al mondo dei DSP. Per questo motivo Texas mette a disposizione dell’utilizzatore un software chiamato Baseline Software che, una volta installato, copia sull’hard disk nella cartella “TIF28xxxSysSW” un programma esempio dal quale partire per sviluppare i propri progetti. Quest’ultimo programma la scheda in modo che una volta avviato il programma questa faccia lampeggiare il LED integrato. Il lavoro forse pi` u complesso, quello di inizializzare tutto il sistema, viene quindi gi`a svolto dal programma creato da Texas. Ogni utilizzatore pu`o poi modificarlo per renderlo pi` u coerente alle proprie necessit`a, ma, per compiere i primi passi nel mondo dei DSP, `e una configurazione base che risulta sufficiente.
1.3.4
Avvio del programma Code Composer Studio
All’avvio il programma presenta sulla sinistra una finestra che mostra i file contenuti nella cartella di lavoro, il resto dello schermo rester`a vuoto in quanto non `e stato ancora aperto nessun progetto. Dal menu “project” selezioniamo “open” e apriamo il progetto “FlashingLeds”. Il programma vero e proprio di lampeggiamento `e contenuto nella cartella “source” alla voce “FlashingLed-main.c”. Ora l’utente ha a disposizione un programma funzionate da modificare per far compiere al DSP i processi che desidera. Questo procedimento operativo `e stato seguito anche per lo sviluppo del progetto trattato in questa tesi.
1.3 Il sistema di sviluppo
1.3.5
5
Esecuzione del programma
Per eseguire un programma si collega l’emulatore al pc quindi quest’ultimo alla scheda; dal menu “debug” selezioniamo “connect” e la scheda verr`a connessa al pc. Una volta generato il programma in linguaggio C dal menu “project” si seleziona la voce “build”, il software generer`a il file in formato .out per il DSP. Il comando “re-build all” `e disponibile anche in formato icona nella “project toolbar”, assieme a questa troviamo l’icona “incremental build” che realizza un processo pi` u rapido andando a riscrivere solamente le parti di codice che sono state modificate dall’ultimo build. Dal menu “file” selezioniamo la voce “load program”, il programma viene trasferito alla scheda; infine si seleziona dal menu “debug” la voce “run” ed il nostro programma verr`a eseguito dalla scheda.
Connect.
Load.
Build.
Run. Figura 1.2: Simulazione
6 1.3.5.1
La Scheda di elaborazione L’uso dei breakpoint
Durante la simulazione di un programma uno degli strumenti pi` u utili per verificare il funzionamento del software `e il breakpoint. Il Code composer studio permette di inserire breakpoint nel codice semplicemente cliccando sulla colonna grigia alla sinistra del codice. Il breakpoint verr`a aggiunto nel menu dei breakpoint e sar`a possibile selezionare la varie azioni da intraprendere. E’ infatti possibile, oltre al semplice blocco del programma implementare delle funzioni quali ad esempio leggere o scrivere dati su file. Queste funzionalit`a si sono rivelate, nel nostro progetto, Figura 1.3: Menu Breakpoints. molto utili perch`e hanno permesso di simulare un flusso audio che era stato precedentemente salvato in formato testo senza dover realizzare fisicamente un circuito di condizionamento del segnale ed utilizzare un dispositivo di riproduzione audio, viceversa la riproduzione del segnale elaborato dalla scheda non ha richiesto hardware esterno come amplificatori e diffusori. La procedura `e la seguente: una volta inserito il breakpoint si apra la “property window”. Alla voce “action” si selezioni “read data from file”, alla voce “file” va inserito il percorso dove il file risulta salvato infine il campo “start address” va completato con il simbolo &, seguito dal nome della variabile che si vuole aggiornare con il contenuto del file. E’ molto importante che il file sia in formato .dat e la prima riga del file deve contenere una particolare stringa di valori formata da: un numero standard, un numero di formato, un indirizzo di partenza, un numero di pagina ed una lunghezza. Il numero standard `e 1651; il numero di formato `e un numero da 1 a 4 che rappresenta esadecimali, integer, long, o float; l’indirizzo di partenza del blocco fornisce le informazione a riguardo del salvataggio del blocco; il numero di pagina rappresenta la pagina dal quale il blocco `e stato estratto; la lunghezza `e la dimensione del blocco. Una possibile stringa di valori `e “1651 2 c00e 1 1”.
1.3 Il sistema di sviluppo 1.3.5.2
7
Visualizzazione delle variabili
Risulta molto pratico in fase di simulazione controllare costantemente il valore delle variabili del programma, il Code composer studio permette di visualizzarne il contenuto in tempo reale. Per fare ci`o `e sufficiente selezionare dal menu “View” la voce “Watch window”. Si aprir`a quindi una finestra vuota, in essa si selezioner`a la scheda “Watch 1”, da qui `e possibile, semplicemente scrivendo il nome della variabile, visualizzare il valore aggiornato in tempo reale del contenuto stesso. E’ ora possibile ora inserire tutte le variabili di nostro interesse. 1.3.5.3
Salvataggio del Workspace
Durante lo sviluppo del progetto `e necessario simularne delle parti, inserire dei breakpoint, mostrare il contenuto di alcune variabili o altro. Per fare ci`o `e necessario configurare tutti questi parametri, quindi aprire finestre di visualizzazione e tali settaggi vengono persi alla chiusura del Code Composer Studio. Per evitare ad ogni riavvio di dover riconfigurare tutto, il software permette di salvare il proprio workspace, cio`e tutti i file aperti, i breakpoint inseriti, le variabili visualizzate e tutto ci`o che `e stato configurato all’ultimo utilizzo. Per effettuare questo `e sufficiente dal menu “file” selezionare la voce “Workspace” e successivamente “save workspace” oppure “load workspace”.
Figura 1.4: Il Sistema di Sviluppo
8 1.3.5.4
La Scheda di elaborazione Organizzazione della memoria
Il programma di prova visto in precedenza organizza la memoria in due pagine, la pagina uno dedicata al programma mentre la pagina due dedicata ai dati. Le pagine vengono poi ulteriormente divise in blocchi di lunghezza variabile. La pagina dei dati invece ha blocchi di dimensione fissata pari a 2000 byte ciascuno. Per i nostri scopi questa `e una grande limitazione, vogliamo infatti creare variabili di buffer della lunghezza di almeno 22050 campioni. Per risolvere il problema `e sufficiente modificare il file “C28345-RAM-FlashingLeds.CMD”, che `e il file in cui il programmatore gestisce la memoria, pi` u precisamente la parte relativa alla pagina due. Il codice modificato `e quello mostrato di seguito, si noti che si `e preferito non cancellare la versione precedente del file ma di trasformare il vecchio codice in commento ed aggiungere il nuovo codice a seguire. I commenti, le parti di codice compreso tra i simboli /* e */ non vengono eseguiti dall’elaboratore. MEMORY { ... PAGE 1 : RAMM1 : origin = 0x000400, /* on-chip RAM block M1 */ /* RAML1 : origin = 0x00a000, RAML2 : origin = 0x00C000, RAML3 : origin = 0x00E000, RAML4 : origin = 0x010000, RAML5 : origin = 0x012000, RAML6 : origin = 0x014000, RAML7 : origin = 0x016000, RAMBUFFER : origin = 0x00a000, ZONE7B : origin = 0x20FC00, /* XINTF zone 7 - data space */ RAMHBUFFER : origin = 0x300000, RAMH3 : origin = 0x318000, RAMH4 : origin = 0x320000, RAMH5 : origin = 0x328000, }
length = 0x000400 length length length length length length length length length
= = = = = = = = =
0x002000 0x002000 0x002000 0x002000 0x002000 0x002000 0x002000 */ 0x00e000 0x000400
length length length length
= = = =
0x010000 0x008000 0x008000 0x008000
1.3 Il sistema di sviluppo
9
Una volta definita la composizione della memoria, sempre nello stesso file “C28345-RAM-FlashingLeds.CMD” vengono definite le allocazioni delle varie sezioni del codice. Imposteremo quindi che le variabili “buffer” siano allocate nella pagina 1 nelle sezioni create in precedenza “RAMBUFFER” e RAMHBUFFER” come mostra il listato seguente. SECTIONS { /* Setup for "boot to SARAM" mode: The codestart section (found in DSP28_CodeStartBranch.asm) re-directs execution to the start of user code. */ codestart : > BEGIN, PAGE = 0 ramfuncs : > RAML0, PAGE = 0 .text : > RAML0, PAGE = 0 .cinit : > RAML0, PAGE = 0 .pinit : > RAML0, PAGE = 0 .switch : > RAML0, PAGE = 0 .stack .ebss .ebss:buffer .ebss:hbuffer .econst .esysmem
: : : : : :
> > > > > >
RAMM1, PAGE RAML0, PAGE RAMBUFFER, PAGE RAMHBUFFER,PAGE RAML0, PAGE RAMM1, PAGE
= = = = = =
1 0 1 1 0 1
... } Per indirizzare le variabili create nel codice sorgente del programma non sar`a sufficiente dichiarare solamente il tipo ed il nome del vettore ma sar`a necessario l’utilizzo del comando PRAGMA per dichiarare la creazione della variabile e la sua allocazione nella zona di memoria desiderata. Questa sintassi `e mostrata nel codice sorgente riportato di seguito. #pragma DATA_SECTION(buffer , ".ebss:buffer") int buffer[28000]; //` e lungo e000 #pragma DATA_SECTION(h1buffer , ".ebss:hbuffer") int h1buffer[28000]; #pragma DATA_SECTION(h2buffer , ".ebss:hbuffer") int h2buffer[28000];
10 1.3.5.5
La Scheda di elaborazione Combinazioni di tasti rapide
Una volta presa confidenza con il software per velocizzare la creazione di un progetto diventa naturale l’utilizzo di scorciatoie da tastiera, combinazioni di tasti rapide, senza dover cercare le voci nei menu. Di seguito vengono elencate alcune delle funzionalit`a pi` u utilizzate: alt-C Connette il pc alla scheda; ctr-L Apre una finestra nella quale selezionare il programma da caricare nella scheda; ctr-shift-L Carica nella scheda il programma caricato in precedenza con le eventuali modifiche apportate; F5 Avvia la simulazione del programma; shift-F5 Blocca l’esecuzione del programma; ctr-M Visualizza il file Main, utile quando sono aperte pi` u funzioni; ctr-R Effettua un reset della scheda; F11 Permette l’esecuzione di una singola istruzione C, `e una esecuzione passo passo; F10 Esegue interi cicli di codice; shift-F11 All’interno di un ciclo permette di finire l’esecuzione del ciclo e fermarsi al termine di questo;
Capitolo 2 Filtri Digitali La maggior parte degli effetti musicali viene generata, partendo dal flusso audio originale, semplicemente interponendo tra l’ingresso e l’uscita un opportuno filtro. Un semplice esempio pu`o essere un equalizzatore, al suo interno ne contiene diversi che amplificano in modo opportuno determinate frequenze. I filtri qui utilizzati saranno di tipo digitale, dovendo essere elaborati da un processore, e come per i filtri analogici anche quelli digitali vengono classificati in quattro gruppi: passa-basso, passa-alto, passa-banda ed elimina-banda. La modalit`a di progettazione genera due tipologie distinte di filtri: i filtri FIR e quelli IIR. Dall’utilizzo combinato di questi si pu`o ottenere tutta la gamma di filtri analogici come i filtri parametrici, e i filtri a pettine.
2.1
Filtri FIR
Il termine FIR `e l’acronimo di Finite Impulse Response che appunto significa risposta impulsiva di durata finita. Dal nome stesso del filtro si pu`o capire che il valore in uscita sar`a una combinazione lineare di un numero finito di valori precedenti. Definendo x il valore in ingresso, h un opportuno coefficiente e y il valore del segnale in uscita; matematicamente possiamo esprimere questo concetto come segue: y(n) =
K X
hi x(n − i)
i=0
e anche graficamente come mostra Figura 2.1.
11
(2.1.1)
12
Filtri Digitali
Figura 2.1: Struttura di un filtro FIR
2.2 Filtri IIR
2.2
13
Filtri IIR
L’acronimo IIR sta per Infinite Impulse Response, cio`e risposta impulsiva di durata infinita. Questo significa che il segnale processato dal filtro sar`a una combinazione degli infiniti istanti precedente, ovviamente non ha un significato letterale infatti risulta palese che un sistema non possa avere infiniti campioni ma tale espressione `e da interpretare nel senso che l’ultimo campione in uscita dal filtro `e formato in parte anche dal contributo dato dal primo. Ci`o `e possibile in quanto assieme al segnale di ingresso viene elaborata una certa percentuale del segnale di uscita precedente. Dal punto di vista matematico risulta: y(n) =
M X i=1
−ai y(n − i) +
L X
bj x(n − j)
j=0
Graficamente si pu`o esprimere come in Figura 2.2.
Figura 2.2: Struttura di un filtro IIR
(2.2.1)
14
2.3
Filtri Digitali
Filtri Parametrici
I filtri parametrici sono molto utilizzati nella industria del suono perch`e hanno la capacit`a di amplificare o attenuare particolarmente specifiche frequenze che compongono il segnale. I parametri di progetto sono la larghezza di banda, il centro di banda, ed il guadagno; da questi, utilizzando delle semplici formule si ricavano i quattro coefficienti necessari alla realizzazione del filtro. Sono filtri che hanno una risposta in frequenza che `e per lo pi` u piatta e di valore unitario sull’intero spettro di interesse mentre amplificano o attenuano molto in un intorno ristretto di ω0 , come si pu`o osservare dalla Figura 2.3. Sono quindi dei Notch-filter oppure dei Peak-filter a seconda di come vengono impostati i poli e gli zeri della funzione di trasferimento. Esprimendo in termini matematici il valore dell’uscita risulta: y(n) = b0 x(n) + b1 x(n − 1) + b2 x(n − 2) + a1 y(n − 1) + a2 y(n − 2) (2.3.1)
Figura 2.3: Risposta in frequenza di un filtro parametrico
2.4 Filtri a Pettine
2.4
15
Filtri a Pettine
I filtri a pettine, pi` u comunemente conosciuti con la loro traduzione inglese comb-filter, vengono utilizzati per ridurre il disturbo dovuto a segnali periodici e sono impiegati nella generazione di effetti musicali quali l’eco, il chorus, il flanger e il riverbero. Il loro funzionamento `e molto semplice: al segnale originale viene sommato il segnale ritardato ed attenuato: Questo processo altera l’ampiezza del segnale in maniera non costante sullo spettro del segnale. Orfanidis [1] nel suo studio, ha dimostrato che tale filtro pu`o essere derivato sia attraverso l’utilizzo della struttura FIR sia attraverso quella IIR. Matematicamente i concetti formulati da Orfanidis si possono esprimere cos`ı: 1 + z −D 1 − az −D
(2.4.1)
1 1 − z −N D N 1 − z −D
(2.4.2)
HIIR = b HF IR =
Come dice il nome stesso la risposta in frequenza di questo filtro ha una caratteristica forma a pettine come si pu`o notare in Figura 2.4.
Figura 2.4: Risposta in frequenza di un filtro a pettine
16
Filtri Digitali
Capitolo 3 Effetti Audio I vari effetti che si possono ricreare vengono suddivisi in effetti audio di ritardo temporale, effetti digitali basati sulla modulazione della linea temporale ed effetti audio basati sulle variazioni del valore di ampiezza. Per la realizzazione dei primi e dei secondi `e necessario introdurre il concetto di linea temporale. In elettronica digitale un flusso audio `e una sequenza di campioni equispaziati nel tempo di un valore T sample (equivalente a 1/F sample ). Tutti i campioni rispecchiano quindi un valore di ampiezza del segnale in ingresso in un determinato istante. La linea temporale `e quindi un susseguirsi ordinato di questi, una riproduzione non ordinata dei campioni produce alcuni degli effetti pi` u interessanti nel settore della manipolazione del suono. Gli effetti che sfruttano le modificazioni della linea temporale dovranno quindi necessariamente avere a disposizione intere porzioni del segnale e non solamente un singolo campione; per questo motivo `e necessario dedicare parte di memoria all’immagazzinamento dei dati. Questo settore di memoria viene chiamato buffer ed organizzato secondo lo schema del buffer circolare.
3.1
Il buffer circolare
La sua importanza, la semplicit`a di utilizzo e realizzazione rendono questo strumento fondamentale per l’implementazione digitale di effetti audio. Il buffer `e un dispositivo in grado di immagazzinare informazioni; si pu`o immaginare in termini matematici come un vettore dotato di lunghezza finita. Supponendo di voler immagazzinare dati all’interno del vettore, ogni dato che viene ricevuto `e salvato nella prima posizione. Per fare ci`o il codice avrebbe dovuto preventivamente traslare il dato che precedentemente occupava la prima posizione nella seconda, il secondo nella terza il terzo nella quarta e cos`ı via. Questo procedimento avrebbe un costo computazionale notevole; pensando infatti che 17
18
Effetti Audio
il buffer sia formato da 28000 campioni, significa che ad ogni nuovo dato in ingresso il processore dovr`a compiere 28000 trasferimenti. Per ovviare a questo problema si `e sviluppato il concetto di buffer circolare: anzich`e traslare tutti i dati, ed inserire quello in ingresso nella prima posizione, viene considerato variabile l’indice del vettore ed incrementato ad ogni nuovo dato. In tal modo i dati vengono lasciati fissi nelle loro posizioni e sostituiti di volta in volta che l’indice punta la locazione ed un nuovo dato `e presente all’ingresso. Quando poi l’indice raggiunge il fondo del vettore basta semplicemente riportarlo alla prima posizione e ricominciare il ciclo. In questo modo `e possibile muoversi con semplicit`a all’interno della linea temporale variando solamente l’indice del buffer.
Figura 3.1: Struttura del buffer Circolare
3.2
Motivazione delle scelte
Per lo sviluppo di questo progetto `e stato utilizzato il software di calcolo Matlab, una `e stata una scelta obbligata data dalla facilit`a nel suo utilizzo e la sua velocit`a di simulazione. Si `e deciso quindi di creare un codice per ogni effetto e poi una volta testata la funzionalit`a si `e convertito il codice in linguaggio C per l’elaboratore finale, il DSP. Per semplicit`a di simulazione in Matlab si `e scelto di non creare un sistema in grado di leggere un campione per volta ma si `e preferito lavorare offline. Questa metodologia richiede quindi di inserire sotto forma di vettore l’intero flusso audio da elaborare; le modifiche da apportare per rendere il codice utilizzabile online sono minime. Per le simulazioni con Matlab non sar`a necessario l’uso del buffer circolare. Le funzioni realizzate nel seguito prevedono, dove possibile, l’utilizzo di algoritmi gi`a implementati nel
3.2 Motivazione delle scelte
19
software Matlab, quali ad esempio le funzioni filter e freqz che hanno, per`o, la particolarit`a di ricevere in ingresso i vettori contenenti i coefficienti del filtro ed il segnale da filtrare. Risultano molto utili per quel settore di effetti che ha filtri costanti perch`e ne rendono il codice pi` u snello e di facile lettura. In questa categoria rientra la famiglia degli effetti a ritardo temporale. E’ necessario precisare che tali funzioni nella traduzione al linguaggio C per il DSP sono state sostituite dalla implementazione matematica che le compone. Sono invece totalmente inefficaci nel settore della modulazione della linea temporale dove le funzioni filter e freqz non sono state utilizzate; si `e deciso di realizzarle esplicitamente applicando la relazione matematica che ogni effetto comporta ed utilizzando un ciclo che processa tutto il segnale. Proprio per questo motivo si evidenzia la necessit`a di dover lavorare offline. Un problema che `e stato necessario affrontare riguarda la capacit`a di memoria del DSP. La memoria viene suddivisa di default in sezioni di dimensioni relativamente ridotte per gli usi che ne faremo. La suddivisione della memoria impedisce infatti di creare lunghi vettori in quanto alla dichiarazione del vettore segue un allocamento contiguo di memoria. E’ stato necessario riprogrammare queste sezioni al fine di accorparne alcune e creare due gruppi di lunghezza e000 e 10000 espressi in base esadecimale (57344 e 65536 in base decimale). Nonostante queste modifiche abbiano migliorato la disposizione della memoria per i nostri scopi, non `e stato possibile dedicare ulteriore memoria alle variabili del software cos`ı da costringere il programmatore a dedicare solamente 28000 valori per il buffer circolare (vedi Figura 3.1). Questa `e stata la motivazione principale che ha portato alla scelta di una frequenza di campionamento pari a 22050 Hz per ottenere un buffer di circa 1,27 secondi, necessario per la realizzazione di effetti quali ad esempio quelli appartenenti alla famiglia del ritardo temporale.
20
Effetti Audio
Capitolo 4 Ritardo temporale Questa tipologia di effetti si basa su una riproduzione di campioni presenti in ingresso e contemporaneamente di altri allocati in istanti di tempo precedenti, dove per`o la distanza temporale resta sempre costante.
4.1
Delay
L’effetto delay `e uno degli effetti pi` u semplici da realizzare, ma funge da base per la realizzazione di quelli pi` u complessi. Fisicamente il delay `e la riproposizione del segnale, in forma attenuata, dopo un certo lasso di tempo. Le onde sonore, emesse dalla sorgente raggiungono l’ascoltatore in linea sia diretta che indiretta. Le prime dalla sorgente sono ricevute direttamente dall’ascoltatore, le seconde come conseguenza di diverse riflessioni dell’onda originale nell’ambiente circostante, saranno quindi ritardate ed attenuate.
Figura 4.1: Struttura fisica del Delay
21
22
Ritardo temporale
Il ritardo `e causa della maggior distanza percorsa mentre il valore di ampiezza inferiore `e una concausa di perdite nel mezzo trasmissivo, propagazione omnidirezionale e perdite dovute alla non perfetta riflessione da parte dell’ostacolo che non pu`o essere definito uno specchio ideale con coefficiente di riflessione unitario. Si parla di delay a singola riflessione. L’implementazione matematica risulta essere quindi: y(n) = x(n) + ax(n − D)
(4.1.1)
dove y `e il segnale di uscita, x quello di ingresso, α un coefficiente di attenuazione e D il valore in numero di campioni del ritardo. Alla frequenza di lavoro, 22050 Hz, se si vogliono ottenere 0,5 secondi di ritardo, D sar`a uguale a 11025. La funzione di trasferimento `e quindi: H(z) = 1 + az −D
(4.1.2)
Figura 4.2: Implementazione, Delay
Come si vede in Figura 4.3, data la frequenza di campionamento di 22050 Hz, si `e deciso di riproporre la versione riflessa del segnale dopo 17640 campioni, ci`o significa 0,8 secondi dopo la versione originale e con una attenuazione di un fattore 10. Dalla Figura 4.4 si nota invece che in frequenza il filtro ha un comportamento sinusoidale. Questo significa che alcune frequenze vengono amplificate ed altre attenute. L’onda che si propaga viene riflessa dall’ostacolo e l’onda riflessa va a sommarsi all’onda diretta, a determinate frequenze le due onde saranno perfettamente in fase; producendo cos`ı un valore di ampiezza maggiore, ad altre le due onde si trovano in contro-fase e la loro somma sar`a quindi inferiore.
4.1 Delay
23
Figura 4.3: Filtro nel tempo, Delay
Figura 4.4: Filtro in frequenza, Delay
24
2
4
6
8
10
12
14
16
18
20
22
24
Ritardo temporale
Effetto Delay function out=delay(in) Fs=22050; %definisce la frequenza di campionamento rit del ms=900; %definisce il ritardo del delay in ms rit del=round(rit del ms∗Fs/1000); %ritardo in numero di campioni temp=zeros(rit del, 1); %genera un vettore di zeri per estendere il segnale ingresso=vertcat(in, temp); %estende il segnale b=zeros(1, Fs); %genera il vettore dei coefficienti del filtro b(rit del)=0.1; %definisce i coefficienti del filtro b(1)=1; %definisce i coefficienti del filtro figure(1) stem(b); %stampa a video il filtro title(’Risposta nel tempo del filtro’) axis([−500 Fs 0 1.1]) [H,F] = freqz(b, 1, 10∗Fs, Fs); %trova la risposta in frequenza del filtro figure(2) plot(F,abs(H)); %stampa a video il filtro title(’Risposta in frequenza del filtro’) axis([0 20 0.85 1.15]) out=filter(b, 1, ingresso); %effettua il filtraggio del segnale in ingresso soundsc (out,Fs); %riproduce il segnale d’uscita end
Il codice `e il listato della funzione Matlab che genera l’effetto delay. Al segnale di ingresso viene concatenata una stringa di zeri della lunghezza del ritardo massimo, questo procedimento `e necessario altrimenti l’elaborazione dell’ultimo campione del segnale di ingresso non verrebbe riprodotta in uscita. Il segnale elaborato con lo scopo di ottenere l’effetto eco `e necessariamente pi` u lungo del segnale di ingresso in quanto deve prevedere anche la ripetizione degli ultimi campioni. Come si pu`o notare viene generato un vettore b che contiene i coefficienti del filtro FIR che vengono successivamente passati alla funzione filter del Matlab che restituisce il vettore dei campioni uscita. L’utilizzo della funzione filter ha come unico scopo un maggior ordine ed una maggior leggibilit`a. La versione senza tale funzione `e in ogni caso semplice perch`e basterebbe semplicemente implementare la 4.1.1.
4.1 Delay
4.1.1
25
Parametri
I parametri che `e possibile gestire per generare l’effetto che pi` u soddisfa le specifiche dell’utente sono: Ritardo del delay in questo progetto si pu`o variare tra 0 e 1 secondi; Valore di ampiezza del segnale ritardato `e stato selezionato un valore pari a 0,1;
26
Ritardo temporale
4.2
Slapback Eco
Con la stessa architettura vista per l’effetto delay, Figura 4.5, modificando solamente il ritardo della versione traslata si possono ottenere varianti interessanti come ad esempio lo Slapback Eco. Quest’ultimo ha la particolarit`a di avere un ritardo estremamente breve (intorno ai 15-40 millisecondi) ed un rapporto unitario tra segnale originale e copia traslata, per evitare possibili overflow vengono quindi amplificati entrambi di un fattore 1/2. La formula risulta essere sempre: y(n) = ax(n) + ax(n − D)
(4.2.1)
Questa volta quindi con un D molto piccolo ed il coefficiente a pari a 0,5.
Figura 4.5: Implementazione, Slapback Eco
Il comportamento del filtro utilizzato si pu`o vedere in formato grafico in Figura 4.6 nella sua versione nel tempo e in Figura 4.7 nella sua versione in frequenza. Si nota la tipica forma a pettine che permette di realizzare questa tipologia di effetti.
4.2.1
Parametri
I parametri che `e possibile gestire per generare l’effetto che pi` u soddisfa le specifiche dell’utente sono: Ritardo del delay per ottenere un effetto realistico il ritardo deve essere compreso tra i 15 e i 40 millisecondi; Valore di ampiezza del segnale ritardato per un effetto migliore `e consigliabile mantenere la configurazione proposta in questa tesi con i due coefficienti uguali e pari a 0,5;
4.2 Slapback Eco
Figura 4.6: Filtro nel tempo, Slapback Eco
Figura 4.7: Filtro in frequenza, Slapback Eco
27
28
2
4
6
8
10
12
14
16
18
20
22
24
Ritardo temporale
Effetto Slapback Eco function out=slapback(in) Fs=22050; %definisce la frequenza di campionamento rit eco ms=20; %definisce il ritardo dell’eco in ms rit eco=round(rit eco ms∗Fs/1000); %ritardo in numero di campioni temp=zeros(rit eco, 1); %genera un vettore di zeri per estendere il segnale ingresso=vertcat(in, temp); %estende il segnale b=zeros(1, Fs); %genera il vettore dei coefficienti del filtro b(rit eco)=0.5; %definisce i coefficienti del filtro b(1)=0.5; %definisce i coefficienti del filtro figure(1) stem(b); %stampa a video il filtro title(’Risposta nel tempo del filtro’) axis([−500 Fs 0 1.1]) [H,F] = freqz(b, 1, 10∗Fs, Fs); %trova la risposta in frequenza del filtro figure(2) plot(F,abs(H)); %stampa a video il filtro title(’Risposta in frequenza del filtro’) axis([0 150 −0.15 1.15]) out=filter(b, 1, ingresso); %effettua il filtraggio del segnale in ingresso soundsc (out,Fs); %riproduce il segnale d’uscita end
Il codice Matlab riportato realizza la funzione dell’effetto. L’effetto Slapback, seppur molto semplice restituisce un segnale che fa si che l’impressione dell’ascoltatore sia che ad interpretare il brano siano due musicisti; da infatti maggior una profondit`a all’audio. Vedremo in seguito che esistono algoritmi pi` u raffinati per generare questo tipo di percezione. Applicando questo algoritmo ad un flusso audio che riproduce della voce in uscita avremo un suono quasi metallico.
4.3 Multi-tap Eco
4.3
29
Multi-tap Eco
Anche questo secondo effetto `e una elaborazione del delay. Per generarlo `e sufficiente implementare una sequenza di delay (eco), questo permette di ottenere un suono pi` u realistico, che ripropone pi` u versioni ritardate e attenuate del segnale originale. In questo progetto si `e implementato un tri-tap eco, sono presenti 3 riproposizioni con attenuazioni e ritardi diversi. L’implementazione matematica del filtro `e la seguente: y(n) = x(n) + a1 x(n − D) + a2 x(n − 2D) + a3 x(n − 3D)
(4.3.1)
e la funzione del filtro risulta essere: H(z) = 1 + a1 z −D + a2 z −2D + a3 z −3D
(4.3.2)
In questo progetto, a causa di una ristrettezza della memoria da dedicare ai buffer, si `e deciso di utilizzare come ritardo base D un valore di 8820 campioni che corrisponde a 400 millisecondi come si vede in Figura 4.9 . E’ decisamente troppo poco per ricreare l’effetto di un eco in alta montagna, infatti sapendo che la velocit`a del suono `e di circa 343 m/s possiamo stimare che con questo algoritmo la distanza dall’ostacolo riflettente sia solamente di 68 metri circa. Utilizzando DSP dotati di maggiore memoria, sar`a sufficiente modificare il codice sorgente e pi` u precisamente la variabile rit eco ms al valore che si desidera.
Figura 4.8: Implementazione, Multi-tap Eco
30
Ritardo temporale
Figura 4.9: Filtro nel tempo, Multi-tap Eco
Figura 4.10: Filtro in frequenza, Multi-tap Eco
4.3 Multi-tap Eco
2
4
6
8
10
12
14
16
18
20
22
24
26
31
Effetto Multi−tap Eco function out=multitap(in) Fs=22050; %definisce la frequenza di campionamento rit eco ms=400; %definisce il ritardo dell’eco in ms rit eco=round(rit eco ms∗Fs/1000); %ritardo in numero di campioni temp=zeros(3∗rit eco, 1); %genera un vettore di zeri per estendere il segnale ingresso=vertcat(in, temp); %estende il segnale b=zeros(1, Fs); %genera il vettore dei coefficienti del filtro b(rit eco)=0.1; %definisce i coefficienti del filtro b(2∗rit eco)=0.05; %definisce i coefficienti del filtro b(2∗rit eco)=0.025; %definisce i coefficienti del filtro b(1)=1; %definisce i coefficienti del filtro figure(1) stem(b); %stampa a video il filtro title(’Risposta nel tempo del filtro’) axis([−500 Fs 0 1.1]) [H,F] = freqz(b, 1, 10∗Fs, Fs); %trova la risposta in frequenza del filtro figure(2) plot(F,abs(H)); %stampa a video il filtro title(’Risposta in frequenza del filtro’) axis([0 20 0.85 1.2]) out=filter(b, 1, ingresso); %effettua il filtraggio del segnale in ingresso soundsc (out,Fs); %riproduce il segnale d’uscita end
4.3.1
Parametri
I parametri che `e possibile gestire per generare l’effetto che pi` u soddisfa le specifiche dell’utente sono: Ritardo del delay base in questo progetto non pu`o superare i 0,4 secondi, in caso di DSP con maggiore memoria `e possibile aumentarlo; Valore di ampiezza dei singoli segnali ritardati buona norma `e ricordare che la somma di tutti coefficienti non deve scostarsi troppo da 1 per evitare possibili distorsioni per overflow nel segnale di uscita;
32
Ritardo temporale
Capitolo 5 Modulazione della linea temporale Questa classe di effetti trova le sue basi nella variazione della linea temporale. Vengono riprodotti sia i campioni del segnale originale sia alcuni campioni che compongono la linea temporale, con la condizione che non `e necessario mantenere costante il ritardo D.
5.1
Chorus
Il chorus `e uno degli effetti pi` u utilizzati e pi` u interessanti perch`e il flusso audio elaborato ha una profondit`a e un corpo che lo rendono particolarmente piacevole all’ascolto. D`a l’impressione che pi` u musicisti stiano suonando lo stesso brano anche se in realt`a il musicista `e uno solo. L’implementazione `e basata sulla cella delay. I due musicisti non saranno mai perfettamente sincronizzati; si `e stimato che il ritardo massimo `e compreso circa tra i 15 e i 35 millisecondi; non solo, anche il valore dell’ampiezza del segnale non sar`a sempre lo stesso quindi anche questo valore varier`a di intensit`a nel tempo. Il flusso audio di uscita sar`a quindi la sovrapposizione del segnale originale e una versione traslata con un ritardo variabile e amplificata con un coefficiente anch’esso variabile nel tempo. Per ottenere un risultato ottimale `e necessario che il ritardo venga modulato da un oscillatore a bassa frequenza casuale (random low-frequency oscillator); per lo sviluppo di questo progetto `e stato invece scelto, per comodit`a di programmazione, di utilizzare una sinusoide a bassa frequenza.
33
34
Modulazione della linea temporale
Matematicamente possiamo esprimere questi concetti come mostrato di seguito: y(n) = a1 x(n) + a2 (n)x(n − D(n)) la cui implementazione risulta essere quella mostrata in Figura 5.1
Figura 5.1: Implementazione, Chorus
Figura 5.2: Filtro in frequenza, Chorus
(5.1.1)
5.1 Chorus
35
Nell’espressione precedente, a1 `e fissato a 0,5 per evitare possibili distorsioni dovute a overflow del segnale e a2 invece `e, come mostra Figura 5.3, un segnale sinusoidale lentamente variabile (0,3 Hz). Il termine D, che rappresenta il ritardo, `e anche un segnale sinusoidale lentamente variabile (0,1 Hz), rappresentato in Figura 5.3. a2 (n) = (1 + V ariazione)cos(2πnT sF a) D(n) =
Ritardo − massimo 2
(1 + sin(2πnT sF d))
Figura 5.3: Coefficienti, Chorus
(5.1.2) (5.1.3)
36
5.1.1
Modulazione della linea temporale
Parametri
Per l’effetto chorus i parametri che l’utente pu`o definire sono molti e si possono suddividere in parametri di ampiezza e parametri di ritardo. Una rappresentazione grafica dei parametri di ritardo `e in Figura 5.4 Valore di variazione percentuale dell’ampiezza designa quanto l’intensit`a della seconda versione del segnale si discosta dalla prima; Frequenza della sinusoide che modula la variazione di ampiezza `e un valore tipicamente inferiore ad 1 Hz, per valori superiori si profila una distorsione eccessiva del segnale che deteriore le caratteristiche stesse dell’effetto; Ritardo nominale definisce la profondit`a media del ritardo applicato, in questo progetto `e stata fissata a met`a del ritardo massimo; Frequenza della sinusoide che modula la variazione temporale coefficiente fissato attorno a qualche frazione di Hz, variazioni troppo rapide producono infatti modificazioni della frequenza del segnale originale;
Figura 5.4: Parametri ritardo, Chorus
5.1 Chorus
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
Effetto Chorus function out=chorus(in) Fs=22050; %definisce la frequenza di campionamento Ts=1/Fs; Fa=0.3; %frequenza che modula la variazione di ampiezza Fd=0.1; %frequenza che modula la variazione di ritardo rit cho ms=25; %definisce il ritardo dell’eco in ms rit cho max=round(rit cho ms∗Fs/1000); %ritardo massimo in campioni amp var max=30; %massima variazione di ampiezza percentuale temp=zeros(rit cho max, 1); %genera un vettore per estendere il segnale ingresso=vertcat(in, temp); %estende il segnale lung=length(ingresso); n=0:1:lung; s=round((rit cho max/2)∗(1+sin(2∗pi∗Ts∗Fd∗n))); p=(1+(amp var max/100)∗cos(2∗pi∗Ts∗Fa∗n)); out=zeros(lung,1); for i=1:lung %effettua il filtraggio a=i−s(i); if (a<=0); a=1; end; out(i)=0.5∗ingresso(i)+0.5∗p(i)∗ingresso(a); end; figure(1) %stampa a video i segnali subplot(2,1,1), plot(ingresso); title(’segnale ingresso’); subplot(2,1,2), plot(out); title(’segnale uscita’); figure(2) %stampa a video i coefficienti subplot(2,1,1), plot(p); title(’fattore di ampiezza’); subplot(2,1,2), plot(s); title(’coefficiente di ritardo’); soundsc (out,Fs); %riproduce il segnale d’uscita end
37
38
Modulazione della linea temporale
Come si vede dal listato Matlab per questa implementazione non `e stato possibile utilizzare la funzione filter, in quanto i coefficienti b del filtro sono variabili nel tempo. Per ovviare a ci`o si `e deciso di realizzare esplicitamente lo stesso algoritmo della funzione filter con le opportune modifiche per rendere variabili i coefficienti. Si realizza quindi un ciclo FOR che percorre tutta la lunghezza del segnale e applica la 5.1.1. Questo procedimento `e possibile solamente perch`e stiamo elaborando segnali offline, cio`e elaboriamo i dati dopo averli acquisiti completamente. Il codice che invece `e stato implementato sul DSP prevede comunque una elaborazione in real time. In appendice `e possibile trovare il listato di questo codice.
5.2 Flanger
5.2
39
Flanger
L’effetto Flanger origina da un evento fortuito; la leggenda vuole che un tecnico del suono in fase di registrazione di uno stesso brano su due nastri magnetici cercando di riprodurre un effetto di sdoppiamento si rese conto che variando la velocit`a relativa tra i due nastri si otteneva un effetto simile a quello creato dalle turbine dei jet, uno swooshing. L’implementazione di questo si basa quindi su una diversa velocit`a di riproduzione di un brano che va a sommarsi al brano riprodotto alla velocit`a corretta. La struttura `e quindi identica a quella dell’effetto chorus con la differenza che i coefficienti di amplificazione sono costanti e pari a 0,5 al fine di evitare possibili problemi di overflow e la modulazione del ritardo non avviene tramite un oscillatore casuale a bassa frequenza ma seguendo una sinusoide. Mentre per il chorus il ritardo era compreso tra i 15 e i 35 millisecondi per ottenere un buon risultato il flanger deve avere un ritardo compreso tra 0,25 e 25 millisecondi. Matematicamente: y(n) = 0, 5x(n) + 0, 5x(n − D(n))
(5.2.1)
dove D(n) `e appunto un segnale lentamente variabile. Ritardo − massimo
(1 − cos(2πnT sF d)) (5.2.2) 2 Questi concetti vengono poi implementati quindi nella forma che si pu`o trovare D(n) =
sotto.
Figura 5.5: Implementazione, Flanger Come si pu`o vedere in Figura 5.7 il valore del ritardo varia sinusoidalmente tra 0 e 221 campioni che corrispondono a 10 millisecondi. Viene maggiormente apprezzato se applicato a segnali musicali piuttosto che a segnali vocali.
40
Modulazione della linea temporale
Figura 5.6: Filtro in frequenza, Flanger
Figura 5.7: Coefficiente, Flanger
5.2 Flanger
5.2.1
41
Parametri
Per l’effetto flanger i parametri che l’utente pu`o definire sono: Ritardo nominale `e la profondit`a media del ritardo applicato, in questo progetto, `e stata fissata a met`a del ritardo massimo; Ritardo massimo `e la profondit`a massimo del ritardo applicato; Frequenza della sinusoide che modula la variazione temporale `e il coefficiente fissato attorno a qualche frazione di Hz, variazioni troppo rapide producono infatti modificazioni della frequenza del segnale originale, in questo progetto si `e deciso di imporla pari a 0,5 Hz;
42
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
Modulazione della linea temporale
Effetto Flanger function out=flanger(in) Fs=22050; %definisce la frequenza di campionamento Ts=1/Fs; Fd=0.5; %frequenza che modula la variazione di ritardo rit fla ms=20; %definisce il ritardo dell’eco in ms rit fla max=round(rit fla ms∗Fs/1000); %ritardo massimo in campioni temp=zeros(rit fla max, 1); %genera un vettore per estendere il segnale ingresso=vertcat(in, temp); %estende il segnale lung=length(ingresso); n=0:1:lung; s=round((rit fla max/2)∗(1−cos(2∗pi∗Ts∗Fd∗n))); out=zeros(lung,1); for i=1:lung a=i−s(i); if (a<=0); a=1; end; out(i)=0.5∗ingresso(i)+0.5∗ingresso(a); end figure(1) %stampa a video i segnali subplot(2,1,1), plot(ingresso); title(’segnale ingresso’); subplot(2,1,2), plot(out); title(’segnale uscita’); figure(2) %stampa a video i coefficienti plot(s); title(’coefficiente di ritardo’); soundsc (out,Fs); end
5.3 Vibrato
5.3
43
Vibrato
Il vibrato si pone come obbiettivo quello di simulare quel particolare effetto che genera un chitarrista quando muove la ’whammy bar’ oppure un violinista quando muove ciclicamente la mano sinistra sulle corde. Fisicamente `e una modificazione ciclica e ripetitiva della frequenza del segnale attorno alla frequenza originale. Il segnale avr`a quindi un susseguirsi di suoni la cui frequenza si incrementa e decrementa. Ipotizziamo per semplicit`a di voler sottoporre all’elaboratore una nota di violino, come sappiamo ogni nota ha la sua determinata frequenza che la rende distinguibile dalle altre, l’uscita sar`a un suono variabile con continuit`a e sonorit`a che diventano pi` u acute e pi` u gravi nell’intorno della nota originale. La struttura implementativa ricalca a grandi linee quella degli altri effetti che fanno parte della famiglia della modulazione del ritardo. Infatti come si pu`o vedere in Figura 5.8 `e presente un filtro che introduce un ritardo variabile, modulato da una sinusoide. A differenza per`o delle altre strutture questa non prevede la sovrapposizione di due segnali, il segnale originale viene cancellato e riprodotto solamente quello elaborato. Questi concetti vengono espressi matematicamente dalle seguenti relazioni. y(n) = x(n − D(n)) con D(n) =
Ritardo − massimo 2
(1 + sin(2πnT sF d))
(5.3.1) (5.3.2)
Figura 5.8: Implementazione, Vibrato
Nell’esempio proposto in questa tesi si `e fissato il ritardo massimo a 3 millisecondi ed una frequenza Fd di 10 Hz, come si vede in Figura 5.9 .
44
Modulazione della linea temporale
Aumentando il valore di ritardo massimo viene aumentato il range di frequenze esplorato dal segnale attorno alla frequenza portante della nota in ingresso mentre modificando la frequenza Fd varia il numero di ripetizioni cicliche che si creano.
Figura 5.9: Coefficiente, Vibrato
5.3.1
Parametri
Per l’effetto vibrato i parametri che l’utente pu`o definire sono: Profondit` a del ritardo ovvero la variazione di frequenze attorno alla frequenza di ingresso; Frequenza di ripetizione rappresenta il numero di cicli da effettuarsi in un secondo;
5.3 Vibrato
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
Effetto Vibrato function out=vibrato(in) Fs=22050; %definisce la frequenza di campionamento Ts=1/Fs; Fd=10; %frequenza che modula la variazione di ritardo rit vib ms=3; %definisce il ritardo dell’eco in ms rit vib max=round(rit vib ms∗Fs/1000); %ritardo massimo in campioni temp=zeros(rit vib max, 1); %genera un vettore per estendere il segnale ingresso=vertcat(in, temp); %estende il segnale lung=length(ingresso); n=0:1:lung; s=round((rit vib max/2)∗(1+sin(2∗pi∗Ts∗Fd∗n))); out=zeros(lung,1); for i=1:lung %effettua il filtraggio a=i−s(i); if (a<=0); a=1; end; out(i)=ingresso(a); end; figure(1) %stampa a video i segnali subplot(2,1,1), plot(ingresso); title(’segnale ingresso’); subplot(2,1,2), plot(out); title(’segnale uscita’); figure(2) %stampa a video il coefficiente plot(s); title(’coefficiente di ritardo’); axis([0 22050 0 80]) soundsc (out,Fs); %riproduce il segnale d’uscita end
45
46
Modulazione della linea temporale
5.4
Pitch Shifter
Il pitch shifter `e uno dei pi` u interessanti ed utilizzati effetti per la modificazione del timbro della sorgente. Viene realizzato in due diversi modi, utilizzando la struttura implementativa del chorus, se si vuole ottenere un segnale in uscita che `e una sovrapposizione del segnale originale e quello alterato, oppure la struttura del vibrato, che quindi riproduce in uscita solamente il segnale modificato. La differenza rispetto a queste due strutture `e il modulante del ritardo, per chorus e vibrato era infatti un segnale sinusoidale, per generare questo particolare effetto viene usata un rampa o meglio un segnale e dente di sega. Viene applicato cio`e un ritardo che varia linearmente fino ad un massimo per poi ripartire da zero come si vede in Figura 5.11. Modificare il timbro della sorgente restituisce, applicato alla voce, un flusso audio nel quale `e possibile di distinguere chiaramente il contenuto ma la voce risulta irriconoscibile. Viene comunemente applicato nelle interviste televisive in cui l’interlocutore vuole restare anonimo. Questi concetti possono essere espressi matematicamente: y(n) = x(D(n))
(5.4.1)
dove D(n) `e come mostra Figura 5.11 un segnale a dente di sega.
Figura 5.10: Implementazione, Pitch Shifter Come si pu`o vedere in Figura 5.10 il segnale modulato con il ritardo variabile viene, prima di essere portato in uscita, filtrato da un filtro passa basso. Questa operazione risulta necessaria per ottenere un segnale dal contenuto distinguibile e per attenuare le alte frequenze che vengono a crearsi in seguito alla modulazione del ritardo. Il filtro che si `e deciso di usare `e mostrato in Figura 5.12 ed ha una frequenza della banda passante di 3000Hz e quella della banda attenuata di 3500Hz. Tale filtro viene creato con le funzioni Matlab ellipord ed ellip che restituiscono i coefficienti del filtro ellittico. L’uscita viene poi generata dalla funzione Matlab filter.
5.4 Pitch Shifter
47
Figura 5.11: Coefficiente, Pitch Shifter
Figura 5.12: Filtro Passa-basso, Pitch Shifter
48
5.4.1
Modulazione della linea temporale
Parametri
Per l’effetto Pitch Shifter i parametri che l’utente pu`o definire sono: Profondit` a del ritardo ovvero la variazione di frequenze attorno alla frequenza di ingresso; Pendenza della rampa imposta la velocit`a con cui avviene la variazione di frequenza, definendo un valore troppo alto il segnale elaborato presenta frequenze troppo elevate ed il contenuto diventa indistiguibile, sperimentalmente `e stato fissato il valore di 2.5 che comporta un buon compromesso tra irriconoscibilit`a della voce e distinguibilit`a del contenuto;
5.4 Pitch Shifter
2
Effetto Pitch shifter
48
function out=pitch shifter(in) Fs=22050; %definisce la frequenza di campionamento indice=1; rit pit ms=4; %definisce il ritardo in ms rit pit max=round(rit pit ms∗Fs/1000); %ritardo massimo in campioni temp=zeros(rit pit max, 1); %genera un vettore per estendere il segnale ingresso=vertcat(in, temp); %estende il segnale lung=length(ingresso); out temp=zeros(lung,1); saw=zeros(lung,1); for i=1:lung %effettua il filtraggio while (indice>=rit pit max); indice=indice−rit pit max; %genero il segnale a dente di sega end; %utilizzando l’asse dei tempi saw(i)=round(2.5∗indice); %come base e la variabile indice a=(i−saw(i)); %tiene conto dell’azzeramento ogni if (a<=0); %volta che si raggiunge il valore massimo a=1; end; out temp(i)=ingresso(a); indice=i; end; Rp=−20∗log10(0.95); Rs=−20∗log10(0.05); Wp=3000/Fs∗2; Ws=3500/Fs∗2; [N, Wn] = ellipord(Wp, Ws, Rp, Rs); [b, a]=ellip (N,Rp,Rs,Wn); [H, f]=freqz(b,a,220500,Fs); out=filter(b,a,out temp); figure(1) %stampa a video i segnali subplot(2,1,1), plot(ingresso); axis([0 lung −1.1 1.1]) title(’Segnale in ingresso’); subplot(2,1,2), plot(out); axis([0 lung −1.1 1.1]) title(’Segnale in uscita’); figure(2) %stampa a video i coefficienti plot(saw); title(’Coefficiente di ritardo’); axis([0 350 0 250]) figure(3) %stampa a video i coefficienti plot(f, abs(H)); title(’Filtro passa basso’); soundsc (out,Fs); %riproduce il segnale d’uscita
50
end
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
44
46
49
50
Modulazione della linea temporale
Capitolo 6 Riverbero digitale E’ chiamato riverbero l’effetto sonoro che si produce in un grande ambiente. E’ quasi certamente una delle elaborazioni pi` u complesse da realizzare in quanto per ottenere un effetto realistico sono necessarie diverse manipolazioni successive del segnale. M.A Schroeder e James A. Moorer svilupparono un algoritmo che permetteva di ottenere una simulazione sufficientemente realistica, l’algoritmo da loro proposto sar`a quello che verr`a utilizzato e studiato in questa tesi. Analizziamo ora in dettaglio quali fisicamente siano i fattori che producono l’effetto riverbero. Il flusso audio ricevuto dall’ascoltatore `e una combinazione lineare di principalmente tre contributi: il primo dovuto alla ricezione diretta (direct sound ), il secondo dalla formato dalle riflessioni singole (early reflections) mentre il terzo composto dalle riflessioni multiple (late reflections).
Figura 6.1: Risposta Impulsiva, Riverbero Le riflessioni singole rappresentano fisicamente le onde che, rimbalzando contro le pareti della grande sala, raggiungono l’ascoltatore entro un ritardo massimo di 100 millisecondi, dopo tale ritardo vengono definite late reflections. 51
52
Riverbero digitale
Possiamo definire le late reflections anche come riflessioni multiple in quanto avendo un ritardo superiore a 100 millisecondi, significa che hanno subito diverse riflessioni su pareti diverse prima di giungere all’ascoltatore. In Figura 6.1 possiamo vedere la risposta impulsiva generata da un grande auditorium e notare quindi la composizione del segnale ricevuto. Moorer in [2] prosegu`ı gli studi e propose un nuovo algoritmo che imposta il problema come una combinazione lineare di tre contributi. Il segnale in uscita `e composto infatti dal segnale originale, dall’uscita di un filtro FIR che genera 18 ritardi diversi e da una componente che deriva da un banco di sei filtri a pettine passa-basso che generano le riflessioni multiple. Lo schema implementativo risulta quindi quello di Figura 6.2.
Figura 6.2: Implementazione, Riverbero Filtro FIR: Il filtro FIR genera una serie di delay molto ravvicinati; il pi` u ritardato infatti `e definito solamente ad 80 millisecondi circa. Dagli studi svolti da Moorer `e emerso che per ottenere un suono realistico `e sufficiente riprodurre 18 delay con ampiezze e ritardi che soddisfano i valori mostrati in Figura 6.3 ed elencati nella Tabella 6.1.
53
Figura 6.3: Filtro FIR, Riverbero Ritardo in ms 43 215 225 268 270 298 459 485 572 587 595 612 707 708 726 741 753 797
Ritardo in campioni 95 475 497 592 596 658 1011 1070 1262 1295 1313 1350 1560 1562 1601 1634 1661 1758
Ampiezza .841 .504 .490 .379 .380 .346 .289 .272 .192 .193 .217 .181 .180 .181 .176 .142 .167 .134
Tabella 6.1: Coefficienti del filtro FIR, Riverbero
54
Riverbero digitale
Filtri a Pettine Passa-Basso: il banco di sei filtri a pettine passa-basso `e stato inserito in cascata al filtro FIR per generare infinite ripetizioni attenuate che generano quindi le late reflections. Moorer ha dimostrato che l’utilizzo di sei filtri IIR ottimizza il rapporto tra la qualit`a del risultato ed il costo computazionale, si `e dimostrato infatti che l’utilizzo di ulteriori stadi apporta migliorie trascurabili. I filtri IIR implementati sono inoltre dei passa basso, questa particolarit`a `e stata ricercata da Moorer in quanto studiando fisicamente le onde sonore ha dimostrato che le alte frequenze vengono attenuate dal mezzo trasmissivo e dalle pareti riflettenti molto di pi` u rispetto alle basse frequenze, segnali a 4 kHz subiscono infatti una attenuazione di oltre 60 dB rispetto ad altri attorno ad 1 kHz. Moorer poi nel suo trattato sull’argomento ha sviluppato una struttura per la cella che contiene all’interno del loop il filtro passa basso; struttura rappresentata in Figura 6.4
Figura 6.4: Cella IIR, Riverbero Matematicamente possiamo esprimere la cella come segue y(n) = x(n − m) + g2 y(n − m) + g1 g2 y(n − m − 1);
(6.0.1)
6.1 Parametri Ritardo in ms 50 56 61 68 72 78
55 Ritardo in campioni 1103 1235 1345 1500 1588 1720
g1 .24 .26 .28 .29 .30 .32
g2 .63 .61 .60 .59 .58 .56
Tabella 6.2: Coefficienti dei filtri IIR, Riverbero I coefficienti dei sei filtri sono stati impostati seguendo le direttive suggerite dagli studi di Moorer e riportati in Tabella 6.2 I coefficienti g1 sono dei coefficienti consigliati da Moorer mentre per trovare i coefficienti g2 `e necessario prima imporre il tempo di riverbero, ad esempio, 2 secondi. Dalla formula 6.0.2 ricaviamo il termine g ed ora per trovare il coefficiente g2 cercato baster`a risolvere la formula 6.0.3.
6.1
g = 1 − (0.366/T );
(6.0.2)
g2 = g(1 − g1 );
(6.0.3)
Parametri
Per l’effetto riverbero i parametri di progetto sono quasi tutti ottimizzati dagli studi di Moorer quindi `e consigliabile non modificare i vari ritardi dei filtri e i coefficienti g1 . L’unica variabile che risulta modificabile dall’utente risulta essere: Variabile temporale T `e il tempo di riverbero. In questo progetto si `e deciso di imporlo pari a due secondi. Ricordiamo che in caso di modifiche su tale parametro `e necessario in seguito ricalcolare la variabile g ed i sei coefficienti g2 del filtro IIR.
56
2
4
6
8
10
12
14
16
18
20
22
24
26
28
Riverbero digitale
Effetto Riverbero Digitale function out=riverbero(in) lunghezza=length(in); Fs=22050; q=zeros(lunghezza+15000,1); y=zeros(lunghezza+15000,1); y1=zeros(lunghezza+15000,1); y2=zeros(lunghezza+15000,1); y3=zeros(lunghezza+15000,1); y4=zeros(lunghezza+15000,1); y5=zeros(lunghezza+15000,1); y6=zeros(lunghezza+15000,1); u=zeros(lunghezza+15000,1); m=zeros(15000,1); out=zeros(lunghezza+15000,1); k=vertcat(in,m); ampli=[.841,.504,.490,.379,.380,.346,.289,.272, .192,.193,.217,.181,.180,.181,.176,.142,.167,.134]; ritar=[95,475,497,592,596,658,1011,1070,1262, 1295,1313,1350,1560,1562,1601,1634,1661,1758]; g1=[.24,.26,.28,.29,.30,.32]; g2=[.63,.61,.60,.59,.58,.56]; ritar1=[1103,1235,1345,1500,1588,1720]; a1=1; a2=0.25; a3=0.075; alfa=0.7;
30
%−−−−−−−−EARLY REFLECTIONS−−−−−−−−−−− 32
34
36
38
40
for i=1:(lunghezza+15000); for j=1:18; a=(i−ritar(j)); if (a<=0); a=1; end; q(i)=q(i)+ampli(j)∗k(a); end; end;
6.1 Parametri
2
%−−−−−−−−−LATE REFLECTIONS−−−−−−−−−−−
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
44
for p=1:(lunghezza+15000); l=1; r=p−ritar1(l); if (r<=0);r=lunghezza+15000; end; s=r−1; if (s<=0); s=lunghezza+15000; end; y1(p)=q(r)+g2(l)∗y1(r)+g1(l)∗g2(l)∗y1(s); end; for p=1:(lunghezza+15000); l=2; r=p−ritar1(l); if (r<=0);r=lunghezza+15000; end; s=r−1; if (s<=0); s=lunghezza+15000; end; y2(p)=q(r)+g2(l)∗y2(r)+g1(l)∗g2(l)∗y2(s); end; for p=1:(lunghezza+15000); l=3; r=p−ritar1(l); if (r<=0);r=lunghezza+15000; end; s=r−1; if (s<=0); s=lunghezza+15000; end; y3(p)=q(r)+g2(l)∗y3(r)+g1(l)∗g2(l)∗y3(s); end; for p=1:(lunghezza+15000); l=4; r=p−ritar1(l); if (r<=0);r=lunghezza+15000; end; s=r−1; if (s<=0); s=lunghezza+15000; end; y4(p)=q(r)+g2(l)∗y4(r)+g1(l)∗g2(l)∗y4(s); end;
57
58
Riverbero digitale
for p=1:(lunghezza+15000); l=5; r=p−ritar1(l); if (r<=0);r=lunghezza+15000; end; s=r−1; if (s<=0); s=lunghezza+15000; end; y5(p)=q(r)+g2(l)∗y5(r)+g1(l)∗g2(l)∗y5(s); end; for p=1:(lunghezza+15000); l=6; r=p−ritar1(l); if (r<=0);r=lunghezza+15000; end; s=r−1; if (s<=0); s=lunghezza+15000; end; y6(p)=q(r)+g2(l)∗y6(r)+g1(l)∗g2(l)∗y6(s); end;
2
4
6
8
10
12
14
16
18
20
22
y=(y1+y2+y3+y4+y5+y6); 24
for t=1:lunghezza+15000; w=(t−130); %circa 6 millisecondi if w<=0; w=1; end; u(t)=−alfa∗y(t)+alfa∗u(w)+y(w); end;
26
28
30
32
for s=1:lunghezza+15000; out(s)=a1∗k(s)+a2∗q(s)+a3∗u(s); end; soundsc(out,Fs);
34
36
end
Capitolo 7 Variazione di Ampiezza 7.1
Distorsione
La distorsione `e un semplice effetto utilizzato per dare incisivit`a al suono di strumenti musicali quali, ad esempio, le chitarre. L’effetto consiste nel creare un segnale di uscita che non ha una corrispondenza lineare con quello in ingresso. Per ottenere questo risultato si possono adottare due metodologie differenti: amplificare il segnale al tal punto da portare i picchi pi` u alti oltre la soglia di fondo scala oppure troncare le componenti con valore di ampiezza superiore ad un soglia fissata. L’effetto che si ottiene `e lo stesso perch`e, ricordiamo che, sia nei sistemi digitali che in quelli analogici, la componente di ampiezza risulta sempre limitata entro un certo intervallo dato dalla tensione massima di uscita negli amplificatori analogici e dalla dimensione finita delle variabili nei sistemi digitali. In questo progetto si `e deciso di sviluppare la metodologia del troncamento dell’ampiezza; l’altra via avrebbe, infatti, comportato un costo computazionale superiore in quanto il segnale avrebbe dovuto essere prima amplificato portando i picchi pi` u alti fuori scala e poi attenuato per riportare l’ampiezza del segnale al valore originale per non modificare il volume del flusso audio.
Figura 7.1: Implementazione, Distorsione 59
60
Variazione di Ampiezza
La struttura implementativa risulta perci`o quella mostrata in Figura 7.1 dove si sono disegnate due bande orizzontali che definiscono il valore di soglia. I due picchi negativi che si notano in Figura 7.1 saranno quindi troncati dal processo. Matematicamente si pu`o esprimere questo concetto come segue: y(n) = x(n)
se |x(n)| < soglia
(7.1.1)
mentre |y(n)| = soglia
se |x(n)| ≥ soglia
(7.1.2)
Risulta molto utile per capire il concetto espresso osservare la Figura 7.2 dove viene mostrato il flusso audio originale nel tempo e quello elaborato dal DSP. In questo esempio si `e fissata una soglia pari al 10 % del segnale originale. Si pu`o vedere infatti come, essendo il segnale di ingresso normalizzato ad 1, il segnale di uscita non presenti valori di ampiezza superiori a 0,1; quelli che superavano la soglia sono stati infatti troncati a tale valore.
Figura 7.2: Segnali nel tempo, Distorsione
7.1 Distorsione
2
4
6
8
10
12
14
16
18
20
22
24
26
61
Effetto Distorsione function out=distorsione(in) Fs=22050; soglia percentuale=25; %definisce il valore della soglia massimo=max(in); soglia=(soglia percentuale/100)∗massimo; lung=length(in); out=zeros(lung,1); for i=1:lung %applica l’algoritmo dell’effetto if in(i)>soglia; out(i)=soglia; elseif in(i)<−soglia; out(i)=−soglia; else out(i)=in(i); end; end figure(1); %stampa i risultati subplot(2,1,1), plot(in); title(’Segnale originale’); axis([0 lung −1.15 1.15]) subplot(2,1,2), plot(out); title(’Segnale elaborato’); axis([0 lung −.2 .2]) soundsc (out,Fs); end
7.1.1
Parametri
Per l’effetto distorsione l’utente pu`o configurare un solo parametro: Soglia `e il valore che definisce lo sbarramento in ampiezza del segnale in uscita. Viene espresso in termini percentuali relativi al valore massimo che il segnale in ingresso pu`o assumere. In questo progetto si `e deciso di impostare un valore pari al 25%. In questo progetto si `e invece deciso di fissare la soglia in valori percentuali relativi al valore massimo che il segnale assume; ci`o `e possibile in quanto per le simulazioni Matlab si `e deciso di lavorare offline; il programma per il DSP rispetta le condizioni di lavoro in tempo reale e per questo motivo la soglia `e appunto fissata ad un valore riferito al fondoscala massimo.
62
Variazione di Ampiezza
7.2
Tremolo
L’effetto tremolo, come gli altri effetti di questa famiglia, consiste nel modulare l’ampiezza del segnale; la forma d’onda modulante `e una sinusoide a bassa frequenza. Viene spesso erroneamente confuso con l’effetto vibrato. Concettualmente per`o si tratta di due tipologie completamente diverse; il vibrato infatti modifica la frequenza del segnale, variandola con un segnale sinusoidale, e non la sua ampiezza. L’implementazione dell’effetto tremolo `e quindi semplicemente quella mostrata in Figura 7.3.
Figura 7.3: Implementazione, Tremolo
Matematicamente si pu`o esprimere come: y(n) = x(n)[1 + αsin(2πnT sF d)]
(7.2.1)
Nell’equazione precedente con α si intende il termine Amp rappresenta l’ampiezza della variazione mentre F d definisce la frequenza del segnale modulante.
7.2 Tremolo
7.2.1
63
Parametri
Per l’effetto tremolo l’utente pu`o definire: Amp `e il valore, compreso tra 0 ed 1, che rappresenta la variazione d’ampiezza del segnale in uscita. Se a = 0 il flusso audio di uscita `e esattamente quello in ingresso; se a = 1, che rappresenta la massima variazione possibile, il segnale presenter`a degli istanti in cui il valore di ampiezza si annulla ed altri in cui il valore `e pari al doppio di quello in ingresso. In questo progetto si `e fissato a pari all’80% del segnale. Fd rappresenta la frequenza di oscillazione della sinusoide modulante. Ricordiamo che questa deve essere un segnale lentamente variabile. Per questo motivo si `e deciso di utilizzare un valore pari a 3Hz.
La Figura 7.4 mostra evolve il segnale Amp avendo definito i parametri Amp pari all’80% e F d pari a 3 Hz.
Figura 7.4: Coefficiente, Tremolo
64
2
4
6
8
10
12
14
16
18
20
22
24
26
Variazione di Ampiezza
Effetto Distorsione function out=tremolo(in) Fs=22050; Fd=3; Amp percentuale=80; %definisce il parametro Amp Amp=Amp percentuale/100; lung=length(in); out=zeros(lung,1); ampli=zeros(lung,1); for i=1:(lung) ampli(i)=1+Amp∗sin(2∗pi∗Fd∗i/Fs); %genera la modulante out(i)=in(i)∗ampli(i); %applica la modulazione end; figure(1); %stampa i risultati subplot(2,1,1), plot(in); axis([0 lung −1.25 1.25]) subplot(2,1,2), plot(out); axis([0 lung −1.25 1.25]) figure(2) plot(ampli); title(’Coefficiente di Ampiezza’); axis([0 14000 0 2]) soundsc (out,Fs); end
Capitolo 8 Processi sulla dinamica 8.1
Compressione
La compressione `e una elaborazione che ha effetti sulla dinamica del segnale; quest’ultima la possiamo definire come la distanza in termini di ampiezza tra parti dello stesso flusso audio. Il compressore pu`o quindi essere definito come un amplificatore con guadagno variabile. In accordo con questa definizione possiamo quindi classificarli come: compressori verso il basso (downward compressors) o compressori verso l’alto (upward compressors). I primi hanno la caratteristica di mantenere unitario il guadagno per segnali bassi mentre impongono un’attenuazione per quelli pi` u alti; mentre i secondi applicano una amplificazione dei segnali pi` u deboli mantenendo un guadagno unitario per quelli pi` u forti. Viene molto utilizzato nei sistemi di riproduzione portatili o sistemi home theater perch`e permette di correggere in parte le problematiche dovute ai rumori ambientali che, se intensi, coprirebbero le parti pi` u deboli del segnale; la soluzione che prevede di amplificare con lo stesso guadagno l’intero segnale, per permettere di percepire i suoni pi` u deboli, viene scartata in quanto produrrebbe dei picchi fastidiosi durante le parti in cui il segnale originale `e pi` u forte; l’uso quindi di amplificatori variabili `e l’ideale per affrontare e risolvere queste problematiche.
65
66
Processi sulla dinamica La struttura che implementa il compressore `e mostrata in Figura 8.1
Figura 8.1: Implementazione, Compressore
Matematicamente la realizzazione di questo effetto si pu`o esprimere come: y(n) = x(n)
se |x(n)| < soglia
(8.1.1)
mentre |y(n)| = soglia +
1 ∗ (x(n) − soglia) ratio
se |x(n)| ≥ soglia
(8.1.2)
In Figura 8.2 si possono notare i diversi comportamenti delle due tipologie di compressore: compressione verso l’alto e compressione verso il basso. I risultati dell’utilizzo delle due tipologie sono molto simili; hanno entrambi l’obbiettivo di amplificare i suoni pi` u deboli ed attenuare quelli pi` u forti.
8.1 Compressione
67
Figura 8.2: Comportamento, Compressore In Figura 8.3 si pu`o vedere il risultato dell’applicazione dei compressori mostrati in Figura 8.2 ad una sinusoide di ampiezza 100. Nel grafico di sinistra risulta immediato verificare come la dinamica venga ridotta, i picchi pi` u alti vengono infatti attenuati; nella figura di destra pu`o risultare meno evidente questo risultato ma si nota come i valori pi` u deboli del segnale vengano amplificati maggiormente rispetto al resto della sinusoide, infatti la pendenza dei settori di segnale che hanno valori attorno allo zero `e superiore.
68
Processi sulla dinamica
Figura 8.3: Segnale di Uscita, Compressore In Figura 8.3 la linea rossa rappresenta il segnale sinusoidale originale di ingresso mentre quella blu rappresenta l’uscita elaborata dal DSP.
8.1 Compressione
8.1.1
69
Parametri
Come mostra la Figura 8.1 i parametri che l’utente pu`o definire sono: Soglia `e il valore che definisce la soglia oltre la quale cambia il valore del guadagno. Ratio definisce il rapporto tra l’ampiezza del segnale in ingresso e quella in uscita in zona di compressione, per i compressori verso il basso, mentre per la zona che comprende i piccoli valori di ampiezza, al di sotto della soglia, per i compressori verso l’alto. Tempo di Attacco questo parametro corrisponde al ritardo temporale dopo il quale la compressione si attiva. I compressori pi` u raffinati prevedono la possibilit`a di non attenuare immediatamente tutti i valori che superano la soglia ma attivano l’attenuazione solamente se l’ampiezza del segnale supera la soglia per un tempo superiore al tempo di attacco. Tempo di Rilascio `e un parametro che, come il tempo di attacco, gestisce il rilascio dell’attenuazione. E’ infatti preferibile che il guadagno dell’amplificatore non ritorni istantaneamente ad un valore unitario nel momento in cui il segnale scende al di sotto della soglia, ma lo faccia con un determinato ritardo dato appunto dal tempo di rilascio.
In questo progetto, per rendere l’algoritmo pi` u semplice, si `e deciso di trascurare i parametri tempo di attacco e tempo di rilascio. L’inverso di un compressore viene definito espansore e applica l’algoritmo inverso; attenua infatti le componenti pi` u deboli del segnale e amplifica quelle pi` u forti. Applicando quindi in cascata un compressore ed un espansore si ottiene il segnale di ingresso originale. Per questo progetto si `e deciso di evitare l’implementazione di questo effetto data la sua semplicit`a; basta infatti invertire le zone di applicazione del guadagno ratio.
70
2
4
6
8
10
12
14
16
18
20
Effetto Compressione function out=compressione(in) Fs=22050; lung=length(in); ratio=2; %definisco il valore del ratio soglia percentuale=50; %definisco il valore della soglia out=zeros(lung,1); massimo=max(in); soglia=(soglia percentuale/100)∗massimo; for i=1:lung %applico l’algoritmo if in(i)<0 if in(i)<−soglia; ampli=1/ratio; out(i)=−soglia+ampli∗(in(i)+soglia); else out(i)=ampli∗in(i); out(i)=in(i); end; end if in(i)>0 if in(i)
22
24
26
28
30
32
34
36
38
40
42
Processi sulla dinamica
end
8.2 Soppressore di rumore
8.2
71
Soppressore di rumore
Il soppressore di rumore `e un semplice algoritmo che si applica ad un segnale per eliminare il rumore di fondo sempre presente in esso. Supponendo infatti che i disturbi abbiano una ampiezza molto inferiore rispetto al segnale desiderato, per eliminarli, `e sufficiente azzerare tutti i campioni che presentano una ampiezza inferiore ad una determinata soglia. Questo per`o comporta una certa distorsione in quanto a venire azzerati saranno anche i campioni di segnale desiderato con ampiezza inferiore alla soglia; `e questa per`o una distorsione trascurabile. Questo algoritmo trova la sua applicazione soprattutto in flussi audio che contengono sezioni in cui il segnale dovrebbe essere nullo. Un esempio di tale applicazione `e quello dei segnali audio che esprimono tracce vocali; ci saranno alcuni istanti in cui l’oratore non parler`a ed `e proprio in questi periodi che il soppressore di rumore agisce in maniera pi` u significativa eliminando ronzii oppure rumori di sottofondo. La struttura che implementa il soppressore di rumore `e mostrata in Figura 8.4
Figura 8.4: Implementazione, Soppressore Matematicamente si pu`o esprimere come: y(n) = 0
se |x(n)| < soglia
(8.2.1)
mentre |y(n)| = x(n)
se |x(n)| ≥ soglia
(8.2.2)
Il comportamento del soppressore di rumore `e mostrato in Figura 8.5 dove, a titolo di esempio, si `e fissata una soglia pari a 10; come si vede quindi campioni con valore di ampiezza inferiore a 10 verranno azzerati. In Figura 8.6 `e mostrato un secondo esempio dove si vede come i campioni con ampiezza inferiore alla soglia vengono azzerati in uscita.
72
Processi sulla dinamica
Figura 8.5: Comportamento, Soppressore
Figura 8.6: Segnale nel tempo, Soppressore
8.2 Soppressore di rumore
8.2.1
73
Parametri
L’unico parametro definibile dall’utente `e: Soglia `e il valore che definisce la soglia al di sotto della quale l’ampiezza viene annullata.
74
2
4
6
8
10
12
14
16
18
20
22
24
Processi sulla dinamica
Effetto soppressione function out=soppressione(in) Fs=22050; lung=length(in); soglia percentuale=1; %definisco il valore della soglia out=zeros(lung,1); massimo=max(in); soglia=(soglia percentuale/100)∗massimo; for i=1:lung %applico l’algoritmo if in(i)<0 if in(i)<−soglia; out(i)=in(i); else out(i)=0; end; end if in(i)>0 if in(i)
26
28
30
32
34
36
end
Conclusioni L’obiettivo di questo progetto non `e certo la creazione di un dispositivo per uso professionale quanto la realizzazione di un apparecchio in grado di implementare alcuni dei pi` u conosciuti effetti audio digitali. Le potenzialit`a della scheda sono molto alte, la velocit`a di calcolo e la qualit`a dei convertitori analogico-digitali ne permetterebbero l’uso per utilizzi in settori di fascia medio-alta; ci`o che forse `e mancato per raggiungere questa qualit`a superiore `e stata la carenza di memoria RAM sul dispositivo che non ha permesso l’uso di buffer di grandi dimensioni. La quantit`a di memoria ridotta ha infatti costretto la scelta di una frequenza di campionamento inferiore alle effettive potenzialit`a offerte dalla scheda. Si pu`o affermare quindi che i prossimi sviluppi e migliorie che si potranno apportare a questo progetto dovranno avere come base l’incremento di memoria a disposizione delle variabili del software. Questo studio non ha la pretesa di essere considerato una guida tecnica specializzata quanto invece pu`o essere inteso come un primo approccio, dal carattere prettamente didattico, al vasto campo degli effetti audio digitali implementati su DSP.
75
76
Conclusioni
Appendice A Codice C per la programmazione del DSP Il codice che viene riportato in seguito rappresenta il programma principale in linguaggio C usato per programmare il DSP. Il programma `e strutturato di modo che l’utente possa selezionare pi` u effetti contemporaneamente, uno per famiglia; sar`a quindi possibile, ad esempio, applicare al flusso audio in ingresso un effetto delay che si sovrappone ad un tremolo seguito da una distorsione. E’ anche possibile selezionare solamente uno di questi oppure non selezionarne alcuno cos`ı che l’uscita risulti esattamente uguale all’ingresso. La struttura risulta quindi essere quella di Figura A.1:
Figura A.1: Struttura del Programma Si `e deciso di omettere in questo testo le altre parti necessarie al funzionamento della scheda, quali ad esempio: l’organizzazione della memoria, la definizione delle costanti globali o l’inizializzazione dei registri.
77
78
2
4
6
Codice C per la programmazione del DSP
#include #include #include #include #include #include
”FlashingLeds−Settings.h” ”PeripheralHeaderIncludes.h” ”DSP280x EPWM defines.h” //OK to use 280x file ”float.h” ”math.h” ”stdlib.h”
8
10
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // FUNCTION PROTOTYPES //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12
14
16
// −−−−−−−−−−−−−−−− FRAMEWORK −−−−−−−−−−−−−−−−−−− void DeviceInit(void); void SCIA Init(); void SerialHostComms(); void InitFlash();
18
22
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // VARIABLE DECLARATIONS − GENERAL //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
24
// −−−−−−−−−−−−−−−− FRAMEWORK −−−−−−−−−−−−−−−−−−−
20
26
28
30
32
34
36
38
40
42
44
46
48
50
int16 int16 int16 int16 int16 int16 int16
VTimer0[4]; // Virtual Timers slaved off CPU Timer 0 VTimer1[4]; // Virtual Timers slaved off CPU Timer 1 VTimer2[4]; // Virtual Timers slaved off CPU Timer 2 SerialCommsTimer; CommsOKflg; HRmode; BlinkStatePtr, LED TaskPtr;
// Used to indirectly access all EPWM modules, very useful! volatile struct EPWM REGS ∗ePWM[] = { &EPwm1Regs, //intentional: (ePWM[0] not used) &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs, #if (!DSP2802x DEVICE H) &EPwm5Regs, &EPwm6Regs, #if (DSP2803x DEVICE H || DSP2804x DEVICE H) &EPwm7Regs, #if (DSP2804x DEVICE H) &EPwm8Regs #endif #endif #endif };
79
2
// Used for running BackGround in flash, and ISR in RAM extern Uint16 ∗RamfuncsLoadStart, ∗RamfuncsLoadEnd, ∗RamfuncsRunStart;
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
// −−−−−−−−−−−−−−−−−−− USER −−−−−−−−−−−−−−−−−−−−−− int Fs,i,j,lunghezza buffer,indice,indice 1,indice 2,indice 3; int ritardo eco ms, ritardo eco; int ritardo multi eco ms, ritardo multi eco 1, ritardo multi eco 2; int ritardo multi eco 3; int ritardo chorus ms, ritardo chorus, ritardo chorus max; int percentuale var amp; int ritardo fla ms, ritardo fla max, ritardo fla; int ritardo vib ms, ritardo vib max, ritardo vib; int ritardo pit ms, ritardo pit max, ritardo pit, temp; int soglia percent, soglia; float variaz tre percent, variaz tre max; float ampli[9]; int ritar[9]; float ampiezza, a1, a2; int soglia1, ratio; int soglia2; int beta; int sel eff temp, sel eff amp, sel riv, sel eff din; #pragma DATA SECTION(buffer , ”.ebss:buffer”) int buffer[28000]; //e’ lungo e000 #pragma DATA SECTION(h1buffer , ”.ebss:hbuffer”) int h1buffer[28000]; #pragma DATA SECTION(h2buffer , ”.ebss:hbuffer”) int h2buffer[28000]; //hbuffer ha dimensione 10000h
34
36
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // VARIABLE DECLARATIONS − CCS WatchWindow / GUI support //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38
// −−−−−−−−−−−−−−−− FRAMEWORK −−−−−−−−−−−−−−−−−−− 40
42
44
46
//GUI support variables // sets a limit on the amount of external GUI controls − increase as necessary int16 ∗varSetTxtList[16]; //16 textbox controlled variables int16 ∗varSetBtnList[16]; //16 button controlled variables int16 ∗varSetSldrList[16]; //16 slider controlled variables int16 ∗varGetList[16]; //16 variables sendable to GUI int16 ∗arrayGetList[16]; //16 arrays sendable to GUI
48
// −−−−−−−−−−−−−−−−−−− USER −−−−−−−−−−−−−−−−−−−−−−
80
2
4
6
8
Codice C per la programmazione del DSP
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // MAIN CODE − starts here //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void main(void) { //============================================= // INITIALISATION − General //=============================================
10
// −−−−−−−−−−−−−−−− FRAMEWORK −−−−−−−−−−−−−−−−−−− 12
14
16
18
20
22
DeviceInit(); // Device Life support & GPIO SCIA Init(); // Initalize the Serial Comms A peripheral // Only used if running from FLASH // Note that the variable FLASH is defined by the compiler with −d FLASH // (see TwoChannelBuck.pjt file) #ifdef FLASH // Copy time critical code and Flash setup code to RAM // The RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart // symbols are created by the linker. Refer to the linker files. MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
24
26
28
30
32
34
36
38
// Call Flash Initialization to setup flash waitstates // This function must reside in RAM InitFlash(); // Call the flash wrapper init function #endif //(FLASH) // Timing sync for background loops // Timer period definitions found in PeripheralHeaderIncludes.h CpuTimer0Regs.PRD.all = uSec45; // A tasks CommsOKflg = 0; SerialCommsTimer = 0; HRmode = 1; // Default to HR mode enabled // −−−−−−−−−−−−−−−−−−− USER −−−−−−−−−−−−−−−−−−−−−− // put common initialization/variable definitions here
40
42
44
46
sel eff temp = 0; sel eff amp=0; sel eff din=0; sel riv=1; j=1; i=0; Fs=22050;
48
lunghezza buffer=28000;
81
2
4
6
8
10
12
14
16
//parametri effetti //effetto Eco ritardo eco ms=900; //espresso in ms ritardo eco=(Fs/1000)∗ritardo eco ms; //effetto Multi tap Eco ritardo multi eco ms=400; //espresso in ms ritardo multi eco 1=(Fs/1000)∗ritardo multi eco ms; ritardo multi eco 2=(Fs/1000)∗2∗ritardo multi eco ms; ritardo multi eco 3=(Fs/1000)∗3∗ritardo multi eco ms; //effetto Chorus ritardo chorus ms=25; //espresso in ms ritardo chorus max=(Fs/1000)∗ ritardo chorus ms; percentuale var amp=30;
18
20
//effetto Flanger ritardo fla ms=25; //espresso in ms ritardo fla max=(Fs/1000)∗ritardo fla ms;
22
24
//effetto Vibrato ritardo vib ms=3; //espresso in ms ritardo vib max=(Fs/1000)∗ritardo vib ms;
26
28
30
32
34
36
38
40
42
44
//effetto Pitch Shifter ritardo pit ms=5; //espresso in ms ritardo pit max=(Fs/1000)∗ritardo vib ms; temp=0; //effeto Distorsione soglia percent=2; //espresso in % soglia=(32767/100∗soglia percent); //effetto Tremolo variaz tre percent=80; //espresso in % variaz tre max=variaz tre percent/100; //effetto Riverbero ampli[0]=.841; ampli[1]=.504; ampli[2]=.289; ampli[3]=.192; ampli[4]=.176; ampli[5]=.167; ampli[6]=.134; ampli[7]=.29; ampli[8]=.24; ritar[0]=95; ritar[1]=475; ritar[2]=1011; ritar[3]=1262; ritar[4]=1601; ritar[5]=1661; ritar[6]=1758; ritar[7]=3103; ritar[8]=3478;
46
48
beta=0; a1=1; a2=0.25;
82
Codice C per la programmazione del DSP
//effetto Compressione soglia1=16384; ratio=2;
2
4
//effetto Soppressione del rumore soglia2=50;
6
8
10
//============================================= // INITIALISATION − BUILD OPTIONS − NOTE: select via ProjectSettings.h //=============================================
12
14
16
18
20
// −−−−−−−−−−−−−−−−−−− USER −−−−−−−−−−−−−−−−−−−−−− // Put build specific initialisation here for (j=0; j<=lunghezza buffer; j++) { buffer[j]=0; h1buffer[j]=0; h2buffer[j]=0; }
24
//============================================= // BACKGROUND (BG) LOOP //=============================================
26
// −−−−−−−−−−−−−−−− FRAMEWORK −−−−−−−−−−−−−−−−−−−
22
28
30
32
34
36
for (;;) //infinite loop { if (CpuTimer0Regs.TCR.bit.TIF == 1) { CpuTimer0Regs.TCR.bit.TIF = 1; // clear flag // l’interupt fa partire la conversione dell’ADC // il dato proveniente dall’ADC `asar poi elaborato // come segue: if (i == 0) { temp=temp; }
38
40
42
44
46
48
// // // // // // //
La parte di codice soprariportata risulta necessaria in fase di simulazione in quanto per rendere piu’ semplice tale processo si e’ deciso di utilizzare campioni salvati in precedenza sul pc. L’espressione temp = temp serve infatti a generare un punto in cui e’ possibile inserire un breakpoint di lettura dal file. Per rendere la simulazione piu’ veloce si e’ deciso di leggere 28000 campioni alla volta e terminata l’elaborazione scrivere 28000 campione in uscita.
83
2
4
6
8
10
12
14
16
18
20
//selezione dell’effetto desiderato switch (sel eff temp) { case (0): //effetto:nessun effetto selezionato buffer[i]=h2buffer[i]; h1buffer[i]=buffer[i]; break; case (1): // effetto: Eco buffer[i]=h2buffer[i]; indice=i−ritardo eco; if (indice<0) { indice=indice+lunghezza buffer; } h1buffer[i]=0.8∗buffer[i]+0.2∗buffer[indice]; break;
22
24
26
28
30
32
34
36
38
40
42
case (2): // effetto: Multi−tap Eco buffer[i]=h2buffer[i]; indice 1=i−ritardo multi eco 1; if (indice 1<0) { indice 1=indice 1+lunghezza buffer; } indice 2=i−ritardo multi eco 2; if (indice 2<0) { indice 2=indice 2+lunghezza buffer; } indice 3=i−ritardo multi eco 3; if (indice 3<0) { indice 3=indice 3+lunghezza buffer; } h1buffer[i]=buffer[i]+0.2∗buffer[indice 1]+0.05∗buffer[indice 2]+ +0.01∗buffer[indice 3]; break;
84
Codice C per la programmazione del DSP
case (4): // effetto: Chorus buffer[i]=h2buffer[i]; ritardo chorus=(((ritardo chorus max)/2)∗ ∗(1+sin((2∗3.14∗0.1∗i)/Fs))); ampiezza=(1+(percentuale var amp∗0.01∗cos((2∗3.14∗0.3∗i)/Fs))); indice=i−ritardo chorus; if (indice<0) { indice=indice+lunghezza buffer; } h1buffer[i]=0.5∗buffer[i]+0.5∗ampiezza∗buffer[indice]; break;
2
4
6
8
10
12
14
case (8): // effetto: Flanger buffer[i]=h2buffer[i]; ritardo fla=(((ritardo fla max)/2)∗(1−cos((2∗3.14∗0.3∗i)/Fs))); indice=i−ritardo fla; if (indice<0) { indice=indice+lunghezza buffer; } h1buffer[i]=buffer[indice]; break;
16
18
20
22
24
26
case (16): // effetto:Pitch Shifter buffer[i]=h2buffer[i]; if (temp>ritardo pit max) { temp=temp−ritardo pit max; } indice=i−3∗temp; temp=temp+1; if (indice<0) { indice=indice+lunghezza buffer; } indice 1=i−1; if (indice 1<0) { indice 1=indice 1+lunghezza buffer; } h1buffer[i]=0.5∗buffer[indice]+0.5∗buffer[indice 1]; break;
28
30
32
34
36
38
40
42
44
46
48
default: break; 50
}
85
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
44
46
case (32): // effetto: Vibrato buffer[i]=h2buffer[i]; ritardo vib=(((ritardo vib max)/2)∗(sin((2∗3.14∗10∗i)/Fs))); indice=i−ritardo vib; if (indice<0) { indice=indice+lunghezza buffer; } h1buffer[i]=buffer[indice]; break; switch (sel eff amp) { case (0): //effetto:nessun effetto selezionato break; case (1): // effetto: Distorsione if (h1buffer[i]>=soglia) { h1buffer[i]=soglia; } else if (h1buffer[i]<=−soglia) { h1buffer[i]=−soglia; } else { h1buffer[i]=h1buffer[i]; } break; case (2): // effetto: Tremolo ampiezza=1+variaz tre max∗(sin((2∗3.14∗10∗i)/Fs)); h1buffer[i]=h1buffer[i]∗ampiezza; break; default: break; } switch (sel eff din) { case (0): //effetto:nessun effetto selezionato break;
86
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
Codice C per la programmazione del DSP
case (1): // effetto: compressione if (h1buffer[i] < 0) { if (h1buffer[i] < −soglia1) { h1buffer[i]=−soglia1+(h1buffer[i]+soglia1)/ratio; } } else { if (h1buffer[i] > soglia1) { h1buffer[i]=soglia1+(h1buffer[i]−soglia1)/ratio; } } break; case (2): // effetto: soppressore di rumore if (h1buffer[i] < 0) { if (h1buffer[i] > −soglia2) { h1buffer[i]=0; } } else { if (h1buffer[i] < soglia2) { h1buffer[i]=0; } } break; default: break; } switch (sel riv) { case (0): //effetto:nessun effetto selezionato break;
87
case (1): // effetto: riverbero for (temp = 0; temp < 9; temp++) { beta=i−ritar[temp]; if (beta<=0) { beta=1; } buffer[i]=buffer[i]+ampli[temp]∗h1buffer[beta]; } break;
2
4
6
8
10
12
14
default: break; }
16
18
20
22
24
26
28
30
32
34
36
38
40
42
// // // // // // // // //
A causa di problemi legati alla memoria e alla allocazione della stessa e’ stato impossibile riuscire ad implementare l’effetto riverbero come mostrato in questa tesi ma si e’ scelto di realizzarlo comunque con un algoritmo meno sofisticato omettendo la parte dei filtri IIR e il filtro passa tutto, realizzando solamente un banco di filtri FIR con tempi di ritardo che generano sia le early reflection che le late reflection. E’ questa una semplificazione dell’algoritmo di Moorer necessaria per risolvere i suddetti problemi di allocazione che non trovavano altrimenti soluzione. Le variabili buffer utilizzate non potevano infatti essere modificate in quanto gia’ in uso dagli effetti implementati in precedenza.
if (i == 27999) { if (sel riv==1) { temp=temp; i=−1; } else { temp=temp; i=−1; } } i=i+1; }} }//END MAIN CODE
44
46
48
// // // // //
Questa sezione del codice, come quella iniziale ha lo scopo di creare una parte di codice dove sia corretto inserire i breakpoint in questo caso di scrittura. Per problemi legati alle variabili utilizzate per l’effetto riverbero sono stati creati due punti diversi per l’applicazione del breakpoint in base all’utilizzo o meno di tale effetto.
88
Codice C per la programmazione del DSP
Bibliografia [1] S. J. Orfanidis, Introduction to Signal Processing, Capitolo 8, Sez 8.2, pp. 355-383, Prentice Hall, Englewood Cliffs, NJ, (1996). [2] J. A. Moorer, About this reverberation business,Computer Music journal, 3, 13 (1979). [3] J. Tomarakos, D. Ledger, Using The Low-Cost, High Performance ADSP21065L Digital Signal Processor For Digital Audio Applications, (1998). [4] D. Oboril, M. Balik, J. Schimmel, Z. Smekal, P. Krkavec, Modelling Digital Musical Effects For Signal Processors, Based On Real Effects Manifestation Analysis, (2000) [5] Code Composer Studio getting started guide, Texas Instruments, (2001) [6] TMS320C28343 Delfino Microcontrollers Data Manual, Texas Instruments, (2009) [7] TMS320C28343 Experimenters Kit Overview, Texas Instruments, (2009) [8] Delfino C28343 controlCARD Overview, Texas Instruments, (2009)
89