109
Csound e Python nella realizzazione di programmi per l'elaborazione del suono in tempo reale Bertinoro – Agosto 2008 1 di 109

Corso Perfezionamento Informatica Musicale

  • Upload
    galge

  • View
    20

  • Download
    7

Embed Size (px)

DESCRIPTION

Csound e Python nella realizzazione di programmi per l' elaborazione del suono in tempo reale. Bertinoro - Agosto 2008

Citation preview

Page 1: Corso Perfezionamento Informatica Musicale

Csound e Python nella realizzazione di programmi per l'elaborazione del suono in tempo reale

Bertinoro – Agosto 2008

1 di 109

Page 2: Corso Perfezionamento Informatica Musicale

Introduzione..........................................................................................................................................5Le osservazioni di Koenig sulla costruzione del suono ..................................................................5L'istante zero di Pietro Grossi..........................................................................................................5Il software libero e Richard Stallman..............................................................................................5Programmazione e composzione.....................................................................................................5

Csound..................................................................................................................................................6Primo incontro con cSound .............................................................................................................6Orientarsi tra le versioni di cSound ................................................................................................7

....................................................................................................................................................7 ....................................................................................................................................................7 ....................................................................................................................................................7

Installare Csound su Debian Linux .................................................................................................7 ....................................................................................................................................................7 ....................................................................................................................................................7 ....................................................................................................................................................7

Installazione di Csound 5 in ambiente Windows ............................................................................8 ........................................................................................................................................................8Strumenti e spartiti in cSound .........................................................................................................9

....................................................................................................................................................9 ....................................................................................................................................................9 ....................................................................................................................................................9

Creare un primo file audio con cSound ........................................................................................11 ..................................................................................................................................................11 ..................................................................................................................................................11 ..................................................................................................................................................11

Opzioni cSound da linea di comando ...........................................................................................12Strumenti cSound ..........................................................................................................................12Struttura di un file .csd ..................................................................................................................13Configurazione di CSound per l'elaborazione in tempo reale del suono (Windows) ...................18Un semplic file .csd per il tempo-reale .........................................................................................21Una semplice partitura cSound .....................................................................................................22La codifica octave point pitch-class ..............................................................................................23Tipi di variabili in cSound ............................................................................................................23

..................................................................................................................................................23 ..................................................................................................................................................23 ..................................................................................................................................................23

Scrivere uno strumento cSound ....................................................................................................24Come si scrive una funzione .........................................................................................................25Come si scrive una funzione .........................................................................................................25Variabili di controllo in cSound ....................................................................................................26Variabili di controllo: inviluppi d'ampiezza ..................................................................................27Segnali di controllo: stereo, tremolo, vibrato ...............................................................................28Sintesi additiva con cSound ..........................................................................................................29GEN09 e GEN19 ..........................................................................................................................31Oscillatori complessi: buzz e gbuzz ..............................................................................................32Gestione delle cartelle in Csound (Windows) ..............................................................................35Gestione delle cartelle in Csound (Linux Debian) ........................................................................36Sintesi sottrattiva ...........................................................................................................................36

2 di 109

Page 3: Corso Perfezionamento Informatica Musicale

Sintesi sottrattiva e filtri risonanti .................................................................................................39L'opcode comb ..............................................................................................................................40Sintesi vettoriale ...........................................................................................................................41Modulazione ad anello ..................................................................................................................41

Orchestra per la FM semplice ..................................................................................................43 ..................................................................................................................................................43 ..................................................................................................................................................43 ..................................................................................................................................................43

Spettro armonico di semplici FM .................................................................................................44Introduzione all'opcode foscil .......................................................................................................45Introduzione all'opcode loscil .......................................................................................................46Sintesi per distorsione non lineare ................................................................................................47L'opcode table e la GEN07 ...........................................................................................................49

GEN07..................................................................................................................................49usage.....................................................................................................................................50parameters............................................................................................................................50

Gli opcodes delayr, delayw, deltap ...............................................................................................51Sintesi per modelli fisici: l'opcode pluck ......................................................................................52L'istruzione if .... kgoto .................................................................................................................53

..................................................................................................................................................53 ..................................................................................................................................................53

Algoritmi di sintesi e pedaliera MIDI ...........................................................................................53Una loop station in cSound ...........................................................................................................55

..................................................................................................................................................55Pilotare l'opcode diskin con un MIDI controller ..........................................................................60Pitch detection con gli opcodes spectrum e specptrk ...................................................................61

..................................................................................................................................................61specptrk .........................................................................................................................................62Description.....................................................................................................................................62Syntax............................................................................................................................................62Initialization...................................................................................................................................62Performance...................................................................................................................................63L'opcode specptrk .........................................................................................................................63Sintesi granulare con l'opcode granule .........................................................................................64

Bibliografia...............................................................................................................................65Uso dell'opcode timout .................................................................................................................65

..................................................................................................................................................65 ..................................................................................................................................................65

Sintesi granulare con l'opcode timout ...........................................................................................67Sintesi per formanti: FOF .............................................................................................................68Introduzione agli FLTK Widgets ..................................................................................................71Esempio di costruzione di un'interfaccia FLTK ............................................................................72

Csound e Python.................................................................................................................................75Csound e Python: primo incontro .................................................................................................75Usare Csound con Python: moduli principali ...............................................................................75 ......................................................................................................................................................75PyGame per joystick e joypad ......................................................................................................76 ......................................................................................................................................................76

wxPython e pyGame a confronto .............................................................................................76Programmare joypad e tastiera con pyGame ................................................................................77

3 di 109

Page 4: Corso Perfezionamento Informatica Musicale

Il modulo pySerial ........................................................................................................................78Esplorare il modulo csnd ..............................................................................................................79La variabile d'ambiente PYTHONPATH (windows) ....................................................................79La classe cSoundPerformanceThread ...........................................................................................80Un sistema di macro per i files csd ...............................................................................................81L'opcode chnset e l'istruzione GetChannel ...................................................................................82Alcune considerazioni sull'opcode chnset ....................................................................................83 ......................................................................................................................................................83 ......................................................................................................................................................83L'opcode chnget ed il modulo Python csnd ..................................................................................84 ......................................................................................................................................................84 ......................................................................................................................................................84Creare un lettore di campioni in Python e Csound .......................................................................85Subclassing del controllo wxSlider ...............................................................................................87Una classe Python per grafici in tempo reale ...............................................................................88

Composizione algoritmica e tempo reale ..........................................................................................92Una classe per la gestione di pattern di accenti ............................................................................92Modificare pattern di accenti tramite istogrammi .........................................................................95Generazione di motivi musicali con catene di Markov ................................................................99Rappresentare una catena di Markov con un file XML ..............................................................101Passaggio da un range di valori ad un altro con l'interpolazione lineare ....................................103 ....................................................................................................................................................103Permutazioni o disposizioni senza ripetizione ............................................................................105 ....................................................................................................................................................105 ....................................................................................................................................................105Random walk ..............................................................................................................................105 ....................................................................................................................................................105 ....................................................................................................................................................105Disposizioni con ripetizione .......................................................................................................106 ....................................................................................................................................................106Funzione di conversione di una nota nella sua frequenza corrispondente ..................................107Una classe per il calcolo delle permutazioni di una serie di note ...............................................108 ....................................................................................................................................................108 ....................................................................................................................................................108 ....................................................................................................................................................108

4 di 109

Page 5: Corso Perfezionamento Informatica Musicale

Introduzione

Le osservazioni di Koenig sulla costruzione del suono

L'istante zero di Pietro Grossi

Il software libero e Richard Stallman

Programmazione e composzione

5 di 109

Page 6: Corso Perfezionamento Informatica Musicale

Csound

Primo incontro con cSound

Csound è stato inizialmente scritto da Barry Varcoe nel 1985 (MIT). E' un linguaggio di "programmazione musicale" multipiattaforma, un sintetizzatore virtuale della famosa famiglia dei linguaggi MUSICV.

Per una panoramica dettagliata rimando al sito ufficiale http://www.csounds.com/

Inizialmente distribuito sotto licenza MIT, Csound è ora distribuito sotto licenza LGPL.

Csound è nato come linguaggio orientato alla sintesi ed alla elaborazione audio, ma non in tempo reale: un sintetizzatore programmabile, flessibile, potentissimo, ma progettato essenzialmente per essere una sorta di compilatore/generatore di file audio.

Ho incominciato ad usare Csound nel 1997. Il mio primo lavoro pubblicato, realizzato in Csound, è presente nel secondo cd di Anatrofobia: "Ruote che girano a vuoto". "Musica a piccole dimensioni", questo è il titolo, è stato realizzato seguendo la tipica procedura di lavoro con il "vecchio" Csound. Con molta pazienza e tempo ho scritto due file di testo: "musicaapiccoledimensioni.orc" e "musicapiccoledimensioni.sco". Questi due file contenevano l'orchestra e la partitura Csound. Il file .orc conteneva gli strumenti di sintesi, il file .sco "le note" da sintetizzare. Prendendo come input questi due file Csound generava il file audio finale.

Il lavoro con Csound è molto simile a quello con un compilatore di un qualsiasi linguaggio di programmazione. Si scrivono i sorgenti. Si compila. Si ottiene, infine, facendola breve, il programma desiderato. Ecco, con Csound il meccanismo è simile. Semplicemente ciò che si ottiene è un file audio..

E' importante ribadire che Csound è nato innanzitutto come compilatore che prendendo come parametri un file .orc ed un file .sco, è in grado di generare un file audio finale (aiff, .wav ecc....)

Oggi siamo arrivati alla versione 5 del linguaggio, versione che ha introdotto molte essenziali innovazioni.

• La prima novità è che Csound è diventato anche uno strumento adatto all'elaborazione del suono in tempo reale ( o lo sta diventando)

• Csound è ora un sistema che può essere incluso in altre applicazioni. Offre delle API che possono essere richiamate all'interno di programmi scritti in diversi linguaggi di programmazione (Python,Java,LISP...).

• Csound è un progetto open-source, che fa ampio uso di librerie standard quali la libreria grafica FLTK

6 di 109

Page 7: Corso Perfezionamento Informatica Musicale

Orientarsi tra le versioni di cSound

Navigando nel sito http://sourceforge.net relativo alla sezione di cSound, si può rimanere indecisi su quale pacchetto scaricare.

cSound è disponibile per sistemi Windows, Linux e Mac. Mentre per Linux e Mac, la scelta del pacchetto d'installazione è unica; per Windows abbiamo a disposizione due versioni: la versione -d e la versione -f. Come si evince dal testo sotto riportato, preso dalla FAQ di cSounds.com, la versione più adatta al realtime è la -f, mentre la -d permette, con i samples memorizzati a 64 bits un rendering più accurato (e quindi maggior potenza computazionale).

Installers with 'f' in the filename (short for "float") contain a Csound compiled so that audio samples are internally represented using single-precision (32-bit) floating-point numbers. This results in about 15% faster performance relative to the "d" versions on Windows and should have similar performance gains on other platforms.

Installers with 'd' in the filename (short for "double") contain a Csound compiled so that audio samples are internally represented using double-precision (64-bit) floating-point numbers. This results in about 15% slower performance relative to the single-precision version, but will give greater precision for calculations, especially in filter performance. (Note though that many filters have recently been changed to always use double-precision calculations where they are critical).

The float version is probably better for real-time performance although the double version is OK for "light" real-time usage. The double version is to be preferred for non-real-time rendering where it is available, especially for producing a "finished" rendition of a work

Installare Csound su Debian Linux

L'installazione di Csound su Debian Linux (distribuzione studio 64) non è proprio banale per un utente linux alle prime armi.In ogni caso i passaggi che ho effettuato sono stati i seguenti.

Nei prossimi articoli cercheremo di motivare meglio le istruzioni sotto riportate.

7 di 109

Page 8: Corso Perfezionamento Informatica Musicale

• Mi sono scaricato l'ultima versione di Csound da http://csound.sourceforge.net/#Downloads, nella fattispecie il file "Csound5.07-i386f.tar.gz", quindi mi sono copiato il file nella mia directory d'utente: /home/utente

• Ho aperto una finestra terminale root.

• Ho estratto i file dall'archivio .tar.gz con il solito comando tar -xvzf Csound5.07-i386f.tar.gz.

• Mi sono posizionato nella cartella d'estrazione (es. 64studio:/home/administrator/linux_f32) e ho digitato il comando ./installer

• Nella finestra che si è aperta con il precedente comando ho selezionato il checkbox "install in System files" e tutti gli altri checkbox

• Con il comando cp /opt/linux_f32/lib/libcsound.so.5.1 /usr/lib/libcsound.so.5.1 ho copiato la libreria libcsound.so.5.1. Ricordo che il file d'origine potrebbe essere in un altra cartella. L'obiettivo è mettere nella cartella delle librerie condivise di Debian, la libreria libcsound.so.5.1.

• Con il comando cd /usr/local/bin/bin sono entrato nella cartela contenente il programma csound

• Tramite gedit ho creato due semplici file .sco e .orc e li o salvati nella cartella /usr/local/bin/bin

Installazione di Csound 5 in ambiente Windows

In questo articolo vediamo come installare Csound 5 su una postazione Windows XP Professional.

Prima di installare cSound, se non lo abbiamo già installato sulla nostra macchina, occorre installare Python.Anche se nelle FAQ di cSound, Python viene indicato come opzionale, in realtà per i nostri futuri scopi, avere Python installato è necessario. Addirittura alcune versioni di cSound 5 proprio non funzionano senza l'interprete Csound installato (o meglio senza la libreria py.dll) .

Quindi innanzitutto andiamo sul sito

http://www.python.org/download/

e scarichiamoci la versione di Python 2.5.x con Windows Installer.

8 di 109

Page 9: Corso Perfezionamento Informatica Musicale

Installiamo il pacchetto Python seguendo le semplici ed immediate indicazioni.

Quindi procuriamoci l'ultima versione di cSound dal sito

http://csound.sourceforge.net/

Come abbiamo già scritto precedentemente i pacchetti di Csound a disposizione, allo stato attuale, sono due

Csound5.0.x-win32-f.exe e Csound5.0.x-win32-d.exe

Per capire le differenze tra le due versioni cito la risposta di Michael Gogins

Installers with 'f' in the filename (short for "float") contain a Csound compiled so that audio samples are internally represented using single-precision (32-bit) floating-point numbers. This results in about 15% faster performance relative to the "d" versions on Windows and should have similar performance gains on other platforms.Installers with 'd' in the filename (short for "double") contain a Csound compiled so that audio samples are internally represented using double-precision (64-bit) floating-point numbers. This results in about 15% slower performance relative to the single-precision version, but will give greater precision for calculations, especially in filter performance. (Note though that many filters have recently been changed to always use double-precision calculations where they are critical). The float version is probably better for real-time performance although the double version is OK for "light" real-time usage. The double version is to be preferred for non-real-time rendering where it is available, especially for producing a "finished" rendition of a work.

Dati gli interessi di Live-Electronics per le performance in tempo reale, scarichiamo la versione "f".

Quindi seguendo le semplici indicazioni installiamo il pacchetto Csound5.07.2-win32-f.exe (o successivo)

Strumenti e spartiti in cSound

cSound, come abbiamo già detto all'inizio di questo tutorial, appartiene alla famiglia di linguaggi di programmazione per la computer music di tipo "Music N". Tutti questi linguaggi partono dal concetto di strumento, da una parte, e di spartito o parte, dall'altra.

Dal punto di vista di un linguaggio di programmazione tradizionale lo strumento può essere pensato come il programma vero e proprio, ciò che implementa gli algoritmi di calcolo. E' la classica macchina di elaborazione che prende in input certi dati con lo scopo di produrre un determinato output.

9 di 109

Page 10: Corso Perfezionamento Informatica Musicale

Lo strumento agisce ed elabora la partitura.

La partitura può essera pensata come l'insieme dei dati principali su cui lo strumento agisce.

Un pCreare un primo file audio con cSound Scritto da Luca Cartolari giovedì 29 novembre 2007 In questo articolo vediamo come creare un primo file audio con Csound in ambiente Windows.

Mi limito, per ora, a elencare le operazioni pratiche da seguireDopo aver installato l'ultima versione di Csound creiamo due file di testo (il solito "Notepad", va benissimo).

Prova.orc; Initialize the global variables.sr = 44100kr = 4410ksmps = 10nchnls = 1

; Instrument #1 - a basic oscillator.instr 1 kamp = 10000 kcps = 440 ifn = 1

a1 oscil kamp, kcps, ifn out a1endin

e

Prova.sco

;Table #1, a sine wave.f 1 0 16384 10 1

; Play Instrument #1 for 2 seconds.i 1 0 2e

Salviamo i nostri due file nella sottocartella bin della cartella principale di cSound (Es. c:\programmi\csound\bin).Quindi apriamo il prompt dei comandi. (Start>Esegui>digitare cmd) Attraverso le opportune istruzioni cd ci posizionamo sotto la directory bin di Csound (Es. c:\programmi\csound\bin)A questo punto scriviamo

csound -W -oc:\prova.wav prova.orc prova.sco

e premiamo Invio

Dopo alcuni istanti cSound ha compilato e creato per noi il nostro primo file audio: il file prova.wav sotto la cartella C.\

rogramma cSound è quindi l'applicazione di uno o più strumenti ad una o più partiture. Ogni partitura del resto è sempre scritta per un determinato strumento.

10 di 109

Page 11: Corso Perfezionamento Informatica Musicale

Nei prossimi articolo vedremo come gli strumenti cSound vengano scritti o in appositi file di testo con estensione .orc oppure nella sezione CsInstruments di un file csd; inoltre vedremo come la partitura o score venga scritta o in appositi file di testo con estensione .sco oppure nella sezione CsScore di un file csd.

Creare un primo file audio con cSound

In questo articolo vediamo come creare un primo file audio con Csound in ambiente Windows.

Mi limito, per ora, a elencare le operazioni pratiche da seguireDopo aver installato l'ultima versione di Csound creiamo due file di testo (il solito "Notepad", va benissimo).

Prova.orc; Initialize the global variables.sr = 44100kr = 4410ksmps = 10nchnls = 1

; Instrument #1 - a basic oscillator.instr 1 kamp = 10000 kcps = 440 ifn = 1

a1 oscil kamp, kcps, ifn out a1endin

e

Prova.sco

;Table #1, a sine wave.f 1 0 16384 10 1

; Play Instrument #1 for 2 seconds.i 1 0 2e

Salviamo i nostri due file nella sottocartella bin della cartella principale di cSound (Es. c:\programmi\csound\bin).

11 di 109

Page 12: Corso Perfezionamento Informatica Musicale

Quindi apriamo il prompt dei comandi. (Start>Esegui>digitare cmd) Attraverso le opportune istruzioni cd ci posizionamo sotto la directory bin di Csound (Es. c:\programmi\csound\bin)A questo punto scriviamo

csound -W -oc:\prova.wav prova.orc prova.sco

e premiamo Invio

Dopo alcuni istanti cSound ha compilato e creato per noi il nostro primo file audio: il file prova.wav sotto la cartella C.\

Opzioni cSound da linea di comando

Come abbiamo visto cSound è un programma che può essere utilizzato direttamente dalla linea di comando

Le opzioni che possono essere utilizzate sulla linea di comando sono molte. E' possibile ricavare l'elenco completo dei diversi flag direttamente dal manuale di riferimento di cSound.

http://www.csounds.com/manual/html/CommandFlags.html

Nell'esempio precedentemente riportato

csound -W -oc:\prova.wav prova.orc prova.sco

sono stati usati due dei principali flag cSound

-W, che specifica che il formato del file prodotto da cSound è di tipo Microsoft Wav

-o. che specifica il nome (con path completo o relativo) del file di output.

Strumenti cSound

Programmare suoni con cSound significa innanzitutto realizzare strumenti.

12 di 109

Page 13: Corso Perfezionamento Informatica Musicale

Uno strumento cSound può essere pensato come il programma che a partire dai parametri introdotti nel file .sco o nella sezione CsScore del file .csd produce un output audio. Più semplicemente uno strumento Csound è uno strumento virtuale progettato per l'esecuzione della sua corrispondente parte strumentale.

Gli strumenti Csound vengono scritti o in file di testo dedicati, con estensione .orc o nell'apposita sezione CsInstruments di un file .csd.

Per definire uno strumento in cSound occorre utilizzare il costrutto instr n, dove n è un numero intero positivo.Ad esempio se voglio definire lo strumento 1 dovrò scrivere

instr 1

<ISTRUZIONI DI DEFINIZIONE DELLO STRUMENTO>

endin

Il costrutto instr è quindi l'accorgimento formale atto a contenere la definizone vera e propria dello strumento. Ad esempio l'esempio precedente dichiara che le istruzioni interne al costrutto instr/endin servono a definire lo strumento 1

Struttura di un file .csd

In questo articolo vediamo come è strutturato un file .csd.

Un file .csd (Unified cSound Format for Orchestras and Scores) compone in un unico file con struttura a marcatori: i flag della linea di comando di cSound, il contenuto del file '.sco' e il contenuto del file '.orc'.

Il file deve incominciare con il tag <CsoundSynthesizer> e terminare con </CsoundSynthesizer>. Tutti gli altri tag devono essere inclusi all'interno di questo tag principale.

Il tag <CsOptions></CsOptions> contiene i command line flags.I flag sono molti. Nell'esempio ne sono riportati 6.

-bNUMNumero di campioni audio per il buffer dell' I/O software. Per un uso di cSound in tempo reale occorre specificare un buffer il più piccolo possibile. Questo numero, multiplo di 2, dovrà essere settato ad un valore testato sperimentalmente di volta in volta in base agli opcode e ai calcoli dell'orchestra cSound realizzata. Un numero troppo piccolo potrà comportare perdita di dati.

-BNUMNumero di campioni audio per il buffer del DAC hardware. Per un uso di cSound in tempo reale

13 di 109

Page 14: Corso Perfezionamento Informatica Musicale

occorre specificare un buffer il più piccolo possibile. Questo numero, multiplo di 2, dovrà essere settato ad un valore testato sperimentalmente di volta in volta in base agli opcode e ai calcoli dell'orchestra cSound realizzata.Un numero troppo piccolo potrà comportare perdita di dati.

-odacNUMSpecifica il numero con cui è individuato da cSound il driver audio di output. La corretta scelta i questo driver permetterà o meno l'uso di cSound per il tempo reale

-idacNUMSpecifica il numero con cui è individuato da cSound il driver audio di input. La corretta scelta i questo driver permetterà o meno l'uso di cSound per il tempo reale.

-MNUMSpecifica il numero con cui è individuato da cSound il driver MIDI per l'elaborazione in tempo reale degli stream MIDI.

-mNUMSpecifica il livello di messaggistica di cSound durante l'elaborazione.

La sezione <CsInstruments> contiene la definizione dell'orchestra, ossia ciò che può venir scritto in un file .orc, autonomo.

La sezione <CsScore> contiene la definizione della partitura cSound, ossia ciò che può venir scritto in un file .sco autonomo.

Ecco un esempio completo di file .csd

<CsoundSynthesizer><CsOptions> -b80 -B160 -odac4 -iadc4 -M1 -m0</CsOptions><CsInstruments>;Pedale 121sr = 44100kr = 22050ksmps = 2nchnls = 2gaL init 0gaR init 0gkMute init 0

instr 1 gkMute chnget "mute" kVol chnget "volume" kTrik1 chnget "sampler1" kTrik2 chnget "sampler2" kTrik3 chnget "sampler3" kTrik4 chnget "sampler4" kTrik5 chnget "sampler5"

14 di 109

Page 15: Corso Perfezionamento Informatica Musicale

kFilters chnget "filters" klivemicro chnget "livemicro" knotamin chnget "n1" knotamax chnget "n2" if gkMute == 1 kgoto ESCI

asig1,asig2 ins asig = asig1 + asig2 aGate linseg 0, 2, 1, p3 - 4,1, 2, 0 aGate2 = a(kVol) ictlno =1 ichan = 1 knota ctrl7 ichan, ictlno, knotamin, knotamax

a1 = asig aRec1,koutrec1 sndloop a1, 1, kTrik1, 5, 0.05 aRec2,koutrec1 sndloop a1, 1, kTrik2, 7, 0.05 aRec3,koutrec1 sndloop a1, 1, kTrik3, 11, 0.05 aRec4,koutrec1 sndloop a1, 1, kTrik4, 13, 0.05 aRec5,koutrec1 sndloop a1, 1, kTrik5, 17, 0.05

kRec1 rms aRec1 * aGate2 kRec2 rms aRec2 * aGate2 kRec3 rms aRec3 * aGate2 kRec4 rms aRec4 * aGate2 kRec5 rms aRec5 * aGate2 k1 rms a1 if kFilters == 0 kgoto SALTA_FILTRI

ifdbgain1 = 0.96 a1 streson a1, knota, ifdbgain1 iord1 = 50 iskip1 = 0.90 ifdbgain2 = 0.96 aRec1 streson aRec1, knota, ifdbgain2 aRec2 streson aRec2, knota, ifdbgain2 aRec3 streson aRec3, knota, ifdbgain2 aRec4 streson aRec4, knota, ifdbgain2 aRec5 streson aRec5, knota, ifdbgain2 iord2 = 60 iskip2 = 0.99 kfeedback2 ctrl7 ichan, ictlno, 0.30, 0.99 aRec1 phaser1 aRec1,knota,iord2,kfeedback2,iskip2 aRec2 phaser1 aRec2,knota,iord2,kfeedback2,iskip2 aRec3 phaser1 aRec3,knota,iord2,kfeedback2,iskip2 aRec4 phaser1 aRec4,knota,iord2,kfeedback2,iskip2

15 di 109

Page 16: Corso Perfezionamento Informatica Musicale

aRec5 phaser1 aRec5,knota,iord2,kfeedback2,iskip2; gaL = a1 + aRec1 + aRec3 + aRec5; gaR = a1 + aRec2 + aRec4 + aRec5 SALTA_FILTRI: gaL = aRec1 + aRec3 + aRec5 gaR = aRec2 + aRec4 + aRec5 if klivemicro == 0 kgoto SALTA_LIVEMICRO_1 gaL = gaL + a1 gaR = gaR + a1

SALTA_LIVEMICRO_1: aRec1 gain aRec1 * aGate2, kRec1 aRec2 gain aRec2 * aGate2, kRec2 aRec3 gain aRec3 * aGate2, kRec3 aRec4 gain aRec4 * aGate2, kRec4 aRec5 gain aRec5 * aGate2, kRec5 a1 gain a1, k1 aL = aRec1 + aRec3 + aRec5 aR = aRec2 + aRec4 + aRec5 if klivemicro == 1 kgoto SALTA_LIVEMICRO_2 aL = aL + a1 aR = aR + a1 SALTA_LIVEMICRO_2: outs aL * aGate, aR * aGate ESCI:endin

instr 2

kGranule chnget "microsound"kAtt chnget "attacco"kRil chnget "rilascio"kPau chnget "pausa"kVolL chnget "volumeL"kVolR chnget "volumeR"if gkMute == 1 kgoto SALTAif (kGranule ==0) kgoto SALTAa1 = gaLa2 = gaRktempAtt = kAtt / 2krandAtt rand ktempAttktempAtt = kAtt + krandAtt

ktempRil = kRil / 2krandRil rand ktempRil

16 di 109

Page 17: Corso Perfezionamento Informatica Musicale

ktempRil = kRil + krandRil

ktempPau = kPau / 2krandPau rand ktempPauktempPau = kPau + krandPau

start:iPause = i(ktempPau) iDur1 = i(ktempAtt)iDur2 = i(ktempRil)iVolL = i(kVolL)iVolR = i(kVolR)igap = iDur1 + iDur2 + iPausetimout 0, igap, continuereinit start

continue: agateL linseg 0, iDur1 , iVolL, iDur2 , 0agateR linseg 0, iDur1 , iVolR, iDur2 , 0rireturn

outs a1 * agateL , a2 * agateRSALTA:endin

</CsInstruments>

<CsScore>

i1 0 900 i2 0 900

</CsScore>

</CsoundSynthesizer>

17 di 109

Page 18: Corso Perfezionamento Informatica Musicale

Configurazione di CSound per l'elaborazione in tempo reale del suono (Windows)

Configurazione di CSound5 per l'elaborazione in tempo reale del suono: CSound5Gui versione Microsoft Windows.

In questo breve articolo ci soffermeremo sulla configurazione di CSound5 per l'elaborazione in tempo reale di un suono live.Più precisamente configureremo CSound5Gui versione Microsoft Windows.Innanzitutto occorre specificare quali sono i driver che CSound5 deve utilizzare per l'input e per l'output.Aperto CSound5Gui è sufficiente cliaccare Options > CSound.Dalla versione 5.05 di CSound la configurazione è banale. Infatti è sufficiente entrare nella scheda Real Time Audio e scegliere gli opportuni Driver, dai due menu Output Device ed Input DeviceSe questo menu fosse inutilizzabile (come nella mia versione 5.06 ) occorre indicare nella sezione CsOptions del proprio file .csd il numero di driver di output (parametro -odac) e quello di input (-idac). Per capire quale numero scrivere, una soluzione empirica, ma efficace, può essere quella di mandare in errore il compilatore cSound, indicando un numero di driver scorretto (es. -odac1000). Tra i messaggi di errore, cSound evidenzierà anche i driver disponibili con il loro numero associato. A questo punto il gioco è fatto.

Questa è la configurazione di un mio recente file csd

<CsOptions> -b20 -B20 -odac4 -iadc4 -M1

</CsOptions

Questa è, invece, un'immagine della GUI di cSound.

18 di 109

Page 19: Corso Perfezionamento Informatica Musicale

Di seguito riporto come esempio un altro mio file .csd, utilizzato con cSound 5.0.x. E' un file che elabora un segnale di ingresso Mono. L'istruzione utilizzata è la classica in. L'output ottenuto è stereo (istruzione outs).

Per i nostri scopi la sezione CsOptions è fondamentale.Il flag -b indica in numero di campioni la capacità del buffer di esecuzione di CSound.Il flag -B indica invece in numero di campioni la capacità del buffer di esecuzione dell'interfaccia hardware. Esso deve essere un multiplo intero di -b. Solo l'opportuna sperimentazione ci permetterà di trovare i giusti valori per la nostra DAW. Tipicamente i driver ASIO sono quelli con una miglior risposta e quindi minor ritardo. Più i valori di -b e -B sono bassi più l'output audio sarà immediato e maggiore sarà il carico della CPU (quindi anche il rischio di errori di elaborazione)

<CsoundSynthesizer><CsOptions>-b20 -B40</CsOptions><CsInstruments>

19 di 109

Page 20: Corso Perfezionamento Informatica Musicale

sr = 44100kr = 2205ksmps = 20nchnls = 2

instr 1

kampMiL linseg 0, p3/6,1, p3/6, 0.6, p3/6 , 0.5, p3/6, 0, p3/6, 0, p3/6,0kampMiR linseg 0, p3/6, 0, p3/6, 0.6, p3/6 , 1, p3/6, 1, p3/6, 1, p3/6,0kampSiL linseg 0, p3/6, 0, p3/6, 0.6, p3/6 , 1, p3/6, 1, p3/6, 1, p3/6,0kampSiR linseg 0, p3/6, 1, p3/6, 0.6, p3/6 , 0.5, p3/6, 0, p3/6, 0, p3/6,0

iOrder=28iFeedback = 0.82ainput in k1 rms ainputipch = p4kNotaMi = cpspch(ipch)ipch = p5kNotaSi = cpspch(ipch)ipitchm = p6aMi = ainputaMi phaser1 aMi , kNotaMi, iOrder, iFeedbackifdbgain = 0.88aMi streson aMi, kNotaMi, ifdbgain aMi streson aMi, kNotaMi, ifdbgain aSi = ainputaSi phaser1 aSi , kNotaSi, iOrder,iFeedbackifdbgain = 0.88aSi streson aSi, kNotaSi, ifdbgain aSi streson aSi, kNotaSi, ifdbgain aOutMiL gain aMi , k1 * kampMiL aOutMiR gain aMi , k1 * kampMiR aOutSiL gain aSi , k1 * kampSiL aOutSiR gain aSi , k1 * kampSiR aL, aR reverbsc aOutMiL + aOutSiL, aOutMiR + aOutSiR, 0.85, 12000, sr, ipitchm, 1 outs aL,aRendin

</CsInstruments><CsScore>

i1 0 300 7.09 8.04 0.5e

</CsScore></CsoundSynthesizer>

20 di 109

Page 21: Corso Perfezionamento Informatica Musicale

Un semplic file .csd per il tempo-reale

In questo esempio viene illustrato un primo file .csd per l'uso di CSound in tempo reale

<CsoundSynthesizer><CsOptions> -b80 -B160 -odac4 -iadc4 -M1 -m0</CsOptions>

Commentiamo la sezione CsOptions. I flag -b -B settano le grandezze dei buffer software ed hardware. -odac4 e -idac4 individuano il numero dei driver per l'output e l'input audio. -M1 specifica il driver per l'input MIDI. -m0 indica nessun messaggio a video, da parte di cSound.

<CsInstruments>sr = 44100kr = 2205ksmps = 20nchnls = 2

sr indica la frequenza di campionamento audio.kr indica la frequenza di controllo.ksmps deve essere uguale a sr/krnchnls indica il numero di canali di uscita (1 mono, 2 stereo ecc...)

instr 1 asig1,asig2 ins outs asi1, asig2 endin

L'opcode ins legge, di default, il segnale stereo in ingresso, assegnandolo a due variabili audio. outs manda un segnale stereo all'output device.

</CsInstruments>

<CsScore>i1 0 60

La partitura esegue lo strumento 1 per 60 secondi.

</CsScore>

</CsoundSynthesizer>

21 di 109

Page 22: Corso Perfezionamento Informatica Musicale

Una semplice partitura cSound

Come abbiamo visto negli articoli precedenti, la sezione <CsScore> contiene la definizione della partitura cSound, ciò che può anche venir scritto in un file .sco autonomo.

<CsScore>i1 0 60</CsScore>

In questo esempio la partitura esegue lo strumento 1 per 60 secondi, a partire dall'istante (secondo) 0. Quindi un file .csd deve contenere almeno una riga che inizi con i: infatti una volta definito uno strumento devono essere specificati gli eventi sonori propri di quello strumento. Per emettere qualche suono il nostro strumento virtuale deve eseguire qualche cosa, non necessariamente delle note, ma un qualche tipo di evento sonoro.Ogni riga di tipo i-strumento ha tre parametri obbligatori, gli stessi riportati nell'esempio precedente:primo parametro (p1) indica il numero di strumento, secondo parametro (p2) indica l'istante di inizio di esecuzione dell'evento sonoro (es. istante 0),terzo parametro (p3) indica la durata di esecuzione (es. durata di 60 secondi).Nell'esempio seguente viene riportata una riga di tipo i-strumento con anche parametri non obbligatori.

instr 2 ifreq = cpspch(p4) knh = 3; ifn = 3 ifdbgain2 = p5 iGain = p6 iL = p7 iR = p8....................endin

::::::::::::::::::::::::::::::::::::::::::::::::::

i2 0 10 8.03 0.80 0.70 0.9 0.8

Si vede come ogni parametro passato a livello di score venga visto all'interno dello strumento con la sintassi pn. Ad esempio il parametro 4 con valore 8.03 viene visto dallo strumento 2 con la sintassi p4. Così a seconda dello strumento che creeremo potremo avere diversi parametri (p4, p5, p6 ....). Ogni parametro assumerà un significato diverso a seconda dello strumento che dovrà eseguire l'evento da esso rappresentato.

22 di 109

Page 23: Corso Perfezionamento Informatica Musicale

La codifica octave point pitch-class

Il tipico parametro p4 di un'istruzione i-statement rappresenta la nota che lo strumento cSound deve eseguire. Questa nota è spesso rappresentata in notazione con punto: l'octave point pitch-class notation.

Così:

8.00 = DO centrale del pianoforte (261.63 Hz)8.01 = DO# (277.18 Hz)8.02 = RE (293.67 Hz)

I numeri interi rappresentano l'ottava (8), mentre i decimali i semitoni. Aggiungendo più decimali è anche possibile riuscire a rappresentare musica microtonale.Ad esempio per rappresentare i quarti di noto si può usare la sequente sintassi

C4 = 8.00C4+ = 8.005 C# = 8.01

La maggior parte degli opcodes cSound richiede che la frequenza venga espressa in Hz.In cSound esiste l'espressione il convertitore cpspch, che converte ciò che è stato scrittto inpitch in cps (cycles per second).

ifreq = cpspch(p4)

Tipi di variabili in cSound

Nel comprendere il funzionamento di cSound di particolare importanza è il concetto di variabile.

Possiamo pensare le variabili come celle di memoria contenente valori. Nel tutorial di cSound leggiamo:variables are named cells containing numbers. In realtà esistono variabili Csound contenenti anche sequenze di caratteri (stringhe). Le variabili una volta istanziate, e quindi dal momento in cui esistono, mettono continuamente a disposizione il loro valore. A seconda del loro tipo, le variabili possono essere aggiornate con frequenza diversa. Ci sono variabili che possono modificare il loro valore solo al momento della creazione dell'orchestra (non del singolo strumento), variabili modificabili in fase di inizializzazione del singolo strumento (i-variables), variabili modificabili alla frequenza di controllo (k-variables), variabili modificabili alla frequenza audio (a-variables). Il nome di ogni i-variabile deve incominciare con la lettera "i". Le k-

23 di 109

Page 24: Corso Perfezionamento Informatica Musicale

variabili devono aver nomi che iniziano con la "k". Infine le variabili audio devono avere nomi che iniziano con la "a".

Le variabili permanenti (quelle del primo tipo) sono definite nel tutorial di cSound come "rsymbol". rsymbol is a special reserved symbol (e.g. sr, kr).

Le variabili possono essere divise in locali e globali. Le variabili locali sono variabili che esistono fino a quando l'istanza di un determinato strumento è attiva. Quelle globali, invece, sono variabili condivise tra tutte le istanze di un'orchestra. Queste variabili devono avere dei nomi che iniziano con la lettera "g" (gk..., gi....., ga ecc...).

global variables are cells that are accessible by all instruments. The names are either like local names preceded by the letter g, or are special reserved symbols. Global variables are used for broadcasting general values, for communicating between instruments (semaphores), or for sending sound from one instrument to another (e.g. mixing prior to reverberation). ,

Scrivere uno strumento cSound

Analizziamo un semplice strumento cSound.

instr 1aSuono oscil 10000,220,1out aSuonoendin

In questo esempio viene definito lo strumento instr1.oscil è uno dei più importanti opcode cSound. La sintassi generica degli opcode cSound è la seguente:

variabile opcode aromento_1, argomento_2, ...... argomento_n

In questo caso abbiamo l'opcode oscil, che simula un oscillatore al quale vengono passati tre argomenti: l'ampiezza 10000 (espressa in valori assoluti e non in db) del segnale generato, la frequenza 220 e il numero di funzione 1 (Questa funzione verrà poi definita in partitura). L'oscillatore oscil a partire dai suoi parametri produce un valore, depositato nella variabile aSuono.

L'opcode out invia il risultato depositato in aSuono alla scheda, per farcelo ascoltare.

24 di 109

Page 25: Corso Perfezionamento Informatica Musicale

Come si scrive una funzione

Le funzioni servono a creare forme d'onda di cui noi possiamo scegliere le caratteristiche.

Le funzioni per la creazione delle forme d'onda possono essere molto varie. Nell'esempio precedente avevamo stabilito che la forma d'onda era determinata dalla funzione numero 1.

aSuono oscil 10000,220,1

Creiamo dunque questa funzione numero 1.Scriveremo questa funzione, come qualsiasi altra all'inizio della sezione <CsScore> di un file .csd, oppure all'inizio di un file .sco.

f1 0 4096 10 1

f1 indica il numero della funzione (funzione 1). Ogni funzione deve essere identificata da un numero univoco.0 (creation time) indica da che momento nella partitura viene creata la funzione, se il numero fosse 3 questa funzione verrebbe creata al terzo secondo.4096 è il numero di punti che definiscono la forma d'onda nella tabella di lettura dell'eventuale oscillatore. In questo esempio, la nostra onda è una sinusoide tracciata nella tabella mediante 4096 punti. Nella maggior parte dei casi il numero di punti richiesto in una funzione è una potenza di due (256, 512, 1024, 2048,4096 etc.), in altri casi una potenza di due più uno, come vedremo. Il massimo valore possibile è 16777216.10 Questo quarto parametro è dedicato al metodo di generazione di forma d'onda o di funzione, detto GEN. Ogni GEN ha un suo numero con cui viene identificata (GEN01, GEN02...) ed utilizza un metodo diverso per la generazione di forme d'onda. Bene in questo caso abbiamo la GEN 10, che crea sinusoidi, perciò ogni volta che ci servirà una semplice sinusoide useremo questa GEN10.1 il fatto che ci sia solo un numero dopo il 10 significa che vogliamo una sola sinusoide. Se scrivessimo f1 0 4096 10 1 1 1, creeremmo tre sinusoidi in rapporto armonico tra loro (fondamentale, seconda e terza armonica) e con la stessa ampiezza = 1. Per ora accontentiamoci di una sola armonica.

Come si scrive una funzione

Le funzioni servono a creare forme d'onda di cui noi possiamo scegliere le caratteristiche.

Le funzioni per la creazione delle forme d'onda possono essere molto varie. Nell'esempio precedente avevamo stabilito che la forma d'onda era determinata dalla funzione numero 1.

25 di 109

Page 26: Corso Perfezionamento Informatica Musicale

aSuono oscil 10000,220,1

Creiamo dunque questa funzione numero 1.Scriveremo questa funzione, come qualsiasi altra all'inizio della sezione <CsScore> di un file .csd, oppure all'inizio di un file .sco.

f1 0 4096 10 1

f1 indica il numero della funzione (funzione 1). Ogni funzione deve essere identificata da un numero univoco.0 (creation time) indica da che momento nella partitura viene creata la funzione, se il numero fosse 3 questa funzione verrebbe creata al terzo secondo.4096 è il numero di punti che definiscono la forma d'onda nella tabella di lettura dell'eventuale oscillatore. In questo esempio, la nostra onda è una sinusoide tracciata nella tabella mediante 4096 punti. Nella maggior parte dei casi il numero di punti richiesto in una funzione è una potenza di due (256, 512, 1024, 2048,4096 etc.), in altri casi una potenza di due più uno, come vedremo. Il massimo valore possibile è 16777216.10 Questo quarto parametro è dedicato al metodo di generazione di forma d'onda o di funzione, detto GEN. Ogni GEN ha un suo numero con cui viene identificata (GEN01, GEN02...) ed utilizza un metodo diverso per la generazione di forme d'onda. Bene in questo caso abbiamo la GEN 10, che crea sinusoidi, perciò ogni volta che ci servirà una semplice sinusoide useremo questa GEN10.1 il fatto che ci sia solo un numero dopo il 10 significa che vogliamo una sola sinusoide. Se scrivessimo f1 0 4096 10 1 1 1, creeremmo tre sinusoidi in rapporto armonico tra loro (fondamentale, seconda e terza armonica) e con la stessa ampiezza = 1. Per ora accontentiamoci di una sola armonica.

Variabili di controllo in cSound

Se una variabile audio è tipicamente utilizzata per memorizzare segnali audio, le variabile di controllo possono servire a molti scopi differenti.

Una variabile di controllo viene aggiornata alla frequenza di controllo. Come abbiamo visto la frequenza di controllo è in genere più bassa di quella di campionamento ed è specificata dal comando iniziale kr=n oppure come valore implicito risultante di sr/ksmps.Nell'esempio seguente viene creato un segnale di controllo per realizzare un glissando.

<CsoundSynthesizer><CsOptions> -W -o C:\tone.wav</CsOptions><CsInstruments>sr = 44100ksmps = 10nchnls = 1 instr 1kglis line 220, p3, 440 ;Creazione di un segmento che varia linearmente da 220 a 400 nel tempo p3.

26 di 109

Page 27: Corso Perfezionamento Informatica Musicale

;I risultati affluiscono nella variabile di controllo kglis.a1 oscil p4, kglis,1 ;Gestione della frequenza tramite il segmento sopra descritto (memorizzato in kglis).adeclick linen 1,0.02, p3, 0.02 out a1*adeclick endin</CsInstruments>

line è un opcode che genera un segmento. Come tutti gli opcode, line vuole alcuni argomenti, cioè ha bisogno di alcuni dati per operare. Gli argomenti di line sono: valore iniziale, tempo (per arrivare dal valore iniziale a quello finale), valore finale. Nell'esempio line crea un segmento che va da 220 Hz a 440 Hz. Il risultato di questa operazione viene depositato in kglis. Successivamente i dati contenuti in kglis vengono inseriti nel nostro oscillatore, al posto del secondo parametro (quello per la frequenza).Quindi dal momento che questo segmento che va da 220 a 440 viene utilizzato per la frequenza, crea un glissando per ogni nota che suonerà quello strumento.In quanto tempo arriverà da 220 a 440 Hz quella nota? Nel tempo p3, che è specificato come secondo argomento di line. Come sappiamo il parametro 3 di una score indica sempre la durata di una nota. Ogni nota di questo strumento glisserà quindi da 220 a 440 Hz nel tempo della sua durata (p3).

Variabili di controllo: inviluppi d'ampiezza

In questo ulteriore esempio tratto da

http://www.lim.dico.unimi.it/membri/elisa/csound0708/Lez02/Esempi01/02_inviluppo.csd

Viene illustrata una variabile di controllo che crea una dinamica interna al suono, cioè un inviluppo, l'ampiezza del suono cambierà nel tempo della sua esecuzione.

<CsoundSynthesizer><CsOptions> -W -o C:\tone.wav</CsOptions><CsInstruments> sr = 44100 ksmps = 10 nchnls = 1 instr 1 kenv line 0,p3,10000 ;Creazione di un segmento che varia linearmente da 0 a 10000 nel tempo p3. ;I risultati affluiscono nella variabile di controllo kenv.a1 oscil kenv,220,1 ;Gestione dell'ampiezza tramite il segmento sopra descritto (memorizzato in kenv).adeclick linen 1,0.02, p3, 0.02 out a1*adeclick ; endin </CsInstruments>

27 di 109

Page 28: Corso Perfezionamento Informatica Musicale

<CsScore>f1 0 4096 10 1 i1 0 3 ; frequenza fissa a 220, ampiezza che varia da 0 a 10000 in 3 secondii1 4 10 </CsScore></CsoundSynthesizer>

Dove

linen Apply a straight line rise and decay pattern to an input amp signal.kr linen kamp, irise, idur, idecar linen xamp, irise, idur, idecirise: Rise time in seconds. A zero or negative value signifies no rise modification.idur: Overall duration in seconds. A zero or negative value will cause initialization to be skipped.idec: Decay time in seconds. Zero means no decay. An idec > idur will cause a truncated decay.

Segnali di controllo: stereo, tremolo, vibrato

Come abbiamo visto in questa serie di articoli, la funzione di un segnale di controllo non è quella di suonare, quanto piuttosto quella di generare valori che servono a pilotare altre unità. In questo articolo vediamo ulteriori esempi di uso di variabili (segnali) di controllo.

Il vibrato

Il vibrato è una deviazione di frequenza. L'ampiezza della deviazione di frequenza dipende dall'ampiezza dell'oscillazione, la velocità del vibrato dipende dalla frequenza dell'oscillazione.

instr 1kvibrato oscil 2,3,1asuono oscil 10000,220 + kvibrato, 1out asuonoendin

In questo esempio la frequenza centrale è di 220 Hz. Maggiore è l'ampiezza dell'oscillazione, maggiore è la deviazione dalla frequenza centrale. L'ampiezza del'oscillatore modulante è 2, in questo esempio, con valori estremi +2 e -2. Le ampiezze di kvibrato vengono quindi sommate alla frequenza centrale: il vibrato quindi oscillerà tra 218 Hz e 222 Hz.. Qual'è la velocità di vibrazione? La velocità è di 3 cicli al secondo. Pertanto il segnale audio risultante compirà il seguente ciclo 3 volte al secondo: 220 Hz - 222Hz - 220Hz - 218 Hz -220Hz.

Il tremolo

Per produrre un tremolo avremo bisogno di modulare l'ampiezza (non più la frequenza come nel

28 di 109

Page 29: Corso Perfezionamento Informatica Musicale

caso del vibrato) del segnale portante.

instr 2ktremolo oscil .2,2,1ktremolo = ktremolo + 1 ; oscilla fra 1 + .2= 1.2 e 1 - .2=0.8asuono oscil 10000*ktremolo,220,1endin

Stereo

Per valorizzare qualsiasi effetto stereofonico occorrerà rendere modificabile nel tempo i valori d'ampiezza dei due canali stereo.In questo esempio si ottiene uno spostamento stereofonico continuo grazie all'uso di un oscillatore.

instr 3kstereo oscili .5,2,1kstereo = kstereo + .5asuono oscili 10000,220,2outs asuono * kstereo, asuono * (1 - kstereo)endin

Sintesi additiva con cSound

La sintesi additiva è un tipo di sintesi con la quale si può creare una forma d'onda complessa a partire dalla somma di forme d'onda semplici, ad esempio una somma di sinusoidi. E’ stata il primo metodo di sintesi usato nella musica elettronica. Ovviamente è possibile utilizzare anche suoni non solo puri ma complessi.Tali suoni possono avere componenti in rapporto di frequenza intero o no.

www.lim.dico.unimi.it/membri/elisa/csound0708/Lez02/Slides_Additiva.pdf

Come abbiamo visto precedentemente la sintesi additiva più semplice può essere implementata tramite l'uso della GEN10, realizzando una sintesi additiva a spettro fisso con sinusoidi pure in rapporto armonico tra loro.

E' possibile creare suoni di una certa complessità semplicemente modificando l'ampiezza delle diverse armoniche.

Con la funzione seguente otteniamo un' onda a dente di sega f1 0 4096 10 10 5 3.3 2.5 2 1.6 1.4 1.25 1.1 1Con la funzione seguente otteniamo un' onda quadra f1 0 4096 10 10 0 3.3 0 2 0 1.4 0 1.1

29 di 109

Page 30: Corso Perfezionamento Informatica Musicale

Sintesi additiva a spettro variabile

Rende variabile nel tempo l’ampiezza delle componenti armoniche. Generando suoni il cui timbro varia nel tempo.Si ottiene così una grande varietà di timbri, più vicniai suoni naturali, grazie alla variazione nel tempo dell'ampiezzadelle componenti armoniche.

Consideriamo delle componenti armoniche in rapporto intero rispettoalla fondamentale.instr 1kamp1 linseg 0,1,10000,p3-1,0;inviluppo di ampiezza per la fondamentalekamp2 linseg 0,2,6000,p3-2,0;inviluppo di ampiezza per la III armonicakamp3 linseg 0,3,8000,p3-3,0;inviluppo di ampiezza per la V armonicaa1 oscil kamp1,200,1 ;fondamentalea2 oscil kamp2,600,1 ;III armonicaa3 oscil kamp3,1000,1 ;V armonicaaout = a1+a2+a3 ;somma delle tre armonicheout aoutendin

Per la comprensione dell'esempio ricordo la serie delle armoniche:f(fondamentale), 2*f(seconda arm.), 3*f, 4*f, 5*f,6*f, ...L’evoluzione temporale indipendente di ogni componente è una caratteristica fondamentale dei suoni naturali.

Da quanto visto dovrebbe essere chiaro che le due orchestre seguenti ci permettono di ottenere il medesimo risultato sonoro

;orchestra instr 1 a1 oscil 15000,200,1 out a1 endin ;score f1 0 4096 10 1 0 1 0 1 i1 0 8

;orchestra instr 1 a1 oscil 5000,200,1;fondamentale a2 oscil 5000,600,1;III armonica a3 oscil 5000,1000,1 ;V armonica aout = a1+a2+a3 out aout endin ;score

30 di 109

Page 31: Corso Perfezionamento Informatica Musicale

f1 0 4096 10 1 i1 0 8

I battimenti illustrati in questo esempio, sempre di Elisa Russo, sono un caso particolare di sintesi additiva.

<CsoundSynthesizer><CsOptions> -W -o C:\tone.wav</CsOptions><CsInstruments> sr = 44100 ksmps = 10 nchnls = 1 instr 1 k4arm linseg 440,p3/2,444,p3/2,440afond oscili 5000,440,1arm4 oscili 5000,k4arm,1adeclick linen 1,0.02, p3, 0.02out (afond+arm4)*adeclickendin </CsInstruments><CsScore>f1 0 4096 10 1 i1 0 10</CsScore></CsoundSynthesizer>

GEN09 e GEN19

Mentre la GEN10 usa un solo campo per definire una sinusoide, la GEN09 ne utilizza tre: numero della componente, ampiezza relativa alla componente, fase iniziale della componente. Ciò consente di scrivere le componenti in qualsiasi ordine e di utilizzare la fase.Per esempio

f1 0 4096 09 1 1 180

è una sinusoide che inizia con fase a 180 gradi, quindi prima il semiperiodo negativo e poi quello positivo

La GEN19 consente d'indicare l'offset di corrente continua della componenente (una quantità costante sommata a tutta la funzione), applicata dopo il riscalamento.

<CsoundSynthesizer>

31 di 109

Page 32: Corso Perfezionamento Informatica Musicale

<CsOptions> -W -o C:\tone.wav</CsOptions><CsInstruments> sr = 44100 ksmps = 10 nchnls = 1 instr 1 ;usa GEN9a1 oscil 10000,220,1 adeclick linen 1,0.02, p3, 0.02 out a1*adeclick endin instr 2 ;usa GEN10a2 oscil 10000,220,2 adeclick linen 1,0.02, p3, 0.02 out a2*adeclick endin instr 3 ;usa GEN19a3 oscil 10000,220,3 adeclick linen 1,0.02, p3, 0.02 out a3*adeclick endin</CsInstruments><CsScore>f1 0 4096 9 1 3 0 3 1 0 9 .3333 180f2 0 4096 -10 1 .5 .33 .25f3 0 4096 19 .5 1 270 1i1 0 3 i2 4 3 i3 8 3 ;(se il numero di componente è 0.5 viene tracciato solo mezzo ciclo)</CsScore></CsoundSynthesizer>

Oscillatori complessi: buzz e gbuzz

buzz e gbuzz sono oscillatori che generano una serie di armoniche sinusoidali dellastessa ampiezza (buzz) o cosinusoidali di ampiezza variabile conl’ordine dell’armonica (gbuzz).

a1 buzz xamp, xfreq, knh, ifna1 gbuzz xamp, xfreq, knh, klh, km, ifn

knh numero delle armoniche desiderateklh numero d'ordine della più bassa armonica desiderata. km moltiplicatore della serie dei coefficienti di ampiezza delle armoniche, Si tratta di una serie esponenziale: se la klh-esima armonica

32 di 109

Page 33: Corso Perfezionamento Informatica Musicale

ha ampiezza A, la klh+n armonica avrà ampiezza A * kmn

I due esempi seguenti ci permettono di ottenere lo stesso risultato.

a1 buzz iamp, ifrq, 10, 1con la funzionef1 0 8192 10 1

e

a1 oscil iamp, ifrq, 2con la funzionef2 0 8192 10 1 1 1 1 1 1 1 1 1 1

Infine riporto un esempio più articolato da

http://iainmccurdy.org/csound.html

;Written by Iain McCurdy, 2006

<CsoundSynthesizer>

<CsOptions>-odevaudio -b400</CsOptions>

<CsInstruments>

sr = 44100 kr = 4410ksmps = 10nchnls = 2

;FLTK INTERFACE CODE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LABEL | WIDTH | HEIGHT | X | Y FLpanel "buzz", 500, 150, 0, 0

;SWITCHES ON | OFF | TYPE | WIDTH | HEIGHT | X | Y | OPCODE | INS | STARTTIM | IDURgkOnOff,ihOnOff FLbutton "On/Off", 1, -1, 2, 150, 30, 0, 0, 0, 1, 0, -1

;NUMBER DISPLAY BOXES WIDTH | HEIGHT | X | Yidamp FLvalue " ", 100, 20, 0, 80idfreq FLvalue " ", 100, 20, 0, 130

;SLIDERS MIN | MAX | EXP | TYPE | DISP | WIDTH | HEIGHT | X | Ygkamp, ihamp FLslider "Amplitude", 0, 10000, 0, 5, idamp, 500, 30, 0, 50

33 di 109

Page 34: Corso Perfezionamento Informatica Musicale

gkfreq, ihfreq FLslider "Oscillator Frequency", 1, 5000, -1, 5, idfreq, 500, 30, 0, 100

;COUNTERS MIN | MAX | STEP1 | STEP2 | TYPE | WIDTH | HEIGHT | X | Y | OPCODEgkharm, ihharm FLcount "No. of Harmonics", -1, 80, 1, 2, 2, 120, 30, 380, 0, -1

;SET INITIAL VALUES VALUE | HANDLE FLsetVal_i 7000, ihamp FLsetVal_i 30, ihharm FLsetVal_i 100, ihfreq

FLpanel_end ;END OF PANEL CONTENTS

;INSTRUCTIONS AND INFO PANEL FLpanel " ", 500, 240, 512, 0;TEXT BOXES TYPE | FONT | SIZE | WIDTH | HEIGHT | X | Yih FLbox " Miscellaneous Waveforms : buzz ", 1, 5, 14, 490, 15, 5, 0ih FLbox "-------------------------------------------------------------", 1, 5, 14, 490, 15, 5, 20ih FLbox "Buzz creates a composite tone of harmonically related sine ", 1, 5, 14, 490, 15, 5, 40ih FLbox "wave partials. ", 1, 5, 14, 490, 15, 5, 60ih FLbox "The user is given control of the number of partials required ", 1, 5, 14, 490, 15, 5, 80ih FLbox "(from the fundemental upwards) and of the the amplitude and ", 1, 5, 14, 490, 15, 5, 100ih FLbox "the fundemental frequency of the tone. ", 1, 5, 14, 490, 15, 5, 120ih FLbox "Buzz requires the user to first supply it with a sine ", 1, 5, 14, 490, 15, 5, 140ih FLbox "waveform via a function table (probably GEN 10). This table ", 1, 5, 14, 490, 15, 5, 160ih FLbox "should not be too small, sizes of 8192 and upwards are ", 1, 5, 14, 490, 15, 5, 180ih FLbox "recommended. ", 1, 5, 14, 490, 15, 5, 200ih FLbox "Buzz provides a useful source for subtractive synthesis. ", 1, 5, 14, 490, 15, 5, 220 FLpanel_end

FLrun ;RUN THE FLTK WIDGET THREAD;END OF FLTK INTERFACE CODE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

instr 1

34 di 109

Page 35: Corso Perfezionamento Informatica Musicale

if gkOnOff!=-1 kgoto CONTINUE ;IF FLTK ON/OFF SWITCH IS NOT OFF SKIP TO 'CONTINUE' LABEL turnoff ;TURNOFF INSTRUMENTCONTINUE: ;LABELifn = 2 ;FUNCTION TABLE USED BY BUZZ OPCODE;OUTPUT OPCODE AMPLITUDE | FREQUENCY | NO.OF HARMONICS | FUNCTION_TABLEasig buzz gkamp, gkfreq, int(gkharm), ifn outs asig, asig ;SEND AUDIO OUTPUT TO THE SPEAKERS endin

</CsInstruments>

<CsScore>f2 0 131072 10 1 ;SINE WAVEf 0 3600 ;DUMMY SCORE EVENT - ALLOW REALTIME PERFORMANCE FOR UP TO 1 HOUR </CsScore>

</CsoundSynthesizer>

Gestione delle cartelle in cSound (Windows) Scritto da Luca Cartolari venerdì 11 luglio 2008 Finchè tutti i file rimangono nella stessa cartella del programma cSound, non c'è bisogno di particolari attenzioni. Le cose cambiano, ad esempio, quando si vuole cambiare cartella per i files prodotti o utilizzati da cSound.

In ambiente windows, se si desidera indicare una specifica cartella in cui cui cSound deve salvare i files audio prodotti, occorre creare una variabile d'ambiente SFDIR (Sound File Directory). Sound Sample Directory (SSDIR) è la cartella dove devono essere posti i soundfile. Sound Analysis Directory (SADIR) è la cartella dove verranno posti i files di analisi generati da cSound

In Windows Xp:Pannello di controllo > Sistema > scheda Avanzate > pulsante Variabili d'Ambiente > Variabili di sistema > Aggiunta di SFDIR con relativo percorso

Gestione delle cartelle in Csound (Windows)

Finchè tutti i file rimangono nella stessa cartella del programma cSound, non c'è bisogno di particolari attenzioni. Le cose cambiano, ad esempio, quando si vuole cambiare cartella per i files prodotti o utilizzati da cSound.

35 di 109

Page 36: Corso Perfezionamento Informatica Musicale

In ambiente windows, se si desidera indicare una specifica cartella in cui cui cSound deve salvare i files audio prodotti, occorre creare una variabile d'ambiente SFDIR (Sound File Directory). Sound Sample Directory (SSDIR) è la cartella dove devono essere posti i soundfile. Sound Analysis Directory (SADIR) è la cartella dove verranno posti i files di analisi generati da cSound

In Windows Xp:Pannello di controllo > Sistema > scheda Avanzate > pulsante Variabili d'Ambiente > Variabili di sistema > Aggiunta di SFDIR con relativo percorso

Gestione delle cartelle in Csound (Linux Debian)

In ambiente Linux Debian (e quindi anche Linux 64Studio), se si desidera indicare una specifica cartella in cui cui cSound deve salvare i files audio prodotti, occorre creare una variabile d'ambiente SFDIR (Sound File Directory)

Inoltre

una variabile d'ambiente SSDIR (Sound Sample Directory) per la cartella dove devono essere posti i soundfile. una variabile d'ambiente SADIR (Sound Analysis Directory) per la cartella dove verranno posti i files di analisi generati da cSound

Per farlo occorre:

Aprile la console terminale da rootScrivere il comando gedit /etc/bash.bashrc

Editare

export SSDIR=/home/administrator/audioexport SFDIR=/home/administrator/audioexport SADIR=/home/administrator/audio

dove /home/administrator/audio è la mia cartella audio.

Sintesi sottrattiva

36 di 109

Page 37: Corso Perfezionamento Informatica Musicale

La sintesi sottrattiva nasce dall’idea di poter creare un suonosottraendo ampiezza ad alcune componenti spettrali di un altrosuono timbricamente più complesso di quello da ottenere, attraverso l’uso di filtri (da cui dipende la modifica del timbro).

www.lim.dico.unimi.it/membri/elisa/csound0708/Lez03/Slides_Sottrattiva.pdf

Disponendo di un suono con uno spettro molto ricco, è possibileottenere qualsiasi spettro costituito da un sottoinsieme dellecomponenti (armoniche o non armoniche) del suono originale.Questa procedura sottrattiva di frequenze è messa in attotramite particolari dispositivi che lasciano passare certe frequenze piuttosto che altre.

Nella sintesi sottrattiva sono di particolare aiutoquegli opcodes csound in grado di generare segnalicasuali,) con compresenza di tutte le frequenze udibili.

;strumentoinstr 1a1 rand p4out a1endin;scorei1 0 3 20000

Un filtro può lavorare non solo sul campione di suono corrente, maanche su uno o più campioni precedenti che vengono conservati inuno spazio di memoria interno al filtro.L’argomento iskip, utilizzato dalla maggior parte delleimplementazioni di filtri con Csound, determina se lo spazio dimemoria interno al filtro vada azzerato ad ogni nota oppure no, aseconda che il suo valore sia 0 (non c’è una coda sonora relativa allanota precedente) o 1 (i campioni precedenti vengono conservati inuno spazio di memoria interno al filtro).

FILTRO PASSA-BASSO: attenua tutte le frequenze al di sopra dellafrequenza di taglio.La curva di taglio è tale per cui alla frequenza doppia di quella di taglio l’attenuazione è di 6 dB, a quella quadrupla è di 12 dB e così via.

ares tone asig, khp [, iskip]

instr 1a1 rand 20000afilt tone a1,1000out afiltendin

FILTRO PASSA-ALTO: attenua tutte le frequenze al di sotto della

37 di 109

Page 38: Corso Perfezionamento Informatica Musicale

frequenza di taglio.La curva di taglio è tale per cui alla frequenza che è la metà diquella di taglio l’attenuazione è di 6 dB, a quella che è un quarto èdi 12 dB e cos` via.

ares atone asig, khp [, iskip]

instr 1a1 rand 20000afilt atone a1,1000out afiltendin

Filtro di secondo ordine: attenuazione doppia rispetto a filtro diprimo ordine.Filtro di terzo ordine: attenuazione tripla rispetto a filtro di primoordine.

instr 3 ;passa-alto II ordinea1 rand 20000afilt atone a1,1000afilt2 atone afilt,1000out afilt2endin

instr 4 ;passa-basso III ordinea1 rand 20000afilt tone a1,1000afilt2 tone afilt,1000afilt3 tone afilt2,1000out afilt3endin

Filtro passa banda: Consente di attenuare le frequenze al di sopra e al di sotto di unacerta banda.

ares reson asig, kcf, kbw [, iscl] [, iskip]

L’unica frequenza che rimane inalterata è quella centrale (kcf).La larghezza di banda di un filtro passa-banda (kbw) ideale del primoordine prevede che i suoi estremi abbiano un’ampiezza di -3dBrispetto alla frequenza centrale.

I tre valori codificati per il riscalamento (iscl) sono: 0 = nessun riscalamento; 1 = riscalamento in modo tale che l’ampiezza di picco del segnale filtrato sia la stessa della parte del segnale d’ingresso che ricade nella banda passante del filtro; 2 = riscalamento in modo tale che il valore efficace (RMS) del

38 di 109

Page 39: Corso Perfezionamento Informatica Musicale

segnale filtrato sia lo stesso del segnale d’ingresso.

Sintesi sottrattiva e filtri risonanti

La sintesi sottrattiva è una delle tecniche di sintesi più utilizzate. Consiste nel ricavare da un suono di partenza (spesso del rumore bianco) un suono finale, sottraendo dalla sorgente alcune frequenze ed amplificandone altre. Per la sintesi sottrattiva CSound mette a disposizione molti opcode.

Opcode stresonares streson asig, kfr, ifdbgain

L'opcode streson simula la risonanza tipica di uno strumento a corde. Evidenzia la frequenza specificata da kfr filtrando il segnale asig. La risonanza è tanto più forte quanto il parametro ifdbgain si avvicina a 1. Se ifdbgain tende a 0 il segnale d'ingresso rimane invariato. Nell'esempio seguente la frequenza di risonanaza è il do centrale 8.00

<CsInstruments>..........................instr 1 asig in aGate linseg 0, 2, 1, p3 - 4, 1, 2, 0 k1 rms (asig * aGate) asig gain asig, k1 inota1 = cpspch(p4) ifdbgain = 0.94 a1 = asig a1 streson a1, inota1, ifdbgain a1 gain a1, k1 outs a1, a1 endin</CsInstruments><CsScore>i1 0 10 8.00</CsScore>

Opcode phaser1ares phaser1 asig, kfreq, kord, kfeedback [, iskip]

L'opcode phaser1 implementa una catena di filtri collegati in serie che colorano il segnale d'ingresso asig con la frequenza specificata da kfreq. Il numero di filtri in catena è specificato da kord. Il parametro kfeedback, che varia da -1 a +1, specifica la presenza o meno di feedback nell'input dei singoli filtri in catenza. iskip indica se mantenere o meno uno spazio di memorizzazione per preservare il precedente segnale nella catenza dei filtri. Il default 0 non permette la memorizzazione di alcun valore. Valori diversi dallo 0 implicano la parziale

39 di 109

Page 40: Corso Perfezionamento Informatica Musicale

permanenza del segnale audio precedente nella catenza dei filtri. Con iskip =0 il segnale di uscita avrà un sostegno più breve, con un valore diverso da 0 verrà incrementato il sostegno del segnale.

instr 1 asig in aGate linseg 0, 2, 1, p3 - 4, 1, 2, 0 k1 rms (asig * aGate) asig gain asig, k1 inota1 = cpspch(p4) iord = 20 kfeedback = 0.9 iskip = 0.99 a1 = asig a1 phaser1 a1,inota1,iord,kfeedback,iskip a1 gain a1, k1 outs a1, a1 endin

L'opcode comb

L'opcode comb è un tipo di filtro risonante. E' essenzialmente una linea di ritardo con feedback, come illustrato nella figura seguente

http://www.csounds.com/chapter1/index.html

Come si può vedere il segnale entra nella linea di ritardo ed il suo ritardo, dopo averlo moltiplicato con un valore di guadagno (il fattore di feedback), viene messo in feedback nuovamente con il segnale d'ingresso.

L'opcode csound ha la seguente sintassi

a2 comb a1, krvt,ilpt

a2 segnale audio filtratto

40 di 109

Page 41: Corso Perfezionamento Informatica Musicale

krvt -- the reverberation time (defined as the time in seconds for a signal to decay to 1/1000, or 60dB down from its original amplitude). ilpt -- loop time in seconds, which determines the “echo density” of the reverberation.

Come si può vedere dall'immagine riportata la curva di risposta di comb è una sequenza di impulsi ugualmente distanziati dall'intervallo di tempo specificato da ilpt.Questo parametro stabilisce quindi la frequenza di risonanza del filtro, che è data da 1/lpt. Se si desidera settare comb su una certa risposta di frequenza si potrà utilizzare un codice simile.

ifreq = cpspch(p4) ilpt = 1 / ifreq a2 comb a1, krvt,ilpt

Naturalmente se il valore di ilpt è lungo, invece di avvertire una coloritura del segnale avvertiremo degli echi distanziati tra loro da ilpt secondi.

Sintesi vettoriale

La sintesi vettoriale è una variante della sintesi additiva. Se si opera una dissolvenza incrociata fra più tabelle, si parla di sintesi vettorialeScrivere uno strumento che implementi questo tipo di sintesi significa sommare suoni diversi suoni diversi che hanno inviluppi scritti in modo tale che i suoni stessi siano in dissolvenza incrociata, si tratta solo di studiare da quale tabella prenderel'attacco, quanto deve durare, in quanto tempo si svolge la dissolvenza incrociata con il secondo suono, quale sia il secondo suono, qual'è il suo inviluppo fino alla sua dissolvenza ecc...

Modulazione ad anello

La modulazione ad anello è una delle tecniche di sintesi storiche, utilizzata tra gli altri da K.Stockhausen in molti suoi pezzi elettronici degli anni '60 e '70, tra cui KontaKte, Mantra, Hymnen. Consiste nella moltiplazione di due segnali bipolari, uno portante (C) e uno Modulante (M)

Il segnale portante (C) è tipicamente il segnale principale con uno spettro armonico ricco, mentre quello modulante (M) è tradizionalmente una sinusoide. La formula della modulazione ad

41 di 109

Page 42: Corso Perfezionamento Informatica Musicale

anello è quindi semplicemente:

C x M

Quando la frequenza del segnale modulante è sotto i 20Hz, l'effetto che si ottiene è il classico tremolo. Quando M ha una frequenza udibile, il timbro di C cambia. Per ogni componente sinusoidale di C, il segnale modulante M produce due nuovi segnali laterali uno uguale alla somma di C ed M, l'altro uguale alla loro differenza. Un'altra caratteristica della modulazione ad anello è che nello spettro complessivo risultante non compariranno nè il segnale modulante nè il segnale portante. Inoltre se i due segnali sono in un rapporto esprimibile con un numero razionale, i segnali risultanti saranno in rapporto armonico, altrimenti verranno generate delle componenti in rapporto non armonico.

Per fare un esempio, se C è una sinusoide con frequenza 440 e M un'altra sinusoide con frequenza 220, le risultanti saranno di frequenza 660 e 220. D

Il comportamento della modulazione ad anello è facilmente comprensibile tenendo presente la seguente formula di Werner, derivata dalle note formule di prostaferesi.

Concludo riportando un esempio di codice cSound che implementa una modulazione ad anello. La modulazione è attivata in base al valore della variabile del canale software kRing. La frequenza del segnale modulante è letta via MIDI tramite l'istruzione ctrl7 . Il segnale modulante è una semplice sinusoide. Mentre il segnale portante è il segnale stereo a2L a2R.

kRing chnget "Ring"

if kRing != 1 kgoto END_RINGif kRing == 1 kgoto START_RING

START_RING: kFre ctrl7 ichan, ictlno2,220, 440

abimod oscili 5000, kFre, 1

kL rms a2L kR rms a2R a2L = a2L * abimod a2R = a2R * abimod a2L gain a2L, kL a2R gain a2R, kREND_RING:

42 di 109

Page 43: Corso Perfezionamento Informatica Musicale

Orchestra per la FM semplice

Come si può vedere dal precedente diagramma di flusso, la sintesi per modulazione di frequenza (FM) semplice può essere pensata come l'alterazione o la distorsione della frequenza di un oscillatore a causa del valore d'ampiezza di un segnale modulante. In altre parole la sintesi per modulazione di frequenza si ottiene con un'amipezza di vibrato tanto alta da rientrare nel campo delle frequenze udibili.

Per ottenere una modulazione di frequenza semplice si utilizzano tipicamente due oscillatori sinusoidali: un'oscillatore portante (Carrier Oscillator) ed un oscillatore modulante (Modulating Oscillator). Una frequenza portante fc viene sommata all'ouput dell'oscillatore modulante. Il risultato è passato come frequenza di input all'oscillatore portante.

Se l'ampiezza del segnale modulante è 0 (ossia quando il valore d è 0), non c'è modulazione e l'output dell'oscillatore portante è semplicemente uguale all'uscita di un oscillatore con frequenza fc, ampiezza AMP e forma d'onda ifn1. Quando il segnale modulante è diverso da 0 avviene la modulazione vera e propria. Più d è alto più aumenta la distorsione del segnale dell'oscillatore

43 di 109

Page 44: Corso Perfezionamento Informatica Musicale

portante.

La modulazione di frequenza è particolarmente interessante perchè con pochi parametri si possono creare spettri particolarmente ricchi.Inoltre è possibile prevedere con una semplice equazione quali parziali verranno create tramite la modulazione e con quali intensità.

Ecco una parte di una mia orchestra Csound che implementa la FM semplice.

kcamp =k1 kcfrq = koct ifn1 = 1 kmfrq = 100 kindx ctrl7 ichan, ictlno, 0, 20 kmod oscil kmfrq * kindx, kmfrq, ifn1 a1 oscil kcamp, kcfrq + kmod, ifn1

Spettro armonico di semplici FM

Continuando ad analizzare la modulazione di frequenza semplice, cerchiamo di capire quali frequenze laterali vengono generate con la sintesi di modulazione di frequenza semplice.

Mentre con la modulazione ad anello (MA) semplice, ossia con oscillatori sinusoidali, le bande laterali sono soltanto due, nella corrispondente modulazione di frequenza abbiamo una serie, teoricamente infinita di frequenze aggiunte.Il numero di bande laterali dipende dalla deviazione D. Più alto è il valore di D, più aumenta il

44 di 109

Page 45: Corso Perfezionamento Informatica Musicale

numero di bande udibili, con D = I * fm

Come si può vedere dalla tabella sopra riportata, le bande laterali hanno precisi rapporti matematici, basati sulla somma e la differenza dei valori di fc ed fm.Se è possibile individuare le frequenze generate dalla FM, più commplesso è stabilirne l'ampiezza.

Diciamo innanzitutto che l'ampiezza delle bande laterali dipende dall'indice di modulazione I, definito dalla già citata equazione I = D / fm

Concludiamo per ora, esotericamente, rimandando ad ulteriori articoli per ulteriori approfondimenti.

Il valore assoluto dell'ampiezza della banda laterale k, è dato da Jk(I), dove J è una funzione di Bessel del primo tipo, k è l'ordine della funzione e l'argomento è l'indice di modulazione I

Introduzione all'opcode foscil

L'opcode foscil è un opcode che implementa una semplice modulazione di frequenza

ares foscil xamp, kcps, xcar, xmod, kndx, ifn [, iphs]

ares è la variabile audio d'uscitaxamp è l'ampiezzakcps è la frequenza nominalexcar è il fattore per il quale si moltiplica la frequenza nominale per ottenere la frequenza della portantexmod è il fattore per il quale si moltiplica la frequenza nominale per ottenere la frequenza della modulantekndx è l'indice di modulazioneifn è il numero della tabella (per lo più sinusoide)

In conclusione la frequenza effettiva della portante sarà: kcps*xcar, mentre la frequenza effettiva della modulante sarà kcps*kmod. Se per esempio vogliamo una portante di 200 Hz e una modulante di 350 Hz, potremo assegnare indifferentemente ai tre argomenti i seguenti valori:

kcps: 1kcar:200kmod:350

oppure

kcps:50kcar:4

45 di 109

Page 46: Corso Perfezionamento Informatica Musicale

kmod:7

oppure

kcps:200kcar:1kmod: 1.75

The actual formula used for this implementation of FM synthesis is xamp * cos(2π * t * kcps * xcar + kndx * sin(2π * t * kcps * xmod) - π), assuming that the table is a sine wave.

Ecco un esempio tratto da una mia orchestra

if (gksynth==5) then kamp = k1 ;printk 0.5,kamp kcps = cpsoct(koct) kcps = kcps * 0.5 kcar = 20 * kPitch aosc1 foscil kamp, kcps * 0.125 * 0.125, kcar * 0.25 * kPitch , 60, 2, 1 aosc2 foscil kamp, kcps * 0.125 * 0.25, kcar * kPitch * 2, 80, 2, 1 aosc3 foscil kamp, kcps * 0.125 * 0.25, kcar * kPitch * 3, 70, 3, 1 endif

Introduzione all'opcode loscil

Come si legge dalla documentazione Csound, l'opcode loscil legge un suono campionato da una tabella.

Il suono campionato può avere inclusi dei punti di loop. Questo aspetto dell'opcode, comunque, per ora lo tralasciamo.Per evitare di scrivere il percorso completo del file audio da utilizzare con il nostro loscil, è opportuno settare la variabile d'ambiente SSDIR. Nel mio caso ho assegnato a SSDIR, il percorso C:\Documents and Settings\Administrator\Documenti\Musica\Audio. In questa cartella ho così salvato tutti i miei files audio.

La sintassi di base del nostro opcode è quindi la seguente:

ar1 [,ar2] loscil xamp, kcps, ifn [, ibas] [, imod1]

ar1 [,ar2] - loscil potrà ritorare una o due variabili audio a seconda che il nostro campione sia mono o stereo.xamp - specifica l'ampiezza del segnale in uscita

46 di 109

Page 47: Corso Perfezionamento Informatica Musicale

kcps - specifica la frequenza del segnale in uscitaifn - specifica il numero di tabella contenente il file con il suono campionato caricato tramite la GEN01ibas - specifica la frequenza di base del suono campionato. Se questo valore non è conosciuto occorre indicare il valore 1.imod1 - specifica la modalità di loop del campione: 1 - loop ;2 loop avanti ed indietro; 0 nessun loop

Questo opcode lavora quindi con la funzione GEN01.Nell'esempio successivo la tabella con identificatore 6 costituita da 131072 punti contiene il file "vetri1.wav" caricato dalla directory specificata da SSDIR

f 6 0 131072 1 "vetri1.wav" 0 0 0

E' possibile non indicare il numero di punti, ma lasciare che venga dedotto dal file caricato. Per ottenere questo il valore da specificare è '0'

f 7 0 0 1 "vetri2.wav" 0 0 0

Riassumendo ecco uno strumento che fa uso dell'opcode loscil.

instr 1.............. kcps = cpsoct(koct)*0.03125 * kPitch ibas = 1 imod = 1 ;printk 0.5,kamp ; Play the audio sample stored in Table #1. ifn = 6 aosc1 loscil koscil1 * k1, kcps, ifn, ibas,imod aosc2 loscil k1, kcps, ifn, ibas,imod ifn = 7 aosc2 loscil koscil3 * k1, kcps, ifn, ibas,imod..............endin

f 6 0 131072 1 "vetri1.wav" 0 0 0f 7 0 0 1 "vetri2.wav" 0 0 0

Sintesi per distorsione non lineare

Il 'waveshaping ' è la seconda modalità di approccio (dopo la F.M.) alla sintesi del suono mediante distorsione, ed anch'essa consente di ottenere spettri le cui componenti si evolvono dinamicamente nel tempo. E' una tecnica dal costo computazionale piuttosto basso (rispetto alla sintesi additiva) e

47 di 109

Page 48: Corso Perfezionamento Informatica Musicale

permette di ottenere degli spettri a banda limitata (diversamente dagli spettri prodotti in FM).

http://www.fisica.unina.it/mfa/acust/materiale%20sito/Sistemi%20di%20sintesi/waveshap.htm

Lo spettro prodotto da uno strumento per il waveshaping cambia con l'ampiezza del suono. Va qui sottolineato che questo comportamento spettrale è tipico degli strumenti acustici e per questo motivo questa tecnica di sintesi può essere interessante nella simulazione di alcune famiglie di strumenti tradizionali (in particolare gli ottoni), anche se la tecnica di sintesi per modelli fisici, dal punto di vista della simulazione offre maggiori possibilità.

In sostanza, il waveshaping consiste nella distorsione dell'ampiezza di un suono allo scopo di alterarne la forma d'onda (e quindi il suo contenuto spettrale). Se questa tecnica di distorsione viene controllata con cura, è possibile ottenere timbri interessanti e gradevoli. Il waveshaping permette (come la F.M.) il controllo continuo dello spettro del segnale per mezzo di un indice, rendendo quindi possibile la produzione di spettri dinamici mediante la variazione nel tempo dell' indice.

Il cuore di un sistema waveshaping è costituito dall'elemento chiamato waveshaper, altrimenti definito processore non lineare, il cui scopo è quello di alterare la forma dell'onda che lo attraversa.

Per meglio comprendere ciò che accade, si pensi ad un processore lineare, come potrebbe essere un'amplificatore ideale: in questo amplificatore 'perfetto' un cambio di ampiezza del segnale in ingresso produrrà una identica variazione nel segnale di uscita. Se ad esempio (sempre in questo ipotetico amplificatore) si raddoppiasse l'ampiezza del segnale d'ingresso, anche quella del segnale d'uscita raddoppierebbe.

Nell'esempio riportato la funzione distorcente è stata definita tramite la GEN07, che definisce una spezzata chevale -1 tra i punti 0 e 1635, quindi passa al valore 1 con una semiretta costituita da 827 punti e rimane a 1 per i 1635 punti successivi.Su una tabella di 4096 punti, per valori del segnale d'ingresso a1 (che vanno da 0 a 1 ma che vengono internamentetradotti da 0 a 4096) che vanno da 0 a 1635 il segnale viene distorto e posto uguale a -1; per valori che vanno da 1635a 2436 il segnale non viene modificato; per valori compresi tra 2462 e 4096, il segnale viene distorto e posto uguale a 1.

instr 52 ifreq = cpspch(p4) iAmp = i(gkGain) iGain = p6 ictlno =$ictlno2;7 le -1 ichan = $ichan2 kAmp2 ctrl7 ichan, ictlno, 0.1, 10 iL =p7 iR =p8

48 di 109

Page 49: Corso Perfezionamento Informatica Musicale

kamp linseg 0, p3 * 0.1, 1, p3 * 0.2, 1, p3 - (p3 * 0.5), 0.5, p3 * 0.1,0 a1 = ga1 k1 rms a1 a1 gain a1, kamp aDist table a1,6,1 ; aDist reson aDist, ifreq, 50 aL gain aDist, k1 *iL * kamp * iGain * 0.1 * kAmp2 aR gain aDist, k1 *iR * kamp * iGain * 0.1 * kAmp2 outs aL, aR gagL = gagL + aL gagR = gagL + aR endin

f 6 0 4096 7 -1 1635 -1 827 1 1635 1

L'opcode table e la GEN07

L'opcode table genera segnali che possono essere audio, di controllo o di inizializzazione sulla base della lettura di una tabella.

aOut table andx,ifn,ixmode

andx è l'indice a cui corrispondono i valori indicati in tabella.ifn è il numero della tabellaixmode è il modo d'interpretazione dell'indice: 0 specifica un indice grezzo (tra 0 e la lunghezza della tabella usata), 1 specifica un indice normalizzato(cioè compreso tra 0 e 1).

GEN07

GEN07 generates an f-table function from one or more linear function segments. Each segment is defined with three parameters:

• (a) the starting amplitude,• (b) the width of the segment in samples, and• (c) the ending amplitude.

49 di 109

Page 50: Corso Perfezionamento Informatica Musicale

For GEN07, the segment that's drawn between the starting and ending amplitudes uses a linear function. For the next segment, the ending amplitude is used as the starting amplitude for the next segment. If a discontinuity is required, zero-width segments can be defined.

usage

• f# time size 7 a n1 b n2 c ...

parameters

• size -- number of points in the table. This value must be a power-of-2 or a power-of-2 plus 1.

• a, b, c, ... -- ordinate values, in odd-numbered pfields p5, p7, p9, . . . • n1, n2, ... -- length of segment (no. of storage locations), in even-numbered pfields. Cannot

be negative, but a zero is meaningful for specifying discontinuous waveforms. The sum n1 + n2 + .... will normally equal size for fully specified functions. If the sum is smaller, the function locations not included will be set to zero; if the sum is greater, only the first size locations will be stored.

In questo esempio si vede un uso dell'opcode table e della GEN07 nella realizzazione di un semplice esempio di sintesiper distorsione non lineare

instr 51 ifreq = cpspch(p4) ;ifdbgain2 = p5 iAmp = i(gkGain) iGain = p6 ictlno =$ictlno1;7 ichan = $ichan1 kbw ctrl7 ichan, ictlno, 5, 50 iL =p7 iR =p8 kamp linseg 0, p3 * 0.1, 1, p3 * 0.2, 1, p3 - (p3 * 0.5), 0.5, p3 * 0.1,0 a1 = ga1 k1 rms a1 a1 gain a1, kamp aDist table a1,6,1 aDist areson aDist, ifreq, kbw

50 di 109

Page 51: Corso Perfezionamento Informatica Musicale

aL gain aDist, k1 *iL * kamp * iGain * 0.15 aR gain aDist, k1 *iR * kamp * iGain * 0.15 outs aL, aR gagL = gagL + aL gagR = gagL + aR endin

f 6 0 4096 7 -1 1635 -1 827 1 1635 1

Gli opcodes delayr, delayw, deltap

Gli opcodes delayr, delayw e deltap (deltapi) sebbene presentino un uso leggermente meno intuitivo rispetto all'opcode delay, sono uno strumento prezioso con cui vale la pena esercitarsi.

Gli opcode delayr e delayw sono in realtà un'unica unità. Il loro scopo è quello di ritardare di un certo tempo il segnale entrante:delayr legge da una linea di ritardo, in cui il segnale impiega idlt secondi per passare dall'ingresso all'uscita; delayr scrive nella linea di ritardo.

Nell'esempio sottostante i segnali d'ingresso che si desiderano ritardare (a cui si desidera quindi applicare un delay) sono gaRecL2 e gaRecR2. adump è invece il segnale d'uscita ritardato di 5 secondi .

Siccome il parametro di delayr è di tipo i, adump risulterà sempre in ritardo di 5 secondi durante tutto il periodo di esecuzione dello strumento (a meno di strumenti con opcode di reinizializzazione, ma non è questo il caso...). L'opcode deltap è quindi utile proprio per creare ritardi multipli o variabili. Nell'esempio, infatti, il tempo di ritardo è letto tramite bus software (istruzione chnget) e quindi potrà cambiare durante la performance. La variabile d'ingresso di deltap, nell'esempio kdur_randomized_delay, è in effetti una variabile di controllo.

Dentro ad una linea di ritardo è possibile inserire tanti opcode deltap quanti se ne desidera.

Infine è importante rammentare che deltap legge da punti intermedi della linea di ritardo creata con la coppia delayr/delayw: il suo valore non potrà quindi superare idlt (nell'esempio 5 secondi)

instr 12if gkMute == 1 kgoto SALTAkFilter chnget "Filter"

51 di 109

Page 52: Corso Perfezionamento Informatica Musicale

if kFilter == 0 kgoto SALTA...........................kdur_randomized_delay chnget "delay2".................................adump delayr 5 ; set maximum distanceaRecL1 deltap kdur_randomized_delay ; move sound source pastdelayw gaRecL2 ; the listener

adump delayr 5 ; set maximum distanceaRecR1 deltap kdur_randomized_delay ; move sound source pastdelayw gaRecR2 ; the listener

outs aRecL1 , aRecR1

SALTA:endin

Sintesi per modelli fisici: l'opcode pluck

La sintesi per modelli fisici (in inglese, physical modeling) costituisce un approccio abbastanza diverso rispetto alle tecniche di sintesi più 'standard', in quanto prende l'avvio dall'analisi delle caratteristiche fisiche di un determinato strumento preesistente (od uno assolutamente virtuale) e, attraverso la modellizzazione matematico - fisica di ciascun componente essenziale alla sua realizzazione ne ricostruisce (o ne inventa) il suono.

Nel corso degli anni, molti gruppi di ricerca si sono dedicati allo sviluppo di questa tecnica di sintesi in quanto essa consente di produrre segnali acustici molto "reali" rispetto ad un modello esistente e, pertanto, estremamente utile per studiare e comprendere a fondo i meccanismi di produzione e trasformazione del suono operati dagli strumenti acustici esistenti (o di strumenti nati solo dalla fantasia di chi li progetta).

http://www.fisica.unina.it/mfa/acust/materiale%20sito/Sistemi%20di%20sintesi/modfis.htm

L'algoritmo di Karplus-Strong, in particolare, è un metodo che manipola una forma d'onda attraverso una linea di delay con dei filtri per simulare suoni di corde plettrate (chitarra) o soggette a percussione (pianoforte). È una tecnica di sintesi sottrattiva basata sulla retroazione (feedback loop) simile a quella di un filtro comb.

Csound comprende un opcode che implementa l'algoritmo di Karplus e Strong, con alcune aggiunte: si tratta di pluck e la sua sintassi è:

52 di 109

Page 53: Corso Perfezionamento Informatica Musicale

ar pluck kamp, kcps, icps, ifn, imeth [, iparm1] [, iparm2]

kamp: ampiezzakcps: frequenzaifn: numero di tabella, se uguale a 0, come nell'algoritmo originale, la tabella verrà riempita da valori casuali.imeth è il metodo usato per la modifica dei valori della tabella durante la generazione del suono. Ve ne sono sei, alcuni dei quali utilizzano gli argomenti aggiuntivi iparm1 e iparm2

L'istruzione if .... kgoto

Nella realizzazione di strumenti cSound risulta particolarmente utile un'istruzione di salto quale if..... kgoto. Questa istruzione evidenzia come negli strumenti cSound possano venir inserite istruzioni di controllo di flusso come in un qualsiasi programma tradizionale.

L'istruzione kgoto è un'istruzione che viene eseguita su variabili di controllo (una k-variabile). Tipicamente questo opcode è utilizato in coppia con il classico costrutto if, la cui sintassi è

if <boolean expr> kgoto ETICHETTA

Se l'espressione booleana è verificata il controllo passa al codice etichettato.Nell'esempio seguente viene implementato un comando di mute, particolarmente utile in uno strumento da utilizzare in una situazione live.Quando il canale mute viene valorizzato a 1, il test gkMute==1 è verificato e quindi il controllo viene passato al codice con etichetta ESCI. In pratica il codice dello strumento viene saltato.

instr 1 gkMute chnget "mute" if gkMute == 1 kgoto ESCI .....ESCI:endin

Algoritmi di sintesi e pedaliera MIDI

In questo articolo vediamo come sfruttare gli eventi MIDI di tipo Note-On per sostituire, durante

53 di 109

Page 54: Corso Perfezionamento Informatica Musicale

una performance, un algoritmo di sintesi con un altro

L'opcode Csound che ho utilizzato per catturare l'evento MIDI di Note-On è

midinoteonkey knote, kvelocity

Il canale MIDI, non essendo setttato esplicitamente è il canale 1.Testando questo opcode con l'aiuto della solita comoda istruzione

printk t, knote

è immediato verificare che knote assume il valore di MIDI Note-On, solo quando la nostra pedaliera MIDI solleva il corrispondente evento. In tutti gli altri istanti knote vale 0. Il nostro scopo, chiaramente, è quello di non considerare i valori nulli; invece, ogni volta che viene ritornato un valore utile lo dobbiamo memorizzare e sfruttare per cambiare il nostro algoritmo di sintesi.Un possibile codice per far questo è

midinoteonkey knote, kvelocityif(knote==69) then gksynth=0endifif(knote==71) then gksynth=1endifif(knote==72) then gksynth=2endif

In questo esempio le note significative sono la 69, la 71 e la 72. La variabile globale gksynth memorizza l'algoritmo di sintesi che deve essere eseguito.

In conclusione la nostra orchestra dovrà essere così strutturata:

................

gksynth init 0

..........................

instr 1kvelocity init 0knote init 0

.............................

midinoteonkey knote, kvelocityif(knote==69) then gksynth=0endifif(knote==71) then

54 di 109

Page 55: Corso Perfezionamento Informatica Musicale

gksynth=1endifif(knote==72) then gksynth=2endif

if (gksynth==1 || gksynth==2) then .................................; parte condivisa dell'algoritmoendif

if (gksynth==1) then ........endif

if (gksynth==2) then ...........endif

endin

Una loop station in cSound

Molta musica d'oggi, in particolare quella di estrazione rock, pop, jazz fa ampio uso di sample loops.Sul mercato si possono trovare molte macchine specializzate, le cosiddette loop-station. Ovviamente in cSound è facile realizzarne una, con il vantaggio però, di potervi aggiungere anche qualche bizzarria personale.

Nella nostra loop station l'interfaccia grafica è realizzata usando alcuni dei più comuni controlli FLTK:

Un pannello FLpanel, abbastanza grande da contenere 6 bottoni, di cui 5 servono per mettere in moto 5 possibili campionamenti in parallelo, ed 1 per abilitare o meno i comandi per la granularizzazione del suono. La nostra loop station, infatti, implementa un semplice sistema di granularizzazione pilotandolo mediante 5 FLslider. I primi due slider gestiscono i volumi dei due canali stereo. Gli altri tre servono per definire la durata di ogni singolo grano. I microsuoni possiedono un inviluppo triangolare. Il primo slider serve così per definire la durata dell'attacco del grano, mentre il secondo specifica la durata del rilascio. Il terzo slider definisce la durata della pausa che separa un grano dal successivo.

55 di 109

Page 56: Corso Perfezionamento Informatica Musicale

L'orchestra fa uso di due strumenti.Lo strumento 1 è la loop-station vera e propria. Lo strumento 2 si occupa invece della granularizzazione del suono.

gkTrik1 init 0gkTrik2 init 0gkTrik3 init 0gkTrik4 init 0gkTrik5 init 0

Le variabili gkTrik1-gkTrik5 controllano l'abilitazione o meno degli opcode sndloop. Quando la sua variabile di controllo gkTrickn vale 0 (pulsante non premuto), l'opcode sndloop non campiona ed il suo segnale d'uscita è identico al segnale d'entrata. Quando la variabile di controllo passa a 1 (pulsante premuto) l'opcode sndloop campiona il suono per la durata prefissata. Quindi se continua ad essere premuto manda in play il suono campionato.

gkGranule init 0gaL init 0gaR init 0

Queste tre variabili servono per memorizzare lo stato dell'abilitazione della sezione di granulizzazione e per memorizzare il segnale stereofonico elaborato dal primo strumento mettendolo a disposizione per il secondo.

FLpanel "LOOP STATION", 1000, 600, 600, 100

ion = 1 ioff = 0 itype = 2 iwidth = 200 iheight = 200 ix = 0 iy = 0 iopcode = -1 istarttim = 0 idur = -1

gkTrik1, ihb1 FLbutton "@>", ion, ioff, itype, iwidth, iheight, ix, iy,-1 ix = 200 gkTrik2, ihb1 FLbutton "@>", ion, ioff, itype, iwidth, iheight, ix, iy,-1 ix = 400 gkTrik3, ihb1 FLbutton "@>", ion, ioff, itype, iwidth, iheight, ix, iy,-1 ix = 600 gkTrik4, ihb1 FLbutton "@>", ion, ioff, itype, iwidth, iheight, ix, iy,-1 ix = 800 gkTrik5, ihb1 FLbutton "@>", ion, ioff, itype, iwidth, iheight, ix, iy,-1

ix = 0 iy = 200

56 di 109

Page 57: Corso Perfezionamento Informatica Musicale

iwidth = 1000 iheight = 50 gkGranule, ihb1 FLbutton "@arrow", ion, ioff, itype, iwidth, iheight, ix, iy,-1

idVolL FLvalue " ", 200, 20, 0, 300 gkVolL, ihVolL FLslider "VOLUME L", 0, 4, 0, 5, idVolL, 200, 20, 0, 280 FLsetVal_i 0, ihVolL

idVolR FLvalue " ", 200, 20, 200, 300 gkVolR, ihVolR FLslider "VOLUME R", 0, 4, 0, 5, idVolR, 200, 20, 200, 280 FLsetVal_i 0, ihVolR

idAtt FLvalue " ", 200, 20, 400, 300 gkAtt, ihAtt FLslider "ATTACCO", 0.002, 0.09, 0, 5, idAtt, 200, 20, 400, 280 FLsetVal_i 0.05, ihAtt

idRil FLvalue " ", 200, 20, 600, 300 gkRil, ihRil FLslider "RILASCIO", 0.002, 0.09, 0, 5, idRil, 200, 20, 600, 280 FLsetVal_i 0.008, ihRil

idPau FLvalue " ", 200, 20, 800, 300 gkPau, ihPau FLslider "PAUSA", 0.0009, 0.7, 0, 5, idPau, 200, 20, 800, 280 FLsetVal_i 0.04, ihPau

idVol FLvalue " ", 800, 40, 0, 500 gkVol, ihVol FLslider "VOL", 0, 1, 0, 1, idVol, 800, 40, 0, 440 FLsetVal_i 1, ihVol

FLpanelEnd

FLrun

Lo strumento 1 incomincia leggendo il solito segnale audio monofonico (istruzione asig in).La variabile audio aGate viene ancora una volta utilizzata per creare un fade-in ed un fade-out all'inizio ed alla fine della performance, in modo da evitare eventuali click.La variabile audio aGate2, invece, controlla il volume globale dello strumento 1.

Lo strumento 1 oltre a permettere 5 loop in parallelo è sensibilie ai messaggi di control change 1 su canale 1 (MIDI input)

L'opcode ctl7 viene utilizzato sia per implementare il livello del feedback del filtro phaser1, sia per creare il glissando dalla nota p4 alla nota p5. E' un opcode che cattura i messaggi MIDI in input. Il parametro ichan specifica il canale di ascolto, ictlno il numero di control change ; knotamin e knotamax sono i due valori minimi e massimi su cui vengono mappati i valori effettivi del control change. In questo modo, qualsiasi sequenza può essere mappata sui valori che assume un particolare control-change; anzi, lo stesso control-change, usando diverse occorrenze dell'opcode clt7, può pilotare valori di opcode csound differenti

Il cuore della loop station è rappresentato dalla sequenza di istruzioni sndloop. I 5 loop hanno durata diversa (i numeri primi 5, 7, 11, 13, 17) in modo da evitare il più possibile il

57 di 109

Page 58: Corso Perfezionamento Informatica Musicale

ripresentarsi delle stesse sovrapposizioni di suoni.

instr 1 asig in aGate linseg 0, 2, 0.30, p3 - 4, 0.30, 2, 0 aGate2 = a(gkVol) ictlno =1 knotamin = cpspch(p4) knotamax = cpspch(p5) ichan = 1 knota ctrl7 ichan, ictlno, knotamin, knotamax

a1 = asig aRec1,koutrec1 sndloop a1, 1, gkTrik1, 5, 1 aRec2,koutrec1 sndloop a1, 1, gkTrik2, 7, 1 aRec3,koutrec1 sndloop a1, 1, gkTrik3, 11, 1 aRec4,koutrec1 sndloop a1, 1, gkTrik4, 13, 1 aRec5,koutrec1 sndloop a1, 1, gkTrik5, 17, 1

kRec1 rms (aRec1 * aGate ) kRec2 rms (aRec2 * aGate ) kRec3 rms (aRec3 * aGate ) kRec4 rms (aRec4 * aGate ) kRec5 rms (aRec5 * aGate ) k1 rms (a1 * aGate ) ifdbgain1 = 0.96 a1 streson a1, knota, ifdbgain1 iord1 = 50 iskip1 = 0.90

ifdbgain2 = 0.96 aRec1 streson aRec1, knota, ifdbgain2 aRec2 streson aRec2, knota, ifdbgain2 aRec3 streson aRec3, knota, ifdbgain2 aRec4 streson aRec4, knota, ifdbgain2 aRec5 streson aRec5, knota, ifdbgain2 iord2 = 60 iskip2 = 0.99 kfeedback2 ctrl7 ichan, ictlno, 0.30, 0.99 aRec1 phaser1 aRec1,knota,iord2,kfeedback2,iskip2 aRec2 phaser1 aRec2,knota,iord2,kfeedback2,iskip2 aRec3 phaser1 aRec3,knota,iord2,kfeedback2,iskip2 aRec4 phaser1 aRec4,knota,iord2,kfeedback2,iskip2 aRec5 phaser1 aRec5,knota,iord2,kfeedback2,iskip2

aRec1 gain aRec1, kRec1 aRec2 gain aRec2, kRec2

58 di 109

Page 59: Corso Perfezionamento Informatica Musicale

aRec3 gain aRec3, kRec3 aRec4 gain aRec4, kRec4 aRec5 gain aRec5, kRec5 a1 gain a1, k1 gaL = a1 + aRec1 + aRec3 + aRec5 gaR = a1 + aRec2 + aRec4 + aRec5 outs gaL * aGate2, gaR * aGate2 endin

Lo strumento 2 implementa una semplice sintesi granulare in tempo reale, secondo il modello già illustrato in un precedente articolo.La durata di ogni grano (di forma triangolare) è definita da un attacco, un rilascio ed una pausa.Sia l'attacco che il rilascio hanno una componente randomica, riassumibile con la formula:

Valore = Valore +/- Rand(Valore/2)

In modo da evitare tessiture troppo monotone.

instr 2if (gkGranule ==0) kgoto SALTAa1 = gaLa2 = gaRktempAtt = gkAtt / 2krandAtt rand ktempAttktempAtt = gkAtt + krandAtt

ktempRil = gkRil / 2krandRil rand ktempRilktempRil = gkRil + krandRil

ktempPau = gkPau / 2krandPau rand ktempPauktempPau = gkPau + krandPau

start:iPause = i(ktempPau) iDur1 = i(ktempAtt)iDur2 = i(ktempRil)iVolL = i(gkVolL)iVolR = i(gkVolR)igap = iDur1 + iDur2 + iPausetimout 0, igap, continuereinit start

continue: agateL linseg 0, iDur1 , iVolL, iDur2 , 0agateR linseg 0, iDur1 , iVolR, iDur2 , 0

59 di 109

Page 60: Corso Perfezionamento Informatica Musicale

rireturn

outs a1 * agateL , a2 * agateRSALTA:endin

</CsInstruments>

<CsScore>i1 0 900 7.00 7.02i2 0 900</CsScore>

</CsoundSynthesizer>

Pilotare l'opcode diskin con un MIDI controller

L'opcode diskin è un opcode particolarmente semplice da usare in Csound: permette di leggere un file audio da un device esterno e di metterlo in loop alterandone il pitch .

La sintassi dell'opcode è la seguente:

ar1 [, ar2 [, ar3 [, ... ar24]]] diskin ifilcod, kpitch [, iskiptim] [, iwraparound] [, iformat] [, iskipinit]

Mi soffermo a commentare i due parametri principali dell'opcode:

Il parametro ifilcod può essere un numero indicante l'identificativo di una funzione GEN01, oppure una stringa contenente il nome del file (con indirizzo relativo se le variabili d'ambiente SSDIR e SFDIR sono state valorizzate o con indirizzo assoluto).

Il parametro kpitch ha il seguente significato:può essere un qualsiasi numero reale (un numero negativo significa un esecuzione in reverse). indicante un rapporto di frequenza; ad esempio, riportando l'esempio del manule Csound:

1 = normal pitch2 = 1 octave higher3 = 12th higher, etc..5 = 1 octave lower.25 = 2 octaves lower, etc-1 = normal pitch backward

60 di 109

Page 61: Corso Perfezionamento Informatica Musicale

-2 = 1 octave higher backwards, etc.

In questo esempio di codice Csound viene utilizzato l'opcode ctrl7 per trasformare un valore MIDI in un valore utile per kPitch.I parametri di diskin sono valorizzati con i seguenti valori:Ssample è una variabile di tipo stringa indicante il file da leggerekcps è una variabile contenente il valore di kPitch arrotondato ad un valore significativo per diskiniskiptim è a zero (il file viene letto dall'inizio)iwraparound è a 1 (il file è letto in ciclo continuo)

kPitch ctrl7 ichan, ictlno, 0.25, 10kcps = round(kPitch)if(kcps<1) then kcps = 0.5endifasig1 diskin Ssample, kcps,0,1

Pitch detection con gli opcodes spectrum e specptrk

Attraverso l'uso degli opcodes spectrum e specptrk è possibile riuscire a estrapolare da un segnale audio la sua frequenzadominante.

L'opcode spectrum è il responsabile dell'analisi del segnale audio. L'ouput wsig è di tipo window data (non i più comuni kontrol o audio).L'opcode crea una struttura dati su cui l'opcode specptrk opera successivamente per ricavare ampiezza e frequenza fondamentale.

wsig spectrum xsig, iprd, iocts, ifrqa [, iq] [, ihann] [, idbout] \ [, idsprd] [, idsinrs]

L'analisi è fatta ogni iprd secondi sul segnale xsig. L'analisi consiste nell'applicazione di una particolare implementazione dellaDiscrete Fourier Transform(DFT). Sebbene più efficiente della FFT, la DDT richiede che le frequenze calcolate siano discrete e distanziate tra loro da una costante di frequenza. In particolare la constant-Q, exponentially-spaced DFT, su cui si basa l'opcode spectrum è un banco di filtri geometricamente spaziati intorno ad una frequenza centrale

fk = f0 . 2 k/b dove b indica il numero di filtri per ottava

iprd indica il periodo dell'analisi della DFTiocts indica invece il numero di ottave utilizzate nell'analisi

61 di 109

Page 62: Corso Perfezionamento Informatica Musicale

ifrqa indica il numero di filtri per ottava spaziati esponenzialmenteiq il valore Q dei filtri, dove Q o fattore di risonanza è ugual a:

Q= frequenza di taglio / larghezza di banda

ihann – set to 1 to apply a hanning window or 0 for the default hamming windowidbout – format for the DFT output: 0= magnitude, 1 = dB, 2 = magnitude2, 3= √magnitude

specptrk

spectrk — Estimates the pitch of the most prominent complex tone in the spectrum.

Description

Estimate the pitch of the most prominent complex tone in the spectrum.

Syntaxkoct, kamp specptrk wsig, kvar, ilo, ihi, istr, idbthresh, inptls, \ irolloff [, iodd] [, iconfs] [, interp] [, ifprd] [, iwtflg]

Initialization

ilo, ihi, istr -- pitch range conditioners (low, high, and starting) expressed in decimal octave form.

idbthresh -- energy threshold (in decibels) for pitch tracking to occur. Once begun, tracking will be continuous until the energy falls below one half the threshold (6 dB down), whence the koct and kamp outputs will be zero until the full threshold is again surpassed. idbthresh is a guiding value. At initialization it is first converted to the idbout mode of the source spectrum (and the 6 dB down point becomes .5, .25, or 1/root 2 for modes 0, 2 and 3). The values are also further scaled to allow for the weighted partial summation used during correlation.The actual thresholding is done using the internal weighted and summed kamp value that is visible as the second output parameter.

inptls, irolloff -- number of harmonic partials used as a matching template in the spectrally-based pitch detection, and an amplitude rolloff for the set expressed as some fraction per octave (linear, so don't roll off to negative). Since the partials and rolloff fraction can affect the pitch following, some experimentation will be useful: try 4 or 5 partials with .6 rolloff as an initial setting; raise to 10 or 12 partials with rolloff .75 for complex timbres like the bassoon (weak fundamental). Computation time is dependent on the number of partials sought. The maximum number is 16.

iodd (optional) -- if non-zero, employ only odd partials in the above set (e.g. inptls of 4 would employ partials 1,3,5,7). This improves the tracking of some instruments like the clarinet The default value is 0 (employ all partials).

62 di 109

Page 63: Corso Perfezionamento Informatica Musicale

iconfs (optional) -- number of confirmations required for the pitch tracker to jump an octave, pro-rated for fractions of an octave (i.e. the value 12 implies a semitone change needs 1 confirmation (two hits) at the spectrum generating iprd). This parameter limits spurious pitch analyses such as octave errors. A value of 0 means no confirmations required; the default value is 10.

interp (optional) -- if non-zero, interpolate each output signal (koct, kamp) between incoming wsig frames. The default value is 0 (repeat the signal values between frames).

ifprd (optional) -- if non-zero, display the internally computed spectrum of candidate fundamentals. The default value is 0 (no display).

iwtftg (optional) -- wait flag. If non-zero, hold each display until released by the user. The default value is 0 (no wait).

Performance

At note initialization this unit creates a template of inptls harmonically related partials (odd partials, if iodd non-zero) with amplitude rolloff to the fraction irolloff per octave. At each new frame of wsig, the spectrum is cross-correlated with this template to provide an internal spectrum of candidate fundamentals (optionally displayed). A likely pitch/amp pair (koct, kamp, in decimal octave and summed idbout form) is then estimated. koct varies from the previous koct by no more than plus or minus kvar decimal octave units. It is also guaranteed to lie within the hard limit range ilo -- ihi (decimal octave low and high pitch). kvar can be dynamic, e.g. onset amp dependent. Pitch resolution uses the originating spectrum ifrqs bins/octave, with further parabolic interpolation between adjacent bins. Settings of root magnitude, ifrqs = 24, iq = 15 should capture all the inflections of interest. Between frames, the output is either repeated or interpolated at the k-rate. (See spectrum.)

wsig spectrum a1, .01, 7, 24, 30, 0, 3 ; get a 7-oct spectrum, 24 bibs/oct ktemp,ka specptrk wsig, kvar, 6.0, 10.0, 9.0, 8, 5, .7, 1, 5, 1, .2 ; the pch and amp if (cpsoct(ktemp)>50) then gkNote = cpsoct(ktemp) endif

L'opcode specptrk

Riassumendo il valore dei parametri dell'opcode specptrk

koct, specptrk wsig, kvar, ilo, ihi, istr, idbthresh, inptls, irolloff[, iodd, iconfs, interp, ifprd, iwtflg] kamp

63 di 109

Page 64: Corso Perfezionamento Informatica Musicale

L'opcode ritorna frequenza principale e dinamica dello spettro analizzato e codificato da wsig.

ilo,ihi,istr specificano in formato octave point pitch-class il range di frequenza di analisi ed il punto di partenza della stessa.idbthresh esprime in decibel la soglia minima d'ampiezza del segnale analizzabileinptls rappresenta il numero di parziali che il suono principale deve possedere per essere preso in considerazione nell'analisi.irolloff valore di pendenza del filtro nella zona di transizione di bandaiodd se è diverso da zero, l'analisi d'individuazione dell'altezza prende in considerazione solo le parziali dispari (e. clarinetto)iconfs è il numero di conferme richieste prima che il pitch-tracker cambi l'ottava di riferimento.

Sintesi granulare con l'opcode granule

L'opcode granule è uno degli opcode più utilizzati in csound per la sintesi granulare.

Elettronica1_basso.csd

Come scivevo in un precedente articolo, la sintesi granulare sintetizza il suono, partendo da nubi di microsuoni. Il risultato ottenuto dipende così, tanto dalle caratteristiche dei singoli microsuoni, quanto dalla forma della nube. I parametri di granule permettono di controllare la sintesi:

ares granule xamp, ivoice, iratio, imode, ithd, ifn, ipshift, igskip, \ igskip_os, ilength, kgap, igap_os, kgsize, igsize_os, iatt, idec \ [, iseed] [, ipitch1] [, ipitch2] [, ipitch3] [, ipitch4] [, ifnenv]

ifn: specifica l'f-table usata come sorgente per la sintesi; i micrograni vengono creati segmentando il suno campionato memorizzato nella fTable. Il valore da assegnare a ifn nell'opcode granule è quindi il numero della f-Table .

ifn = 6................aSignalL granule ksegL, ivoices, iratio, iptrmode, ithd, ifn, inumpchs, iskip, iskipos, ilen, kgapL, igapos, ksizeL, isizeos, 35, 35, 0.39, 0.5,1,0.5,1..........................

f 6 0 16777216 1 "DoViolS.wav" 0 4 1

ivoice: Indica il numero di voci "polifoniche". Questo parametro permette di considerare la sintesi creata con granule come una particolare forma di sintesi additiva. iratio: definisce la velocità del cursore di lettura della fTable con valori relativi ad sr. Un valore di 0.1 espanderà una durata di 1 secondo con un fattore 10. Quello che nel campione originale durava

64 di 109

Page 65: Corso Perfezionamento Informatica Musicale

1 secondo ora ne durerà 10. Viceversa un valore di10 comprimerà il suono originale da 1 secondo originale a 0.1 secondi

Bibliografia

THE CSOUND BOOK - Richard Boulanger Editor - MIT Press (2000)MICROSOUND - Curtis Roads - MIT Press (2001)

Uso dell'opcode timout

In un precedente articolo abbiamo visto come utilizzare l'opcode timeout per implementare una versione molto semplificata di sintesi granulare. In questo articolo presento un uso un pò più articolato dello stesso opcode.

Come si vede nell'esempio, l'opcode timeout può essere usato in quei contesti in cui si richiede che vengano riassegnati ciclicamente alle variabili di inizializzazione dei nuovi valori. Nel'esempio, alle variabile iStereoL e iStereoR (e a tutte le variabili di inizializzazioni presenti nella sezione start:) verrano assegnati nuovi valori ad ogni idur_delay + idur_sample secondi. Quindi gli opcodes utilizzati nella sezione continue lavoreranno ogni volta partendo da valori di inizializzazione potenzialmente diversi. In particolare nell'esempio, i valori delle principali variabili vengono modificate tramite comunicazione attraverso il canale software (iStereoL chnget SpanL). Il musicista potrà così intervenire, tipicamente tramite GUI e vari controller interfacciati tramite Csound API, a modificare l'evoluzione del segnale audio prodotto dalla sezione continue dell'istruzione timeout.

instr 2

iduration = p3idur_attack = p4idur_decay = p5idur_sustain = p6idur_release = p7 idur_delay = p8iFlagInstr = p10iFlagInstr2 = p11kdurDelay init idur_delay

Svolume sprintf "volume%d", p9Scounter sprintf "counter%d", p9Spitch sprintf "pitch%d", p9

65 di 109

Page 66: Corso Perfezionamento Informatica Musicale

SpanL sprintf "panL%d", p9SpanR sprintf "panR%d", p9Sdist sprintf "dist%d", p9Scomb sprintf "comb%d", p9

kVol chnget SvolumekPitch chnget Spitchkdist chnget Sdistkcomb chnget Scomb

idur_sample = idur_attack + idur_decay + idur_sustain + idur_release ilpt = idur_sample * 0.25itransaz = 0.05icounter=1ifn = 1

if (iFlagInstr2 == 0) then aRecL, koutrec1 sndloop gaL , kPitch, 1, idur_sample , itransaz aGateRec linseg 0,idur_sample ,0,idur_sample,1,iduration - (idur_sample)*3,1, idur_sample,0 aRecL = aRecL * aGateRecelse aRecL = gaLendif

if (kdist > 0.1) then aRecL distort aRecL, kdist, ifn endif

if (kcomb > 0.1) then aRecL distort aRecL, kcomb*10, 4 endif

if (iFlagInstr == 1) then aRecL gain aRecL, gkInstrVolendif

start:chnset icounter, Scountericounter = icounter + 1iStereoL chnget SpanLiStereoR chnget SpanR ; ------ >LETTURA DI PARAMETRI DAL CANALE SOFTWARE iPitch chnget SpitchiStereoR chnget SpanR

timout 0, idur_delay + idur_sample, continuereinit start; ---------------- > OGNI idur_delay + idur_sample VIENE RIESEGUITA LA

66 di 109

Page 67: Corso Perfezionamento Informatica Musicale

SEZIONE DI INIZIALIZZAZIONE (start)

continue:

kGate linseg 0,idur_delay,0,idur_attack ,0.6,idur_decay,0.4,idur_sustain,0.3,idur_release,0

aRecR = aRecL

aRecL = aRecL * kGate * iStereoL; * aMainGate ;; ------ >USO DEI PARAMETRI LETTI PER MODIFICARE L'EVOLUZIONE DEL SEGNALE AUDIOaRecR = aRecR * kGate * iStereoR; * aMainGatega2L = ga2L + aRecLga2R = ga2R + aRecRouts aRecL * kVol, aRecR * kVolendin

Sintesi granulare con l'opcode timout

La sintesi granulare è una tecnica di sintesi classica, figlia di una delle tante intuizioni geniali di Iannis Xenakis. Si basa sull'idea che un suono possa essere scomposto in una nube di microsuoni. Il suono che si ottiene con questo tipo di sintesi dipende così tanto dalla forma della nube sonora (densità dei grani) quanto dalla forma dei singoli micrograni. Csound mette a disposizione diversi opcode per realizzare musiche che sfruttano la sintesi granulare: timout è uno di questi

L'opcode timout può essere utilizzato per implementare una particolare forma di sintesi granulare. La sua sintassi é la seguente:

timout istrt, idur, label

timeout salta all'etichetta label a partire da istr secondi e dopo ogni idur secondi.

Esempio1.csd

instr 1a1 ink1 rms a1

start:iPause = p4 iDur1 = p5

67 di 109

Page 68: Corso Perfezionamento Informatica Musicale

iDur2 = p6igap = iDur1 + iDur2 + iPausetimout 0, igap, continuereinit start

continue: agate linseg 0, iDur1 , 1, iDur2 , 0rireturn

outs a1 * agate , a1 * agateendin

timout passa il controllo all'etichetta continue a partire dall'istante 0 e dopo ogni igap secondi. Il ruolo di timeout all'interno di instr1 è quello di generare degli eventi sonori composti da micrograno + pausa: la durata complessiva è composto così da iDur1 (durata attacco dell'inviluppo del micrograno), iDur2 (durata rilascio inviluppo micrograno), iPause (pausa). L'inviluppo di ogni micrograno ha così durata iDur1 + iDur2 e possiede forma triangolare.L'istruzione timeout è spesso utilizzata con reinit. Questo opcode è un'istruzione di tipo goto, con la particolarità di rieseguire istruzioni di inizializzazione. Nell'esempio, le istruzioni di inizializzazione che vengono rieseguite sono quelle introdotte dall'etichetta start.

Sintesi per formanti: FOF

Con FOF (Fonction d’onde formantique) si indica una tecnica di sintesi sviluppata all’IRCAM nell’ambito del progetto CHANT, il cui obiettivo era l’elaborazione di tecniche per la sintesi realistica della voce cantata. Il principio fondamentale è il modello della voce umana a partire da un generatore di impulsi (che corrisponde alle corde vocali) filtrati da filtri passa-banda (che rappresentano l’escursione delle caratteristiche vocali) e che replicano l’inviluppo delle formanti.

Poiché il generatore di impulsi produce una sequenza di “grani”, questa tecnica viene anche accostata alla sintesi granulare. Tuttavia, la FOF differisce da quest’ultima in quanto utilizza grani regolari e sincroni che producono una forma d’onda periodica, com’è appunto nel caso della voce (Fonte - Richard Dobson (1992). A Dictionary of Electronic and Computer Music Technology. Oxford University Press.).

http://www.ears.dmu.ac.uk/spip.php?page=rubriqueLang&lang=it&id_rubrique=353

Dal momento che i grani FOF durano pochi millisecondi, si crea una modulazione d'ampiezza fra inviluppo del grano e la sinusoide,per cui si creano una serie di bande laterali intorno alla frequenza della sinusoide, che producono un formante.

68 di 109

Page 69: Corso Perfezionamento Informatica Musicale

Sommando più generatori FOF si può ottenere uno spettro con diversi picchi formantici.Ogni generatore FOF è controllato da alcuni parametri, compresi la frequenza fondamentale e l'ampiezza:1) frequenza centrale del formante2) la rghezza di banda del formante3) ampiezza di picco del formante4) larghezza del formant skirt (letteralmente, 'gonna del formante') che costituisce la parte più bassa del piccoformantico, intorno a -40 db rispetto all'ampiezza di picco. Il parametro "gonna" è indipendente dalla larghezza delformante e definisce la curva che va da 0 a -40db.

Il principale opcode csound per implementare la sintesi per formanti è l'opcode FOF

ar fof xamp, xfund, xform, koct, kband, kris, kdur, kdec, iolaps, ifna, ifnb, itotdur[, iphs[, ifmode]]

xamp ampiezza di picco di ogni treno di sinusoidixfund frequenza fondamentale, in Hz, dell'impulso che crea nuovi treni di sinusoidixform frequenza del formantekoct indice di ottavizzazione, solitamente zero. Se è maggiore di zero traspone verso il grave la frequenza fondamentale xfund attenuando i treni di sinusoidi dispari. E' possibile sia usare gli interi, che indicano le ottave, che i numeri frazionarikband larghezza di banda del formante ( a -6db)kris, kdur, kdec tempi di attacco, di durata totale e di decay (in secondi) del treno di sinusoidi. kris determina la gonna del formanteiolaps numero di spazi preallocati nella memoria necessari a contenere i dati dei treni che si sovrappongono.ifna, ifnb numeri di tabella per le funzioni; ifna deve essere una sinusoide di dimensione almeno pari a 4096; ifnb è una tabella che contiene la forma da attribuire all'attacco e al decay di ogni treno di sinusoidi. itotdur tempo durante il quale fof rimane attivoiphs (opzionale) fase iniziale della fondamentale, espressa come frazione di un ciclo (da 0 a 1). Il valore di default è 0.ifmode (opzionale) modo di frequenza del formante. Se è zero, ogni treno di sinusoidi mantiene la frequenza xform con la quale ha iniziato.Se è diverso da zero, all'interno di ogni xform cambia continuamente.

; Instrument #61. instr 61 ; Values common to all of the formants. koct init 0 kris init 0.003 kdur init 0.02 kdec init 0.007 iolaps = 14850 ifna = 8 ifnb = 9

69 di 109

Page 70: Corso Perfezionamento Informatica Musicale

itotdur = p3 iL =p7 iR =p8 ifreq = cpspch(p4) kfund = ifreq ; First formant. a1 = ga1 k1 rms a1 kamp linseg 0, p3 * 0.1, 0.5, p3 * 0.2, 0.35, p3 - (p3 * 0.5), 0.25, p3 * 0.1,0 k1amp = k1 k1form = ifreq k1band init 80 ; Second formant. k2amp = ampdb(-4) k2form = k1form * 3 /2 k2band init 90 ; Third formant. k3amp = ampdb(-20) k3form = k1form * 2 k3band init 120 ; Fourth formant. k4amp = ampdb(-36) k4form = k1form * 2 * 2 k4band init 130 ; Fifth formant. k5amp = ampdb(-60) k5form = k1form * 2 * 2 * 3 /2 k5band init 140 a1 fof k1amp, kfund, k1form, koct, k1band, kris, kdur, kdec, iolaps, ifna, ifnb, itotdur a2 fof k2amp, kfund, k2form, koct, k2band, kris, kdur, kdec, iolaps, ifna, ifnb, itotdur a3 fof k3amp, kfund, k3form, koct, k3band, kris, kdur, kdec, iolaps, ifna, ifnb, itotdur a4 fof k4amp, kfund, k4form, koct, k4band, kris, kdur, kdec, iolaps, ifna, ifnb, itotdur a5 fof k5amp, kfund, k5form, koct, k5band, kris, kdur, kdec, iolaps, ifna, ifnb, itotdur ; Combine all of the formants together. aL =(a1+a2+a3+a4+a5)*iL * kamp aR = (a1+a2+a3+a4+a5) *iR *kamp outs aL,aR gagL = gagL + aL gagR = gagL + aR endin

70 di 109

Page 71: Corso Perfezionamento Informatica Musicale

Introduzione agli FLTK Widgets

Gli FLTK Widgets permettono di realizzare una GUI (Graphic User Interface) personalizzata per pilotare un'orchestra Csound in tempo reale.

I controlli grafici Csound sono derivati dalla libreria open-source FLTK (Fast Light Tool Kit ). Questa libreria è multi-piattaforma (Windows, Linux, Unix and Mac OS) e compatibile con OpenGL. Il sottoinsime FLTK implementato in CSound comprende:

FLTK Containers, widgets che possono contenere altri widgets:

• Panels • Scroll areas • Pack • Tabs • Groups

FLTK Valuators, particolarmente adatti per modificare il valore di un parametro di uno strumento in tempo reale

• Sliders • Knobs • Rollers • Text fields • Joysticks • Counters

Ci sono poi altri FTLK widgets che non rientrano nelle prime due categorie:

• Buttons • Button banks • Labels

Quindi ci sono degli opcodes che modificano la visualizzazione dei controlli:

• FLcolor • FLcolor2 • FLhide • FLlabel • FLsetAlign • FLsetBox • FLsetColor

71 di 109

Page 72: Corso Perfezionamento Informatica Musicale

• FLsetColor2 • FLsetFont • FLsetPosition • FLsetSize • FLsetText • FLsetTextColor • FLsetTextSize • FLsetTextType • FLsetVal_i • FLsetVal • FLshow

Infine ci sono tre importanti famiglie di opcodes che permettono le tre seguenti azioni principali

• Apertura di un widget thread: FLrun• Caricamento in memoria di una configurazione di widgets precedentemente salvata

FLgetsnap e FLloadsnap. • Salvataggio di widgets: FLsavesnap e FLsets

Esempio di costruzione di un'interfaccia FLTK

In questo articolo costruiamo una semplice interfaccia FLTK per pilotare in tempo reale i principali parametri di un'orchestra.

Esempio 1Viene creato un pannello che rimane aperto per 10 secondi e quindi viene chiuso dopo che l'ultimo evento della sezione score è stato eseguito.

<CsoundSynthesizer><CsOptions> -b16384 -B16384</CsOptions><CsInstruments>sr = 44100kr = 441ksmps = 100nchnls = 2 ;LABEL | WIDTH | HEIGHT | X | YFLpanel "ELETTRONICA1 - BASSO" , 800, 700, 700, 0FLpanel_endFLrun instr 1endin

72 di 109

Page 73: Corso Perfezionamento Informatica Musicale

</CsInstruments><CsScore>i 0 10 </CsScore></CsoundSynthesizer>

Esempio 2 All' FLpanel è stato aggiunto un valutatore FLslider, un visualizzatore del valore corrente del valutatore (FLvalue), un'istruzione che setta il valore iniziale dell'FLslider (FLsetVal_i). Il valore dell'FLslider viene assegnato alla variabile di controllo globale gkamp1L. FLSlider modifica il volume dello strumento: infatti il valore di gkampi1L, che varia da 500 a 800, viene usato come parametro d'ampiezza dell'operatore oscil. I valori intermedi da 500 a 800 seguono un andamento esponenziale, come indicato dal quarto parametro (-1).

<CsoundSynthesizer><CsOptions> -b16384 -B16384</CsOptions><CsInstruments>

sr = 44100kr = 22050ksmps = 2nchnls = 2

gkamp1L init 0

;LABEL | WIDTH | HEIGHT | X | YFLpanel "ELETTRONICA1 - BASSO" , 300, 90, 700, 0 idamp1L FLvalue "Vol.", 75, 20, 0, 25 ;FLvalue — Shows the current value of a FLTK valuator. gkamp1L, ihamp1L FLslider "I", 120, 90, -1, 5, idamp1L, 280, 20, 0, 0FLsetVal_i 600, ihamp1L

FLpanel_end

FLrun

instr 1 printk 1, gkamp1L aOutL oscil gkamp1L, 440, 1 outs aOutL, aOutLendin</CsInstruments>

<CsScore>f1 0 4096 10 1 3 7 1 3

73 di 109

Page 74: Corso Perfezionamento Informatica Musicale

i1 0 20 </CsScore>

</CsoundSynthesizer>

74 di 109

Page 75: Corso Perfezionamento Informatica Musicale

Csound e Python

Csound e Python: primo incontro

Prima o poi, lavorando con cSound nasce l'esigenza di controllare il motore del sintetizzatore virtuale con degli strumenti software più sofisticati rispetto ai semplici opcodes FLTK , ad esempio con un linguaggio di programmazione come Python.

Python è un linguaggio di script multipiattaforma (Windows, Linux,Mac) ad oggetti ed open source. Il sito ufficiale è : www.python.org.Nel tutorial di cSound è presentato, per la sua flessibilità e velocità d'apprendimento, come il linguaggio principe per interfacciarsi a cSound.In effetti script Python possono essere utilizzati dentro a strumenti cSound, sfruttando particolari opcode, oppure per realizzare applicazioni che utilizzano le cSound API.Nel numero primaverile di cSounds Journal è possibile trovare un articolo scritto da Andrés Cabrera che analizza gli opcode per utlizzare Python dentro a strumenti cSound

http://www.csounds.com/journal/issue6/pythonOpcodes.html

La sottocartella examples delle ultime releases di cSound, è ricca di sorgenti python. La maggior parte di questi, esemplifica come realizzare un'interfaccia grafica per pilotare orchestre cSound. Quasi tutti gli esempi sono realizzati usando la GUI python standard: Tkinter.Solo uno, invece, fa uso della libreria wxPython. (http://www.wxpython.org), sviluppata sulla libreria C++ multipiattaforma wxWidgets (www.wxWidgets.com)

Quindi per incominciare ad usare cSound come modulo Python occorre:

• Installare cSound 5.0 o successivo• Installare Python 2.5 o successivo• Installare wxPython per Python 2.5

Usare Csound con Python: moduli principali

Una volta installati cSound, Python e wxPython il primo problema che dobbiamo risolvere nello

75 di 109

Page 76: Corso Perfezionamento Informatica Musicale

scrivere il nostro sorgente Python è:

Quali packages dobbiamo importare?

Il package principale per l'uso di Csound in Python è: csnd. Questo package contiene il wrapper Python per richiamare all'interno dei nostri script le Csound API.

Se abbiamo istallato wxPython e desideriamo pilotare Csound tramite un'interfaccia grafica fatta di finestre, controlli e menu, dovremo allora importare anche il package wx.

Infine, se vogliamo temporizzare dei comandi, ad esempio far eseguire una certa istruzione Csound ad un determinato punto dell'esecuzione della nostra partitura, allora sarà opportuno importare anche la libreria threading

In definitiva il nostro script tipicamente inizierà con le seguenti istruzione d'importazione:

import csndimport wximport threading

PyGame per joystick e joypad

Un'altra libreria Python da inserire nella nostra cassetta degli attrezzi è la libreria pyGame. Questa libreria, dal nostro punto di vista, può servirci per trasformare joystick, joypad, tastiera e mouse in formidabili strumenti per il controllo delle nostre elaborazioni

http://www.pygame.org

wxPython e pyGame a confronto

Nello scegliere quale libreria grafica adottare per le nostre applicazioni è meglio soffermarci un attimo sulle differenze principali tra le due librerie prese in esame:wxPython e pyGame.

76 di 109

Page 77: Corso Perfezionamento Informatica Musicale

wxPython è una libreria progettata per realizzare applicazioni con GUI tradizionale: finestre con menu e controlli vari.Il punto di debolezza attuale di questa libreria è una gestione degli eventi da tastiera piuttosto lacunosa. Ad esempio, su sistema operativo windows xp, la libreria mostra diversi bugs fastidiosi. Il punto di forza è invece, la facilità con cui è possibile creare menu, pulsanti e la gestione dei relativi eventi (mouse incluso).

pyGame è invece una libreria per la realizzazione di giochi in ambiente Python. Il suo punto di debolezza sta nel fatto che non è affatto pensata per realizzare GUI tradionali. Il suo punto di forza consiste nella facilità di gestione di puntatori di input quali i tradizionali mouse e tastiera ma anche joistick e joypad.

Programmare joypad e tastiera con pyGame

Il joypad può tornare utile anche come controller per pilotare le elaborazioni di Csound. Nella sezione download ho pubblicato un semplice esempio che illustra come raggiungere questo scopo.

Innanzitutto dobbiamo importare i moduli principali di pyGame.

from pygame.locals import *from pygame import *

Quindi iniziare la fase di inizializzazione. La visualizzazione di una finestra pyGame è essenziale per ricevere gli input da tastiera.

pygame.init()pygame.mouse.set_visible(0)pygame.display.set_mode((400,50))pygame.display.flip()

Inizializzare i joystick rilevati dal sistema

for x in range(joystick.get_count()): j = joystick.Joystick(x) print "Joystick %i: " % x + j.get_name() j.init()

Creare un loop principale di analisi degli eventi in coda.

while 1: key.getkey() if key.type == KEYDOWN:

77 di 109

Page 78: Corso Perfezionamento Informatica Musicale

...................... if key.type == JOYBUTTONDOWN:...................... elif key.type == JOYAXISMOTION:..................... elif key.type == JOYHATMOTION:

Analisi che si basa sul metodo getKey definito in guiinput.py (incluso nell'esempio)

def getkey(self): for e in event.get(): self.type = e.type #print self.type # KEYBOARD if e.type == KEYDOWN: self.value =int(e.key)

elif e.type == JOYBUTTONDOWN: self.value = int(e.dict['button'])

elif e.type == JOYHATMOTION: self.value1 = float(e.dict['value'][0]) self.value2 = float(e.dict['value'][1]) # JOYAXIS elif e.type == JOYAXISMOTION: self.subtype = str(e.dict["axis"]) self.value = float(e.dict['value'])

Il tutto termina con le consuete operazioni di pulizia

pygame.display.flip()pygame.quit()sys.exit()

Il modulo pySerial

Un altro modulo python che può tornarci utile nell'interfacciarci con Csound è il modulo pyserial

http://pyserial.sourceforge.net/

Questo modulo ci permette di leggere e scrivere verso la porta seriale. In particolare mi è tornato utile per iniziare a leggere il flusso dati proveniente da un sistema di sensori come lo USB-

78 di 109

Page 79: Corso Perfezionamento Informatica Musicale

microSystem

http://infusionsystems.com

Esplorare il modulo csnd

Per approfondire la conoscenza delle API cSound accessibili tramite il modulo csnd, è opportuno ripassare le istruzioni Python che ci permettono di investigare il contenuto di un modulo

Innanzitutto occorre importare il modulo da esplorare

import csnd

La funzione dir elenca tutti i metodi e gli attributi del parametro su cui viene applicata

print dir(csnd)print dir(csnd.CsoundPerformanceThread)

Attraverso la funzione dir si arriva così ad ottenere un elenco di tutte gli oggetti, le costanti, le funzioni accessibili a partire dal modulo csnd.Per avere delle informazioni dettagliate sui singoli metodi si può usare l'attributo __doc__. Questo attributo è presente in ogni oggetto Python.E' fondamentale per raggiungere immediatamente la firma di un metodo.

print csnd.CsoundPerformanceThread.Pause.__doc__>>> Pause(self)

La variabile d'ambiente PYTHONPATH (windows)

Se si rendere visibile una cartella contenente dei moduli (librerie) Python, occorre settare la variabile PYTHONPATH

Per settare questa variabile in Windows Xp, occorre seguire queste indicazioni:

Pannello di controllo > Sistema > scheda Avanzate > pulsante Variabili d'Ambiente > Variabili di sistema > Aggiunta o modifica della variabile PYTHONPATH con valore il percorso scelto. I

79 di 109

Page 80: Corso Perfezionamento Informatica Musicale

diversi valori devono essere separati da un ";".

C:\Programmi\Csound\bin;C:\Documents and Settings\Administrator\Documenti\Python\csound;C:\Documents and Settings\Administrator\Documenti\CSound\Anatrofobia

La classe cSoundPerformanceThread

Per l'uso di cSound in tempo reale occorre che venga eseguito in un thread separato. La classe CsoundPerformanceThread, come indica il suo nome, ha il compito di creare un apposito thread per l'esecuzione di cSound.Dopo aver creato un'istanza di questa classe sarà possibile avviare, mettere in pausa, stoppare l'esecuzione di una partitura Csound eseguita dall'orchestra corrispondente.

Vediamo un esempio di uso del Perfomance Thread di cSoundIl nostro script Python deve importare, come al solito, il modulo csnd.

import csnd

Occorre creare un oggetto cSound e, ad esempio, compilare un file csd.

self.csound = csnd.CppSound()self.csound.Compile("Gretchen.csd")

Quindi far incominciare la performance.

self.perf = csnd.CsoundPerformanceThread(self.csound)self.perf.Play()

Durante la performance sarà possibile far eseguire alle nostre orchestre particolari eventi tramite l'istruzione InputMessage

self.perf.InputMessage("i%d 0 %f %f %f %f %f %f" % ((nButton+1), duration, self.dur_attack[nButton -1],self.dur_decay[nButton -1],self.dur_sustain[nButton -1],self.dur_release[nButton -1],delay))

L'istruzione InputMessage ci permette di far eseguire "al volo" alla nostra orchestra degli eventi Csound. Il tutto in tempo reale.

80 di 109

Page 81: Corso Perfezionamento Informatica Musicale

Un sistema di macro per i files csd

Csound prevede due sistemi di macro: per i files orchestra e i files partitura. Attualmente non è però possibile definire delle macro a livello di sezione CsOptions.

In questo articolo presento una classe Python che permette d'implementare macro anche a livello di CsOptions.

Lo scopo è quindi quello di poter scrivere all'interno del nostro codice csd, una sintassi come questa:

<CsoundSynthesizer><CsOptions>$CsOptions</CsOptions><CsInstruments>

Ho quindi definito la classe CSDfile nel modulo mod_csd.py.Il codice significativo l'ho inserito nel costruttore:

class CSDfile: def __init__( self, filenameIn, filenameOut,configFile,separatore ): f = open( configFile, "r" ) self.filenameOut = filenameOut lista = f.readlines() dizionario = {} for linea in lista: nuovachiave = linea.split( separatore ) if len( nuovachiave ) == 2: dizionario[ nuovachiave[0].strip() ] = nuovachiave[1].strip() f.close() f = open( filenameIn, "r" ) lista = f.readlines() for k, v in dizionario.items(): for i in range(len(lista)): lista[i]=lista[i].replace(k,v)

f = open( filenameOut, "w" ) f.writelines(lista) f.close()

81 di 109

Page 82: Corso Perfezionamento Informatica Musicale

Nel file principale python richiamo il costruttore passandogli gli opportuni parametri.

filenameIn: Il file csd da elaborare contenente le macro da esploderefilenameOut: Il nuovo file csd risultato finale dell'elaborazioneconfigFile: Il file di configurazione contenenete la definizione delle macroseparatore: Il separatore utilizzato nell'elenco delle definizioni delle macro.

csdFile = CSDfile("csd/Pad_percussion1.csd", "csd/temp.csd","conf/percussionPad.con","=")csound.Compile("csd/temp.csd")

Il file di configurazione potrà contenere, ad esempio, le seguenti righe:

$CsOptions=-b320 -B640 -odac4 -iadc4 -m0 -M1$ictlno1=1$ichan1=1$ictlno2=1$ichan2=1$nota1=69$nota2=71

L'opcode chnset e l'istruzione GetChannel

Python e Csound possono comunicare facilmente tra loro. La comunicazione avviene attraverso i cosiddetti canali (Bus) software. In particolare, grazie all'opcode cSound chnset e all'API GetChannel è possibile passare delle variabili dal server CSound al client Python (o altro front-end). In questo modo viene creato un canale di comunicazione (lettura e scrittura) tra Csound e Python.

Durante l'esecuzione di uno strumento cSound può tornare utile passare il valore di una varibile ad un programma di controllo o semplicemente ad un'interfaccia grafica. L'opcode che permette questo è chnset. Questo opcode prende due parametri.Il primo parametro rappresenta il valore della variabile, che si vuole passare; il secondo la stringa-etichetta (in pratica il nome della variabile di comunicazione).

chnset icounter, "counter3"

Per leggere il valore della variabile passata da Csound all'interno di Python, è necessario importare il modulo csnd. Il valore della variabile cSound viene letto tramite il metodo GetChannel, dell'oggetto csound, che prende come parametro l'etichetta assegnata.

try: self.counters[nButton -1] = self.csound.GetChannel("counter%d" % b); tc = self.textcounters[nButton -1]

82 di 109

Page 83: Corso Perfezionamento Informatica Musicale

tc.SetLabel("%d" % self.counters[nButton -1]);except: print "Error GetChannel"

Alcune considerazioni sull'opcode chnset

Prima di continuare ad analizzare le altre API di comunicazione tra Csound e Python, è opportuno soffermarci ancora sull'opcode chnset.

Il manuale di Csound elenca quattro "firme" per l'opcode chnset.

chnset ival, Snamechnset kval, Snamechnset aval, Snamechnset Sval, Sname

Le quattro sintassi differiscono in base al tipo della prima variabile. Quindi è possibile passare attraverso il bus di comunicazione variabili d'inizializzazione, variabili di controllo, variabili audio, stringhe.

Analizziamo nel dettaglio l'opcode chnset con variabile di controllo, partendo ancora da un esempio.

a1 = asig1 + asig2gkGain rms a1if gkGain > iSoglia then kTrig=1else kTrig=0endif

chnset kTrig, "Triggered"

In questo codice il mio scopo è di "avvisare" il programma Python che sta pilotando Csound, ogni volta che il valore rms del segnale audio (gkGain ) supera una certa soglia (iSoglia). In particolare, se la soglia viene superata la variabile di canale "Triggered" viene posta ad 1, altrimenti continua a valere 0. Voglio così che il programma Python venga avvisato continuamente, in base alla frequenza di controllo.

Ora vediamo un errore, che anch'io ingenuamente avevo commesso.

a1 = asig1 + asig2gkGain rms a1

83 di 109

Page 84: Corso Perfezionamento Informatica Musicale

if gkGain > iSoglia then chnset 1, "Triggered"else chnset 0, "Triggered"endif

Il codice è stato riscritto. Addirittura è più compatto. Non viene usata la variabile kTrig. Sorge però un problema: il programma Python non viene più avvisato correttamente quando la soglia viene superata. Come mai? Il motivo è semplice, usando delle costanti nell'opcode chnset, l'opcode viene eseguito solo in fase di inizializzazione (e quindi una volta sola).

In conclusione se vogliamo che il nostro opcode sia eseguito continuamente, non è possibile assegnare a chnset una costante come valore del primo argomento.

L'opcode chnget ed il modulo Python csnd

In questo articolo vediamo una classe Python che utilizza il modulo csnd e un'orchestra csound che adopera l'opcode chnget. L'esempio illustra un possibile upgrade della nostra Loop-station (battezzata Faust loop-station ). L'esempio illustrato è scaricabile dalla sezione download.Occorre innanzitutto importare nel nostro script Python il modulo csound csnd, contenente le API cSound

import csnd

Quindi occorre istanziare (ad esempio nel costruttore della nostra classe) un oggetto cSound e compilare il file csd di riferimento,

self.csound = csnd.CppSound()self.csound.Compile("faust.csd")

Infine bisogna far partire in un Thread dedicato il processo cSound.

self.performanceThread = csnd.CsoundPerformanceThread(self.csound)self.performanceThread.Play()

A questo punto cSound è in esecuzione! Se vogliamo passare dei parametri dalla nostra interfaccia Python all'orchestra cSound possiamo utilizzare quello che nella documentazione cSound è chiamato software bus

84 di 109

Page 85: Corso Perfezionamento Informatica Musicale

Da una parte del nostro canale software vi è cSound, dall'altra vi è Python. L'istruzione Python per inviare dati nel canale è SetChannel. Prende due argomenti: il nome del canale ed il valore da passare.

Mentre la nostra orchestra è in esecuzione è quindi possibile modificarne dei parametri interagendo con la GUI Python.

self.mute = 0 self.csound.SetChannel("mute", self.mute)

L'istruzione da utilizzare nell'orchestra cSound è chnget. E' un istruzione che legge, in base alla frequenza del tipo della variabile di output, il valore del canale del software bus. Nell'esempio seguente l'opcode chnget legge alla frequenza di controllo, il valore dal canale mute e lo assegna alla variabile globale gkMute, responsabile del muting degli strumenti cSound della loop station

gkMute chnget "mute"

Creare un lettore di campioni in Python e Csound

In questo articolo vediamo un esempio di classe Python, che permette di caricare in una Combobox un elenco di nomi di files audio con estensione data e quindi di laniciare l'esecuzione dell'opportuno strumento Csound.

Lo strumento Csound potrà contenere un'istruzione tipo diskin, ma soprattutto dovrà assegnare ad una variabile data (Ssample) il nome del file passato come parametro dal programma Python

instr 2.....if gkMute == 1 kgoto ESCI

Ssample = p4.......

Passiamo ad analizzare la classe Python.Particolarmente importanti sono gli ultimi parametri passati al costruttore:path (il percorso contenente i files audio), ext (l'estensione dei files audio), perf (l'istanza della classe CsoundPerformanceThread ), instr (il numero di strumento Csound che dovrà essere

85 di 109

Page 86: Corso Perfezionamento Informatica Musicale

eseguito, ogni volta che l'utente sceglierà un nuovo campione)

La classe è molto semplice.Visualizza in una combo i files audio presenti nella cartella SSDIR (caricando solo quelli con opportune estensioni). Ogni volta che l'utente seleziona una voce dalla combo,viene eseguita una nota dello strumento instr con durata casuale.

import utilitiesimport osimport random

from wxPython.wx import *import wx

class SamplesCtrl: def __init__(self, panel, id_Combo, point,size, path,ext,perf,instr): self.samplesList =[] for filename in os.listdir(path): if filename.find(ext)>-1: self.samplesList.append(filename) self.Mod = [] self.panel = panel self.instr = instr self.perf = perf self.cb = wx.ComboBox( self.panel, id_Combo, self.samplesList[0], point,size,self.samplesList, wx.CB_DROPDOWN ) self.panel.Bind(wx.EVT_TEXT, self.EvtText, self.cb) def EvtText(self, evt): sample = str(evt.GetString()) durata = random.sample([120, 180, 240, 120, 180, 240], 1) s = "i%d 0 %f \"%s\"" % (self.instr, durata[0],sample ) self.perf.InputMessage(s) evt.Skip()

Ecco infine una chiamata del costruttore della classe cb = SamplesCtrl(self.panel, 500,(980, 320), (-1, -1),"C:\Documents and Settings\Administrator\Documenti\CSound\Audio",".wav",self.perf,2)

86 di 109

Page 87: Corso Perfezionamento Informatica Musicale

Subclassing del controllo wxSlider

In questo articolo presento un esempio di personalizzazione del controllo wxSlider della libreria wxPython con l'obiettivo di creare un componente specializzato nella comunicazione con cSound.

La tecnica adottata è quella del subclassing. Ho innanzitutto derivato il mio wxMediaSlider dal wxSlider. Ho quindi realizzato un costruttore ad hoc, con un maggior numero di parametri.Al nuovo costruttore (__init) viene passato l'ggetto cSound (csndObj), il nome della variabile da utilizzare nel canale software (varName), il fattore di divisione con cui dividere il valore attuale del controllo per poi passarlo a Csound (nDiv). Ogni volta che l'utente modifica il valore dello slider, viene inviato un messaggio al server cSound con variabile varName e valore GetValue()/nDiv. In questo modo la classe che conterrà il wxMediaSlider non dovrà più di preoccuparsi di alcuni noiosi dettagli implementativi.

La classe wxMediaSlider sovrascrive anche il metodo SetValue. In pratica ogni volta che verrà richiamato questo metodo, lo Slider non solo aggiornerà la sua interfaccia grafica, ma invierà anche un messaggio a cSound.

In definitiva al wxSlider è stata aggiunta una seconda modalità di output del proprio valore memorizzato. Oltre alla visualizzazione il wxMediaSlider aggiorna anche la vista del server cSound sul proprio valore memorizzato.

Riporto il codice di questa semplice tecnica di subclassing.

from wxPython.wx import *import wximport csnd

class wxMediaSlider(wxSlider): def __init__(self, parent, ID, defaultValue, minValue, maxValue, position,size,style, csndObj,varName,nDiv): wx.Slider.__init__(self, parent, ID, defaultValue, minValue, maxValue, position,size,style) self.csndObj = csndObj self.varName = varName self.nDiv = nDiv self.__SetValue(defaultValue) self.SetTickFreq(2, 1) EVT_SLIDER(self, ID, self.OnSliderMove)

def __SetValue(self,value):

87 di 109

Page 88: Corso Perfezionamento Informatica Musicale

d = value / self.nDiv self.csndObj.SetChannel(self.varName, d)

def SetValue(self,value): wx.Slider.SetValue(self,value) self.__SetValue(value)

def OnSliderMove(self, event): self.__SetValue(self.GetValue())

Ecco un esempio d'uso della classe appena definita:

l = wxMediaSlider(self.panel, 20 + i, 0, 0, 6000, (2 + ((i-1) *200), 340),(140,50),wxSL_HORIZONTAL | wxSL_LABELS,self.csound,"volume%d" % (i + 1 ),1000.0)

Una classe Python per grafici in tempo reale

La classe Python che riporto in questo articolo è un semplice visualizzatore grafico di dati cangianti nel tempo. Ad esempio, mi è tornata utile per visualizzare il valore attuale di un controller Midi.

Il visualizzatore rappresenta graficamente gli ultimi n valori ricevuti dalla classe in base ad una logica First In First Out (FIFO). Inoltre visualizza in una casella di testo l'ultimo valore in ingresso (Es. 175.83) e l'etichetta di approssimazione più consona (F3).

88 di 109

Page 89: Corso Perfezionamento Informatica Musicale

from wxPython.wx import *from ReadConfig import *import wxMAX_F = 2.0SPACE = 30MAX_PUNTI = 10

#Class for istograms drawingclass GraphPanel(wx.Panel): def __init__(self, parent, pos, size, pen, title, pMin, pMax, config_file,sep): wx.Panel.__init__(self, parent,333, pos, size, wx.WANTS_CHARS) self.ID =100 self.pen = pen self.Max = pMax self.Min = pMin r = ReadConfig(config_file,sep) self.dizionario = r.getDizionario()#Resizing buttons and static text panelSize = self.GetSize() self.height = panelSize[1] self.width = panelSize[0] self.bottom = SPACE self.top = self.bottom self.Msg=wx.StaticText(self, -1, title, (0, self.height - SPACE / 2)) font = wx.Font(14, wx.SWISS, wx.NORMAL, wx.NORMAL) self.Msg.SetFont(font)

self.punti =[] self.Bind(wx.EVT_PAINT, self.OnPaint)

def getRightLabel(self, Y): best_value = -1 best_label = "" for k, v in self.dizionario.items(): if(best_value == -1): best_value = abs(float(v)- Y) best_label = k else: if abs(float(v)- Y)< best_value : best_value = abs(float(v)- Y) best_label = k return (best_label,best_value)

def AddValue(self,Y): if (Y >= self.Min and Y <= self.Max): H = self.Max - self.Min

89 di 109

Page 90: Corso Perfezionamento Informatica Musicale

h = self.height - (self.top + self.bottom) modulo = Y * h / H y = self.top + h - modulo s = self.getRightLabel(Y) self.Msg.SetLabel(" Value: %.2f - Label:%s" % (Y,s[0])) self.punti.append(wx.Point(self.GetSize().GetWidth(),y)) if len(self.punti)> MAX_PUNTI: self.punti.pop(0) w = self.width / (MAX_PUNTI - 1) for i in range(0,len(self.punti)): self.punti[len(self.punti) - (i + 1)].x = self.width - w * i #print self.punti[len(self.punti) - (i + 1)].y self.Refresh()

def OnPaint(self, evt): dc = wx.PaintDC(self) self.PrepareDC(dc)

try: gc = wx.GraphicsContext.Create(dc) except NotImplementedError: dc.DrawText("This build of wxPython does not support the wx.GraphicsContext " "family of classes.", 25, 25) return

font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) font.SetWeight(wx.BOLD) gc.SetFont(font) path = gc.CreatePath() start=0 s = self.GetSize() h= self.height w = s.GetWidth()

path.AddRectangle(0, self.top, w-1, h-(self.top + self.bottom)) gc.PushState() gc.SetPen(wx.Pen("green", 5)) gc.SetBrush(wx.Brush("black"))

for label, PathFunc in [("StrokePath", gc.StrokePath), ("FillPath", gc.FillPath), ("DrawPath", gc.DrawPath)]: if "wxGTK" in wx.PlatformInfo: w, h = dc.GetTextExtent(label) # NYI in Cairo context else: w, h = gc.GetTextExtent(label) PathFunc(path)

90 di 109

Page 91: Corso Perfezionamento Informatica Musicale

gc.PopState()

#istograms drawing path2 = gc.CreatePath() start=0 if len(self.punti)>0: path2.MoveToPoint(self.punti[0].x, self.punti[0].y) for i in range(1,len(self.punti)): path2.AddLineToPoint(self.punti[i].x, self.punti[i].y)

gc.PushState() gc.SetPen(wx.Pen(self.pen, 5)) for label, PathFunc in [("StrokePath", gc.StrokePath), ("FillPath", gc.FillPath), ("DrawPath", gc.DrawPath)]: if "wxGTK" in wx.PlatformInfo: w, h = dc.GetTextExtent(label) # NYI in Cairo context else: w, h = gc.GetTextExtent(label) PathFunc(path2) gc.PopState()

91 di 109

Page 92: Corso Perfezionamento Informatica Musicale

Composizione algoritmica e tempo reale

Nel tutorial, Composizione algoritmica, ci soffermeremo principalmente su tutte quelle tecniche informatiche che possono essere d'aiuto, non tanto alla composizione musicale in genere, ma alla cosiddetta composizione istantanea. In altre parole, l'obiettivo è quello di fornire alcuni strumenti per cercare di risolvere il problema principale del musicista elettronico interessato all'elaborazione del suono in tempo reale: come gestire la modifica contemporanea di più parametri durante la performance secondo determinate scelte estetiche im modo pratico, flessibile ed intelligente?

La composizione algoritmica applicata all'elaborazione del suono in tempo reale trova principale motivazione nel fatto che durante una performance, il musicista ha il tempo di pilotare soltanto un limitato numero di parametri. Molti aspetti dell'esecuzione devono essere così necessariamente delegati alla macchina.Solo grazie ad algoritmi intelligenti il musicista potrà sfruttare pienamente lo strumento che ha tra le mani: il computer.

Nel preparare una performance il musicista deve così farsi, almeno idealmente, programmatore.

Le forme musicali che verranno eseguite durante il live, saranno sempre il frutto dell'interazione tra musicista e programmi ( anche e soprattutto di composizione automatica).

I programmi che il musicista realizzerà o assemblerà definirinno alcuni dei confini della sua estetica.

Chiramente tali algoritmi in nessun modo sostituiscono l'uso da parte del musicista di particolari "controlli" ed interfacce fisiche adeguate per interagire con la macchina, ma ne sono l'inevitabile completamento.

Una classe per la gestione di pattern di accenti

Ho realizzato la classe PatternCtrl partendo da questo problema esecutivo:

Mi son ritrovato a campionare, durante una performace, un breve frammento sonoro, e quindi a mandarlo in loop. Ovviamente durante l'esecuzione del loop il frammento veniva eseguito sempre in maniera identica. Ho quindi voluto creare una classe per applicare al loop una sequenza di

92 di 109

Page 93: Corso Perfezionamento Informatica Musicale

accenti, in modo da renderlo più vivo e meno monotono.

Ho deciso di memorizzare la sequenza degli accenti in un file e di salvare tutti i file in un'unica cartella.Ogni file è composto da sole tre righe:

• riga di accenti per il canale sinistro

• riga di accenti per il canale destro

• modalità di lettura dei valori.

Se la terza riga contiene il simbolo ">" i valori verranno letti in sequenza, se il simbolo contenuto è una "r" i valori verranno letti "randomicamente".Ogni riga di accenti è costituita da una sequenza di numeri. Ogni numero è un fattore di moltiplicazione da applicarsi al volume del frammento.L'esempio 1 quindi rappresenta una sequenza del tipo: accento forte, accento debole, accento forte, accento debole.

Esempio 1 1.0 0.1 1.0 0.11.0 0.2 1.0 0.3>

Esempio 21.0 0.0 0.5 2.0 1.0 0.7 0.2 0.0 0.81.0 0.0 0.7 0.8 1.0 0.3 1.5 1.0 0.0r

I nomi dei possibili pattern di accenti vengono visualizzati in una casella combinata. La casella viene popolata con i nomi dei files presenti nella directory passata come argomento (path) al costruttore della classe.

cb = PatternCtrl(self.panel, 500,( 10 + ((i-1) *195), 420), (-1, -1),os.getcwd() + "\pattern")

La classe si occupa così di leggere i files dei pattern di accenti, visualizzarne i nomi nella combo, infine e soprattutto offrire all'esterno della classe il valore dell'accento corrente.

from math import floor

import utilitiesimport osimport random

from wxPython.wx import *import wx

93 di 109

Page 94: Corso Perfezionamento Informatica Musicale

class PatternCtrl: def __init__(self, panel, id_Combo, point,size, path): self.panList = os.listdir(path) i=0 self.panL = [] self.panR = [] self.Mod = [] self.R_Counter=0 for fileName in self.panList: fn = fileName.split(".") t= path + "\\" + fileName f = open(t,'rb') lines =f.readlines()

l = lines[0] l = l.strip() x = l.split() self.panL.append(x) l = lines[1] l = l.strip() x = l.split() self.panR.append(x) l = lines[2] l = l.strip() self.Mod.append(l) self.panList[i] =fn[0] i = i + 1 self.panel = panel self.cb = wx.ComboBox( self.panel, id_Combo, self.panList[0], point,size,self.panList, wx.CB_DROPDOWN ) def getIndex(self,name): for i in range(0,len(self.panList)): if self.panList[i]==name: return i return -1 def getPanValue(self): i = self.getIndex(self.cb.GetValue()) if self.Mod[i]=="r" or self.Mod[i]=="R": x = random.sample(self.panL[i],1) y = random.sample(self.panR[i],1) return [float(x[0]),float(y[0])] if self.Mod[i]==">": self.R_Counter = self.R_Counter + 1 if self.R_Counter == len(self.panL[i]): self.R_Counter = 0 l = self.panL[i]

94 di 109

Page 95: Corso Perfezionamento Informatica Musicale

r = self.panR[i] #print "ok" return [float(l[self.R_Counter]),float(r[self.R_Counter])] return [1.0,1.0]

Modificare pattern di accenti tramite istogrammi

Questo articolo presenta un componente grafico per visualizzare nella forma di istogrammi un pattern di accenti, seguendo la formalizzazione già presentata.

L'esempio completo è presente nella sezione download.

Attraverso i due pulsanti ADD e REMOVE è possibile aggiungere o rimuovere un rettangolo dal grafico. Ogni volta che viene aggiunto un rettangolo, tutti i rettangoli già presenti vengono ridimensionati.Cliccando con il pulsante sinistro del mouse nell'area di disegno, viene ridimensionato il rettangolo selezionato.

Le stringhe di accenti , ad esempio "1.0 2.0 0.0 1.0", possono essere utilizzate per caricare in un colpo solo i rettangoli del grafico. Il valore 2.0 è il valore massimo consentito, mentre quello minimo è 0.0.

Grazie ad un metodo della classe è possibile esportare in formato stringa l'istogramma disegnato.

Ho realizzato la classe per permettere ad un utente di visualizzare e modificare in tempo reale una sequenza di accenti. Ogni rettangolo è un accento. L'altezza del rettangolo rappresenta la forza

95 di 109

Page 96: Corso Perfezionamento Informatica Musicale

dell'accento.

from wxPython.wx import *import wxMAX_F = 2.0SPACE = 10

#Class for istograms drawingclass IstoPanel(wx.Panel): def __init__(self, parent, pos, size, env, pen, brush, title): wx.Panel.__init__(self, parent,333, pos, size, wx.WANTS_CHARS) self.ID =100 self.pen = pen self.brush = brush

#Add Button self.ID_BUTTON_ADD = self.ID self.ID=self.ID + 1 self.buttonInsert = wx.Button(self, self.ID_BUTTON_ADD , "ADD", (20, 20)) EVT_BUTTON(self, self.ID_BUTTON_ADD, self.OnClickButtonAdd)

#Remove Button self.ID_BUTTON_REMOVE = self.ID self.ID=self.ID + 1 self.buttonRemove = wx.Button(self, self.ID_BUTTON_REMOVE , "REMOVE", (100, 20)) EVT_BUTTON(self, self.ID_BUTTON_REMOVE, self.OnClickButtonRemove)

#Resizing buttons and static text panelSize = self.GetSize() self.height = panelSize[1] buttonSize = self.buttonInsert.GetSize() self.buttonInsert.SetPosition((0, self.height - self.buttonInsert.GetSize().GetHeight() + SPACE / 2)) self.buttonRemove.SetPosition((buttonSize.GetWidth() + SPACE, self.height - self.buttonInsert.GetSize().GetHeight() + SPACE / 2)) self.bottom = self.buttonInsert.GetSize().GetHeight() self.top = self.bottom x = self.buttonRemove.GetPosition() x =x[0] + self.buttonRemove.GetSize().GetWidth() + SPACE wx.StaticText(self, -1, title, (x, self.height - self.buttonInsert.GetSize().GetHeight() + SPACE / 2))

self.rettangoli =[] self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)

def OnClickButtonAdd(self, event): w = self.GetSize().GetWidth()

96 di 109

Page 97: Corso Perfezionamento Informatica Musicale

if len(self.rettangoli)==0: rw = w else: rw = int(w / (len(self.rettangoli) + 1))

i=0 for i in range(0,len(self.rettangoli)): self.rettangoli[i].x = i * rw self.rettangoli[i].width = rw if len(self.rettangoli) > 0: i = i + 1

self.rettangoli.append (wxRect(rw * i,self.top,rw,self.height - (self.top + self.bottom))) self.Refresh() def OnClickButtonRemove(self, event): if len(self.rettangoli)>0: self.rettangoli.pop() w = self.GetSize().GetWidth() if len(self.rettangoli)==0: rw = w else: rw = int(w / (len(self.rettangoli)))

i=0 for i in range(0,len(self.rettangoli)): self.rettangoli[i].x = i * rw self.rettangoli[i].width = rw if len(self.rettangoli) > 0: i = i + 1

self.Refresh()

def LoadRects(self,lista): w = self.GetSize().GetWidth() self.rettangoli =[] if len(lista)==0: rw = w else: rw = int(w / len(lista)) i=0 for l in lista: r = float(l.strip()) h = r * (self.height - (self.top + self.bottom)) / MAX_F top = (self.height - self.top) - h self.rettangoli.append (wxRect(rw * i,top,rw,h)) i= i + 1

97 di 109

Page 98: Corso Perfezionamento Informatica Musicale

self.Refresh()

def Load(self, Str): lista = Str.split(" ") self.LoadRects(lista) def Get(self): ris = "" for r in self.rettangoli: h = r.height * MAX_F / (self.height - (self.top + self.bottom)) ris = ris + ("%.1f " % h) ris = ris.strip() return ris

def OnLeftDown(self, event):

x = event.GetX() y = event.GetY() if y >= self.top and y <= (self.height - self.bottom) : if len(self.rettangoli) >0: w = self.rettangoli[0].width i = int(x / w) if i < len(self.rettangoli): self.rettangoli[i].y= y self.rettangoli[i].height = self.height - (self.bottom) - y self.Refresh()

def OnPaint(self, evt): dc = wx.PaintDC(self) self.PrepareDC(dc)

try: gc = wx.GraphicsContext.Create(dc) except NotImplementedError: dc.DrawText("This build of wxPython does not support the wx.GraphicsContext " "family of classes.", 25, 25) return

font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) font.SetWeight(wx.BOLD) gc.SetFont(font) path = gc.CreatePath() start=0 s = self.GetSize() h= self.height

98 di 109

Page 99: Corso Perfezionamento Informatica Musicale

w = s.GetWidth()

path.AddRectangle(0, self.top, w-1, h-(self.top + self.bottom)) gc.PushState() gc.SetPen(wx.Pen("green", 5)) gc.SetBrush(wx.Brush("black"))

for label, PathFunc in [("StrokePath", gc.StrokePath), ("FillPath", gc.FillPath), ("DrawPath", gc.DrawPath)]: if "wxGTK" in wx.PlatformInfo: w, h = dc.GetTextExtent(label) # NYI in Cairo context else: w, h = gc.GetTextExtent(label) PathFunc(path) gc.PopState()

#istograms drawing path2 = gc.CreatePath() for r in self.rettangoli: path2.AddRectangle(r.x, r.y, r.width, r.height) gc.PushState() gc.SetPen(wx.Pen(self.pen, 5)) gc.SetBrush(wx.Brush(self.brush))

for label, PathFunc in [("StrokePath", gc.StrokePath), ("FillPath", gc.FillPath), ("DrawPath", gc.DrawPath)]: if "wxGTK" in wx.PlatformInfo: w, h = dc.GetTextExtent(label) else: w, h = gc.GetTextExtent(label) PathFunc(path2) gc.PopState()

Generazione di motivi musicali con catene di Markov

Esiste una fiorente letteratura su come utizzare una catena di Markov per generare motivi musicali,

99 di 109

Page 100: Corso Perfezionamento Informatica Musicale

melodie o semplici strutture sonore.

Senza entrare nei dettagli, una catena di Markov può essere pensata come un grafo orientato e pesato.Dal nostro punto di vista può essere anche vista come una particolare macchina a stati finiti. I nodi formalizzano gli stati, le freccie le probabilità di passaggio da uno stato ad un altro. In effetti ogni nodo è collegato almeno ad un altro tramite una freccia con un numero che ne indica il peso, ossia la probabilità di passaggio al nodo successivo. Nessun nodo può essere isolato.

Osservando la figura si può notare come il nodo H sia collegato al nodo E con peso/probabilità del 100%. Il nodo L, invece, è legato sia a se stesso che al nodo O con un peso/probabilità del 50%.

I nodi possono rappresentare semplici note con durata, frequenza, timbro specifici, oppure qualsiasi altro oggetto sonoro. Ad esempio se due note hanno stessa frequenza, timbro e durata potranno essere rappresentate dallo stesso nodo.

La catena può avere un nodo iniziale oppure il primo nodo può essere scelto casulamente.Da un nodo si può passare soltanto ai nodi collegati direttamente. Così dal nodo H si passerà sempre e comunque al nodo E. Per esempio dalla nota cSound 8.03 eseguita dallo strumento 1 con durata 1 sec. si potrà passare sempre e solo alla nota denotata da E con la sua specifica articolazione e timbro. Ancora dal nodo E si passare con una probabilità del 33% a "L", del 33% a "_", del 33% a "R".

A questo punto si potranno ottenere con la stessa probabilità tre strutture: "HER","HEL" oppure "HE_"

Il formalismo per la sua semplicità permette di modellare solo strutture musicali molto semplici, dato che ogni stato dipende interamente soltanto dallo stato precedente.

100 di 109

Page 101: Corso Perfezionamento Informatica Musicale

Nei prossimi articoli vedremo alcune implementazioni di catene di Markov in Python e cSound.

Rappresentare una catena di Markov con un file XML

In questo articolo vediamo come rappresentare una catena di Markov con un file XML.

Il nodo principale è il tag <MARKOV_CHAIN>.Un nodo della catena è rappresentato dal tag <NODE ...>, il quale possiede 4 attributi obbligatori: NAME, OCTAVE, PITCH, DURATION, che formalizzano le principali proprietà di una nota. Per convenzione se il valore dell'attributo OCTAVE è uguale a 0, la nota rappresentata è in realtà una pausa.

Gli archi che escono dal nodo sono rappresentati dai tag <LINK ...>. I tag LINK hanno due attributi: NODE, che rappresenta il nome del nodo di arrivo e WEIGTH che rappresenta il peso associato all'arco.

Esempio1

<?xml version="1.0" ?> <MARKOV_CHAIN> <NODES_LIST> <NODE NAME="Do3_1" OCTAVE="3" PITCH="0" DURATION="1"> <NODES_LINK> <LINK NODE="Do3_1" WEIGTH="0.2" /> <LINK NODE="Do4_2" WEIGTH="0.2" /> <LINK NODE="Do4_1" WEIGTH="0.2" /> <LINK NODE="MIB6_2" WEIGTH="0.4" /> </NODES_LINK> </NODE> <NODE NAME="Do4_1" OCTAVE="3" PITCH="0" DURATION="1"> <NODES_LINK> <LINK NODE="Do3_1" WEIGTH="0.2" /> <LINK NODE="Do4_2" WEIGTH="0.3" /> <LINK NODE="MIB6_2" WEIGTH="0.5" /> </NODES_LINK> </NODE> <NODE NAME="Do4_2" OCTAVE="4" PITCH="0" DURATION="0.5"> <NODES_LINK> <LINK NODE="Do4_2" WEIGTH="0.5" /> <LINK NODE="Do6_1" WEIGTH="0.5" /> </NODES_LINK> </NODE>

101 di 109

Page 102: Corso Perfezionamento Informatica Musicale

<NODE NAME="Do6_1" OCTAVE="6" PITCH="0" DURATION="1.0"> <NODES_LINK> <LINK NODE="Do4_2" WEIGTH="0.4" /> <LINK NODE="MIB6_1" WEIGTH="0.25" /> <LINK NODE="PAU_1" WEIGTH="0.25" /> <LINK NODE="PAU_1" WEIGTH="0.2" /> </NODES_LINK> </NODE> <NODE NAME="MIB6_1" OCTAVE="6" PITCH="3" DURATION="1.0"> <NODES_LINK> <LINK NODE="Do4_2" WEIGTH="0.2" /> <LINK NODE="MIB6_1" WEIGTH="0.2" /> <LINK NODE="Do6_1" WEIGTH="0.2" /> <LINK NODE="PAU_1" WEIGTH="0.2" /> <LINK NODE="SOL6_1" WEIGTH="0.1" /> <LINK NODE="MIB6_2" WEIGTH="0.1" /> </NODES_LINK> </NODE> <NODE NAME="SOL6_1" OCTAVE="6" PITCH="8" DURATION="1.0"> <NODES_LINK> <LINK NODE="Do4_2" WEIGTH="0.2" /> <LINK NODE="MIB6_1" WEIGTH="0.2" /> <LINK NODE="SOL6_1" WEIGTH="0.2" /> <LINK NODE="PAU_1" WEIGTH="0.2" /> <LINK NODE="MIB6_2" WEIGTH="0.2" /> </NODES_LINK> </NODE> <NODE NAME="MIB6_2" OCTAVE="6" PITCH="3" DURATION="0.5"> <NODES_LINK> <LINK NODE="MIB6_2" WEIGTH="0.25" /> <LINK NODE="MIB6_1" WEIGTH="0.25" /> <LINK NODE="Do6_1" WEIGTH="0.25" /> <LINK NODE="PAU_1" WEIGTH="0.25" /> </NODES_LINK> </NODE> <NODE NAME="PAU_1" OCTAVE="0" PITCH="0" DURATION="1.0"> <NODES_LINK> <LINK NODE="Do4_2" WEIGTH="0.25" /> <LINK NODE="Do6_1" WEIGTH="0.25" /> <LINK NODE="PAU_1" WEIGTH="0.5" /> </NODES_LINK> </NODE> </NODES_LIST> </MARKOV_CHAIN>

Esempio2

<?xml version="1.0" ?> <MARKOV_CHAIN> <NODES_LIST>

102 di 109

Page 103: Corso Perfezionamento Informatica Musicale

<NODE NAME="SOL6_1" OCTAVE="6" PITCH="8" DURATION="1.0"> <NODES_LINK> <LINK NODE="SOL6_1" WEIGTH="0.4" /> <LINK NODE="PAU_1" WEIGTH="0.2" /> <LINK NODE="RE7_2" WEIGTH="0.4" /> </NODES_LINK> </NODE> <NODE NAME="SOL6_4" OCTAVE="6" PITCH="8" DURATION="0.25"> <NODES_LINK> <LINK NODE="SOL6_1" WEIGTH="0.2" /> <LINK NODE="SOL6_4" WEIGTH="0.4" /> <LINK NODE="PAU_1" WEIGTH="0.2" /> <LINK NODE="RE7_2" WEIGTH="0.2" /> </NODES_LINK> </NODE> <NODE NAME="RE7_2" OCTAVE="7" PITCH="2" DURATION="0.5"> <NODES_LINK> <LINK NODE="SOL6_1" WEIGTH="0.4" /> <LINK NODE="PAU_1" WEIGTH="0.2" /> <LINK NODE="RE7_2" WEIGTH="0.2" /> <LINK NODE="SOL6_4" WEIGTH="0.2" /> </NODES_LINK> </NODE> <NODE NAME="PAU_1" OCTAVE="0" PITCH="0" DURATION="1.0"> <NODES_LINK> <LINK NODE="SOL6_1" WEIGTH="0.2" /> <LINK NODE="PAU_1" WEIGTH="0.4" /> <LINK NODE="RE7_2" WEIGTH="0.4" /> </NODES_LINK> </NODE> </NODES_LIST> </MARKOV_CHAIN>

Passaggio da un range di valori ad un altro con l'interpolazione lineare

Conoscere la soluzione a questo problema nella composizione assistita dal computer può tornare utile ogni volta che si desidera tradurre un valore relativo ad un determinato range, in un altro che rientra però in un range più piccolo o più grande.

La soluzione non è altro che l'applicazione della nota formula dell'interpolazione lineare.In particolare x0 e x1 rappresentano gli estremi della gamma di partenza (estremi del segmento

103 di 109

Page 104: Corso Perfezionamento Informatica Musicale

sull'asse X); y0 e y1 rappresentano gli estremi della gamma di arrivo; x è il valore che si desidera tradurre; y è il valore che si desidera trovare

Il problema può essere rappresentato in un asse cartesiano in questo modo: dato un segmento con estremi (x0,y0) (x1,y1) trovare l'ordinata y conoscendone l'ascissa x.

In Python la formula può essere così tradotta

def linear_interpolation(x, xMin, xMax, yMin, yMax): a = (x - xMin) / (xMax - xMin) b = yMax - yMin return a * b + yMin

print linear_interpolation(3.0,1.0,4.0,3.0,9.0)

>>> 7.0

Una tra le tante notevoli applicazioni di questo algoritmo consiste nella traduzione del valore x di un controllo MIDI (0 - 127) in un valore y di range qualsiasi , come per esempio la durata di un delay con gamma da 1 a 10 secondi.

BibliografiaMusimathics vol. 1 di Garteh LoyWikipedia Linear Interpolation

104 di 109

Page 105: Corso Perfezionamento Informatica Musicale

Permutazioni o disposizioni senza ripetizione

Fin dalle mie prime esperieze d'informatica musicale mi sono imbattuto nelle permutazioni: ad esempio quando scrissi uno dei miei primi programmi C, che doveva trovare tutti i possibili accordi eseguibili su uno strumento a corde, quali chitarra o basso elettrico.

Per permutazione si intende una disposizione di elementi ma senza ripetizione

In altre parole, una permutazione è un modo di combinare n oggetti distinti scambiandoli di posizione, come nell'anagrammare una parola (WIKIPEDIA). La formula sopra riportata ci ricorda che dati n elementi, il numero di permutazioni è n!Molti concetti musicali tradizionali, come ad esempio quello di rivolto di un accordo, possono essere ricondotti a quello di permutazione. Tipicamente l'insieme di tutte le permutazioni rappresenta l'universo su cui si applicano specifiche regole di preferenza, che hanno il ruolo di selezionare solo quelle disposizioni che si conformano ai nostri disegni estetico-compositivi

Random walk

Immaginiamo una persona ubriaca, che ad ogni passo non sappia cosa fare... andare avanti o indietro?Ecco, il random walk è un algoritmo, stupido, evidentemente , che permette di scegliere in quale direzione compiere il prossimo passo della nostra camminata...

Il Random walk si utilizza tipicamente per leggere i valori di una matrice o di una lista a 2 o a n dimensioni, o per compiere aleatoriamente una qualsiasi scelta. La matrice contiene tutti i valori del dominio d'interesse (durata dei paramtri di un effetto, serie di altezze, possibili valori d'ampiezza ecc...). La distribuzione delle scelte che si otterrà sarà comunque non uniforme, ma avrà delle densità note, dipendenti dal valore di partenza, da quello minimo e massimo, dal numero degli elementi.L'algoritmo si applica ad una valore attuale (ad esempio un indice di un Array). Tramite un numero pseudo casuale si determina se il valore attuale deve essere incrementato o decrementato di un certo passo. Il nuovo valore sarà sempre incluso tra una soglia massima e una soglia minima, che saranno anche i due valori su cui l'agoritmo potrà eventualmente insistere.

Riporto una possibile implementazione in Python. Questa funzione è usata per determinare i valori

105 di 109

Page 106: Corso Perfezionamento Informatica Musicale

di due wxSpinCtrl (durata di un delay e di un contatore )

def random_walk(ActualValue, MinValue, MaxValue, Step): n = random.sample([0,1],1) if (n[0] == 1): result = ActualValue + Step if result > MaxValue: result = MaxValue else: result = ActualValue - Step if result < MinValue: result = MinValue return result

# Esempio d'uso if self.m_random: self.spindelays[nButton -1].SetValue(utilities.random_walk(self.spindelays[nButton -1].GetValue(), MIN_DELAY, MAX_DELAY, 5)) self.spincounters[nButton -1].SetValue(utilities.random_walk(self.spincounters[nButton -1].GetValue(), MIN_COUNTER, MAX_COUNTER, 5))

BibliografiaAutomated Music Composition - Phil WinsorMusimathics - the matematical foundations of music (volume 1) - Gareth Loy - The Mit Press

Disposizioni con ripetizione

Ripassiamo il concetto di: disposizione con ripetizione.Per esemplificare il concetto supponiamo di partire dalla seguente serie di 4 note SK={Do3, Do4, Mi3, Sol4} e proviamo a chiederci quanti motivi di 6 note (Ad Es. Do3, Do4, Mi3, Sol4 Do3, Do4} possiamo ottenere partendo dalla serie data.

In generale il problema che ci interessa può essere così espresso

Siano S1, S2, S3....Sr, r insiemi ognuno di n1,n2,n3....nr oggetti distinti e si consideri il prodotto cartesiano

Pr = S1 x S2 x ...... x Sr = { (s1,........,sr): s1 in S1 , ........sr in Sr }

Quante r-uple Pr contiene? Ovvero quanti sono gli allineamenti che si possono formare prendendo

106 di 109

Page 107: Corso Perfezionamento Informatica Musicale

un oggetto da S1, un oggetto da S2... un oggetto da Sr? Poichè si può scegliere s1 in n1 modi distinti, s2 in n2 modi distinti..... sr in nr modi distinti, il numero complessivo degli allineamenti possibili sarà dato da

n1 x n2 x ...... nr

Nel caso speciale in cui S1 = S2 =... Sr il risultato sarà nr.

Ritornando al nostro problema di partenza la soluzione sarà data da:

4 * 4 * 4 * 4 * 4 * 4 = 46

Funzione di conversione di una nota nella sua frequenza corrispondente

Come si sa il concetto di frequenza è un concetto fisico-matematico, mentre il concetto di "nota" o "tono" è un concetto legato alla sfera psico-percettiva. La traduzione di un concetto nel suo corrispondente implica un certo grado di approssimazione. In ogni caso, può tornare particolarmente utile avere a disposizone tra le proprie funzioni, una che si occupi della traduzioni di una nota qualsiasi nella sua corrispondente rappresentazione in cicli per secondo.

La funzione cpsch, che si occupa di questa traduzione, è stata scritta in python e corrisponde all'omonimo opcode csound. A differenza di quest'ultimo, però, la cpsch proposta prende sei parametri, di cui due obbligatori: Octave e Note, che indicano il numero di ottava e il numero dell'intervallo più piccolo della scala di riferimento (0....n).Gli altri quattro parametri individuano il sistema di coordinate in cui la coppia (Ottava,Nota) assume il suo corretto significato: la frequenza di riferimento, il numero di intervalli uguali in cui è divisa l'ottava, il numero di ottava ed il numero di intervallo in cui si traduce la frequenza di riferimento. La funzione è stata implementata partendo dalle seguenti osservazioni:

• La traduzione di un tono nella corrispondente rappresentazione in cicli per secondo presuppone che il tono venga identificato in maniera univoca

• Un tono può venir identificato con diversi sistemi di coordinate. La funzione identifica un tono in base ad una scala ottenuta tramite temperamento equabile.

107 di 109

Page 108: Corso Perfezionamento Informatica Musicale

• La suddivisione dell'ottava in dodici parti uguali è una delle possibili suddivisioni "equabili"dell'ottava

• La frequenza di riferimento 440.0 corrispondente al octave-point-pitch-class cSound 8.09, è una delle possibili frequenze di riferimento

• Se un tono ha frequenza Fr, l'ottava è il tono identificato dalla seguente espressione: Fr * (2 ** 1)

• Una frequenza può quindi essere rappresentata da numero di ottava (v) e da un numero di tono entro l'ottava (k), ottenuto dalla divisione in parti uguali della stessa (d)

F(k,v)= Fr * 2**v + k/d

def cpspch(Octave, Note, OctaveDivision=12.0, RefFreq=440.0, OctaveRefNumber=8, NoteRefNumber=9):

return RefFreq * (2.0 ** ((Octave - OctaveRefNumber) + (Note - NoteRefNumber)/OctaveDivision))

print cpspch(8,9)#----->-440.0

Una classe per il calcolo delle permutazioni di una serie di note

In questo articolo presento una classe Python per il calcolo di tutte le possibili permutazioni di una serie di note.

La serie è rappresentata da una lista di coppie. Ogni coppia (ottava,nota) traduce in un formato computazionalmente più comodo il solito octave-point-pitch-class di cSound. Il risultato ottenuto è in formato lista di liste.

def findPermutations(self, p_l, p_lp): if type(p_l) is NoneType: return if (len(p_l)==0): return if (len(p_l)==1): p_lp.append(p_l[0]) self.ris.append(p_lp) else: for i in range(0,len(p_l)): lp=[] lp.extend(p_lp) lp.append(p_l[i])

108 di 109

Page 109: Corso Perfezionamento Informatica Musicale

l=[] l=p_l[0:i] l.extend(p_l[(i+1):len(p_l)]) self.findPermutations(l,lp)

def getPermutations(self): self.ris = [] lp=[] self.findPermutations(self.S,lp) return self.ris

Per utilizzare la classe prima la si istanzia, passando al costruttore la serie da permutare. In seguito si chiama il metodo getPermutations, che ritorna il risultato desiderato. Il lavoro vero e proprio è effettuato dal metodo findPermutations.L'algoritmo segue una logica ricorsiva:

• La permutazione di una lista vuota è uguale alla lista vuota• La permutazione di una lista di un solo elemento è uguale all'elemento stesso• Se la lista comprende n > 1 elementi, le sue permutazioni saranno uguali alle permutazioni

delle liste con n-1 elementi, concatenando ad esse nella posizione i-esima l'elemento sottratto

p = Permutations([(8,0),(9,0),(7,5)])k = p.getPermutations()print k

>>>

[[(8, 0), (9, 0), (7, 5)], [(8, 0), (7, 5), (9, 0)], [(9, 0), (8, 0), (7, 5)], [(9, 0), (7, 5), (8, 0)], [(7, 5), (8, 0), (9, 0)], [(7, 5), (9, 0), (8, 0)]]

La classe completa può essere scaricata dalla sezione download.

109 di 109