Super Collider Guida Prd tSCIRMA a5

328
 Ob Player88  Power GraphParser Model EZSlider E Gra NB SCWindow Collapse Qua SO SimpleContr Date Exception KeyCodeR PatternCond GetFileDialog FreqScope SoundFileViewProgressWindow SoundFileFormat TChoo Insets EventStreamCle TDuty_old UpdateListener Instr OSCResponderQueue Abstr PitchCollection ControlName UnicodeResponder FlowVar Runner GraphView MIDIResp JKeyState S SerialPort MIDIEndPoint GeneralHIDSlot SwingDialog LRUNumberAllocator SoundIn AbstractPlayControl StackNumberAllocator DOMNode KeyMapper Toolbox NodeMapSetting Harmonics PathName PhilologusGuiTable BroadcastServer Actant FreqShift Philologus Gradient SelectXFocus GuidoArt WiiMoteGUI JSoundFi Condition AutoClassHel Rect UGenInstr Color UniqueID GuidoSco HIDInfo Histo Mess Quarks Helper TopicH JPen En SCIBDrag MIDIIn JPeakMeterM HIDDevice DOMImplementation Vo Staff e er SkipJack SCIBT LilyPond Spe SCIBAreaSelection EZNumber C RingNumberAllocat PMOsc Praa SCNSObjectA ClassBrowser ResponderArray Quark AudioIn Graph  SimpleK MultiTap BusSynthDefs JMouseBase PhilologusGuiScore Def HistoryGui ContiguousBlock ModalFreqUG GeoAudio MyClass InBus SystemSynthDefs AutoCompMeth TaskProxy Keyboarder FlowLayout CmdString GuidoV FormantCh Pra OS Inspec PatchIn CtkProtoNotes PitchClass Pi BeatSched JSpeech SCIBView Mono NetA PowerOfTwoBlock J GeneralHID Spe GuidoTimeSig HIDDeviceService EnvGate KeyCodeRe SOScore CmdPeriod Splay  SynthDef DocParser JStethoscope PriorityQueue PageLayout GuidoTime Position ClientFunc HiliteGradient Help Crucial ControlPrototypes Pen Glyph NumChannels RunnerGUI Client a er GuidoMark CtkNoteObject MLIDbrowser CocoaDialog OSCresponderNode VolumeGui Tempo MIDIEvent SlotInspector RunnerMixer QuarkDep WiiRemoteG CocoaGUI Page Chronometer EventTy  CtkOb Post WiiMote ParserGUI SpeechChannel Stethoscope NodeProxyEdi Mix RelativeToP GeoClock CtkTimer ProxyMixer XSession Module JFre Spl Gu QuarkSVNRepository Warp MXHIDAbsInfo Quant N RecordProxyMixe MIDIClient AutoDocTestCla JSCWindow LocalQuarks IODesc Monitor JFont SCVi Midi2FreqUGen XIn Notifica NodeCo SCIBPanelWindow Unix EnvironmentRe XFader4 IndexL ModalDialog TempoBus Fil Bu SynthDesc SynthDescLib SoundFile Manuscri Updater PrettyState PatchOut XInFeedback XFaderN Gra hGenerator InspManager HIDDeviceElement Sheet Painter MXHID Scribe Node NodeIDAllocator SelectButtonSet StartUp Document GetStringDialog WiiNunchukGUI Pitc NotificationRegistration Layout ContiguousBlockAlloc MIDIClockOut GUI Clock Bus JKnob Scheduler AbstractConsole Editor MultiPageLayout AbstractConstrai JavaObj A UI Impulsar SOGui TaskPr MXHIDSlot ProxyMoni OSCService Do MultiChanRecorder Sw AGProcessor SOScoreNodeBox  Semaphore Insp GeoGrapher UGenHelper GeoGraphSynth e o uo e InterplEn GlyphWriter InstrAt SwingGUI GeneralHIDDev Grapher ClassHelper WiiMoteIRObject Point JSpeechCha A ServerOptions GraphBuilder WiiCalibrationInfo Platform Font MIDIOut ImageView Sampl TestDe SelectX RawPointer Magnitude Boolean Nil Symbol Finaliz Abstra Interpreter Process Frame FunctionDef Collection Class  andrea valle

Transcript of Super Collider Guida Prd tSCIRMA a5

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 1/328

ObPlayer88

Power

GraphParser

ModelEZSlider

E

Gra

NB

SCWindow

Collapse

Qua

SO

SimpleContrDate

Exception

KeyCodeR

PatternCond

GetFileDialog

FreqScope

SoundFileViewProgressWindow

SoundFileFormat

TChoo

Insets

EventStreamCle

TDuty_old

UpdateListener

Instr

OSCResponderQueue

Abst

PitchCollection

ControlName

UnicodeResponderFlowVar

Runner

GraphView

MIDIResp

JKeyState

S

SerialPort

MIDIEndPoint

GeneralHIDSlot

SwingDialog

LRUNumberAllocator

SoundIn

AbstractPlayControl

StackNumberAllocator

DOMNode

KeyMapper

Toolbox

NodeMapSetting

Harmonics

PathName

PhilologusGuiTable

BroadcastServer

Actant

FreqShift

Philologus

Gradient

SelectXFocus

GuidoArt

WiiMoteGUI

JSoundFCondition

AutoClassHel

Rect

UGenInstr

Color

UniqueID

GuidoSco

HIDInfo

HistoMess

Quarks

Helper

TopicH

JPen

En

SCIBDrag

MIDIIn

JPeakMeterM

HIDDevice

DOMImplementation

Vo

Staff

e er

SkipJack

SCIBT

LilyPond

Spe

SCIBAreaSelection

EZNumber

C

RingNumberAllocat

PMOsc

Praa

SCNSObjectA

ClassBrowser

ResponderArray

Quark

AudioIn

Graph

SimpleK

MultiTap

BusSynthDefs

JMouseBase

PhilologusGuiScore Def

HistoryGui

ContiguousBlock

ModalFreqUGe

GeoAudio

MyClass

InBus

SystemSynthDefs

AutoCompMeth

TaskProxy

Keyboarder

FlowLayout

CmdString

GuidoVFormantCh

Pra

OS

Inspec

PatchIn

CtkProtoNotes

PitchClass

PiBeatSchedJSpeech

SCIBView

Mono

NetA

PowerOfTwoBlock

J

GeneralHID

Spe

GuidoTimeSig

HIDDeviceService

EnvGate

KeyCodeRe

SOScore

CmdPeriod

Splay SynthDef

DocParser

JStethoscope

PriorityQueue

PageLayout

GuidoTime

Position

ClientFunc

HiliteGradient

Help

Crucial

ControlPrototypes

Pen

Glyph

NumChannels

RunnerGUI

Client

a er

GuidoMark

CtkNoteObject

MLIDbrowser

CocoaDialog

OSCresponderNode

VolumeGui

Tempo

MIDIEventSlotInspector

RunnerMixer

QuarkDep

WiiRemoteG

CocoaGUI

Page

Chronometer

EventTyCtkOb

Post

WiiMote

ParserGUI

SpeechChannel

Stethoscope

NodeProxyEdi

Mix

RelativeToP

GeoClock

CtkTimer

ProxyMixer

XSession

Module

JFre

Spl

Gu

QuarkSVNRepositoryWarp

MXHIDAbsInfo

Quant

N

RecordProxyMixe

MIDIClient

AutoDocTestCla

JSCWindow

LocalQuarks

IODesc

Monitor

JFont

SCVi

Midi2FreqUGen

XIn

Notifica

NodeCo

SCIBPanelWindow

Unix

EnvironmentRe

XFader4

IndexL

ModalDialog

TempoBus

Fil

Bu

SynthDesc

SynthDescLib

SoundFile

ManuscripUpdater

PrettyState

PatchOut

XInFeedback

XFaderN

Gra hGenerator

InspManager

HIDDeviceElement

Sheet

Painter

MXHIDScribe Node

NodeIDAllocator

SelectButtonSetStartUp

Document

GetStringDialog

WiiNunchukGUI

Pitc

NotificationRegistration

Layout

ContiguousBlockAllocMIDIClockOut

GUI

Clock

Bus

JKnob

SchedulerAbstractConsole

EditorMultiPageLayout

AbstractConstrai

JavaObj

A

UI

Impulsar

SOGui

TaskPr

MXHIDSlot

ProxyMonOSCService

Do

MultiChanRecorder

Sw

AGProcessor

SOScoreNodeBox

Semaphore

Insp

GeoGrapher

UGenHelper

GeoGraphSynth

e o uo e

InterplEn

GlyphWriter

InstrAt

SwingGUI

GeneralHIDDev

Grapher

ClassHelper

WiiMoteIRObject

Point

JSpeechCha

A

ServerOptions

GraphBuilder

WiiCalibrationInfo

Platform

Font

MIDIOut

ImageView

Sample

TestDe

SelectX

RawPointerMagnitude

Boolean

Nil

Symbol

Finaliz

Abstra

Interpreter

Process

Frame

FunctionDef

Collection

Class

andrea valle

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 2/328

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 3/328

1

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 4/328

2

Quest’opera è stata rilasciata sotto la licenza Creative Commons Attribuzione-

Non commerciale-Condividi allo stesso modo 2.5 Italia. Per leggere una copia

della licenza visita il sito web http://creativecommons.org/licenses/by-nc-

sa/2.5/it/ o spedisci una lettera a Creative Commons, 171 Second Street, Suite

300, San Francisco, California, 94105, USA.

Questo lavoro utilizza molti software open source

SuperCollider: ciò di cui si parla (http://supercollider.sourceforge.net/)

Praat: analisi e visualizzazione dei segnali audio (http://www.praat.org/)Python: generazione del codice TEX colorato a partire da quello in SuperCol-lider (http://www.python.org/)

TEX: tipografia automatica (http://www.ctan.org/)ConTEXt: preparazione globale del documento basata su TEX(http://www.pragma-ade.nl/)PyX: visualizzazione dei segnali audio (cap. 5)(http://pyx.sourceforge.net/)GraphViz: generazione dei grafi che rappresentano le relazioni di ereditarie-tà tra classi in SuperCollider, diagrammi di flusso per le unità audio(http://www.graphviz.org/)TeXShop: tutto l’editing basato su TEX(http://www.uoregon.edu/~koch/texshop/)

NodeBox: immagine di copertina(http://nodebox.net/)

Sito: http://www.cirma.unito.it/andrea/sc.html

Sussuri e grida: [email protected]

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 5/328

Andrea Valle

tSCIRMAtheSuperColliderItalianManualat

CIRMA

(→ DRAFT: 9 aprile 2008)

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 6/328

3

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 7/328

4

Sommario1 Introduzione 81.1 Ciò di cui si parla: SuperCollider 81.2 Obiettivi 91.3 Fonti 91.4 Convenzioni grafiche 10

2 SuperCollider grado 0 12

2.1 Che cos’è SuperCollider 122.2 Alcuni buoni motivi (a scelta) per usare SC 152.3 Disponibilità rispetto ai sistemi operativi 162.4 Dove reperire SuperCollider 172.5 Interfacce grafiche 182.6 Informazioni di base sull’ambiente di sviluppo 202.7 Salvare ed aprire documenti, help file compresi 23

3 Object Oriented Programming in SC: fondamenti 253.1 Minima objectalia 253.2 Oggetti in SC 283.3 Metodi e messaggi 343.4 I metodi di tipo post e dump 413.5 Numeri 44

4 Sintassi: elementi fondamentali 48

4.1 (Parentesi) 484.2 // Commenti (/*di diverso tipo*/) 494.3 ”Stringhe” 494.4 Variabili 504.5 Simboli 544.6 Espressioni ; 554.7 • Errori 574.8 {Funzioni} 58

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 8/328

5

4.9 Classi, messaggi/metodi e keyword 654.10 Esempio 674.10.1 Il pattern GUI 674.10.2 Il codice 704.10.3 Introduzione 714.10.4 Creazione degli elementi GUI 724.10.5 Interazione 734.10.6 Per finire 754.11 Controlli di flusso 754.12 Ancora un esempio GUI 804.12.1 La funzione di generazione dei valori colore 814.12.2 Modularizzare la GUI 824.12.3 Controllo delle azioni 86

5 Sintesi, I: fondamenti 955.1 Poche centinaia di parole d’acustica 975.2 Algoritmi di sintesi 101

5.3 Nota sul metodo play 1115.4 Altri segnali e altri algoritmi 1125.5 Funzione valore assoluto e funzione quadratica 1245.6 Ancora sull’elaborazione di segnali 1275.7 Segnali di controllo 1325.8 Conclusioni 143

6 L’architettura e il server 144

6.1 L’architettura 1446.2 Esempi 1486.2.1 SwingOSC 1486.2.2 Graphista! 1516.3 Il client sclang 1516.4 Un impianto chimico per la produzione di liquidi

e un server audio in tempo reale 152

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 9/328

6

6.5 Appetizer: un esempio di sintesi e controllo intempo reale 163

6.5.1 Una synthDef 1656.5.2 UGen e UGen-Graph 1676.5.3 Un synth 1726.5.4 GUI e controller 174

7 Controlli e canali 1777.1 Inviluppi 177

7.2 Generalizzazione degli inviluppi 1837.3 Sinusoidi & sinusoidi 1927.4 Segnali pseudo-casuali 2097.5 Espansione e riduzione multicanale 215

8 Sintesi, II: tecniche di generazione del segnale audio 2268.1 Oscillatori e tabelle 2268.2 Campionamento 236

8.2.1 Campionamento semplice 2368.2.2 Resampling e interpolazione 2398.3 Sintesi additiva 2488.4 Sintesi granulare 2598.5 Sintesi sottrattiva 2648.6 Analisi e risintesi 2718.7 Modulazione 2818.7.1 Modulazione ad anello e d’ampiezza 282

8.7.2 Modulazione ad anello come tecnica di elaborazione 2848.7.3 Modulazione di frequenza 2908.7.4 C:M ratio 293

9 Suono organizzato: (minimal) scheduling in SC 3009.1 Server side: attraverso le UGen 3009.2 Server side: le UGen Demand 3049.3 Lang side: Routines 308

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 10/328

7

9.4 Orologi 3109.5 Sintetizzatori/eventi 3149.6 Routine/Task 3199.7 Micro/macro 322

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 11/328

1.1–8

1 Introduzione

1.1 Ciòdicuisiparla:SuperCollider

SuperCollider (SC) è un pacchetto software per la sintesi e il controllodell’audio in tempo reale1. Attualmente rappresenta lo stato dell’artenell’ambito della programmazione audio: non c’è altro software di-sponibile che sia insieme così potente, efficiente, flessibile. L’unicopunto a sfavore di SC è che non è “intuitivo”: richiede competenzerelative alla programmazione, alla sintesi del segnale audio, alla com-posizione musicale (nel senso più lato, aperto e sperimentale del ter-mine). Ci si potrebbe chiedere d’altra parte in che senso un violino,una chitarra elettrica, una batteria presentino un’interfaccia utente“intuitiva”: non c’è forse bisogno di un duro lavoro per cavare fuoriuna nota da un violino o per tenere un tempo suonando una batte-ria? Il disagio che il neofita prova con SC dipende però forse da unaltro fatto: SC è preciso ed efficiente ma è puntiglioso ed ha un forte

Si vedrà più avanti che cosa indica specificamente “pacchetto software”1

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 12/328

1.3–9

senso della responsabilità. Ciò che spetta al programmatore, spetta alui solo: SC non lo aiuterà in caso di sue mancanze. Per chiudere ilparallelo, SC è come uno Stradivari per il violinista: dipende da que-st’ultimo farlo suonare come quello sa fare. Non è come un carillonin cui basta caricare la molla, poiché tutta la competenza relativa allagenerazione e al controllo del suono è in fondo già ascritta al mecca-nismo.Anche se a dire il vero, come si vedrà, SC può tramutare un carillonin uno Stradivari.

1.2 Obiettivi

L’obiettivo di quanto segue è duplice:

1. introdurre alcuni aspetti fondamentali relativi a quell’ambito cheviene usualmente indicato, con una definizione a volte imprecisae a volte impropria, computer music

2. fornire una breve panoramica ed insieme un’introduzione a Su-perCollider in italiano.

L’ipotesi di partenza (e indipendentemente dai risultati) è quella di

far interagire i due ambiti, attraverso una reciproca specificazione

1.3 Fonti

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 13/328

1.4–10

Il materiale presentato è, in qualche misura, “originale”. La parte re-lativa alla sintesi riprende alcune parti di Audio e multimedia2 e vi in-clude parti di materiali provenienti dai corsi degli anni precedenti.Trattandosi di materiale introduttivo, è chiaro che il testo si affidasaldamente al suo intertesto costituito dai molti testi analoghi, piùcomplessi e più completi, che lo precedono. Questo vale a maggiorragione per la parte dedicata a SuperCollider. Non è una traduzio-ne in senso stretto di scritti già esistenti: tra l’altro, attualmente, nonesiste un libro di riferimento per SuperCollider3. E tuttavia è chiaroche il testo scritto è fittamente intessuto di prestiti provenienti daglihelp file, dai tutorial di James McCartney, Mark Polishook, Scott Wil-son, dal testo di David Cottle, dalle osservazioni preziosi fornite dallaSuperCollider mailing list, dalle informazioni accessibili attraverso ilSuperCollider wiki. La lettura di queste fonti non è in nessun modoresa superflua dal testo seguente, il quale ha invece semplicementeun ruolo propedeutico rispetto alle stesse, perché quantomeno evitaal lettore italiano la difficoltà supplementare della lingua straniera.

1.4 Convenzionigrafiche

Il manuale prevede tre distinzioni:

Lombardo, V. e Valle, A., Milano, Apogeo 2008 (3ed.).2

È in corso di pubblicazione (l’uscita è prevista per la fine del 2008) il progetto di un3

SuperCollider Book , sull’esempio del Csound Book , per gli stessi tipi della MIT press.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 14/328

1.4–11

1. testo: in carattere nero normale, senza particolarità, esattamentecome quanto scritto qui

2. codice: è scritto in carattere typewriter , utilizza lo schema co-lori della versione MacOSX per la sintassi, è riquadrato in blu ele righe sono numerate. Al di sotto di ogni esempio è presenteun marcatore interattivo. Esso permette di accedere al file sor-gente dell’esempio che è incluso nel pdf  , e di aprirlo direttamentecon l’applicazione SuperCollider. Per garantire la funzione è bene

usare Acrobat Reader (che è gratuito e multipiattaforma). Alla pri-ma apertura Reader richiede di impostare il suo comportamentonei confronti dell’allegato

1 // ad esempio

2 "a caso".postln ;

3. post-window: è scritto in nero; con carattere typewriter , e riportauna parte di sessione con l’interprete SuperCollider. È riquadrato inarancio e le righe sono numerate.

1 "così".postln

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 15/328

2.1–12

2 SuperCollidergrado0

2.1 Checos’èSuperCollider

SuperCollider (SC) è un pacchetto software per la sintesi e il control-lo dell’audio in tempo reale. La definizione di “pacchetto software”tuttavia si rivela piuttosto vaga. Per arrivare ad una definizione piùanaliticamente ed esauriente, è meglio partire dalla definizione di SCche appare sulla homepage di Sourceforge:

“SuperCollider is an environment and programming languagefor real time audio synthesis and algorithmic composition. Itprovides an interpreted object-oriented language which func-tions as a network client to a state of the art, realtime soundsynthesis server”

(http://supercollider.sourceforge.net/)

Più analiticamente:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 16/328

2.1–13

1. an environment: SC è un’applicazione che prevede più componentiseparate. Di qui l’utilizzo del termine “ambiente”.

2. and: SC è anche un’altra cosa del tutto diversa.

3. a programming language: SC è infatti anche un linguaggio di pro-grammazione. Come si dice in seguito, appartiene alla famigliadei linguaggi ”orientato agli oggetti”, ed è, tra l’altro, tipologica-mente vicino a Smalltalk. Il codice del linguaggio SC, per essere

operativo (“per fare qualcosa”), deve essere interpretato da un in-terprete. Un interprete è un programma che ”capisce” il linguag-gio e agisce di conseguenza. SC è anche l’interprete del linguaggioSC.

4.  for realtime sound synthesis: SC è ottimizzato per la sintesi del se-gnale audio in tempo reale. Questo lo rende ideale per un’utilizzostrumentale (performance live) così come per la realizzazioni di

installazioni/eventi. È senz’altro possibile utilizzare SC non intempo reale per generare materiale audio, ma in un certo sensoè meno immediato che non utilizzarlo in tempo reale.

5. and algorithmic composition: uno dei punti di forza di SC sta nel fat-to che permette due approcci complementari e opposti alla sintesiaudio. Da un lato, permette di svolgere operazioni di basso livel-lo sul segnale audio. Dall’altro, permette al compositore di espri-

mersi ad alto livello, cioè non in termini di campioni audio, ma distrutture che rappresentino oggetti per la composizione musicale(ad esempio: scale, pattern ritmici, etc.). In questo senso, si rive-la ideale per la composizione algoritmica, ovvero per un approc-cio alla composizione musicale basato sull’utilizzo di procedureformalizzate. In SC questo tipo di operazioni può essere svoltointerattivamente ed in tempo reale.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 17/328

2.1–14

6. [the] language [. . .] functions as a network client to a [. . .] server: l’applicazioneche interpreta il linguaggio SC è anche un cliente che comunica, at-traverso una rete, con un server, un fornitore di servizi.

7. a state of the art: attualmente SCrappresenta lo stato dell’arte nell’ambitodella programmazione audio: non c’è altro software disponibileche sia insieme così potente, efficiente, flessibile (e ormai ancheportabile).

8. sound synthesis server: SC è un fornitore di servizi, in particolare diservizi audio. La locuzione può sembrare misteriosa. Si traducecosì: SuperCollider genera audio in tempo reale su richiesta. Inquesto senso, SC fornisce audio su richiesta: chi richiede audio aSC è un suo cliente (client).

Riassumendo: quando si parla di SC si possono indicare (generandouna certa confusione) cinque cose diverse. Queste cose sono:

1. un server (→ un fornitore di servizi) audio2. un linguaggio di programmazione per l’audio3. l’interprete (→ il programma interprete) per il linguaggio4. l’interprete in quanto cliente del server audio5. il programma (→ l’applicazione complessiva) che comprende tut-

te le componenti 1-4

La situazione è schematizzata in 2.1. L’applicazione SC prevede due

parti: una è il server audio (denominato scsynth), l’altra è l’interpreteper il linguaggio (denominato sclang) che, oltre a interpretare il lin-guaggio SuperCollider, svolge il ruolo di client rispetto a scsynth.Può sembrare complicato. In effetti lo è.Installare SC vuol dire perciò installare un’applicazione complessivache comprende un server audio e un interprete del linguaggio/clientdel primo. Si vedrà in seguito meglio che cosa indicano i termini: per

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 18/328

2.2–15

Client Server

Linguaggio

Interprete

sclang scsynth  

SuperCollider application

1

2

3

4

5

Fig. 2.1 Struttura di SC.

ora si tenga a mente che esistono due programmi distinti, e che quan-do si installa SC si ottengono due programmi al costo di 1 (il costo sicalcola così: 2×0 = 0. Come recita un madrigale di Cipriano de Rore,“mia benigna fortuna”).

2.2 Alcunibuonimotivi(ascelta)perusare

SC

Alcune applicazioni di SC, in ordine sparso:

• costruire un proprio sistema per fare musica live, interfaccia gra-fica compresa

http://www.dewdrop-world.net/sc3/index.php

• fare musica dance (nel senso più vago del termine)http://crucial-systems.com/SuperCollider

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 19/328

2.3–16

•allestire un dj set

http://www.durftal.com/music/cylob/bf/

• fare composizione elettroacustica (nel senso più vago del termine)http://www.bridgerecords.com/pages/catalog/9210.htm

• sonificare datihttp://www.sonification.de/

• controllare un complesso sistema di altoparlanti (> 170) dal vivohttp://www.woutersnoei.nl/

• ricostruire in audio binaurale il Poème électronique (ovvero: la dif-fusione di 3 tracce in movimento su 350 altoparlanti)

http://www.edu.vrmmp.it/vep/

• integrare audio e video dal vivohttp://www.klippav.org/

• praticare live codinghttp://www.toplap.org/

Una ricerca su YouTube permette agevolmente di vedere all’operaSuperCollider in situazioni molto diverse. Alcuni video sono qui rac-colti qui:

http://supercollider.sourceforge.net/videos

2.3 Disponibilitàrispettoaisistemioperativi

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 20/328

2.4–17

SuperCollider è stato originariamente sviluppato da James McCart-ney su piattaforma Macintosh. In particolare la versione 2 era forte-mente integrata con il sistema operativo Mac OS9. SuperCollider 3(che è insieme molto simile e molto diverso da SC 2) è stato sviluppa-to per il sistema operativo Mac OSX ed è ora un software open source,sviluppato da una consistente comunità di programmatori a partiredal lavoro di James McCartney. La comunità di sviluppatori ha co-sì effettuato il porting anche per le piattaforme Windows e Linux 4.Queste ultime due versioni di SC differiscono principalmente per di-fetto rispetto alla versione per OSX, nel senso che alcune funzionalitàpresenti in quest’ultima non sono state portate nelle altre due. Tutta-via, nell’arco della seconda metà del 2007 è stato compiuto un grandesforzo dalla comunità si sviluppatori, in vista dell’uscita (prossima)del SuperCollider Book. La versione attuale (3.2), che è quella di riferi-mento per il libro, ha apportato notevoli migliorie al software, oltread un notevole incremento della documentazione ed un aumentatacompatibilità tra le piattaforme. Si può dire che le differenze tra lepiattaforme sia ormai limitate agli ambienti di sviluppo (necessaria-mente dipendenti dal sistema operativo)5.

2.4 DovereperireSuperCollider

SuperCollider può essere scaricato da Sourceforge, in particolare all’indirizzohttp://supercollider.sourceforge.net/downloads

In particolare, Stefan Kersten è il principale autore della versione Linux, mentre la4

versione Windows è stata implementata da Christopher Frauenberger.I riferimenti, scarsi, a piattaforme specifiche in questo testo si riferiscono alle versioni5

MacOSX e Windows, non a Linux.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 21/328

2.5–18

Nel caso si utilizzino i file binari, l’installazione in sé è un processo banale, poiché prevede un file .dmg su Mac 6 e un file .exe per Win-dows7.In generale, il sito ufficiale presso Sourceforge

http://sourceforge.net/projects/supercollider

costituisce il punto di riferimento della comunità di utilizzatori e svi-luppatori, ed è utile farvi riferimento. In particolare, vale la penamenzionare la mailing list degli utilizzatori, attraverso la quale è pos-sibile confrontarsi rapidamente con i migliori programmatori di SC.

http://www.create.ucsb.edu/mailman/listinfo/sc-users

Gli archivi della mailing list sono poi una risorsa preziosa, in cui mol-to spesso è già disponbile una risposta ai propri quesiti. L’interfacciaweb via Nabble è forse di più agevole consultazione:

http://www.nabble.com/Supercollider—User-f535.html

Infine, il sito di James McCartney ha un valore eminentemente stori-co:

http://www.audiosynth.com/

2.5 Interfaccegrafiche

Esistono versioni compilate anche per versioni ormai superate del sistema operativo6

(10.2) così come per processori più datati (G3). Per ottenerle si può consultare il sito ela mailing list.La versione per Windows prende il nome di PsyCollider. Il nome deriva da Py + SCol-7

lider (con metatesi), poiché l’implementazione utilizza il linguaggio Python. A diffe-renza di quanto avveniva inizialmente, l’utente finale non è tenuto né conoscere néad avere Python installato sulla propria macchina per potre eseguire Psycollider.exe.Python è incluso nei file binari ed è utilizzato internamente da Psycollider.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 22/328

2.5–19

La principale differenza tra le versioni per i diversi sistemi operativiconcerne le classi per lo sviluppo di interfacce grafiche (in SC è pos-sibile programmare la GUI così come si programma la generazionedell’audio), rispetto alle quali ogni piattaforma ha le sue specificità.È importante sottolineare che SC permette di programmare gli ele-menti della GUI facendo astrazione dal pacchetto grafico prescelto.In sostanza in questo modo è possibile costruire pulsanti, cursori, fi-nestre riferendosi genericamente ad essi e selezionando un gestoregrafico che si occuperà di costruirle. Si pensi alle “skin´´ in cui unastessa funzione è gestita secondo modalità grafiche diverse. In SC siseleziona un gestore grafico tra quelli disponibili e questi costruiràl’oggetto prescelto. A dopo il dettaglio in termini di programmazio-ne. I gestori grafici non sono molti. L’interfaccia grafica nativa su Ma-cOSX è Cocoa, mentre su Linux il primo gestore grafico è stato SCUM.Recentemente si è reso disponibile il server grafico SwingOSC

http://www.sciss.de/swingOSC/

. SwingOSC è un server grafico del tutto autonomo rispetto a SC(può essere utilizzato anche da altre applicazioni), ma, ed è quan-to qui interessa, può essere utilizzato da dentro SC (in altre parolel’utente può praticamente dimenticarsi dell’esistenza del meccani-smo client/server). SwingOSC è scritto in Java e per funzionare ri-chiede che sia installata il Java Runtime Environment. Per controllarelo stato della propria macchina e installare la versione più recente di

 Java si può visitare il sito dedicato:http://java.com/en/download/installed.jsp

SwingOSC permette la costruzione di interfacce grafiche di qualitàsuperiore rispetto a quelle originariamente sviluppate per MacOSX(almeno, a parere di chi scrive, anche se probabilmente meno efficien-ti computazionalmente). In più, SwingOSC, essendo basata su Java, ècompletamente multipiattaforma, essendo disponibile per Mac, Win-dows, Linux. La versione per Windows (detta “PsyCollider”) integra

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 23/328

2.6–20

in forma predefinita SwingOSC, che è l’unica interfaccia grafica di-sponibile. Se si guarda la Post Window durante l’avviamente di Psy-Collider si potrà notare come il server SwingOSC venga avviato au-tomaticamente (booting java -jar SwingOSC. . . etc).Gli esempi del testo verranno scritti in forma astratta rispetto al gesto-re grafico, ma chi scrive utilizza sempre (pur essendo su Mac) Swin-gOSC.

2.6 Informazioni di base sull’ambiente di

sviluppo

SC funziona in tempo reale ed in forma interattiva attraverso un’interfacciatestuale: tutte le comunicazioni tra utente e programma avvengonoattraverso testo. Si osservino le figure 2.2 e 2.3. Eseguendo il pro-gramma si apre appunto un editor di testo. In particolare si apre laPost Window, la finestra che visualizza i messaggi che SC indirizzaall’utente (2.2 e 2.3 , 1). In Windows, la finestra SC Log stampa gli stes-si messaggi di un terminal aperto in parallelo (2.3 , 4 all’interno peròdell’applicazione PsyCollider, 2.3 , 5). Entrando in esecuzione, SC ef-fettua alcuni passaggi di inizializzazione (di cui si discuterà più avan-ti), il cui risultato viene scritto sulla Post Window. Nel caso di Psy-Collider, viene immediatamente avviato il server audio (si vede benesul terminal, 2.3 , booting 57110 , 6): si notino i messaggi relativi al ri-levamento della scheda audio (Device options: , Booting with:).L’avviamento del server audio avviene invece per mano dell’utente

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 24/328

2.6–21

in OSX, attraverso due interfacce grafiche gemelle: in particolare, so-no disponibili due server distinti, local e internal8 (2.2 , 4 e 5). In Win-dows viene altresì avviato il server grafico SwingOSC (2.3 , 7, bootingjava -jar SwingOSC. . . etc). È possibile utilizzare la Post Window perscrivere il proprio codice (almeno in fase di test) ma è sempre megliocreare una nuova finestra (2.2 e 2.3 , 2). A questo punto, l’utente im-mette del codice e chiede all’interprete di valutarlo. Ad esempio, ilcodice "Hello World".postln richiede di stampare sullo schermo lastringa "Hello World". Si noti la sintassi colorata che distingue trala stringa e il metodo .postln;9. Se l’interpretazione va a buon fine,SC risponderà con un certo comportamento che dipende dal codiceimmesso: in questo caso, stampando sulla Post Window la stringa"Hello World" (2.2 e 2.3 , 3). Altrimenti segnalerà l’errore attraversola Post Window.L’editor di testo (sia in OSX che in Windows) prevede un insieme dicaratteristiche tipiche di ogni editor, ed è inutile soffermarvicisi. Altrefunzioni sono utili ad un utente più avanzato, ed esulano da quantoqui previsto.Alcune indicazioni minimali:

•  MacOSX

− Valutazione del codice: selezionare il codice e premere Enter (nonReturn). Se il codice consiste in una sola riga, è sufficiente po-sizionare il cursore in un punto della riga e premere enter.

− Arresto dell’audio: Apple + .

Si veda dopo.8

Gli schemi colori per le due piattaforme sono differenti (chissà perché). Qui si segue9

quella originale di OSX

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 25/328

2.6–22

1

4

5

2

3

Fig. 2.2 SC in Mac OSX.

45

61

7

2

3

Fig. 2.3 SC in Windows (PsyCollider).

− Aiuto: Apple + ?. Se la combinazione è premuta contestual-mente alla selezione di codice SC, si apre il file di aiuto corre-lato (laddove esistente).

− Pulizia della Post Window: Apple + Shift + k 

• Windows

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 26/328

2.7–23

−Valutazione del codice: selezionare il codice e premere Ctrl + Re-turn (invio). Se il codice consiste in una sola riga, è sufficienteposizionare il cursore in un punto della riga e premere Ctrl +Return (invio).

− Arresto dell’audio: Alt + .− Aiuto: F1. Se la combinazione è premuta contestualmente alla

selezione di codice SC, si apre il file di aiuto correlato (laddoveevistente).

−Pulizia della Post Window: Alt + P

2.7 Salvare ed aprire documenti, help file

compresi

Il contenuto della finestra può essere salvato su file e riaperto in un’altrasessione di lavoro, per essere modificato o semplicemente per esse-re rieseguito. Una caratteristica importante di SC è che gli help filescontengono codice valido che può essere valutato interattivamente.Quando si apre un file di help è allora possibile sperimentare con gliesempi contenuti per capire esattamente il funzionamento descritto-vi. Rispetto al formato dei files predefinito MacOSX e Windows pre-vedono alcune differenze:

• MacOSX: il formato file prescelto in origine è una versione spe-ciale del formato di testo RTF. In MacOSX gli help file sono in for-mato HTML, ma vengono convertiti automaticamente in RTF, esono documenti validi per SC: in altre parole, è possibile valutareil codice che vi è contenuto. L’utilizzo del formato RTF consente

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 27/328

2.7–24

di avere formattazione avanzata nei documenti di SC (font, co-lor, dimensione, etc.). Il formato è però nativo soltanto per Mac,e in caso di utilizzo su un’altra piattaforma, la formattazione de-ve essere eliminata (il file deve essere convertito in testo sempli-ce). In ogni caso è perfettamente possibile e consigliabile (salvospecifici interessi tipografici) utilizzare per i propri file il formatoASCII (cioè: testo semplice), in particolare scegliendo l’estensionescd (SuperCollider Document), per evitare ambiguità.

• Windows: il formato file è soltanto ASCII (si può aprirlo con No-tepad/Blocconote), e spetta all’utente scegliere l’estensione (evi-dentemente, .scd è una scelta sensata). Quando si vuole eseguire ilcodice contenuto nei file di help in HTML è necessario convertireil formato HTML in codice selezionando “HTML To Code Windo-w” dal menu “File” (Ctrl+T). Si apre una finestra in cui il formatoHTML viene convertito in ASCII (la nuova finestra è una finestradi codice, la sintassi è colorata): a questo punto, è possibile valu-

tarlo.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 28/328

3.1–25

3 Object Oriented Programming inSC:fondamenti

3.1 Minimaobjectalia

Nella programmazione orientata agli oggetti si assume che l’utente,per programmare il comportamento di un calcolatore, manipoli enti-tà dotate di proprietà e di capacità. Il termine, volutamente generico,per indicare queste entità è “oggetti”, mentre tipicamente le proprietàsono pensate come “attributi” degli oggetti stessi e le capacità come“metodi” che gli oggetti possono adottare per compiere delle ope-

razioni. Per poter essere riconosciute dal linguaggio le entità devo-no appartenere ad un insieme finito di tipi: un oggetto è del tipo A,l’altro del tipo B e così via. I tipi vengono chiamati “classi” in OOP.Un oggetto è dunque una particolare istanza di una classe: la classepuò essere pensata come il tipo astratto, ma anche come lo stampoda cui si fabbricano le istanza. Da un unico conio (la classe) si stampaun un numero indefinito di monete uguali (gli oggetti). È nella classe

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 29/328

3.1–26

che si definiscono i metodi di cui tutti gli oggetti di quel tipo sarannodotati. Una classe descrive anche il modo in cui creare un oggetto apartire dalla classe. Le classi sono organizzate gerarchicamente: ogniclasse può derivare da un’altra classe e ogni classe può avere del-le classi derivate. Questo principio prende il nome di “ereditarietà”.Ad esempio un conio è una ulteriore specificazione di un più gene-rico “stampo”: lo stampo è la sopraclasse del conio, e il conio è unasottoclasse dello stampo. Un sigillo (per la ceralacca) è un altro stam-po, ma di un tipo completamente diverso dal conio: il sigillo è unasottoclasse dello stampo, da cui eredita alcuni aspetti che condividecon il conio (la capacità di impressione), ma da cui si differenza peraltri (prevede un’impugnatura manuale, mentre il conio viene battu-to a martello).L’ereditarietà va pensata in termini genetici: i caratteri del padre sonopresenti (come patrimonio genetico, appunto) nei figli, ma, a scansodi equivoci, si noti che qui ereditarietà è intesa in termini sistemati-ci, non evolutivi.La relazione di ereditarietà prende infatti a modellole tassonomie naturalistiche. Ad esempio, il grafo seguente illustrala posizione tassomica dell’ippopotamo. L’ippopotamo appartieneal subordine dei Suina (ad esempio, intuibilmente, i maiali), con iquali condivide alcuni tratti, che differenziano entrambi dai Rumi-nantia (ad esempio, le mucche), pur essendo Ruminantia e Suina en-trambi Actiodactyla (e distinguendosi entrambi dai Perissodactyla,ad esempio i cavalli). Se le classi sono astratte (ad esempio, la spe-

cies dell’ippopotamo), gli oggetti (gli ippopotami da classificare) so-no concreti.Tornando alla programmazione, nel paradigma object-oriented il mon-do si presenta al programmatore come un insieme di oggetti che siprestano, sotto determinate condizioni, ad essere manipolati. In par-ticolare, per manipolare un oggetto –per chiedergli di fare qualcosa–

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 30/328

3.1–27

Fig. 3.1 Tassonomia dell’ippopotamo.

è necessario inviargli un “messaggio”. Un oggetto, per poter rispon-dere al messaggio, deve conoscere un metodo. In sostanza, può ri-spondere ad una richiesta (messaggio) attraverso una competenza(metodo). L’oggetto che riceve il messaggio è il “ricevente” di quelmessaggio e vi può rispondere se implementa un metodo corrispon-dente. Riassumendo:

•oggetto e metodo concernono la definizione dell’oggetto dall’interno

• messaggio e ricevente concernono la comunicazione con l’oggettodall’esterno

L’insieme dei messaggi a cui un oggetto può rispondere prende ilnome di “interfaccia”: ed è un’interfaccia in senso proprio, perché èciò che l’oggetto rende disponibile all’utente per l’interazione, dovel’utente può essere anche un altro oggetto. Nella maggior parte dei

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 31/328

3.2–28

linguaggi ad oggetti, la sintassi tipica per passare un messaggio ad unoggetto utilizza il punto (.) e prende la forma oggetto.messaggio. Larelazione tra oggetto e messaggio non va pensata come una descri-zione alla terza persona (“l’oggetto fa una certa cosa”), ma piuttostocome una coppia vocativo/imperativo: “oggetto, fai qualcosa!”. Adesempio, conio.imprimi , o anche: ippopotamo.nuota.

3.2 OggettiinSC

SuperCollider (qui intendendo: sclang) è un linguaggio orientato aglioggetti. Lo è per di più in termini molto “puri”, poiché ha come suomodello storico, e come parente tipologico assai prossimo, il linguag-gio Smalltalk. In Smalltalk, come in SC, letteralmente ogni entità pos-

sibile è un oggetto. Questa radicalità può essere spiazzante inzial-mente, ma è un punto di forza poiché garantisce che tutte (propriotutte) le entità potranno essere controllate dall’utente secondo un uni-co principio: tutte avranno attributi e metodi, a tutte sarà possibileinviare dei messaggi poiché presenteranno all’utente una certa inter-faccia. Si prenda il caso delle strutture dati: SC possiede una grandericchezza di strutture dati, cioè di classi che funzionano da contenito-ri di altri oggetti, ognuna dotati di particolari capacità e specializzata

per certi tipi di oggetti. Ad esempio un “array” è un contenitore ordi-nato di oggetti. Si scriva Array. Se si richiama la colorazione della sin-tassi, si nota come venga applicato il blu, colore che contraddistinguele classi (oltre che le parole riservate var, arg, this e alcune altre).SC sa che Array è una classe perché la prima lettera è maiuscola: tuttociò che inizia con la maiuscola per SC indica una classe. Se si esegueil codice, SC restuituisce (per ora si intenda: stampa sullo schermo) la

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 32/328

3.2–29

classe stessa. Se si richiama l’help file, si nota come immediatamen-te venga indicata la sopraclasse, Superclass: ArrayedCollection. L’helpfile fornisce alcune indicazioni sui metodi disponibili per gli oggettidi tipo Array. Il codice:

z = Array.new;

costruisce un nuovo array vuoto attraverso il messaggio new invo-cato sulla classe Array. Tipicamente un messaggio viene inviato ad

un’istanza particolare e non ad una classe. Ma prima di poterlo fare,è necessario avere un’istanza a cui inviare un messaggio. Al messag-gio new rispondono allora tutte le classi restituendo una loro istanza.Il metodo new è il “costruttore” della classe: il metodo cioè che istan-zia un oggetto a partire dalla classe. Possono esserci molti metodi co-struttori, che restituiscono un oggetto secondo modalità specifiche:sono tutto metodi della classe perché, invocati sulla classe, restitui-scono un oggetto. Uno di essi è il messaggio newClear , che prevede

anche una parte tra parentesi tonde:

z = Array.newClear(12);

Nell’esempio le parentesi contengono una lista di “argomenti” (unosolo, in questo caso), che specificano ulteriormente il messaggio new-

Clear , ovvero “oggetto, fai qualcosa (così)! ”10. In particolare new-

Clear(12) prevede un argomento (12) che indica che l’array dovràcontenere al massimo 12 posti. È possibile indicare esplicitamente

l’argomento: “oggetto, fai qualcosa (nel modo: così)! ”. Ogni argo-mento ha un nome specifico, la sua keyword: nel caso di newClear èindexedSize , che indica il numero di posti contenuti nel nuovo array.Il codice:

z = Array.newClear(indexedSize:12);

Tornando a prima, conio.imprimi(forte) o ippopotamo.nuota(veloce)10

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 33/328

3.2–30

è identico al precedente ma esplicita la keyword dell’argomento. Infi-ne, z = indica che l’array verrà assegnato alla variabile z. Si noti chela lettera utilizzata è minuscola: se si scrivesse Z = SC intepreterebbeZ come una classe (inesistente)11 e solleverebbe un errore. Adesso z

rappresenta un array vuoto di capienza 112: è un’istanza della classeArray. Si può chiedere a z di comunicare la classe a cui appartieneinvocando il metodo class:

1 z.class2 Array

Il metodo class (1) restituisce la classe di z: Array (2). Traducendoin italiano, la frase equivalente potrebbe essere: “z, dichiara la tuaclasse!”. Quando si usano degli array molto spesso si è insoddisfattidei metodi elencati nell’help file: sembra che manchino molti metodiintuitivamente utili. È molto difficile che sia veramente così: molto

spesso il metodo cercato c’è, ma è definito nella sopraclasse ed ere-ditato dalle classi figli. A partire da Array si può navigare la struttu-ra degli help file risalendo a ArrayedCollection, SequenceableCollec-tion, Collection: sono tutte sopraclassi (di tipo sempre più astratto)che definiscono metodi che le sottoclassi possono ereditare. Se si pro-segue si arriva a Object.

superclass: nil

Object is the root class of all other classes. All objects areindirect instances of class Object.

La Z verrebbe colorata di blu.11

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 34/328

3.2–31

Tutti le classi in SC ereditano da Object. Ad esempio, il metodo class

che è stato chiamato su z nell’esempio precedente è definito a livellodi Object ed ereditato, lungo l’albero delle relazioni di ereditarietà,da Array , così che un’istanza di quest’ultima classe (z) vi possa ri-spondere. Al di là della navigazione nella struttura degli help files,SC mette a disposizione dell’utente molti metodi per ispezionare lastruttura interna del codice: è la capacità che tipicamente viene defini-ta “introspezione”. Ad esempio i metodi dumpClassSubtree e dump-

SubclassList stampano su schermo rispettivamente una rappresen-tazione gerarchica delle sottoclassi della classe su cui è invocato ilmetodo e una lista in ordine alfabetico. Le due rappresentazioni so-no equivalenti. Nella prima sono più chiari i rapporti di parentela trale classi attraverso la struttura ad albero, nella seconda è invece possi-

 bile percorrere -per ognuna delle sottoclassi della classe - la strutturadell’albero lungo i rami ascendenti fino a Object. Si prenda la classeCollection , una classe molto generale di cui Array è una sottoclasse,e si inviino i messaggi dumpClassSubtree e dumpSubclassList.Quanto segue è quanto appare sulla Post Window nei due casi.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 35/328

3.2–32

1 Collection.dumpClassSubtree;2 Collection

3 [

4 Array2D

5 Range

6 Interval

7 MultiLevelIdentityDictionary

8 [

9 LibraryBase

10 [ Archive Library ]

11 ]12 Set

13 [

14 Dictionary

15 [

16 IdentityDictionary

17 [

18 Environment

19 [ Event ]

20 ]

21 ]22 IdentitySet

23 ]

24 Bag

25 [ IdentityBag ]

26 Pair

27 TwoWayIdentityDictionary

28 [ ObjectTable ]

29 SequenceableCollection

30 [

31 Order32 LinkedList

33 List

34 [ SortedList ]

35 ArrayedCollection

36 [

37 RawArray

38 [

39 DoubleArray

40 FloatArray

41 [ Wavetable Signal ]

43 […]

45 ]

46 Collection

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 36/328

3.2–33

1 Collection.dumpSubclassList2 Archive : LibraryBase : MultiLevelIdentityDictionary : Collection :

Object

3 Array : ArrayedCollection : SequenceableCollection : Collection :

Object

4 Array2D : Collection : Object

5 ArrayedCollection : SequenceableCollection : Collection : Object

6 Bag : Collection : Object

7 Collection : Object

8 Dictionary : Set : Collection : Object

9 DoubleArray : RawArray : ArrayedCollection : SequenceableCollection :Collection : Object

10 Environment : IdentityDictionary : Dictionary : Set : Collection :

Object

11 Event : Environment : IdentityDictionary : Dictionary : Set :

Collection : Object

12 FloatArray : Raw

14 […]

16 36 classes listed.17 Collection

Con Collection.dumpClassSubtree si vede la posizione di Array inrelazione ai suoi vicini (47). È sullo stesso livello di RawArray (36),entrambi sono sottoclassi di ArrayedCollection (34). Quest’ultimaclasse appartiene alla famiglia delle SequenceableCollection (28). Ilmetodo Collection.dumpSubclassList lista le classi in ordine alfa-

 betico: è agevole trovare Array (2) per poi seguire i rami dell’albero(lungo la stessa riga) fino a Object.La figura 3.2 è una visualizzazione tramite un grafo ad albero dellastruttura delle classi di Collection , ottenuta elaborando automatica-mente l’output di Collection.dumpSubclassList. L’esempio è trat-to dall’help file Internal-Snooping , che è dedicato all’introspezione inSC. Anche l’help file Class è particolarmente interessante al proposito.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 37/328

3.3–34

Array2D

Collection

Range Interval

Archive

LibraryBase

Library

MultiLevelIdentityDictionary

Event

Environment

IdentityDictionary

Dictionary

Set

IdentitySet IdentityBag

Bag Pair

ObjectTable

TwoWayIdentityDictionary

Object

Fig. 3.2 Grafo ad albero delle sottoclassi di Collection , apartire da Object.

L’ultima riga che SC stampa è in entrambi i caso l’oggetto Collection

(39), che è ciò che i metodi ritornano. Il perché verrà discusso a breve.Se si sostituisce a Collection la classe Object , si ottiene tutta la strut-tura delle classi di SC. La figura 3.3 riporta una rappresentazione ra-diale della struttura di tutte delle classi di SC, ottenuta elaborando il

risultato diObject.dumpSubclassList12

. Si noti come un punto di ad-densamento sia rappresentato da UGen , la sopraclasse diretta di tuttele classi che generano segnali in SC. È una classe comprensibilmentemolto numerosa.

3.3 Metodiemessaggi

SC è scritto per la maggior parte in SC (con l’eccezione di un nucleodi primitive scritte in linguaggio C per ragioni di efficienza): il codi-ce stesso del programma è trasparente al programmatore, nel sensoche è scritto in un linguaggio comprensibile per chi parla SC. Questo

Propriamente si tratta delle classi installate sulla macchina di scrive.12

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 38/328

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 39/328

3.3–36

1 Array[slot] : ArrayedCollection {

3 *with { arg … args;

4 // return an array of the arguments given

5 // cool! the interpreter does it for me..

6 ^args

7 }

8 reverse {

9 _ArrayReverse

10 ^this.primitiveFailed

11 }12 scramble {

13 _ArrayScramble

14 ^this.primitiveFailed

15 }

16 mirror {

17 _ArrayMirror

18 ^this.primitiveFailed

19 }

21 // etc

23 sputter { arg probability=0.25, maxlen = 100;

24 var i=0;

25 var list = Array.new;

26 var size = this.size;

27 probability = 1.0 - probability;

28 while { (i < size) and: { list.size < maxlen }}{

29 list = list.add(this[i]);

30 if (probability.coin) { i = i + 1; }

31 };32 ^list

33 }

35 // etc

36 }

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 40/328

3.3–37

Senza addentrarsi nel merito si noti come la prima riga (1) definisca laclasse Array come una sottoclasse di ArrayedCollection(Array[slot]: ArrayedCollection ). Fa seguito (da 3 in poi) la lista dei metodi im-plementati per la classe (width, reverse, scramble , ognuno chiusotra una coppia di graffe). Un modo agevole per ottenere una lista deimetodi implementati consiste nello sfruttare il potere di introspezionedi SC. SC fornisce molti metodi per conoscere informazioni relativi alsuo stato interno. I metodi dumpInterface, dumpFullInterface, dum-pMethodList visualizzano sulla Post Window informazioni sui methodiimplementati per l’interfaccia di una classe.

• dumpInterface: stampa tutti i metodi definiti per la classe

• dumpFullInterface: come prima, ma include anche i metodi ereditatidalle sopraclassi della classe

• dumpMethodList: come il precedente, ma con i metodi in ordine alfa- betico e l’indicazione della classe da cui sono ereditati.

Ad esempio quanto segue riporta il risultato della valutazione diArray.dumpInterface.Le liste fornite dagli altri due metodi proposti sono decisamente più lun-ghe.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 41/328

3.3–38

1 Array.dumpInterface2 reverse ( )

3 scramble ( )

4 mirror ( )

5 mirror1 ( )

6 mirror2 ( )

7 stutter ( n )

8 rotate ( n )

9 pyramid ( patternType )

10 pyramidg ( patternType )

11 sputter ( probability, maxlen )12 lace ( length )

13 permute ( nthPermutation )

14 allTuples ( maxTuples )

15 wrapExtend ( length )

16 foldExtend ( length )

17 clipExtend ( length )

18 slide ( windowLength, stepSize )

19 containsSeqColl ( )

20 flop ( )

21 multiChannelExpand ( )22 envirPairs ( )

23 shift ( n )

24 source ( )

25 asUGenInput ( )

26 isValidUGenInput ( )

27 numChannels ( )

28 poll ( interval, label )

29 envAt ( time )

30 atIdentityHash ( argKey )

31 atIdentityHashInPairs ( argKey )32 asSpec ( )

33 fork ( join, clock, quant, stackSize )

34 madd ( mul, add )

35 asRawOSC ( )

36 printOn ( stream )

37 storeOn ( stream )

38 prUnarchive ( slotArray )

39 jscope ( name, bufsize, zoom )

40 scope ( name, bufsize, zoom )

41 Array

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 42/328

3.3–39

A partire da un metodo è possibile risalire alle classi che lo implemen-tano: è necessario selezionarlo e scegliere dal menu “Lang” la voce “Im-plementations of”: SC apre una finestra dove sono listati le classi cherispondono al metodo e la lista delle keyword.Tornando a z , un metodo più agevole per creare un array consiste sem-plicemente nello scrivere l’array in questione tra parentesi quadre (se-condo una notazione molto diffusa). Ad esempio, z = [1,2,3,4] asse-gna a z l’array [1,2,3,4] (1). Come si è visto nella definizione di classe,uno dei metodi che la classe Array prevede è reverse: intuibilmente, ilmetodo prende l’array e ne inverte l’ordine. Nel momento in cui si passail messaggio reverse a z che ne diventa il ricevente (5), z cerca il metodoreverse tra quelli che sono definiti nella sua classe, e si comporta con-seguentemente. Nel caso in questione, come l’operazione di inversionevenga svolta da SC non è interessante in questa sede (ne è molto interes-sante di per sé): in ogni caso, se si vede la definizione del metodo (supra,8-11), si nota come il metodo chiami una riga misteriosa, _ArrayReverse(supra, 9): l’operazione di inversione è allora realizzata da una primitivadi SC, scritta in linguaggio C e non in SC. Al contrario il metodo sput-

ter è scritto completamente in SC. I metodi restituiscono delle entitàcome risultato delle operazioni svolte: queste entità sono oggetti a tuttigli effetti. Ad esempio, z.reverse restituisce un nuovo array, invertitorispetto a z (7). Poiché è un oggetto diverso, se si intende riutilizzar-lo, è necessario assegnarlo ad una variabile, la stessa z ad esempio (12).L’ultimo oggetto restituito viene stampato da SC sullo schermo come

risultato del processo di intepretazione.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 43/328

3.3–40

1 z = [1,2,3,4]

3 [ 1, 2, 3, 4 ]

5 z.reverse

7 [ 4, 3, 2, 1 ]

9 z

10 [ 1, 2, 3, 4 ]

12 z = z.reverse

13 [ 4, 3, 2, 1 ]

14 z

15 [ 4, 3, 2, 1 ]

17 z.mirror

18 [ 4, 3, 2, 1, 2, 3, 4 ]

20 z

21 [ 4, 3, 2, 1 ]

23 z.reverse.mirror.mirror

24 [ 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1 ]

In una nuova sessione con l’interprete viene valutato il codice z = [1,2,3,4](1): SC restituisce l’array [ 1, 2, 3, 4 ] (2) e lo assegna a z. Nella rigasuccessiva z.reverse (5) chiede a z di svolgere le operazioni previste

da reverse: il risultato è [ 4, 3, 2, 1 ] , che non è assegnato ad alcu-na variabile (7). Se infatti si chiama z , si ottiene [ 1, 2, 3, 4 ] (10).Per assegnare a z il risultato della computazione effettuata da reverse ènecessario riassegnare a z il valore calcolato dal metodo attraverso z =

z.reverse (12). Chiamando z (14) si ottiene il suo valore: questa volta èl’array z invertito (15). Il metodo mirror genera un nuovo array a par-tire da quello a cui il messaggio è passato, simmetrico rispetto al centro(palindromo): z.mirror (17) restituisce [ 4, 3, 2, 1, 2, 3, 4 ] (18),

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 44/328

3.4–41

senza assegnarlo a z , come prima (20-21). L’ultima riga (23) di codicemette in luce un aspetto importante di SC: il cosiddetto concatenamen-to dei messaggi (“message chaining”). Sul risultato di z.reverse vienecalcolato mirror , su questo secondo risultato viene calcolato mirror dinuovo. Si consideri il risultato stampato sulla Post Window (24). Questisono i passaggi a partire da z = [ 4, 3, 2, 1 ] (valore iniziale più tremessaggi):

[4,3,2,1] → [1,2,3,4] → [1,2,3,4,3,2,1]→[1,2,3,4,3,2,1,2,3,4,3,2,1]Sebbene permetta di scrivere codice in forma estremamente economica,il concatenamento dei messaggi va usato con cautela perché rischia direndere di difficile lettura il codice.

3.4 I metodiditipo post e dump

Si è detto che tutti i metodi restituiscono un oggetto. A scanso di equi-voci va ricordato il comportamento dei metodi che permettono di ot-tenere informazioni attraverso la Post Window. Esempi già visti sonodumpClassSubtree e dumpSubclassList , e dumInterface, dumpFullIn-terface, dumpMethodList. Il metodo più usato per ottenere genericheinformazioni su quanto sta avvenendo è postln , che stampa una strin-ga di informazione relativa all’oggetto su cui è chiamato. Ad esempio si

consideri questo codice:

1 Array.postln

2 Array

3 Array

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 45/328

3.4–42

Viene chiamato il metodo postln su Array (1). SC esegue il codice ilquale prevede di stampare informazioni su Array: in questo caso, es-sendo Array una classe, viene semplicemente stampato il nome del-la classe, Array appunto (2). Infine SC stampa sempre sullo schermoun’informazione sull’ultimo oggetto su cui è stato invocato un meto-do: in sostanza SC chiama sull’ultimo oggetto proprio postln. E infattisi ottiene di nuovo Array (3). Se in questo caso l’utilità di postln è vir-tualmente nulla, si consideri invece questo caso:

1 z = [ 4, 3, 2, 1 ]

3 [ 4, 3, 2, 1 ]

5 z.postln.reverse.postln.mirror.postln.mirror

7 [ 4, 3, 2, 1 ]

8 [ 1, 2, 3, 4 ]

9 [ 1, 2, 3, 4, 3, 2, 1 ]

10 [ 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1 ]

12 z.postln.reverse.postln.mirror.postln.mirror.postln

14 [ 4, 3, 2, 1 ]

15 [ 1, 2, 3, 4 ]

16 [ 1, 2, 3, 4, 3, 2, 1 ]

17 [ 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1 ]

18 [ 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2, 1 ]

Come nel caso precedente, a z è assegnato l’array [ 4, 3, 2, 1 ].Viene chiamato il concatenamento di metodi .reverse.mirror.mirror ,senonché dopo ogni metodo è concatenato anche un messaggio postln

(5). In sostanza in questo caso postln permette di vedere sullo schermoil risultato intermedio resituito da ognuno dei metodi invocati. Si no-ti come sia inutile (in questo caso) concatenare di nuovo postln dopo

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 46/328

3.5–43

l’ultimo mirror (come avviene in 12), visto che per definizione SC stam-pa il risultato dell’ultima computazione (ciò che mirror restituisce). Cisi potrebbe aspettare che, poiché postln serve a stampare sullo scher-mo, ciò che questo metodo restituisce sia un oggetto di tipo stringa, uninsieme di caratteri. Non è così: postln

• stampa una stringa sullo schermo

•restituisce l’oggetto su cui è chiamato il metodo

Questo comportamento è assolutamente utile in fase di correzione deglierrori, perché permette di concatenare messaggi di stampa per verifica-re i comportamenti dei metodi invocati, ma senza per questo interferirecon il processo. Se infatti il metodo postln restituiscce una stringa, al-lora in z.postln.reverse il messaggio reverse sarebbe ricevuto da unoggetto di tipo stringa e non da un oggetto array, come nell’esempioseguente.

1 "[ 1, 2, 3, 4 ]".reverse

3 ] 4 ,3 ,2 ,1 [

Questo vale per tutti metodi di introspezione. Si osservino gli esempidi Collection.dumpClassSubtree, Collection.dumpSubclassList,

Array.dumpInterface . In tutti e tre i casi l’ultima riga stampa l’oggetto

che il metodo restituisce: si noti come venga restituita la classe, secon-do quanto stampato nell’ultima riga delle rispettiva schermate (Collec-tion, Collection, Array). Questo tipo di comportamento vale tipica-mente per tutti i metodi di stampa e di introspezione. Sono molti: adesempio varianti di postln sono post, postc, postcln.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 47/328

3.5–44

3.5 Numeri

L’interprete di SC può essere utilizzato come calcolatore. Ad esempio,si cosideri questa sessione interattiva:

1 2.3*22 4.6

4 4/3

5 1.3333333333333

7 4**3

8 64

10 4+2*3

11 18

Due cose sono di rilievo. La prima concerne l’ordine di esecuzione. Sesi osserva 4+2*3 si nota come non ci sia gerarchia tra gli operatori: adesempio, la moltiplicazione non viene valutata prima dell’addizione.Nella riga prima viene valutato 4+2 , quindi *3 che viene riferito al ri-sultato dell’operazione precendente (4 + 2 = 6 × 3 = 1 8). Il secondoaspetto che dovrebbe stupire il lettore è che la sintassi utilizzata con-

traddice il presupposto per cui in SC ogni cosa è un oggetto dotato diun’interfaccia, per cui ogni operazione dovrebbe seguire il modello ge-nerale oggetto.metodo. Qui in effetti SC fa un’eccezione, almeno per lequattro operazioni, che possono essere scritte in modo più intuitivo nel-la consueta forma funzionale. Ciò non toglie che i numeri (interi, a vir-gola mobile, etc.) siano oggetti a tutti gli effetti. Se si chiama il metodo

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 48/328

3.5–45

class su un intero, ad esempio 5 (1), si ottiene la classe a cui appartienein quanto istanza: Integer.

1 5.class

2 Integer

Si può allora chiamare su Integer il metodo superclasses che resti-tuisce un array (attenzione, questa volta il metodo restituisce un array)

contenente tutte le sopraclassi fino a Object.

1 Integer.superclasses

3 [ class SimpleNumber, class Number, class Magnitude, class Object ]

Intuibilmente, a parte Object , che è sopraclasse di tutto, Magnitude è laclasse che più in generale si occupa di grandezze (tra cui i numeri).

1 Magnitude.allSubclasses

3 [ class Association, class Number, class Char, class Polar, class

Complex, class SimpleNumber, class Float, class Integer ]

Con Magnitude.dumpClassSubtree si accede ad una rappresentazionead albero delle sottoclassi di Magnitude: tutte le classi che si occupano

di grandezze: Integer -i numeri interi- è vicino a Float -i numeri a vir-gola mobile-, poiché sono due sottoclassi di SimpleNumber. Qust’ultimaclasse fa parte del più vasto insieme delle sottoclassi di Number , i numeriin generale, compresi quelli polari e quelli complessi (Polar, Complex ,che qui non interessano).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 49/328

3.5–46

1 Magnitude.dumpClassSubtree2 Magnitude

3 [

4 Association

5 Number

6 [

7 Polar

8 Complex

9 SimpleNumber

10 [ Float Integer ]

11 ]12 Char

13 ]

14 Magnitude

In quanto oggetto, è possible passare ai numeri, il 3 ad esempio, il mes-saggio postln , il quale stampa il numero e restituisce il numero stesso.

1 3.postln2 3

3 3

5 3.postln * 4.postln

6 3

7 4

8 12

Per numerose operazioni matematiche è disponibile una doppia nota-zione, funzionale e ad oggetti. Ad esempio sqrt(2) (10) chiede di ese-guire la radice quadrata di 2: in notazione ad oggetti si tratta di chia-mare su 2 il metodo sqrt (14), che restituisce il risultato dell’operazioneradice quadrata applicata all’oggetto su cui è chiamato. Analogamen-te, l’elevamento a potenza può essere scritto funzionalmente come 4**3

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 50/328

3.5–47

(18), oppure come 4.pow(3) (22): si chiama il metodo pow con argomen-to 3 sull’oggetto 4. Ovvero, “oggetto 4, èlevati a potenza con esponente3”.

1 sqrt(2)

3 1.4142135623731

5 2.sqrt

7 1.4142135623731

9 4**3

11 64

13 4.pow(3)

15 64

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 51/328

4.2–48

4 Sintassi:elementifondamentali

4.1 (Parentesi)

Negli esempi di codice SC si troveranno spesso le parentesi tonde, () ,utilizzate come delimitatori. Le parentesi tonde non sono esplicitamentepreviste a tal fine nella sintassi di SC. Tuttavia è una convenzione che laloro presenza indichi un pezzo di codice che deve essere valutato tuttoinsieme (ovvero, selezione di tutte le linee e valutazione). In Mac OSXil doppio-click dopo una parentesi tonda di apertura permette la sele-zione di tutto il blocco di codice: le parentesi agevolano perciò di moltol’interazione dell’utente con l’interprete. Nell’esempio di pagina 71 le

parentesi alle righe 1 e 20 indicano il che il codice 2-19 è un blocco unico.In generale la presenza delle parentesi è per convenzione un’indicazionenon all’interprete SC quanto all’utente (magari a se stessi il giorno dopoche si è scritto il codice).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 52/328

4.3–49

4.2 //Commenti(/*didiversotipo*/)

La colorazione della sintassi nell’esempio in discussione evidenzia inrosso i commenti (“comments”), le parti di codice che l’interprete nontiene in considerazione e che si rivelano molto utili per rendere il codice

leggibile fino all’autodocumentazione. In SC i commenti sono di duetipi:

a. // indica un commento che occupa una riga o la parte terminale diessa;

 b. la coppia /* */ , che delimita un commento multilinea: tutto ciò cheè incluso tra i due elementi è ignorato dall’interprete.

4.3 ”Stringhe”

Una sequenza di caratteri delimitata da doppi apici è una stringa. Lestringhe possono occupare più linee. La classe String è una sottoclassedi RawArray: le strighe sono cioè sequenze di oggetti a cui è possibileaccedere.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 53/328

4.4–50

1 t = "stringa"2 stringa

4 t[0]

5 s

7 t[1]

9 t

11 t.size12 7

Così, t[0] chiede il primo elemento dell’array "stringa" , ovvero s , ecosì via.È nella classe String che vengono definiti i metodi post e affini. Quan-do si invia ad un oggetto il messagio di post , SC tipicamente chiedeall’oggetto una sua rappresentazione in stringa, e sulla stringa richiama

il metodo post. Ad esempio il metodo di concatenazione di stringhe ++vale anche se gli oggetti concatenati alla prima stringa non sono strin-ghe: ++ chiede internamente a tutti gli oggetti una loro rappresentazionecome stringa: . . .++ 5 equivale cioè a . . .++ (5.asString).

1 "stringa"++5

3 stringa5

4.4 Variabili

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 54/328

4.4–51

In SC è necessario dichiarare le variabili che si intendono utilizzare. Inomi di variabili devono iniziare con un carattere alfabetico minuscoloe possono contenere caratteri alfanumerici (caratteri maiuscoli, numeri).La dichiarazione delle variabili richiede la parola riservata var (che dun-que non può essere usata come nome di variabile). È possibile assegnareun valore ad una variabile mentre la si dichiara.

1 var prima, seconda;

2 var terza = 3;

3 var quarta;

5 nil

Nell’esempio si noti che l’inteprete resituisce nil. Nel valutare una se-rie di espressioni, l’interprete resituisce sempre il valore dell’ultima: inquesto caso quello della variabile quarta , a cui non è stato ancora asse-gnato alcun valore, come indicato da nil. La dichiarazione può ancheoccupare più righe, purché iniziali e consecutive. Le lettere a-z sono giàriservate da SC per le variabili d’ambiente: in altre parole si possonoutilizzare (ad esempio in fase di testing) senza bisogno di dichiararle.Nell’esempio (pagina 52 , 1) l’utilizzo della variabile a in a = [1,2,3]

è ammissibile senza dichiarazione: l’espressione è valutata e alla varia- bile viene assegnato l’array (SC restituisce l’array, 2). Nella valutazionedell’espressione seguente

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 55/328

4.4–52

1 a = [1,2,3]2 [ 1, 2, 3 ]

4 array = [1,2,3]

5 • ERROR: Variable 'array' not defined.

6 in file 'selected text'

7 line 1 char 17 :

8 array = [1,2,3]

9 ———————————–

10 nil

l’interprete solleva un errore, poiché riconoscendo un’assegnazione divalore a una variabile, rileva che la variabile in question (array) non èstata dichiarata (• ERROR: Variable 'array' not defined.). Il proble-ma si risolve dichiarando la variabile:

1 (

2 var array ;

3 array = [1,2,3]

4 )

5 [ 1, 2, 3 ]

Si noti l’uso delle parentesi tonde ad indicare che le riga di codice van-no valutate tutte insieme. L’esistenza della variabile vale soltanto per ilmomento in cui viene valutato il codice. In altre parole, se si esegue il

seguente codice:

1 array.postln

Si ottiene di nuovo:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 56/328

4.5–53

1 • ERROR: Variable 'array' not defined.2 in file 'selected text'

3 line 1 char 5:

4 array•.postln

5 ———————————–

6 nil

Durante una sessione interattiva può essere desiderabile mantenere l’esistenzadi variabili per poterle riutillizare in un secondo momento. A tal fine,

si possono utilizzare le variabili d’ambiente13. Come si è visto, i carat-teri alfabetici sono per convenzione interna assegnabili senza dichiara-zione. In più, ogni variabile il cui primo carattere sia è una variabiled’ambiente. Una volta dichiarata in questo modo

1 ~array = [1,2,3]

la variabile array è persistente per tutta la sessione14

.

1 ~array

3 [ 1, 2, 3 ]

Una nota più avanzata. Le variabile sono “d’ambiente” perché sono persistenti13

nell’intera sessione interattiva di lavoro con SC. Sebbene possa sembrare, non sonointese come variabili globali (che sono molto pericolose per la programmazione, sem-plicemente perché sono sempre accessibili, e dunque scarsamente controllabili). Ser-vono piuttosto per poter lavorare interattivamente con SC, per “conversare” –per cosìdire– con SC, ma non per scrivere codice in forma strutturata.Si discuterà più avanti il problema dello scoping, cioè dell’ambito di validità delle14

variabili.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 57/328

4.5–54

4.5 Simboli

Un simbolo è un nome che rappresenta qualcosa. Può essere pensatocome un identificativo assoluto. È cioè un nome che rappresenta univo-camente un oggetto. Si scrive tra apici semplici, o, nel caso la sequenza

di caratteri non preveda spazi al suo interno, preceduto da un\

1 a = \symbol

3 symbol

5 b = 'sono un simbolo'

7 sono un simbolo

9 [a.class, b.class].postln

11 [ class Symbol, class Symbol ]

Una stringa è una sequenza di caratteri. Ad esempio, qui a e b sono duestringhe.

1 a = "symbol"

3 symbol

5 b = "symbol"

7 symbol

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 58/328

4.6–55

Le due stringhe sono equivalenti (detto approssimativamente: “hannolo stesso contenuto”).

1 a == b // == chiede: sono equivalenti?

2 true // risposta: sì

ma non sono lo stesso oggetto.

1 a === b // === chiede invece: sono lo stesso oggetto?

2 false // no

Invece, la relazione di identità è vera nel caso dei simboli:

1 a = \symbol

3 symbol

5 b = 'symbol' // scrittura equivalente

7 symbol

9 a == b

10 true

12 a === b // lo stesso oggetto?

14 true // sì

4.6 Espressioni;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 59/328

4.6–56

Un’espressione in SC è un enunciato finito e autonomo del linguaggio:una frase conclusa, si potrebbe dire. Le espressioni in SC sono delimitatedal ;. Ogni blocco di codice chiuso da un ; è dunque un’espressione diSC. Quando si valuta il codice SC nell’interprete, se il codice è compostodi una riga sola è possibile omettere il ;.

1 a = [1,2,3]

3 [ 1, 2, 3 ]

5 a = [1,2,3] ;

7 [ 1, 2, 3 ]

In generale, meglio prendere l’abitudine di mettere il ; anche quando siesperimenta interattivamente con l’interprete riga per riga. Quando sivalutano più linee di codice la presenza del ; è l’unica informazione di-

sponibile all’interprete per sapere dove finisce un’espressione e ne iniziaun’altra. Le due espressioni seguenti sono uguali, poiché l’a capo non èrilevante per SC (questo permette di utilizzare l’a capo per migliorarela leggibilità del codice). Si noti come in questo caso l’assenza del pun-to in virgola nella seconda versione non crei problemi. In assenza del ;SC considera un’espressione tutto ciò che è selezionato: in questo casoil codice selezionato è effettivamente un’unica espressione “sensata”, edunque l’inteprete non segnala errori.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 60/328

4.7–57

1 (2 a = [1,2,3]

3 )

5 (

6 a = [ 1,

7 2,

8 3 ]

9 )

L’ordine delle espressioni è l’ordine in cui SC esegue le istruzioni fornite.

4.7 •Errori

Si riconsideri l’esempio precedente:

1 array = [1,2,3]

2 • ERROR: Variable 'array' not defined.

3 in file 'selected text'

4 line 1 char 17 :

5 array = [1,2,3]

6 ———————————–

7 nil

L’esempio illustra il modo in cui SC segnale gli errori. SC è molto fiscale:è un inteprete decisamente poco caritatevole. Questo richiede una par-ticolare attenzione ai principianti, che rischiano di impiegare un tempointeressante prima di riuscire a costruire un’espressione corretta. In più,la segnalazione degli errori è piuttosto laconica in SC: se nel caso pre-cedente è decisamente chiara, in altri può esserlo meno. In particolare

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 61/328

4.8–58

può essere poco agevole individuare dov’è che si trova l’errore. Di so-lito la parte di codice segnalata da SC mentre riporta l’errore è il puntoimmediatamente successivo a dove si è verificato l’errore. Nel caso inesame, ciò che manca è una dichiarazione di variabile  prima di array =[1,2,3].

4.8 {Funzioni}

Le funzioni sono uno degli elementi meno intuitivi da comprendere perchi non arrivi da un background informatico. Si consideri la definizionefornita dall’help file:

“A Function is an expression which defines operations to be per-formed when it is sent the ’value’ message.”

La definizione è precisa ed esaustiva. Una funzione è:

1. un’espressione

2. che definisce operazioni

3. che vengono effettuate soltanto nel momento in cui la funzione rice-ve il messaggio value. Una funzione è perciò un oggetto: implemen-ta un metodo value con cui risponde al messaggio value (si provi

Function.dumpInterface).

Una funzione può essere pensata come un oggetto (fisico) capace di unfare certe cose. Nel momento in cui la si dichiara si dice a SC di costruire

l’oggetto, non di farlo funzionare. A quel punto l’oggetto c’è: si tratta poidi metterlo in funzione quando serve attraverso il messaggio value.Le definizioni delle funzioni sono racchiuse tra parentesi graffe {}.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 62/328

4.8–59

1 f = { 5 } ;

3 a Function

5 f.value ;

6 5

La funzione f è un oggetto che butta fuori a richiesta il valore 5. La de-finizione stocca l’oggetto funzione il cui comportamento viene attivato

a richiesta attraverso il messaggio value (5, 6).

1 g = { arg input; input*2 } ;

3 a Function

5 g.value(2) ;

7 4

9 g.value(134) ;

11 268

Un uso più interessante delle funzioni prevede l’uso di “argomenti”:gli argomenti possono essere pensati come gli input dell’oggetto. Gliargomenti vengono definiti attraverso la parola riservata arg cui fan-

no seguito i nomi degli argomenti separati da una , e delimitati da un;. Ad esempio la funzione g è definita come { arg input; input*2

} (8): g accetta un argomento e restituisce il risultato dell’operazionesull’argomento. In particolare g restituisce il doppio del valore input

che gli viene dato in entrata. La funzione g è come un frullatore: si mettel’uovo input in entrata e il frullatore restituisce il risultato di frullato-re.sbatti(uovo) in uscita.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 63/328

4.8–60

1 h = { arg a, b; (a.pow(2)+b.pow(2)).sqrt } ;

3 a Function

5 c = h.value(4,3) ;

7 5

Infine la funzione h =

{arg a, b; (a.pow(2)+b.pow(2)).sqrt

}(20)

è un oggetto-modulo di calcolo che implementa il teorema di Pitagora:accetta in entrata i due cateti a e b e restituisce l’ipotenusa c , secondo

la relazione c =√ 

a2 + b2 (24, 26). Si noti tra l’altro come la radicequadrata sia un messaggio inviato all’intero risultante dal calcolo dellaparentesi.In una seconda versione (qui di seguito) la definizione non cambia in so-stanza ma permette di definire ulteriori aspetti. Al codice fa seguito unasessione della Post window in cui la funzione definita viene utilizzata.

1 (

2 h = { // calcola l'ipotenusa a partire dai cateti

3 arg cat1, cat2 ;

4 var hypo ;

5 hypo = (cat1.pow(2)+cat2.pow(2)).sqrt ;

6 "hypo: "++hypo } ;

7 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 64/328

4.8–61

1 h.value(4,3) ;

3 hypo: 5

5 h.value(4,3).postln.class

7 hypo: 5

8 String

Si notino alcuni passaggi:

• i commenti funzionano come al solito all’interno delle funzioni (2);

• i nomi degli argomenti seguono i criteri definiti per le variabili (3);

• a seguito degli argomenti è possibile aggiungere una dichiarazionedi variabili (4). Nel corpo della funzione, specie se complessa, puòessere utile avere a disposizione dei nomi di variabili. In questo ca-

so, hypo è un nome significativo che permette di rendere più leggi- bile l’ultima riga, in cui vi si fa riferimento ("hypo: "++hypo). Per levariabili valgono le osservazioni già riportate.

• una funzione restituisce un unico valore (sia esso un numero, unastringa, un oggetto, un array, etc): il valore dell’ultima espressio-ne definita nel corpo della funzione. L’ultima espressione è alloral’output della funzione. In particolare la funzione restituisce una strin-

ga composta da "hypo: " a cui è concatenato attraverso ++ il conte-nuto della variabile hypo. Ciò che la funzione restituisce in questocaso è una stringa (cfr. 5-8 della Post window).

Quest’ultimo punto ha conseguenze di rilievo. Se si ridefinisce h -nellasua prima versione- secondo quanto proposto dall’esempio seguente, sene altera radicalmente il funzionamento. L’aggiunta dell’espressione a

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 65/328

4.8–62

in coda alla definizione fa sì che la funzone h restituisca in uscita a (cioèil primo argomento in entrata (1)).

1 h = { arg a, b; (a.pow(2)+b.pow(2)).sqrt ; a } ;

3 a Function

5 h.value(4,3) ;

7 4

9 h.value(3,4)

11 3

In definitiva una funzione ha tre parti, tutte e tre opzionali, ma in ordinevincolante:

1. una dichiarazione degli argomenti (input)

2. una dichiarazione delle variabili (funzionamento interno)

3. un insieme di espressioni (funzionamento interno e output)

Una funzione che ha solo la dichiarazione degli argomenti è un ogget-to che accetta entità in entrata, ma non fa nulla. La funzione i accettaa in entrata, ma alla dichiarazione degli argomenti non fanno seguito

espressioni: la funzione non fa nulla e resituisce nil. Al suo caso limite,è possibile anche una funzione che non ha nessuno dei tre componenti:ad esempio La funzione l (7) restituisce sempre e solo nil.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 66/328

4.8–63

1 i = {arg a;}2 a Function

4 i.value(3)

5 nil

7 l = {}

9 a Function

11 l.value

13 nil

La situazione può essere schematizzata come in figura 4.1 , dove le fun-zioni sono rappresentate come moduli, che possono essere dotati di en-trate ed uscite. Il testo in grassetto nell’ultima riga rappresenta il codiceSC, il testo in corpo normale i possibili input e output.

{ 5 } { arg a, b; ... a+b }{ arg a, b; }

a+b5nilnil

a+b5

a b a b

{ }

...arg a, barg a, b

Fig. 4.1 Funzioni.

L’introduzione delle funzioni permette di affrontare il problema dell’ambitodi visibilità delle variabili (“scope”). Nell’esempio seguente seguente,

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 67/328

4.9–64

func.value restituisce 8 perché la variabile val , essendo dichiarata fuo-ri della funzione func , vale anche al suo interno.

1 (

2 var val = 4 ;

3 var func = { val*2 } ;

4 func.value ;

5 )

Qui di seguito invece func restituisce sempre 8 , ma è ciò dipende dalladichiarazione di val all’interno di func.

1 (

2 var val = 4 ;

3 var func = { arg val = 4 ; val*2 } ;

4 func.value ;

5 )

Tant’è che l’esempio seguente solleva un errore perché a val (dichiaratadentro func non è assegnato valore.

1 (

2 var val = 4 ;

3 var func = { arg val ; val*2 } ;4 func.value ;

5 )

In sostanza, l’ambito di visibilità delle variabili procede dall’esterno all’interno.Una variabile è visibile fintanto che non viene lo stesso nome non è di-chiarato più internamente.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 68/328

4.9–65

4.9 Classi,messaggi/metodiekeyword

Si è già visto come in SC le classi siano indicate da una sequenza dicaratteri che inizia con una maiuscola. Si osservi l’esempio seguente diinterazione con la Post Window:

1 superCollider

2 • ERROR: Variable 'superCollider' not defined.

3 in file 'selected text'

4 line 1 char 13 :

5 superCollider•

6 ———————————–

7 nil

9 SuperCollider

10 • ERROR: Class not defined.11 in file 'selected text'

12 line 1 char 13 :

13 SuperCollider•

14 ———————————–

15 nil

Come già ricordato, un messaggio viene inviato a una classe a ad un og-getto con il .: rispettivamente per il tramite delle sintassi Classe.metodoe oggetto.metodo. I metodi possono in fondo essere pensati come fun-zioni definite per una classe o un oggetto: quando si invoca un metodotramite un messaggio è come se si mandasse un messaggio value a unafunzione. In più, anche i metodi possono avere argomenti che costitui-scono i parametri di entrata. SC tipicamente prevede opportuni valoridi default nel caso in cui il metodo richieda degli argomenti, così che

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 69/328

4.10–66

in molti casi non è necessario specificare gli argomenti. L’uso delle key-word è utile perché consente di selezionare di quale argomento si vuolespecificare il valore, lasciando agli altri i valori predefiniti. Laddove nonsi usino le keyword, l’unico criterio disponibile per SC per poter attri-

 buire un valore ad un argomento è l’ordine in cui il valore si presentanella lista degli argomenti. Ad esempio il metod plot per gli oggettiArrayedCollection prevede gli argomenti

plot(name, bounds, discrete, numChannels, minval, maxval, parent,

labels)

Il metodo crea una finestra e vi disegna sotto forma di spezzata un og-getto di tipo ArrayCollection. L’argomento name definisce il titolo dellafinestra. Così, la finestra creata da [1,2,3,1,2,3].plot("test") ha co-me titolo “test”. Il metodo consente anche di definire il numero dei ca-nali numChannels. Se il numero è superiore a 1, plot assume che i primin campioni siano i campioni numero 1 dei canali 1 . . . n. Ad esempio,

se i canali sono due, allora i primi due campioni sono i campioni nume-ro 1 dei canali 1 e 2, e così via: plot disegna una finestra per canale15. Sesi volesse specificare che numChannels deve essere pari a 2, senza key-word sarebbe necessario specificare anche gli argomenti precedenti. Adesempio:

[1,4,3,2].plot("test", Rect(200 , 140, 705, 410), false, 2)

Assai più agevolmente è possibile scrivere:[1,4,3,2].plot(numChannels:2)

L’utilità del metodo sta nel fatto che i segnali audio multicananle, rappresentabili at-15

traverso un array, sono memorizzati in questa forma. Se il segnale è stereo, plot connumChannels:2 disegna la forma d’onda dei segnali sui due canali.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 70/328

4.10–67

Infine, l’uso delle keyword è in generale leggermente più costoso da unpunto di vista computazionale ma rende il codice molto più leggibile.

4.10 Esempio

Un esempio di codice relativo alla creazione di un semplice elementografico permette di introdurre i fondamenti della sintassi di SC. Il codicepresentato si propone di creare un elemento grafico a manopola, la cuirotazione controlli in forma parametrica il colore dello sfondo.

4.10.1 IlpatternGUI

La generazione di elementi GUI (Graphical User Interface) richiede dicostruire oggetti GUI, cioè di istanziare oggetti a partire da classi spe-cializzate. Intuibilmente, ogni gestore grafico definisce le sue classi. Adesempio, se si vuole creare una finestra usando il gestore di Mac Cocoa,è necessario istanziare un oggetto dalla classe SCWindow. Se invece (comeavviene necessariamente su Windows) si vuole creare una finestra ana-

loga usando SwingOSC bisogna invece utilizzare la classe JSCWindow.Intuibilmente, questa soluzione vincola la programmazione della GUIal gestore grafico. SwingOSC definisce le sua classi a partire da Cocoa,che è stato il primo gestore grafico: come si vede nell’esempio, aggiungeuna J alle classi definite in Cocoa. Così, una strategia di “cerca e sostitui-sci” permette di adattare il codice per usare uno dei due gestori. Sebbenepraticabile, la soluzione non è soddifacente:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 71/328

4.10–68

•“cerca e sostituisci” lavora sulle stringhe e potrebbe introdurre errorinon previsti

• ne risultano due copie del codice• non vale per altri eventuali gestori grafici

Tuttavia, si potrebbe anche osservare come tutti i gestori grafici sostan-zialmente offrano funzionalità simili: finestre, pulsanti, cursori, etichet-te, campi per l’immissione di testo, e così via. Si possono allora defi-nire astrattamente le funzionalità che un gestore deve/può offrire, per

poi chiedere al gestore attualmente in uso (o disponibile) di realizzarle.Nell’esempio precedente, ciò che interessa è una finestra,indipendentementedla gestore grafico. La classe GUI implementa questo comportamento, edè un esempio interessante di programmazione ad oggetti. Per costruireuna finestra si potrebbe scrivere utilizzando la classe di Cocoa

1 w = SCWindow.new

Oppure SwingOSC:

1 w = JSCWindow.new

Invece, è bene scrivere:

1 w = GUI.window.new

Che cosa succede nella riga precedente? La classe GUI si occupa, per cosìdire, di inoltrare i messaggi successivi al gestore grafico prescelto. Dun-que, GUI riceve un messaggio window , e seleziona la classe opportunapresso il gestore grafico attuale. A questa classe viene inviato il messag-gio new. Si noti la differenza:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 72/328

4.10–69

1 w = GUI.window

3 JSCWindow

5 w = GUI.window.new

7 a JSCWindow

Nel primo caso (1), SC risponde restituendo la classe che implementa la

funzione astratta window (“finestra”) presso il gestore attuale, cioè JSC-Window (3). Nel secondo caso (5), avviene la stessa cosa, ma attraverso ilconcatenamento dei messaggi, alla classe così ottenuta si invia il messag-gio new , che istanzia un oggetto attuale (7). Poiché il gestore predefinitosu Mac è Cocoa, in quel caso si avrebbe tipicamente:

1 w = GUI.window

3 SCWindow

5 w = GUI.window.new

7 a SCWindow

Attraverso l’uso della classe GUI , può anche cambiare il gestore grafico,ma ciò non richiede di cambiare il codice, che astrae la funzione (“fareuna finestra”) rispetto all’implementazione (“con SwingOSC”, con “conCocoa”, e così via). Nel caso in cui si abbiano più gestori disponibili,è possibile selezionare il gestore attuale attraverso un messaggio allaclasse GUI.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 73/328

4.10–70

1 GUI.cocoa // seleziona Cocoa (Mac)2 CocoaGUI

4 GUI.swing //selezione SwingOSC (Mac, Win, Linux)

5 CocoaGUI

Gli esempi successivi utilizzano sempre il metodo descritto.

4.10.2 Ilcodice

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 74/328

4.10–71

1 (2 /* accoppiamento di view e controller */

4 var window, knob, screen ; // dichiarazione delle variabili usate

6 // una finestra contenitore

7 window = GUI.window.new("Knob", Rect(300,300,100, 100)) ;

9 // una manopola nella finestra, range: [0,1]

10 knob = GUI.knob.new(window, Rect(30, 30, 50, 50)) ;

11 knob.value = 0.5 ;

13 // una finestra-sfondo

14 screen = GUI.compositeView.new(window,Rect(0,0, 150,150));

15 screen.background = Color.black;

17 // azione associata a knob

18 knob.action_({ arg v;

19 var red, blue, green ;

20 red = v.value ;

21 green = red*0.5 ;22 blue = 0.25+(red*0.75) ;

23 ["red, green, blue", red, green, blue].postln ;

24 screen.background = Color(red, green, blue);

25 });

27 // non dimenticarmi

28 window.front ;

29 )

4.10.3 Introduzione

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 75/328

4.10–72

•1: il blocco di codice è racchiuso tra parentesi tonde (1 e 31);

• 3: un commento multilinea è utilizzato a mo’ di titolo (3) e molti altricommenti che forniscono alcune informazioni sulle diverse parti delcodice (ad esempio, 7).

• 5: a parte i commenti, il codice inizia con la dichiarazione delle trevariabili utilizzate;

4.10.4 CreazionedeglielementiGUI

• 7-9: la prima cosa da fare è creare una finestra contenitore, cioè unoggetto di riferimento per tutti gli altri elementi grafici che verran-no creati in seguito. È un approccio tipico nei sistemi di creazione di

GUI. Alla variabile window viene assegnato un oggetto GUI.window ,generato attraverso il metodo costruttore new. A new vengono pas-sati due argomenti: una stringa che indica il titolo visualizzato dallafinestra ("Knob" e un oggetto di Rect , cioè un rettangolo di 100x100pixel, il cui angolo superiore sinistro è nel pixel (300,300).

• 10-12: la costruzione di un elemento grafico a manopola segue unprocedimento analogo a quanto avvenuto per la finestra-contenitore.

Alla variabile knob viene assegnato un oggetto GUI.knob (11). Il co-struttore sembra uguale a quello di GUI.window: senonché questavolta è necessario specificare a quale finestra-contenitore vada riferi-to l’oggetto GUI.knob: la finestra-contenitore è window , e il rettangoloche segue prende come punto di riferimento non lo schermo, ma lafinestra window. Dunque un rettangolo 50x50, la cui origine è nel pi-xel (30,30) della finestra window. Il punto di partenza della manopolaè 0.5 (12). Per default l’escursione di valori di un oggetto GUI.knob

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 76/328

4.10–73

varia tra 0.0 e 1.0: dunque attraverso l’attributo knob.value = 0.5 siindica la metà.

• 14-16: si tratta ora di costruire una finestra da “spalmare” sul tuttolo sfondo di window , a cui far cambiare colore attraverso knob. La fi-nestra screen è un oggetto di tipo GUI.compositeView (14). Si notiche è più estesa della finestra-contenitore (è grande 150x150 pixel,a partire dal punto (0,0) di window): è soltanto un trucco per esseresicuri che occupi tutto lo sfondo visibile (si provi a ridurre le dimen-

sioni). All’attributo della finestra screen viene assegnato un coloreattraverso un oggetto Color. Anche i colori sono oggetti in SC e laclasse Color prevede alcuni attributi predefiniti, che permettono diavere a disposizione i nomi più comuni dei colori: ad esempio il nero(Color.black).

4.10.5 Interazione

• 18-26: dal punto di vista del design del codice screen rappresentaun display i cui attributi dipendono da knob , che opera come con-troller: si può pensare a screen come ad un dispositivo di outputche dipenda dall’input di knob. All’oggetto knob è possibile associa-re un azione: è previsto per definizione che l’azione venga portata a

termine tutte le volte che l’utente cambia il valore di knob , cioè muo-ve la manopola. Una funzione rappresenta opportunamente questotipo di situazione, poiché come si è visto è un oggetto che defini-sce un comportamento richiamabile di volta in volta e parametriz-zato da un argomento. Il metodo knob.action_ chiede di attriburea knob l’azione seguente, descritta attraverso una funzione: la fun-zione è tutto quanto è compreso tra parentesi graffe, 19-26. Quanto

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 77/328

4.10–74

avviene è che, dietro le quinte, quando si muove la manopola al-la funzione viene spedito un messaggio value. Il messaggio value

chiede di calcolare la funzione per il valore della manopola, che èl’input della funzione: dietro le quinte cioè viene inviato alla fun-zione il messaggio value(knob.value). Nella funzione l’input è de-scritto dall’argomento v (19): in altre parole, la funzione risponde al-la domanda “cosa bisogna fare quando arriva un certo valore v dallamanopola knob”.

• 20-25: il comportamento previsto richiede di cambiare il colore disfondo di screen. Vengono dichiarate tre variabili (red, green, blue)(20). Esse identificano i tre componenti RGB del colore di screen ,che SC definisce nell’intervallo [0, 1]. A red viene assegnato il va-lore in entrata di v (21). A green e blue due valori proporzionali(ma in modo diverso) a v , in modo da definire un cambiamento con-tinuo in funzione di v nelle tre componenti cromatiche. Quindi sidice di stampare su schermo un array composto da una stringa e

dei tre valori (24): in questo caso SC stampa gli elementi dell’arraysulla stessa riga opportunamente formattati. La stampa su scher-mo permette di capire come vengono calcolati i valori (ed è utilesenz’altro in fase di debugging). Infine, all’attributo background discreen viene assegnato un oggetto Color , a cui sono passate le trecomponenti. Il costruttore di Color , new accetta cioè le tre compo-nenti RGB in escursione [0,1] come definizione del colore da gene-rare. Dov’è new? In generale tutti i metodi costruttori possono essere

omessi per semplificare il codice: quando SC vede una classe seguitada una coppia di parentesi contenenti dati assume che si sia invocatoClass.new(argomenti) . È una delle molte abbreviazioni possibili inSC. Dunque, Color(red, green, blue) è equivalente in tutto e pertutto a Color.new(red, green, blue).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 78/328

4.11–75

4.10.6 Perfinire

• 29: è importante. Tutti i sistemi GUI distinguono tra creazione e vi-sualizzazione. Un conto è creare gli oggetti GUI, un conto è dire chedebbano essere visibili: questa distinzione permette di fare appari-

re/sparire elementi GUI sullo schermo senza necessariamente co-struire e distruggere nuovi oggetti. Il metodo front rende window egli elementi che da essa dipendono visibili: in caso d’omissione tuttofunziona uguale, ma nulla è visualizzato sullo schermo.

4.11 Controllidiflusso

In SC il flusso delle informazioni segue l’ordine di lettura delle espres-sioni. I controlli di flusso sono quei costrutti sintattici che possono mo-dificare quest’ordine. Ad esempio, un ciclo for ripete le istruzioni an-nidata per un certo numero di volte, e quindi procede sequenzialmenteda lì in avanti, un condizionale if valuta una condizione rispetto allaquale il flusso di informazioni si biforca (se è vero / se è falso). I control-

li di flusso sono illustrati nell’help file “Control structures”, da cui sonotratti (con una piccola modifica) i tre esempi (rispettivamente if , whilee for).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 79/328

4.11–76

1 (2 var a = 1, z;

3 z = if (a < 5, { 100 },{ 200 });

4 z.postln;

5 )

7 (

8 i = 0;

9 while ( { i < 5 }, { i = i + 1; [i, "boing"].postln });

10 )

12 for (3, 7, { arg i; i.postln });

14 forBy (0, 8, 2, { arg i; i.postln });

Nel primo caso è illustrato l’uso di if. La sintassi è:

if ( condizione da valutare,

{funzione se è vero

},

{funzione

se è falso })

In altre parole la valutazione della condizione dà origine a una biforca-zione a seconda che il risultato sia true oppure false. Passando all’esempio,la variabile a (che è dichiarata anche se potrebbe non esserlo) vale 1. Lacondizione è a < 5. Se la condizione è vera, viene eseguita la funzione {100 } , che restituisce 100 , se è falsa viene eseguita la funzione { 200 } ,che restituisce 200. Poiché la condizione è vera, viene restituito il valore

100 , che viene assegnato a z: z vale 100.Come è noto, la traduzione in italiano di while (in computer science) è”finché”:

while ({ condizione è vera }, { funzione da eseguire } )

Nell’esempio , i vale 0. Finché i è inferiore a 5, viene chiamata la funzio-ne seguente. La funzione incrementa i (altrimenti non si usicrebbe mai

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 80/328

4.11–77

dal ciclo) ed esegue una stampa di un array che contiene i e la stringa"boing".Infine, il caso del ciclo for , che itera una funzione.

for (partenza, arrivo, { funzione } )

Nell’esempio La funzione viene ripetuta cinque volte (3, . . . 7). Il va-lore viene passato alla funzione come suo argomento in modo che siaaccessibile: la funzione infatti stampa i per ogni chiamata (3, . . . 7). Si

noti che il fatto che l’argomento si chiami i è del tutto arbitrario. Ovvero:

1 for (3, 7, { arg i; i.postln });

2 3

3 4

4 5

5 6

6 7

7 3

9 for (3, 7, { arg index; index.postln });

11 3

12 4

13 5

14 6

15 7

16 3

L’istruzione ForBy richiede un terzo parametro che specifica il passo:

forBy (partenza, arrivo, passo, { funzione } )

L’esempio è una variazione del precedente che stampa l’escursione [0, 8]ogni 2. Esistono altre strutture di controllo. Qui vale la pena di introdur-re do , che itera sugli elementi di una collezione. Si può scrivere così:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 81/328

4.11–78

do ( collezione, funzione )

ma molto più tipicamente la si scrive come un metodo definito sullacollezione. Ovvero:

collezione.do({ funzione })

l’esempio è tratto dall’help file “Control-structures”, con alcune piccolemodifiche.

1 [ 101, 33, "abc", Array ].do({ arg item, i; [i, item].postln; });

3 5.do({ arg item; ("item"+item.asString).postln });

5 "you".do({ arg item; item.postln });

Se si valuta la prima riga si ottiene nella Post Window:

1 [ 0, 101]

2 [ 1, 33 ]

3 [ 2, abc ]

4 [ 3, class Array ]

5 [ 1, 2, abc, class Array ]

A scanso d’equivoci, l’ultima riga semplicemente restituisce l’array dipartenza. Alla funzione vengono passati l’elemento su cui sta effettuan-do l’iterazione (item) e un contatore (i). Meglio ribadire: i nomi item ei sono totalmente arbitrari. È il loro posto che ne specifica la semantica.Ovvero:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 82/328

4.12–79

1 [ 101, 33, "abc", Array ].do({ arg moby, dick; [dick, moby].postln;});

2 [ 0, 101 ]

3 [ 1, 33 ]

4 [ 2, abc ]

5 [ 3, class Array ]

6 [ 101, 33, abc, class Array ]

La funzione stampa un array che contiene il contatore i (colonna di si-

nistra delle prime quattro righe) e l’elemento item (colonna di destra).Il metodo do è definito anche sugli interi (n volte.valuta la funzio-

ne). Il funzionamento è illustrato nel secondo esempio. Se lo si esegue siottiene:

1 5.do({ arg item; ("item"+item.asString).postln });

3 item 0

4 item 15 item 2

6 item 3

7 item 4

8 5

L’ultima riga è l’intero su cui è chiamato il metodo. La funzione stampauna stringa costituita dal concatenamento di "item" e della rappresen-tazione sotto forma di stringa restituta dal metodo asString chiamato

sul numero intero item (0, . . . 4). Poiché la maggior parte dei cicli foriterano a partire da 0 e con passo 1 , molto spesso si trovano scritti inSC attraverso do. La sintassi di do (oggetto.metodo) è più OOP. Infine,l’ultimo esempio dimostra semplicemente che ogni stringa è una colle-zione i cui elementi sono i singoli caratteri alfanumerici che compongola stringa.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 83/328

4.12–80

4.12 AncoraunesempioGUI

L’esempio seguente presenta il codice di creazione di una GUI, utiliz-zando SwingOSC. Come nel caso precedente, l’esempio è doppiamen-te eccentrico: non utilizza in nessun modo l’audio ed è completamente

inutile (. . .). In ogni caso, il controllo di elementi GUI è particolarmenteinteressante per dimostrare alcuni aspetti della sintassi, e la visualizza-zione del processo è di aiuto alla comprensione.La widget risultante si compone di un certo numero di manopole. Ognimanopola controlla il colore dei quattro riquadri alla sua destra. Il va-lore della manopola viene passato ad una funzione che calcola il valoredelle componenti rossa, verde e blu. I primi tre riquadri visualizzanosoltanto le singole componenti (rossa, verde e blu), il quarto il colore

complessivo risultante dal contributo di tutte e tre. Quando si muove lamanopola, si ottengono due comportamenti diversi:

• fino ala metà della sua escursione, la manopola attivata controlla lealtre manopole (in sostanza, le manopole sono sincronizzate).

• oltre la metà, ogni movimento della manopola innesca, in ognunadelle altre, la scelta di un valore casuale nell’escursione possibile, apartire dal quale vengono calcolati i colori dei riquadri (secondo la

stessa funzione)

Il processo è illustrato in Figura 4.2 , dove si rappresenta il caso in cuile manopole siano quattro e la manopola con cui interagisce l’utente siala numero 1 (la seconda dall’alto). Poiché è oltre la meta, ad ogni scattomuove casualmente le altre tre (0, 1, 3).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 84/328

4.12–81

Red Green Blue All

0

1

2

3

random 

Fig. 4.2 Una GUI widget.

4.12.1 Lafunzionedigenerazionedeivaloricolore

Prima di tutto, si può definire la funzione che mappa il valore della ma-nopola su una tripla di colori.

1 colorFunction = { arg val ;

2 var red, green, blue ;

3 val = val.max(0).min(1) ;

4 red = val ;

5 green = (val*0.7)+0.3 ;

6 blue = 1.0-(val*0.7) ;

7 [red, green, blue]} ;

La funzione accetta un valore in entrata. I colori sono definiti in SCnell’intervallo [0, 1]. La funzione assume perciò genericamente che l’argomentoval sia compreso in quell’intervallo. Se così non fosse, la riga 3 provvedea troncare ogni numero minore di 0 a 0 e ogni numero maggiore di 1 a 1.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 85/328

4.12–82

Il metodo max(0) restituisce il massimo tra il numero sui cui è invocato e

0: se val è negativo, max(0) restituisce 0 , altrimenti val. Analogamentesi comporta min(1): se val è minore a 1 viene restituio val , altrimenti 1.Si noti che si sarebbe potuto usare un doppio condizionale (if (val <0 . . . ; if (val > 1 . . . ;) ma serebbe stato più complesso da legge-re e meno efficiente computazionalmente. Le righe 4-6 definiscono unatriplice correlazione tra val e le variabili che rappresentano le compo-nenti rgb16. Poiché val è compreso in [0, 1] , lo sono anche i valori delletre variabili. Infine (7), la funzione restituisce un array che contiene i trevalori. La funzione riceve dunque in entrata il valore selezionato dallamanopola (che tra l’altro è compreso nell’intervallo [0, 1]) e restituisceuna tripla i cui valori possono essere utilizzati per regolare il colore deiriquadri. Siccome deve essere richiamata più volte, la funzione vieneassegnata alla variabile colorFunction , che deve essere dichiarata.

4.12.2 ModularizzarelaGUI

Si tratta ora di generare gli elementi GUI, che sono di due tipi: manopole(dalla classe JKnob e riquadri (qui si impiegano istanze diGUI.compositeView ,di cui l’unico attributo di rilievo è il colore dello sfondo).

1 window = GUI.window.new("Some knobs", Rect(300,300, step*8, step*n)) ;

Il primo elemento è semplicemente la finestra contenitore alla quale tut-ti gli elementi fanno riferimento (1), assegnata alla variabile window. Se

Il mapping qui non è di rilievo: quello proposto è del tutto empirico.16

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 86/328

4.12–83

si osserva la Figura 4.2 si nota come tutti gli elementi (manopole e ri-quadri) siano contenuti in un quadrato. In sostanza si trarra di costruireuna griglia basata su un simile quadrato, assumendo perciò come mo-dulo il lato dello stesso. Si potrebbe “blindare” il lato definendolo inpixel ogni volta (ad esempio, 50 pixel). Poiché si tratta di un modulo,un approccio più flessibile consiste nel definire una variabile step a cuiviene assegnato un valore (ad esempio, 50), e nel richiamarla ogni qual-volta sia necessario. Un ragionamento analogo vale per il numero dellemanopole, che non deve necessariamente essere 4 , ma può essere arbi-trario: dunque si può assegnarlo ad una variabile n. Quale dovrà esserela dimensione di window? L’altezza dipende dal numero delle manopole,ognuna delle quali è alta step: dunque, n × step. Ogni gruppo mano-pola/riquadri occupa una riga: quattro riquadri a cui si può aggiungereuno spazio equivalente per la manopola, per un totale di 8×step. Dun-que il rettangolo occupato dalla finestra ha il suo vertice in alto a sinistrain (300, 300) , è largo step*8 ed è alto step*n.La programmazione di un’interfaccia grafica può essere piuttosto noio-sa e richiedere molte righe di codice. Se si dovessero gestire direttamen-te tutti gli elementi GUI previsti bisognerebbe allocare (e modificare)5 × n variabili (manopola+quattro riquadri per n). Un approccio piùintelligente (e molto usato in SC) consiste nel raccogliere gli elementi inun array. Questo permette di generare gli elementi stessi sfruttando imetodi di costruzione della classe . Il problema di richiamare ogni og-getto (manca infatti una variabile) può essere risolto attraverso l’indice

dell’array, che di fatto identifica in termini univoci l’oggetto. Una similetecnica permette di generare gli elementi GUI anche in assenza di unnumero predefinito. Più concretamente, si consideri la riga 1. L’arrayscreenArrRed contiene tutti gli n elementi di tipo GUI.compositeView

che rappresentano la componente rossa. Attraverso il metodo fill vie-ne costruito un array che contiene riquadri (viene riempito di istanze

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 87/328

4.12–84

GUI.compositeView generate da new: ogni riquadro è un quadrato di di-mensioni step × step. L’aspetto più interessante è il posizionamen-to: ogni riquadro ha infatti una ascissa fissa (step*4 , inizia dalla se-conda metà della finestra window), mentre l’ordinata varia in funzionedell’argomento i , che è l’indice progressivo 0 . . . n−1. La riga disegnainsomma la prima colonna di riquadri, che sono memorizzati nell’arraycon gli indici 0 . . . n − 1. Analogamente avviene per le altre tre colon-ne, i cui elementi di ognuna sono contenuti in un array dedicato. Infi-ne, l’array delle manopole. Il ragionamento è del tutto analogo, ma conuna aggiunta “decorativa”: il posizionamento orizzontale varia pseudo-casualmente nell’escursione [0,step × 3]. Se step = 50 px alloral’ascissa dell’angolo in alto a sinistra può valere al massimo 150 px. Sevi si aggiunge il lato (= step) del quadrato si copre la metà della lar-ghezza della finestra window (200 px).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 88/328

4.12–85

1 screenArrRed = Array.fill(n, { arg i ;2 GUI.compositeView.new(window,Rect(step*4, step*i, step,step));

3 }) ;

5 screenArrGreen = Array.fill(n, { arg i ;

6 GUI.compositeView.new(window,Rect(step*5, step*i, step, step));

7 }) ;

9 screenArrBlue = Array.fill(n, { arg i ;

10 GUI.compositeView.new(window,Rect(step*6, step*i, step, step));

11 }) ;

13 screenArrRGB = Array.fill(n, { arg i ;

14 GUI.compositeView.new(window,Rect(step*7,step*i, step,step));

15 }) ;

17 knobArr = Array.fill(n, { arg i ;

18 GUI.knob.new(window, Rect(rrand(0,step*3), step*i, step,

step)) ;

19 }) ;

La situazione è schematizzata in Figura 4.3 , dove sono evidenziati i cin-que array: ognnuno rappresenta una colonna). Allo stesso indice corri-spondono poi gli elementi comuni correlati alla manopola.Dunque, la dichiarazione delle variabili è infine la seguente:

1 var colorFunction ;

2 var window, step = 50, n = 4 ;

3 var knobArr, screenArrRed, screenArrGreen, screenArrBlue, screenArrRGB

;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 89/328

4.12–86

screenArrRed

screenArrGreenscreenArrBlue

screenArrRGB

knobArr

1

2

0

4

5

3

7

8

6

9

Fig. 4.3 Struttura della GUI widget.

4.12.3 Controllodelleazioni

Si tratta ora di collegare ad ogni manopola l’azione opportuna. In parti-colare l’azione deve prevedere due parti:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 90/328

4.12–87

1. il calcolo della funzione colore per il valore della manopola e l’aggiornamentodei colori dei riquadri;

2. l’aggiornamento delle altre manopole e dei rispettivi riquadri, in fun-zione della soglia 0.5.

In primo luogo, va osservato come la stessa azione debba essere asso-ciata a tutte le manopole. Poiché le manopole sono raccolte in un array,che è una sottoclasse di Collection è possibile utilizzare il metodo do e

ciclare sugli elementi di knobArr (cioè: su tutti gli oggetti JKnob). È be-ne ribadire il punto: in un array l’ordine degli elementi è vincolante edunque attraverso l’indice dell’elemento è possibile identificare univo-camente ogni elemento. La funzione contenuta in do ha due argomenti:il primo è l’elemento, il secondo l’indice dell’elemento (ovvero un nu-mero progressivo a partire da 0) - nel codice indicati da knob e da index.Dunque, il valore di partenza di ogni manopola viene impostata a 0.5(knob.value = 0.5). Nella definizione del metodo action_ l’argomento

(qui k) indica l’istanza della manopola: dunque, k.value accede al va-lore selezionato dall’utente. Nella definizione sono presenti due parti.

1 rgb = colorFunction.value(k.value) ;

2 red = rgb[0] ;

3 green = rgb[1] ;

4 blue = rgb[2] ;

6 screenArrRed[index].background = Color(red,0,0) ;

7 screenArrGreen[index].background = Color(0,green,0) ;8 screenArrBlue[index].background = Color(0,0,blue) ;

9 screenArrRGB[index].background = Color(red,green,blue) ;

10 ("operating on knob: "+index +" with: "+rgb.round(0.001)

).postln ;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 91/328

4.12–88

Nella prima viene descritto il punto 1: con il calcolo della funzione co-lore a partire dal valore assunto dalla manopola vengono assegnate letre componenti alle variabili red, green, blue. Si ricorderà che index

è l’indice dell’elemento manopola. Allo stesso indice corrispondono percostruzione negli array dei riquadri i rispettivi elementi. Cioè, ad esem-pio l’indice 3 seleziona nell’array delle manopole knobArr quella corre-lata ai riquadri con indice 3 nei quattro array screenArrRed, scree-

nArrGreen, screenArrBlue, screenArr A questo punto, per ognunodei riquadri viene definito il valore opportuno di colore per la propri-tà background (un’unica componte per i primi tre, tutte per l’ultimo).L’ultima riga stampa sulla Post Window alcuni dati che permettono dicontrollare il risultato del processo17.

1 indexArr = Array.series(n) ;

2 indexArr.removeAt(index) ;

L’idea è che, mentre si ruota la manopola, le altre manopole girino an-ch’esse e aggiornino i riquadri. A parte la manopola attivamente con-trollata dall’utente, tutte le altre manopole devono eseguire il compor-tamento di aggiornamento È di nuovo il caso di definire un ciclo, co-me quello in cui l’azione è contenuta, ma definito su tutte le manopo-le a parte quella attiva. L’array indexArr contiene una serie numerica

0 . . . n − 1 , ovvero tutti gli indici degli array (1). Da questo array ènecessario eliminare l’indice relativo alla manopola che che sta control-lando il processo: si tratta dell’argomento index. Il metodo removeAt

rimuove l’elemento specificato, “stringe” la collezione su cui è invoca-to, ma restituisce l’elemento stesso: quindi in questo caso non si effettua la

È una funzionalità molto utile in fase di debugging. Si tenga presenta che può essere17

computazionalmente più costosa di quanto immaginato.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 92/328

4.12–89

riassegnazione dell’array (indexArr = indexArr.removeAt(index) sa-rebbe uguale a indexArr = index). A questo punto, sui restanti n − 1elementi di tuti gli array è necessario definire l’azione di aggiornamento.

1 indexArr.do({ arg index ;

2 var iknob, ired, igreen, iblue, itotal ;

3 var rgb ;

4 var chosenValue ;

5 iknob = knobArr[index] ;

6 ired = screenArrRed[index] ;

7 igreen= screenArrGreen[index] ;

8 iblue = screenArrBlue[index] ;

9 itotal = screenArrRGB[index] ;

10 if ( knob.value < 0.5,

11 { chosenValue = knob.value ;

12 },

14 { chosenValue = 1.0.rand ;

15 }

16 );

18 iknob.value = chosenValue ;

19 rgb = colorFunction.value(chosenValue) ;

20 ired.background = Color(rgb[0], 0, 0) ;

21 igreen.background = Color(0, rgb[1], 0) ;

22 iblue.background = Color(0, 0, rgb[2]) ;

23 itotal.background = Color(rgb[0], rgb[1], rgb[2]) ;

24 ("knob no. "+index.asString+": "+rgb.round(0.001)).postln;

26 });

In primo luogo qui va notato come index sia il nome di un argomento edunque non indichi più l’indice dell’elemento “esterno”: è una questio-ne di ambito di validità delle variabili. Il ciclo è definito per ogni indexin indexArray. Le righe 5-9 attribuiscono a variabili gli elementi numero

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 93/328

4.12–90

index degli array di manopole e riquadri: in sostanza viene elaborato ilgruppo (la “fila”) index. Il condizionale valuta il valore della manopolaattiva knob , il cui valore, essendo definito fuori del ciclo, è accessibiledentro il ciclo. Se knob.value è inferiore a 0.5 , allora il valore prescel-to (chosenValue) è quello di knob , altrimenti è un valore scelto a casonell’intervallo [0, 1]. Il valore prescelto viene attribuito alla manopolaindex passato a colorFunction: i valori rgb così ottenuti permettono didefinire la proprietà backgrounddei riquadri index Infine, di nuovo unastampa su schermo dei dati calcolati (26).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 94/328

4.12–91

1 (

3 /* The useless GUI:

4 demonstrating some

5 syntax stuff

6 – first part –

7 */

9 var colorFunction ;

10 var window, step = 50, n = 4 ;

11 var knobArr, screenArrRed, screenArrGreen, screenArrBlue, screenArrRGB;

13 colorFunction = { arg val ;

14 var red, green, blue ;

15 val = val.max(0).min(1) ;

16 red = val ;

17 green = (val*0.7)+0.3 ;

18 blue = 1.0-(val*0.7) ;

19 [red, green, blue]} ;

21 window = GUI.window.new("Some knobs", Rect(300,300, step*8, step*n)) ;

23 screenArrRed = Array.fill(n, { arg i ;

24 GUI.compositeView.new(window,Rect(step*4, step*i, step,step));

25 }) ;

27 screenArrGreen = Array.fill(n, { arg i ;

28 GUI.compositeView.new(window,Rect(step*5, step*i, step, step));

29 }) ;

31 screenArrBlue = Array.fill(n, { arg i ;

32 GUI.compositeView.new(window,Rect(step*6, step*i, step, step));

33 }) ;

35 screenArrRGB = Array.fill(n, { arg i ;

36 GUI.compositeView.new(window,Rect(step*7,step*i, step,step));

37 }) ;

39 knobArr = Array.fill(n, { arg i ;

40 GUI.knob.new(window, Rect(rrand(0,step*3), step*i, step,step)) ;

41 }) ;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 95/328

4.12–92

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 96/328

4.12–93

1 /* The useless GUI: – continue –*/

3 knobArr.do( { arg knob, index;

4 knob.value = 0.5 ;

5 knob.action_({ arg k;

6 var indexArr ;

7 var rgb, red, blue, green ;

8 rgb = colorFunction.value(k.value) ;

9 red = rgb[0] ;

10 green = rgb[1] ;

11 blue = rgb[2] ;12 screenArrRed[index].background = Color(red,0,0) ;

13 screenArrGreen[index].background = Color(0,green,0) ;

14 screenArrBlue[index].background = Color(0,0,blue) ;

15 screenArrRGB[index].background = Color(red,green,blue) ;

16 ("operating on knob: "+index +" with: "+rgb.round(0.001)

).postln ;

17 indexArr = Array.series(n) ;

18 indexArr.removeAt(index) ;

19 indexArr.do({ arg index ;

20 var iknob, ired, igreen, iblue, itotal ;21 var rgb ;

22 var chosenValue ;

23 iknob = knobArr[index] ;

24 ired = screenArrRed[index] ;

25 igreen= screenArrGreen[index] ;

26 iblue = screenArrBlue[index] ;

27 itotal = screenArrRGB[index] ;

28 if ( knob.value < 0.5,

29 { chosenValue = knob.value ;

30 },31 { chosenValue = 1.0.rand ;

32 }

33 );

34 iknob.value = chosenValue ;

35 rgb = colorFunction.value(chosenValue) ;

36 ired.background = Color(rgb[0], 0, 0) ;

37 igreen.background = Color(0, rgb[1], 0) ;

38 iblue.background = Color(0, 0, rgb[2]) ;

39 itotal.background = Color(rgb[0], rgb[1], rgb[2])

; ("knob no. "+index.asString+": "+rgb.round(0.001)).postln;40 });

41 }) ;

42 }) ;

43 window.front ;

44 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 97/328

4.12–94

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 98/328

95

5 Sintesi,I:fondamenti

Un suono è una variazione continua della pressione atmosferica perce-pibile dall’orecchio umano. In quanto vibrazione, dipende dall’eccitazionedi corpi del mondo fisico (una chitarra suonata con un plettro, una tendaagitata dal vento, un tavolo battuto con le nocche). Un suono può esse-re registrato in forma di segnale analogico -cioè rappresentato in formacontinua- o digitale -in forma numerica. Si osservino le due figure dedi-cate alla catena dell’audio analogico e digitale (Figura 5.1).

Onda di

pressione

Elaborazione

analogica

Supporto

Microfono

Onda di

pressione

Altoparlante

Elaborazione

analogica

Scrittura

Lettura

trasduzione

elettroacustica

trasduzione

elettroacustica

Master

es. disco

vinile

es. piatto

Onda di

pressione

Elaborazione

analogica

Microfono

Onda di

pressione

Altoparlante

Elaborazione

analogica

Conversione

Conversione

trasduzione

elettroacustica

trasduzione

elettroacustica

es. hard

disk

DAC

ADC

DIGITALE

Supporto

Fig. 5.1 Catena dell’audio: analogico e digitale

Nel caso dell’audio digitale, il segnale, appunto “digitalizzato”, è dispo-nibile sotto forma di informazione numerica, e dunque può essere riela-

 borato attraverso un calcolatore: si possono cioè fare calcoli a partire dai

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 99/328

5.1–96

numeri che rappresentano il segnale. I passi principali della registrazio-ne digitale sono i seguenti:

1. conversione anologico-digitale: il segnale analogico viene filtratoe convertito dal dominio analogico (in quanto variazione continuadella tensione elettrica, ad esempio prodotta da un microfono) nelformato numerico attraverso l’ADC;

2. elaborazione: il segnale digitalizzato, che ha assunto la forma di una

sequenza di numeri, può essere modificato;

3. conversione digitale-analogica: per essere ascoltabile, la sequenzanumerica che compone il segnale viene riconvertita in segnale ana-logico attraverso il DAC: effettuato il filtraggio, si origina di nuovouna variazione continua della tensione elettrica che può, ad esempio,mettere in azione un altoparlante.

L’assunto di partenza della computer music è che il calcolatore possaessere impiegato per sintetizzare direttamente il suono. Il cuore dellasintesi digitale sta nell’escludere il passaggio 1, generando direttamen-te la sequenza numerica che poi verrà convertita in segnale analogico.Questo non esclude affatto la possibilità di lavorare con campionamentiprovenienti da fonti “esterne”, ma sottolinea piuttosto come l’aspettofondamentale risieda nei metodi e nelle procedure di calcolo che pre-siedono alla sintesi. Se dunque è sempre possibile per il compositore

“digitale” lavorare sulla componente analogica (ad esempio registrandoed elaborando analogicamente il segnale), la componente più caratteriz-zante della sua prassi sta nello sfruttare la natura numerica (e dunque“calcolabile”) del segnale digitale (Figura 5.2.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 100/328

5.1–97

Onda di

pressione

Elaborazione

analogica

Supporto

Microfono

Scrittura

trasduzione

elettroacustica

Master

es. disco

vinile

Onda di

pressione

Elaborazione

analogica

Microfono

Conversione

trasduzione

elettroacusticaes. hard

disk

ADC

DIGITALE

Supporto

Fig. 5.2 Composizione analogica e digitale: ambiti

5.1 Pochecentinaiadiparoled’acustica

Un segnale è una rappresentazione di un andamento temporale. Poi-ché rappresenta una sequenza di compressioni/rarefazioni della pres-sione atmosferica, un segnale audio assume la forma di una oscillazionetra valori positivi e valori negativi. Se quest’oscillazione è regolare neltempo, il segnale è periodico, altrimenti è aperiodico: la maggior partedei suoni si colloca in punto tra i due estremi, è cioè più o meno pe-riodica/aperiodica. Il segnale periodico più elementare è la sinusoide,corrispondente al suono di un diapason. Come si vede in Figura 5.3 , col-legando un pennino alla lamella del diapason se ne registra l’escursioneed il tracciato che ne consegue è appunto una sinusoide.La periodicità indica che il segnale si ripete nel tempo: la frequenza di unsegnale è il numero delle ripetizioni nell’unità di tempo mentre la du-rata di un ciclo è il periodo. L’escursione tra il massimo positivo e quello

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 101/328

5.1–98

Fig. 5.3 Vibrazione di un diapason e sinusoide

negativo è l’ampiezza del segnale. Le frequenze udibili sono (approssi-

mativamente) comprese tra i 16 e i 25.000Hz (Hz -Herz- indica numerodei cicli al secondo, anche cps). Il teorema di Fourier stabilisce che ognisegnale periodico può essere rappresentato come una somma di sinu-soidi di diversa ampiezza: come se un numero (teoricamente infinito)di sinuosoidi di diverso volume suonassere tutte insieme. Se si rappre-senta un segnale non nel tempo ma in frequenza si ottiene il suo spettro:a partire dal teorema di Fourier, si può osservare come lo spettro di ognisegnale complesso (non sinusoidale) sia costituito di molte componentidi frequenza diversa. In un segnale periodico queste componenti (det-te “armoniche”) sono multipli interi della frequenza fondamentale (chene è il massimo comun denominatore). Segnali di questo tipo sono adesempio l’onda a dente di segna, l’onda quadra, l’onda triangolare, ed ingenerale la fase stazionaria di tutti i segnali ad altezza musicale riconon-scibile (“intonabile”). In un segnale aperiodico le componenti possonoessere distribuite in frequenza in maniera arbitraria. Quando si parla(molto vagamente) di rumore spesso (ma non sempre) si indicano se-gnali aperiodici. Un segnale digitale è una rappresentazione numericadi un segnale analogico ed è doppiamente discreto: rappresenta cioè va-riazioni d’ampiezza discrete (quantizzazione) in istanti discreti di tempo( frequenza , o meglio tasso di campionamento). Può essere cioè pensatocome una griglia che viene sovrapposta ad un segnale analogico (Figure5.4 e5.5).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 102/328

5.1–99

Time (s)0 0.00625

 –1

1

0

0Time (s)

0 0.00625 –1

1

0

Time (s)0 0.00625

 –1

1

0

Time (s)0 0.00625

 –1

1

0

segnale analogico campionamento

quantizzazione campionamento + quantizzazione

Fig. 5.4 Digitalizzazione del segnale. Forma d’onda,campionamento, quantizzazione, campionamento equantizzazione.

Sebbene rappresentato nei software tipicamente come un curva conti-nua, il segnale digitale è dunque una sequenza ordinata di impulsi (si

vedano diverse rappresentazioni possibili in Figura 5.5).

−1

−0.5

0

0.5

1

0 20 40 60 80 100

−1

−0.5

0

0.5

1

0 20 40 60 80 100

−1

−0.5

0

0.5

1

0 20 40 60 80 100

Fig. 5.5 Segnale digitale: rappresentazioni.

Un segnale è descrivibile, nel caso discreto, attraverso una funzione ma-tematica

y = f [x]la funzione indica che per ogni istante discreto di tempo x il segnale hail valore d’ampiezza y. Un segnale digitale è una sequenza di casellex0, x1, x2, . . . a cui corrispondono valori d’ampiezza y0, y1, y2, . . ..

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 103/328

5.2–100

La struttura dati che rappresenta un segnale è allora tipicamente un ar-ray, una sequenza di celle di memoria consecutive e omogenee, conte-nenti cioè lo stesso tipo di dati (il tipo numerico prescelto per il segnalein questione). Così ad esempio un array come

[0, 0.5, 0, -0.25, 0, 0.1, -0.77, 0.35]

descrive un segnale composto da 8 campioni (Figura 5.6), dove l’indice(il numero d’ordine che etichetta progressivamente ognuno degli ottovalori) rappresenta x inteso come istante di tempo, mentre il dato nu-merico associato rappresenta y , inteso come il valore d’ampiezza delsegnale nell’istante x:

x = 0 → y = 0x = 1 → y =0.5. . .

x = 7 → y =0.35

−1

−0.5

0

0.5

1

0 2 4 6 8

Fig. 5.6 [0, 0.5, 0, -0.25, 0, 0.1, -0.77, 0.35]

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 104/328

5.2–101

5.2 Algoritmidisintesi

Un algoritmo per la sintesi del suono è una procedura formalizzata cheha come scopo la generazione della rappresentazione numerica di unsegnale audio.

Il linguaggio SC (sclang) permette di sperimentare algoritmi di sintesidel segnale in tempo differito senza scomodare -per ora- il server au-dio (scsynth). Ad esempio, la classe Array risponde al messaggio plot

generando una finestra e disegnandovi la curva spezzata ottenuta con-giungendo i valori contenuti nell’array. Il metodo plot è implementatonon solo nella classe Array ma in altre, ed è estremamente utile per ca-pire il comportamento dei segnali su cui si sta lavorando. Il codice

[0, 0.5, 0, -0.25, 0, 0.1, -0.77, 0.35].plot("an array")

genera l’elemento grafico 5.7.

Fig. 5.7 [0, 0.5, 0, -0.25, 0, 0.1, -0.77, 0.35]

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 105/328

5.2–102

Poiché il segnale audio previsto per i CD audio è campionato a 44.100Hz (attualmente lo standard audio più diffuso), se si vuole generare unsegnale mono della durata di 1 secondo a qualità CD, è necessario co-struire un array di 44.100 posti: il processo di sintesi del segnale con-siste allora nel definire ed implementare un algoritmo che permetta di“riempire” ognuno di questi posti (letteralmente numerati) con un va-lore. Così, se si vuole generare un segnale sinusoidale puro, il metodopiù semplice consiste nel calcolare l’ampiezza y per ogni campione xdel segnale in accordo con la funzione del seno e nell’associare il valorey all’indice x dell’array A , che rappresenta S . Una funzione periodicasi definisce come segue:

y = f (2π × x)

Un segnale sinusoidale è descritto dalla formula:

y = a × sin(2π × k × x)

L’effetto dei parametri a e k è rappresentato in Figura 5.8 , dove è di-segnato (in forma continua) un segnale (discreto) composto da 1000campioni.L’algoritmo di sintesi per un segnale sinusoidale, scritto in pseudo-codice(ovvero in un linguaggio inesistente ma essenziale), è dunque il seguen-te:

1 Per ogni x in A:2 y = a*sin(k*x)

3 A[x] = y

dove la riga 1 del ciclo calcola il valore y in funzione di due parametri a ek che controllano l’ampiezza e la frequenza della sinusoide, mentre la se-conda riga assegna all’indice x di A il valore y. SC permette agevolmentedi implementare un simile algoritmo. Una classe utile a tal fine è Signal ,

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 106/328

5.2–103

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

a = 1, k = 1/1000 a = 1, k = 2/1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

a = 0.5, k = 1/1000 a = 0.5, k = 2/1000Fig. 5.8 Sinusoide e variazione dei parametri a e k.

che è una sottoclasse di ArrayedCollection (la superclasse più generaledegli oggetti array-like) specializzata per la generazione di segnali. Nelcodice, la riga 3 assegna a sig un array Signal di 44100 celle, ovvero unsecondo di segnale audio mono a qualità CD. Le righe 4-7 sono occupa-te da un ciclo: sig.size restituisce la dimensione dell’array (44100). Persig.size (44100) volte viene valutata la funzione nel ciclo do: poiché x

rappresenta l’incremento lungo l’array (che rappresenta il tempo, ovve-ro 0, 1, 2 . . . 44098, 44099), è in funzione di x che viene calcolato ilvalore della funzione (f [x]). Il valore della frequenza del segnale desi-derato indica il numero di cicli (2π) al secondo: se la frequenza deside-rata è 440 Hz (→ cicli al secondo) allora ci devono essere 440×2π cicliogni secondo (2*pi*freq ). Questo valore deve essere calcolato per tutti i

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 107/328

5.2–104

posti dell’array (x/44100). Ottenuto il valore val , questo sarà compreso(per definizione trigonometrica) nell’escursione [−1, 1] e dunque puòessere scalato per amp. La riga 6 assegna al posto x di sig il valore val. Sinoti che per sicurezza in SC è sempre meglio, quando si usano gli array,riassegnare alla variabile che contiene l’array: sig = sig.put(x, val)indica che sig è uguale a se stesso, ma con il posto x occupato da val. Ilsegnale viene quindi disegnato nell’escursione d’ampiezza [−1, 1] (8).Infine, è possibile invocare il metodo play su un oggetto Signal: SC svol-ge tutte le operazioni necessarie per poter ascoltare il segnale (il “come”lo si vedrà poi): l’argomento true specifica che l’esecuzione avviene inloop.

1 (

2 var sig, amp = 0.75, freq = 440, val ;

3 sig = Signal.newClear(44100) ;

4 sig.size.do({ arg x ;

5 val = amp*sin(2*pi*freq*(x/44100)) ;

6 sig = sig.put(x, val) ;7 }) ;

8 sig.plot(minval:-1, maxval:1]) ;

10 sig.play(true) ;

12 )

14 (

15 var sig, amp = 0.75, freq = 440 ;

16 sig = Signal.newClear(44100) ;17 sig.waveFill({ arg x ; amp*sin(x) }, 0, 2pi*freq) ;

19 sig.plot(minval:-1, maxval:1]) ;

21 sig.play(true)

22 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 108/328

5.2–105

La classe Signal prevede molte possibilità di elaborazione. Ad esempiol’algoritmo precedente è in realtà più agevolmente implementabile uti-lizzando il metodo waveFill che permette di riempire il segnale con ilrisultato di una funzione ({ arg x ; amp*sin(x) }) che viene calcolatotra 0 e 2pi*440. In altre parole, la funzione viene calcolata per 440 volte(440 cicli, 2π) a partire dall’indice 0. Si noti come nel caso di costantidefinite in SC il segno di moltiplicazione possa essere omesso: si puòscrivere 2pi invece che 2*pi.

1 (

2 var sig, amp = 0.75, freq = 440 ;

3 var soundFile ;

5 sig = Signal.newClear(44100) ;

6 sig.waveFill({ arg x, i; amp*sin(x) }, 0, 2pi*440) ; // 1 cycle for

440 times

8 soundFile = SoundFile.new ;9 soundFile.headerFormat_("AIFF").sampleFormat_("int16").numChannels_(1)

;

10 soundFile.openWrite("sounds/signalTest.aiff") ;

11 soundFile.writeData(sig) ;

12 soundFile.close ;

13 )

Il segnale ottenuto può essere salvato su hard disk: Signalpuò così esse-re utilizzato per generare materiali audio utilizzabili in seguito. Sempredal lato client (in sclang) è disponible la classe SoundFile , che crea unfile audio (8), di cui sono specificabili le proprietà (9): il tipo ("AIFF"), la

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 109/328

5.2–106

quantizzazione (16 bit, "int16"), il numero di canali (mono, 1)18. È im-portante specificare la quantizzazione perché SCinternamente (e per de-fault) lavora a 32 bit: un formato utile per la precisione interna ma piutto-sto scomodo come formato di rilascio finale. Dopo aver create l’oggettoti tipo file è necessario specificare il percorso del file richiesto (10). Aquesto punto si possono scrivere sul file i dati contenuti nell’array sig

(11). Ad operazioni concluse, il file deve essere chiuso (12).Anche nel caso in cui la funzione sia diversa, si tratta di una proceduradi estrema semplicità concettuale. Ad esempio, è possibile generare altrisegnali periodici già ricordati. Per definizione, un onda a dente di segaè un segnale periodico che ha infinite armoniche di frequenza f  × n ,dove f è la frequenza fondamentale e n = 2, 3, 4, . . . , e di ampiezza ri-spettivamente pari a 1/2, 3, 4 . . . (ovvero inversamente proporzionaleal numero di armonica). Il metodo sineFill di Signal permette agevol-mente di osservare questo comportamento. I suoi argomenti sono

1. la dimensione

2. un array che specifica una serie di ampiezze3. un array che specifica una serie di fasi

Ampiezze e fasi sono riferite alle armoniche del segnale sinusoidale. Adesempio, un array d’ampiezze [0.4, 0.5, 0, 0.1] indica che verrannocalcolate le prime 4 armoniche, dove f 2 avrà ampiezza 0.4 , f 3 0.5 e cosìvia. Si noti che per eliminare una componente armoniche è sufficientepassare un valore d’ampiezza 0 (è il caso di f 4. Il file di help propone il

codice:

Signal.sineFill(1000, 1.0/[1,2,3,4,5,6])

Il codice genera un array di 1000 punti e lo riempie con una sinusoide econ le sue prime 5 armoniche, come si vede in Figura 5.9.

Si noti il concatenamento dei messaggi: ognuno dei metodi restituisce infatti l’oggetto18

stesso.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 110/328

5.2–107

1

−0.5

0

0.5

1

0 200 400 600 800 1000

Fig. 5.9 Prime sei armoniche dispari.

La sintassi 1.0/[1,2,3,4,5,6] è interessante. Se la si valuta, la Post Win-dow restituisce:

1 1.0/[1,2,3,4,5,6]

2 [ 1, 0.5, 0.33333333333333, 0.25, 0.2, 0.16666666666667 ]

Cioè: un numero diviso un array restituisce un array in cui ogni ognielemento è pari al numero diviso all’elemento di partenza. In altre pa-role è come scrivere [1.0/1, 1.0/2, 1.0/3, 1.0/4, 1.0/5, 1.0/6].L’array contiene dunque una serie di 6 ampiezze inversamente propor-zionali al numero di armonica. Il segnale risultante approssima infattiun’onda a dente di sega19 (Il contributo delle 6 armoniche è visibile nel

numero delle “gobbe” che il segnale presenta). Nell’esempio seguentel’approssimazione è decisamente migliore. Il metodo series , definitoper Array , crea un array ed ha come argomenti size -la dimensione-start e step: l’array è riempito da una serie di size interi successiviche, iniziando da start , proseguono incrementando di step. Dunque,

Qui non si considera la fase, ma il discorso è analogo.19

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 111/328

5.2–108

l’array contiene i valori 1, 2, 3, . . . 1000. Il segnale sig genera una si-nusoide e i suoi primi 999 armonici superiori con valore inversamenteproporzionale al numero d’armonica.

1 (

2 var sig, arr ;

3 arr = Array.series(size: 1000, start: 1, step: 1) ;

4 sig = Signal.sineFill(1024, 1.0/arr) ;

5 sig.plot ;

7 sig.play(true)

9 )

Un’onda quadra può essere generata nello stesso modo dell’onda a den-te sega, ma aggiungendo soltanto le armoniche dispari (n = 1, 3, 5 . . .).La stessa cosa: un’onda a dente di sega in cui le armoniche pari hannoampiezza nulla. Il codice è riportato nell’esempio seguente (anche Figu-ra 5.10 , a).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 112/328

5.2–109

1 (2 var sig, arr, arr1, arr2 ;

3 arr1 = Array.series(size: 500, start: 1, step: 2) ;

4 arr1 = 1.0/arr1 ;

5 arr2 = Array.fill(500, 0) ;

6 // arr2 = Array.fill(500, 0) ;

7 arr = [arr1, arr2].flop.flat ;

8 // arr = [arr1, arr2].lace(1000) ;

10 sig = Signal.sineFill(1024, arr) ;

11 sig.plot ;

13 sig.play(true)

15 )

Le ampiezze delle armoniche pari devono essere pari a 0, quelle dispa-ri inversamente proporzionali al loro numero d’ordine. L’array arr1 èl’array delle ampiezze delle armoniche dispari. Si noti che step: 2 , eche arr1 è già opportunamente scalato (4). L’array arr2 (5) è creato conil metodo fill che riempie un array della dimensione voluta (qui 500)valutando per ogni posto la funzione. Siccome è necessario un array co-stituito da zeri, la funzione deve semplicemente restituire 0. La riga 6crea il nuovo array arr , ed è più interessante, poiché fa uso dei metodiflop e flat. Si veda l’esempio dalla Post Window seguente:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 113/328

5.2–110

1 a = Array.fill(10, 0) ;

3 [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]

5 b = Array.fill(10, 1) ;

7 [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]

9 c = [a,b] ;

11 [ [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] ]

13 c = c.flop ;

15 [ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ], [ 0, 1 ], [ 0, 1 ], [ 0, 1 ], [ 0, 1

], [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ]

17 c = c.flat ;

19 [ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 ]

Dopo aver creato due array di 10 posti (1, 5), viene create un nuovo ar-ray c che contiene i due array a e b come elementi (9). Il metodo flop

(13) “interallaccia” coppie di elementi dai due array (si veda 15). Il me-todo flat “appiattisce” un array “eliminando tutte le parantesi”: si per-de la struttura in sotto-array degli elementi. Rispetto alla riga 9 il ri-sultato è un’alternanza di elementi da uno e dall’altro array (da a eda b). Nell’esempio relativo all’onda quadra il risultato della riga 6 èun’alternanza di elementi di arr1 e di zeri (provenienti da arr2). Co-me accade molto spesso, l’operazione è in realtà praticabile in SC piùsemplicemente attraverso un metodo dedicato, lace (7, commentata):lace(1000) restituisce un array di dimensione 1000 pescando alternati-vamente da arr1 e arr2. Il risultato è disegnato in Figura 5.10 , b.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 114/328

5.3–111

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

a b

Fig. 5.10 Onda a dente di sega e onda quadra.

5.3 Notasulmetodo play

Il metodo play offre la possibilità di ascoltare il contenuto dell’oggettoSignal (come ciò avvenga nel dettaglio lo si vedrà poi). Ci si può chie-dere a quale frequenza. In tempo reale SC per default genera un segnalecon un tasso di campionamento (sample rate, sr) pari a 44.100 campionial secondo. Il contenuto dell’array, dopo essere stato messo in un buf-fer (una locazione di memoria temporanea) viene letto alla frequenza di44.100 campioni al secondo. In altri termini, SC preleva un valore dal

 buffer ogni 1/44.100 secondi. Con il metodo play(true) l’esecuzioneè in loop: una volta arrivato alla fine, SC riprende da capo. Dunque, se

size è la dimensione in punti dell’array, il periodo del segnale (“quantodura” in secondi) è size/sr , e la frequenza è il suo inverso: 1/size/sr =sr/size. Se size = 1000 , allora f  = 44100/1000 = 44.1HzViceversa, se si intende ottenere un segnale la cui fondamentale sia f  ,la dimensione dell’array deve essere size = sr/f . È un calcolo sol-tanto approssimativo perché size deve essere necessariamente intero.Si consideri di nuovo l’esempio:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 115/328

5.4–112

1 (2 var sig, amp = 0.75, freq = 440 ;

3 sig = Signal.newClear(44100) ;

4 sig.waveFill({ arg x ; amp*sin(x) }, 0, 2pi*freq) ;

6 sig.plot(minval:-1, maxval: 1) ;

8 sig.play(true)

9 )

Se dimensione dell’array è 44.100 (come in molti esempi relativi a wa-

veFill) allora il segnale viene letto una volta al secondo. Poiché l’arraycontiene un numero freq di cicli, freq indica effettivamente la frequen-za del segnale.

5.4 Altrisegnaliealtrialgoritmi

Un’onda triangolare può essere generata per approssimazione in manie-ra analoga all’onda quadra (sempre attraverso componenti sinusoidalisuperiori di ampiezza opportuna). Un approccio diverso è invece di ti-po geometrico. Il periodo di un’onda triangolare può essere pensato co-

me costituito di quattro segmenti: il primo nell’intervallo [0.0, 1.0] , ilsecondo in quello [1.0, 0.0] , il terzo in quello [0.0, −1.0] e il quartoin quello [−1.0, 0]. Nell’esempio la variabile size rappresenta la di-mensione degli array che contengono i quattro segmenti, mentre step èl’incremento del valore di ampiezza (ogni segmento copre un’escursionedi 1 campionata nell’array). Il primo segmento è allora un array di tipoSignal riempito da un numero step di valori con incremento step: con-tiene valori da 0 a 1 − step (8). Il secondo segmento segue il percorso

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 116/328

5.4–113

contrario (il metodo reverse restituisce un array leggendo dall’ultimoal primo elemento l’array sui cui è chiamato). Prima, viene aggiunto unostep ad ognuno degli elementi dell’array: second contine valori da 1 a0+step. I segmenti successivi sono ottenuti generando due array third

e fourth che sottraggono 1 rispettivamente a second e first , cioè li ”tra-slano in basso” (10, 11). Infine l’array total è ottenuto concatenando iquattro segmenti. Si noti che le operazioni di addizione (come le altreoperazioni sugli array) restituiscono un array in cui ognuno degli ele-menti risulta dall’applicazione dell’operazione sul rispettivo elementodell’array di partenza. Ovvero:

1 [1, 2, 3, 4]*2

2 [ 2, 4, 6, 8 ]

1 (

2 // Segment-generated triangle wave

4 var first, second, third, fourth, total ;

5 var size = 50 , step;

7 step = 1.0/size ;

8 first = Signal.series(size, 0, step) ;

9 second = (first+step).reverse ;

10 third = second-1 ;

11 fourth = first-1 ;

12 total = (first++second++third++fourth) ;

14 total.plot

15 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 117/328

5.4–114

Il metodo di sintesi geometrico permette in effetti di ottenere risultatimigliori di una somma di sinusoidi che può soltanto ad approssima-re l’onda triangolare, poiché sarebbero necessarie infinite componenti,gli spigoli risultanti sono sempre un po’ “smussati” (Figura 5.11). Gliapprocci di questo tipo alla sintesi del segnale audio sono tipicamentechiamati “sintesi diretta”.

−1

−0.5

0

0.5

1

0 50 100 150 200

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

a b

Fig. 5.11 Onda a triangolare e somma dei primi 20 armonici con am-piezza pseudo-casuale.

Tornando alla sintesi attraverso componenti sinusoidali, nell’esempioseguente (disegnato in Figura 5.11 , b) la variabile harmonics contiene ilnumero degli elementi dell’array arr , cioè il numero delle armoniche. Inquesto caso, il valore d’ampiezza di ognuna delle componente è genera-to dalla funzione {1.0.rand} ed è un valore pseudo-casuale compreso

tra [0.0, 1.0] (tra assenza e massimo valore normalizzato). Se si ese-gue il codice più volte si noterà che il suono cambia, poiché l’apportodelle componenti dipende dalla funzione del metodo fill. Se si incre-menta o decrementa il valore di partials il segnale rispettivamente siarrichisce o si impoverisce di componenti elevate. La riga 7 permette divisualizzare l’array delle ampiezze come una spezzata che unisce i valo-ri discreti che lo compongono: con jplot2 si possono specificare i valori

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 118/328

5.4–115

d’escursione massimi e minimi ([0, 1]). Si tratta, come si vedrà, di unaforma di sintesi additiva.

1 (

2 var sig, arr, harmonics = 20 ;

4 arr = Array.fill(harmonics, {1.0.rand});

5 //arr = Array.fill(harmonics, 1.0.rand);

7 sig = Signal.sineFill(1024, arr) ;

9 arr.plot(minval:0, maxval:1) ;

10 sig.plot ;

12 sig.play(true)

14 )

Si noti la differenza tra le righe 4 e 5. La riga 5 crea un array riempiendolocon il valore calcolato (una volta sola) da 1.0.rand , mentre è necessarioche ad essere invocata sia una funzione: una funzione è un oggetto che,chiamato dal messaggio value (qui “nascosto”) risponde calcolando unvalore. Dunque, per ogni posto di harmonics viene chiamata la funzione{1.0.rand} che calcola un nuovo valore. Ovvero:

1 Array.fill(3, 1.0.rand)

3 [ 0.31042301654816, 0.31042301654816, 0.31042301654816 ]

5 Array.fill(3, {1.0.rand})

7 [ 0.92207717895508, 0.91672122478485, 0.79339396953583 ]

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 119/328

5.4–116

L’introduzione dei numeri pseudo-casuali permette di avvicinare anchei segnali non periodici. Un rumore bianco è un segnale il cui compor-tamento non è predicibile se non in termini statistici. Questo compor-tamento si traduce in una distribuzione uniforme dell’energia su tuttolo spettro del segnale. Un rumore bianco può essere descritto come unavariazione totalmente aperiodica nel tempo: in altre parole, il valore diogni campione è del tutto indipendente da quelli precedenti e da quel-li successivi20. Dunque, il valore di un campione x è indipendente dalvalore del campione precedente x

−1: x può avere qualsiasi valore,

sempre, evidentemente, all’interno dello spazio finito di rappresenta-zione dell’ampiezza. Intuibilmente, l’algoritmo di generazione è moltosemplice. In pseudo-codice:

1 Per ogni x in A:

2 y = a*rand(-1, 1)

3 A[x] = y

Nell’esempio seguente, il metodo fill (6) valuta per ogni campione x

una funzione che restituisce un valore casuale all’interno dell’escursionenormalizzata [−1, 1] (rrand(-1.0,1.0)). Il codice specifica una fre-quenza di campionamento (sr) e una durata in secondi (dur). Il risul-tato (5msec di rumore bianco) viene scalato per amp , e dunque, da-to un valore di 0.75 per amp , si otterrà un’oscillazione (pseudo-)casualenell’escursione [−0.75, 0.75]. Si noti come la funzione (nella definizio-

ne di partenza f [x]) in realtà sia calcolata indipendente da x: essendoaperiodica, il suo comportamento non dipende dal tempo.

Si dice perciò che ha autocorrelazione = 0.20

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 120/328

5.4–117

1 (2 /* 5 msec of white noise*/

4 var sig, amp = 0.75, dur = 0.005, sr = 44100 ;

6 sig = Signal.fill(dur*sr, { amp*rrand(-1.0,1.0) }) ;

7 sig.plot(minval:-1, maxval:1) ;

9 sig.play(true)

10 )

I software rappresentano tipicamente il segnale audio attraverso unacurva continua che connette i valori d’ampiezza. Nel caso del rumore,questa rappresentazione continua -di per sé non corretta rispetto allanatira digitale del segnale ma significativa da un punto di vista acustico-è decisamente meno icastica di una rappresentazione discreta (Figura

5.12).

−1

−0.5

0

0.5

1

0 50 100 150 200−

1

−0.5

0

0.5

1

0 50 100 150 200

Fig. 5.12 Rumore bianco: curva continua e dispersione dei valori

È un’ovvietà ma è bene ricordarsi che un segnale digitale è appuntosemplicemente una sequenza di valori, sulla quale è possibile svolge-re operazioni matematiche. Tutta l’elaborazione digitale del segnale na-sce da quest’assunto. I prossimi sono due esempi tratti da Puckette (?).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 121/328

5.4–118

La funzione seno oscilla periodicamente tra [−

1, 1]. Calcolando il suovalore assoluto si ribalta la parte negativa sul positivo: se si osserva lacurva si nota come i due emicicli siano identici: ne consegue un segnalecon frequenza doppia di quello di partenza. In generale l’applicazionedella funzione del valore assoluto è una tecnica rapida per far saltared’ottava un segnale. Poiché la curva occupa soltanto valori positivi (tra[0, 1]), è possibile traslarla in modo da evitare offset: decrementandodi 0.5 l’escursione del segnale diventa [−0.5, 0.5] ed è simmetrica trapositivi e negativi (Figura 5.13).

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

Fig. 5.13 y = abs(sin(2π × x)), y = abs(sin(2π × x)) − 0.5

Nel codice seguente il primo esempio utilizza il metodo waveFill e cal-cola il valore assoluto per ogni campione: è una tecnica potenzialmenteutilizzabile per il tempo reale. Tuttavia la classe Signal implementa mol-ti metodi matematici. Così, il metodo abs invocato su un oggetto Signal

restituisce un altro oggetto Signal in cui ogni elemento è il risultato del

valore assoluto dell’elemento del segnale di partenza (è come chiamareabs per ogni elemento). Lo stesso vale per la sottrazione -0.5 e per lamoltiplicazione *amp: si applicano a tutti gli elementi dell’array.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 122/328

5.4–119

1 /* Absolute value on a sine */

3 (

4 var sig, amp = 0.75 ;

6 sig = Signal.newClear(44100) ;

7 sig.waveFill({ arg x, i; (sin(x).abs - 0.5)*amp }, 0, 2pi) ;

9 sig.plot(minval:-1, maxval:1) ;

10 )

12 (

13 var sig, amp = 0.75 ;

15 sig = (Signal.sineFill(1024, [1]).abs-0.5)*amp ;

17 sig.plot(minval:-1, maxval: 1) ;

19 )

Nella funzione risultante dall’appplicazione del valore assoluto la pre-senza di uno spigolo molto acuto introduce però molte componenti su-periori. L’utilizzo dell’elevamento al quadrato evita questo problemaottenendo un risultato analogo: infatti il quadrato dei valori negatividel segnale è positivo, e si ottiene un ribaltamento della curva analogoa quanto avviene con il valore assoluto (Figura 5.14.

Anche in questo caso viene indicata nel codice una doppia versione.Nella seconda viene utilizzato al posto di pow(2) il metodo (del tuttoanalogo) squared.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 123/328

5.4–120

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

Fig. 5.14 y = sin(2π

×x)2

, y = sin(2π

×x)2

−0.5

1 /* Squaring the sine */

3 (

4 var sig, amp = 0.75 ;

6 sig = Signal.newClear(1024) ;

7 sig.waveFill({ arg x, i; (sin(x).pow(2)-0.5)*amp }, 0, 2pi) ;

9 sig.jplot2(range:[-1,1]) ;10 )

12 (

13 var sig, amp = 0.75 ;

15 sig = (Signal.sineFill(1024, [1]).squared-0.5)*amp ;

17 sig.plot(minval:-1, maxval: 1) ;

18 )

Come ulteriore esempio di elaborazione del segnale si può considerarel’operazione di “clippping”: in caso di clipping tutti i valori superiori aduna certa soglia s (o inferiori al negativo della stessa) vengono riporta-ti a ±s. Il clipping prende anche il nome di distorsione digitale perché

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 124/328

5.4–121

è quanto avviene quando il segnale digitalizzato ha un’ampiezza su-periore a quella rappresentabile dalla quantizzazione. Il clipping è unasorta di limiter (limita infatti l’ampiezza del segnale) radicale e può es-sere usato come “effetto” di tipo distorcente. In SC è definito il metodoclip2(t) che “taglia” un valore fuori dell’escursione [−t, t] a ±t. Siconsideri l’esempio seguente in cui t =3.

1 1.clip2(3)

3 1

5 -1.clip2(3)

7 -1

9 4.clip2(3)

11 3

12 -4.clip2(3)

14 -3

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 125/328

5.4–122

1 (2 var sig, sig2, sig3, clipFunc ;

4 sig = Signal.sineFill(512, [1]) ;

6 clipFunc = { arg signal, threshold = 0.5 ;

7 var clipSig = Signal.newClear(signal.size) ;

8 signal.do({ arg item, index;

9 var val ;

10 val = if (item.abs < threshold, { item.abs },

11 { threshold}) ;12 val = val*item.sign ;

13 clipSig.put(index, val) ;

14 }) ;

15 clipSig ;

16 } ;

18 sig2 = clipFunc.value( sig ) ;

19 sig3 = clipFunc.value( sig, threshold: 0.75 ) ;

21 //[sig, sig2, sig3].flop.flat.plot(minval:-1, maxval: 1, numChannels:3);

23 sig.play(true) ;

24 //sig2.play(true) ;

25 //sig3.play(true) ;

27 )

Come esercizio può essere interessante implementare un modulo “clip-per”. Si è detto che una funzione esegue un comportamente quando rice-ve il messaggio value in funzione degli argomenti in entrata. Nell’esempioè appunto definita una funzione che implementa il clipping, clipFunc:gli argomenti in entrata prevedono un segnale (un oggetto Signal) eun valore di soglia (threshold). Ciò che clipFunc restituisce è un altro

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 126/328

5.4–123

oggetto Signal. La riga 6 dichiara la variabile a cui viene assegnato il se-gnale e gli assegna subito un oggetto Signal di dimensione pari a quelladel segnale in entrata, riempito di 0. L’idea è quella di valutare ognunodegli elementi (che rappresentano campioni audio) di signal: si trattacioè di ciclare su signal (8). Nel ciclo la variabile val rappresenta il va-lore che dovrà essere scritto nell’array clipSig. Il valore da assegnarea val dipende da una condizione. Se il campione valutato è all’internodell’escursione [−threshold, threshold] allora non ci sarà clipping:val ha lo stesso valore del valore di signal in entrata. Se invece il valorein entrata cade all’esterno dell’intervallo, allora in uscita si avrà il valo-re della soglia stessa. Il condizionale è contenuto nelle righe 10-11. Lavalutaione avviene sul valore assoluto di item (item.abs). Avviene cioènell’intervallo [0, 1]. In uscita si ha lo stesso valore assoluto di item op-pure threshold. Se il valore in entrata è negativo, verrebbe così resitutitoun valore positivo. Il segno del valore in entrata viene però recuperatocon la riga 12 in cui il valore val viene moltiplicato per il segno di item:infatti, item.sign restituisce

±1.

1 0.216.sign

3 1

5 -0.216.sign

6 -1

Se item = -0.4 si ha:

• item.abs = 0.4

• è inferiore a threshold = 0.5? Sì, allora val = item.abs =

0.4

• item.sign = -1 (item = -0.4: è negativo)

• val = 0.4 * -1 = -0.4

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 127/328

5.5–124

Seguono due esempi, uno che sfrutta il valore predefinito di threshold(0.5), l’altro in cui threshold vale 0.75. Il clipping tende a “squadrare”la forma d’onda ed in effetti il segnale risultante tende ad assomigliare-anche all’ascolto- ad un’onda quadra (Figura 5.15).

−1

−0.5

0

0.5

1

0 100 200 300 400 500

−1

−0.5

0

0.5

1

0 100 200 300 400 500

−1

−0.5

0

0.5

1

0 100 200 300 400 500

Fig. 5.15 Clipping: sinusoide,threshold = 0.5 , threshold = 0.75.

5.5 Funzionevaloreassolutoefunzionequadratica

L’approccio modulare dell’esempio precedente permette di riscrivere icasi relativi al valore assoluto e al quadrato. In particolare si possonoesplicitamente definire due funzioni di trasferimento:

W abs : f (x) = x2

W square : f (x) = |x|Queste funzioni si comportano come veri moduli di elaborazione delsegnale in entrata. Sono implementate in SC nell’esempio seguente. Nelcodice l’unica cosa di rilievo è l’eliminazione automatica dell’offset. Ilmetodo peak restituisce l’elemento di Signal che ha il valore assoluto piùalto (il massimo d’ampiezza del segnale). Assumendo che il segnale siasimmetrico rispetto allo 0 , ogni nuovo valore risultante dall’applicazionedella funzione viene traslato di peak/2. Se il segnale è compreso in

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 128/328

5.5–125

[−

0.7, 0.7] allora peak = 0.7: il segnale trasformato sarà compreso in

[0.0, 0.7] e viene traslato di 0.7/2 = 0.35 , così che la sua escursionein ampiezza risulti simmetricamente intorno allo 0 in [−0.35, 0.35].

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 129/328

5.6–126

1 (2 /* abs and quadratic functions */

4 var sig, sig2, sig3, absFunc, squareFunc ;

6 sig = Signal.sineFill(512, [1]);

8 absFunc = { arg signal ;

9 var absSig = Signal.newClear(signal.size) ;

10 var peak;

11 signal.do({ arg item, index;12 var val ;

13 val = item.abs ;

14 absSig.put(index, val) ;

15 }) ;

16 absSig - (absSig.peak*0.5) ;

17 } ;

19 squareFunc = { arg signal ;

20 var squareSig = Signal.newClear(signal.size) ;

21 var peak ;22 signal.do({ arg item, index;

23 var val ;

24 val = item.squared ;

25 squareSig.put(index, val) ;

26 }) ;

27 squareSig - (squareSig.peak*0.5) ;

28 } ;

30 sig2 = absFunc.value( sig ) ;

32 sig3 = squareFunc.value( sig ) ;

34 [sig, sig2, sig3].flop.flat.plot(minval:-1, maxval:1, numChannels:3) ;

36 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 130/328

5.6–127

5.6 Ancorasull’elaborazionedisegnali

La natura numerica del segnale permette di definire operazioni analo-ghe alle precedenti anche su materiale pre-esistente. La classe SoundFi-

le permette non soltanto di scrivere sui file ma anche di accedere a fi-le audio disponibili sull’hard-disk. Il codice seguente riempie l’oggettoSignal sig con il contenuto del file audio sFile attraverso il metodoreadData di sFile. Si noti come la dimensione di sig sia stata fatta di-pendere dal numero di campioni di sFile attraverso l’attributo numfra-

 mes.

1 (2 var sFile, sig ;

4 sFile = SoundFile.new;

5 sFile.openRead("sounds/a11wlk01-44_1.aiff");

6 sig = Signal.newClear(sFile.numFrames) ;

7 sFile.readData(sig) ;

8 sFile.close;

9 )

L’operazione seguente sfrutta la natura di sequenza numerica del se-gnale audio per implementare una sorta di granulazione. In sostanzail segnale audio importato viene suddiviso in un numero numChunks dipezzi, ognuno dei quali comprende un numero step di campioni. Quin-di i pezzi vengono mischiati a caso e rimontati. Nell’implementazione

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 131/328

5.6–128

indices è la sequenza degli indici dei pezzi del segnale ed è una progres-sione a partire da 0. Questa progressione lineare (1, 2, 3, 4 . . .) vienemescolata attraverso il metodo scramble (così da diventare ad esempio9, 1, 3, 7 . . .). Quindi, attraverso il ciclo su ognuno degli indici, vienerecuperato il pezzo corrispondente nel segnale originale e concatenatoin sequenza. È probabile che lo step non si un divisore intero del segna-le in ingresso. La parte che avanza (tail) viene concatenata alla fine delnuovo segnale newSig.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 132/328

5.6–129

1 ( /* Scrambling a signal */

3 var sFile, sig, newSig ;

4 var numChunks, step, rest, indices ;

5 var block, tail ;

7 var period = 441;

9 sFile = SoundFile.new;

10 sFile.openRead("sounds/a11wlk01-44_1.aiff");

11 sig = Signal.newClear(sFile.numFrames) ;12 sFile.readData(sig) ;

13 sFile.close;

15 /*

16 sig = Signal.newClear(44100) ;

17 sig = Signal.sineFill(period, [1]) ;

18 (44100/period).do(sig = sig.addAll(sig)) ;

19 */

21 step = 50 ; // try: 5, 10, 50, 50022 numChunks = (sig.size/step).asInt ;

24 tail = (sig.size-(step*numChunks)) ;

26 indices = Array.series(numChunks);

27 indices = indices.scramble;

29 newSig = Signal.new;

30 indices.do({arg item;

31 block = sig.copyRange(item*step, (item+1)*step-1) ;32 newSig = newSig.addAll(block) ;

34 }) ;

36 tail = sig.copyRange(sig.size-tail, sig.size) ;

37 newSig = newSig.addAll(tail) ;

39 newSig.play(true) ;

40 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 133/328

5.6–130

Questa forma di granulazione del segnale permette di introdurre infineuna forma di sintesi per permutazione. Attraverso lo “scrambling” delsegnal si produce un nuovo segnale che mantiene più o meno “in memo-ria” il segnale originale. Minore è lo steppiù grande è la ricombinazionedel segnale. Se un’operazione simile viene svolta su un segnale sinu-soidale si nota ancora più chiaramente la proporzione tra diminuzionedello step e incremento della rumorosità. Lo si può fare togliendo gliindicatori di commento nell’esempio precedente. In quel caso viene pro-dotta una sinusoide di frequenza pari a 1/period. Si noti che la sintesidella sinusoide è ottenuta concatenando cicli di durata pari a periods

(in campioni). In questo caso la dimensione del segnale è di 44.100 ele-menti: dunque se il periodo è441 , vuol dire che ci staranno 44100/441cicli dentro un secondo (assumendo la frequenza di campionamento pa-ri a 44.110): la frequenza del segnale sarà 44.100/441 = 100Hz.Nell’esempio seguente viene implementata una forma di sintesi per per-mutazione. Il processo è del tutto analogo a quanto avviene nell’esempioprecedente, con una differenza. Il segnale viene sempre suddiviso in

 blocchi di durata step. Al posto dell’operazione di scramble viene in-vece implementata una permutazione di questo tipo:

[ 0, 1, 2, 3, 4, 5 ] → [ 1, 0, 3, 2, 5, 4 ]Essendo la permutazione del tutto periodica si ottiene un segnale dallospettro molto ricco ma che presenta una periodicità che dipende sia dallafrequenza della sinusoide in entrata sia dalla dimensione dello step.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 134/328

5.6–131

1 (2 /* Distorsion via permutation on a sinusoid */

4 var sig, sig2, newSig ;

5 var numChunks, step, rest, indices ;

6 var block, tail ;

7 var period = 441;

9 sig = Signal.new ;

10 sig2 = Signal.sineFill(period, [1]) ;

11 (44100/period).do(sig = sig.addAll(sig2)) ;

13 step = 50 ; // try: 5, 50, 500

14 numChunks = (sig.size/step).asInt ;

15 tail = (sig.size-(step*numChunks)) ;

17 a = Array.series((numChunks/2).asInteger, 1,2) ;

18 b = Array.series((numChunks/2).asInteger, 0,2) ;

19 indices = [a,b].flop.flat ;

21 newSig = Signal.new;22 indices.do({ arg item;

23 block = sig.copyRange(item*step, (item+1)*step-1) ;

24 newSig = newSig.addAll(block) ;

25 }) ;

27 tail = sig.copyRange(sig.size-tail, sig.size) ;

28 newSig = newSig.addAll(tail) ;

30 newSig.play(true) ;

31 sig.plot ;32 newSig.plot

33 )

La periodicità diventa evidente, oltre all’orecchio, se si confronta il pri-mo ciclo della sinusoide, della sinusoide “scrambled” e della sinusoidedistorta per permutazione (Figura 5.16).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 135/328

5.7–132

−1

−0.5

0

0.

5

1

0 100 200 300 400

−1

−0.5

0

0.

5

1

0 100 200 300 400

−1

−0.5

0

0.

5

1

0 100 200 300 400

Fig. 5.16 Sinusoide con un periodo di 441 campioni, “scrambling” e“permutazione” con un periodo di 25 campioni.

5.7 Segnalidicontrollo

Un segnale sinusoidale, come tutti i segnali perfettamente periodici, man-ca totalmente delle caratteristiche di dinamicità usualmente ascritte adun suono “naturale” o, meglio, “acusticamente interessante”: è un suo-no, come direbbe Pierre Schaeffer, senza “forma” temporale, “omoge-

neo”. Suoni di questo tipo, peraltro, arredano il paesaggio sonoro dellamodernità meccanica ed elettrica sotto forma di humming, buzzing -e cosìvia- prodotti dai ventilatori, dall’impedenza elettrica, dai motori. A par-te questi casi, tipicamente la “forma” temporale di un suono prende laforma di un profilo dinamico, di una variazione della dinamica del suo-no che è descritta acusticamente sotto forma di una curva di inviluppo,le cui fasi prendono usualmente il nome di attacco/decadimento/sostegno/rilascio:da cui l’acronimo ADSR. Il modo più semplice di rappresentare un si-

mile inviluppo consiste nell’utilizzare una spezzata (Figura 5.17).A guardare l’inviluppo si osserva agevolmente come si tratti di altra cur-va, e cioè propriamente di un altro segnale, che si distingue dai segnalifinora considerati per due caratteristiche importanti:

1. non è periodico (si compone di un unico ciclo). Dunque, il perio-do del segnale d’inviluppo è pari alla durata del segnale audio: seil segnale dura 2 secondi (ovvero il periodo dell’inviluppo) allora

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 136/328

5.7–133

Time (s)0 4.23184

 –0.8233

0.8881

0

Time (s)0 0.588944

 –0.3398

0.3456

0

Fig. 5.17 Descrizione del profilo dinamico attraverso una spezzata (in-viluppo).

l’inviluppo ha una frequenza 1/2 = 0.5Hz. Si noti come la fre-quenza non rientri nel dominio udibile;

2. è unipolare: assumendo che il segnale audio sia nell’escursione nor-malizzata [−1, 1] (bipolarità), l’inviluppo è compreso in [0, 1] (uni-polarità).

Passando dall’analisi del segnale alla sua sintesi, si tratterà perciò di ri-produrre le proprietà dell’inviluppo (la sua “forma”) e di applicare que-sta forma al segnale audio.L’inviluppo è un tipico segnale di controllo: unsegnale che modifica -controlla- un segnale audio.Essendo un segnale, per rappresentare un inviluppo si può utilizzare unarray. Ad esempio, un tipico inviluppo ADSR potrebbe essere descrittodall’array di dieci punti di Figura 5.18.

Detto interattivamente:

[0, 0.9, 0.4, 0.4, 0.4, 0.4, 0.3, 0.2, 0.1, 0].plot

Per incrementare o decrementare l’ampiezza di un segnale si può (lo siè visto abbondantemente) moltiplicare il segnale per una costante: ognicampione viene moltiplicato per la costante. Ad esempio, se la costante

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 137/328

5.7–134

0

0.25

0.5

0.75

1

0 2 4 6 8 10

Fig. 5.18 [0, 0.9, 0.4, 0.4,

0.4, 0.4, 0.3, 0.2, 0.1, 0].

Amp = 0.5 , l’ampiezza del segnale viene ridotta della metà. Si po-trebbe pensare ad una simile costante nei termini di un segnale: comeun array, di dimensione pari a quella del segnale scalato, che contengasempre lo stesso valore. Ogni valore dell’array da scalare viene moltipli-cato per il rispettivo valore dell’array Amp. L’idea smette di essere unacomplicazione inutile nel momento in cui l’array Amp non contiene

più sempre lo stesso valore, ma contiene invece valori variabili che rap-presentano appunto un inviluppo d’ampiezza. Dunque, ogni campionedel segnale audio (ogni elemento dell’array) viene moltiplicato per unvalore incrementale del segnale d’inviluppo ottenuto. La situazione èrappresentata in Figura 5.19.Dovendo descrivere lo sviluppo del segnale audio in tutta la sua durata,la dimensione dell’array d’inviluppo deve essere la stessa del segnaleaudio. Emerge qui un punto fondamentale, su cui si ritornerà: tipica-

mente è sufficiente un numero molto minore di punti per rappresentareun inviluppo rispetto ad un segnale audio, ovvero -assumendo che ilsegnale audio duri un solo secondo a qualità CD- il rapporto tra i due èpari a 10/44.100. Questo è in effetti il tratto pertinente che identificaun segnale di controllo.Passando all’implementazione in SC, per intanto si può generare una

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 138/328

5.7–135

0

0.25

0.5

0.75

1

0 2 4 6 8 10

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

Fig. 5.19 Inviluppo, segnale audio risultante, segnale audio, segnale au-

dio inviluppato.sinusoide di durata pari ad un secondo attraverso il solito metodo wa-

veFill. La frequenza prescelta è molto grave perché così sono meglio vi-sibili i cicli del segnale. L’array di partenza è composto da dieci segmen-ti: poiché questi devono essere ripartiti sulla durata del segnale audio,ognuno dei segmenti comprenderà 44100/10 campioni. Questo valo-re è assegnato alla variabile step. Si tratta ora di generare gli array checostituiscono i quattro segmenti ADSR (gli array att, dec, sus, rel),per poi concatenarli in un array complessivo env. Poiché devono esseremoltiplicati per un oggetto Signal allora devono anch’essi essere oggettiSignal. Il metodo series(size, start, step) crea una progressione li-neare di size valori a partire da start con incremento step. L’attaccoparte da 0 e arriva a 0.9 , occupa un segmento, cioè 4410 campioni.Il valore 0.9 deve cioè essere raggiunto in 4410 punti: l’incremento diognuno sarà perciò di 0.9/4410. Dunque, 0.9/step. All’ultimo punto

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 139/328

5.7–136

si avrà un valore pari a 0.9/step×

step = 0.9. Nel caso di dec si trat-ta di scendere a 0.5 nella durata di un altro segmento. In questo caso laprogressione parte da 0.9 e l’incremento è negativo: bisogna scenderedi 0.5 in uno step, dunque l’incremento è −0.5/step. Nel terzo caso(sus) il valore è costante a 0.4 per una durata di 4 passi, dunque si puòpensare ad un incremento 0. Il caso di rel è analogo a quello di dec. Ilnuovo segnale di inviluppo env è ottenuto concatenando i quattro seg-menti ed è impiegato come moltiplicatore di sig per ottenere il segnaleinviluppato envSig.

1 /* inviluppi, I */

3 (

4 var sig, freq = 440, size = 44100, step ;

5 var env, att, dec, sus, rel, envSig ;

7 step = 44100/10 ;

8 sig = Signal.newClear(size) ;

9 sig.waveFill({ arg x, i; sin(x) }, 0, 2pi*50) ;

11 att = Signal.series(step, 0, 0.9/step) ;

12 dec = Signal.series(step, 0.9, -0.5/step) ;

13 sus = Signal.series(step*4, 0.4, 0) ;

14 rel = Signal.series(step*4, 0.4, -0.4/(step*4)) ;

16 env = att++dec++sus++rel ;

17 envSig = sig * env ;

19 [sig, env, envSig].flop.flat.plot(minval:-1, maxval: 1], numChannels:

3) ;

20 envSig.play(true)

21 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 140/328

5.7–137

Il metodo precedente è piuttosto laborioso. SC prevede una classe Env

specializzata nel costruire inviluppi. Env assume che un inviluppo siauna spezzata che connette valori d’ampiezza nel tempo e fornisce di-verse modalità di interpolazione per i valori intermedi. Si considerino idue array seguenti v e d:

1 v = [0, 1, 0.3, 0.8, 0] ;

2 d = [ 2, 3, 1, 4 ] ;

Una coppia simile è tipicamente utilizzata per specificare un inviluppo:

• v: indica i punti che compongono la spezzata (i picchi e le valli);

• d: indica la durata di ogni segmento che connette due punti.

Dunque, l’array delle durate contiene sempre un valore di durata in me-no di quello delle ampiezze. Infatti, t[0] (= 2) indica che per andare da

v[0] (= 0) a v[1] (= 1) sono necessari 2 unità di tempo (in SC: secondi).Attraverso i due array v, d è così possibile descrivere un profilo (v)temporale (d). Nell’esempio, resta tuttavia da specificare cosa succedeper ogni campione compreso nei due secondi che intercorrono tra 0 e1. Il modo in cui i campioni sono calcolati dipende dalla modalità dininterpolazione. Nell’esempio seguente e1, e2, e3 sono oggetti Env spe-cificati dalla stessa coppia di array v, d , ma con differenti modalità diinterpolazione (lineare, discreta, esponenziale).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 141/328

5.7–138

1 (2 /* Using Env*/

4 var v, d, e1, e2, e3 ;

6 v = [0, 1, 0.3, 0.8, 0] ;

7 d = [ 2, 3, 1, 4 ] ;

9 e1 = Env.new(v, d,'linear').asSignal ;

10 e2 = Env.new(v, d,'step').asSignal ;

12 v = [0.0001, 1, 0.3, 0.8, 0] ;

13 e3 = Env.new(v, d,'exponential').asSignal ;

15 [e1, e2, e3].flop.flat.plot(numChannels:3) ;

16 )

Si noti che nel caso di un inviluppo esponenziale il valore di partenzanon può essere pari a 0: il primo valore di v viene quindi ridefinito conun valore prossimo allo zero. Il significato dei parametri è illustrato nellaFigura 5.20 che commenta quanto disegnato dal metodo plot.La classe Env eredita direttamente da Object e dunque non è un oggettodi tipo array. Tipicamente vine utilizzata come specificazione di invi-luppo per il tempo reale (come si vedrà). Quando però un oggetto Env

riceve il messaggio asSignal Env restituisce un oggetto Signal che con-

tiene un inviluppo campionato nel numero di punti che compongono ilnuovo array. La classe Env permette allora di utilizzare anche in tempodifferito una specificazione per gli inviluppi decisamente più comoda.Inoltre, la classe prevede alcuni costruttori che restituiscono inviluppiparticolarmente utili. Ad esempio:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 142/328

5.7–139

0

0.5

1

0 200 400 600 800 1000

0

0.5

0 200 400 600 800 1000

0

0.5

0 200 400 600 800 1000

0.0 1.0 0.3 0.8 0.0v:

2 3 1 4d:

'linear'

'step'

'exponential'

Fig. 5.20 Env: parametri.

•triangle richiede due argomenti: il primo indica la durata, il secon-

do il valore di picco di un inviluppo triangolare (il picco cade cioè ametà della durata).

• perc: permette di definire un inviluppo percussivo (attacco + rila-scio). Gli argomenti sono tempo d’attacco, tempo di rilascio, valoredi picco e valore di curvatura.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 143/328

5.7–140

1 /* inviluppi, I */

3 (

4 var sig, freq = 440, size = 1000 ;

5 var envT, envP ;

7 sig = Signal.newClear(size) ;

8 sig.waveFill({ arg x, i; sin(x) }, 0, 2pi*50) ;

10 envT = Env.triangle(1,1).asSignal(size);

11 envP = Env.perc(0.05, 1, 1, -4).asSignal(size) ;

13 [sig, envT, sig*envT, envP, sig*envP].flop.flat.plot(minval:-1, maxval:

1, numChannels: 5) ;

15 )

Gli inviluppi envT e envP , e le loro applicazioni a sig (Figura 5.19 , b),sono rappresentati in Figura 5.21.L’applicazione di un segnale di inviluppo è ovviamente possibile ancheper un segnale audio di provenienza concreta. Nell’esempio seguenteal segnale sig , ottenuto importando il contento di sFile , viene appli-cato un segnale di inviluppo env: env è ottenuto attraverso due arrayriempiti di numeri pseudo-casuali, v e d. Il primo oscilla nell’intervallo[0.0, 1.0] (è un segnale unipolare). Per evitare offset nell’ampiezza, il

primo e l’ultimo valore dell’array vengono posti a 0 , ed aggiunti dopo.L’array d è composto di un numero di elementi pari a quelli di v , secon-do quanto richiesto dalla sintassi di Env. Gli intervalli di durata varianonell’intervallo [0.0, 4.0].

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 144/328

5.7–141

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

−1

−0.5

0

0.5

1

0 200 400 600 800 1000

Fig. 5.21 Inviluppi con Env: envT, sig*envT, envP, sig*envP

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 145/328

5.8–142

1 /* inviluppi, II */

3 (

4 var sig, freq = 440 ;

5 var env, v, d, breakPoints = 10 ;

6 var sFile ;

8 sFile = SoundFile.new;

9 sFile.openRead("sounds/a11wlk01-44_1.aiff");

10 sig = Signal.newClear(sFile.numFrames) ;

11 sFile.readData(sig) ;12 sFile.close;

14 v = Array.fill(breakPoints-2, { arg i ; 1.0.rand ; }) ;

15 v = v.add(0) ; v = [0.001].addAll(v) ;

16 v.size.postln;

17 d = Array.fill(breakPoints-1, { arg i; 4.0.rand ;}) ;

19 env = Env(v, d, 'lin').asSignal(sig.size) ;

21 // Achtung! next line can be computationally expensive22 [sig, env, sig*env].flop.flat.jplot2(minval:-1, maxval: 1, numChannels:

3) ;

23 )

Tre inviluppi sono disegnati in Figura 5.22: ad ogni valutazione del codi-ce l’inviluppo assume infatto una forma diversa, a parte per i due ester-

mi pari a 0.

0

0.25

0.5

0.75

1

0 20 40 60 80 100

0

0.25

0.5

0.75

1

0 20 40 60 80 100

0

0.25

0.5

0.75

1

0 20 40 60 80 100

Fig. 5.22 Inviluppi pseudo-casuali.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 146/328

5.8–143

5.8 Conclusioni

L’obiettivo di quanto visto finora era di introdurre il concetto di segnaledigitale, attraverso alcune operazioni che si rendono tipicamente possi-

 bili grazie alla sua natura numerica. Si è poi avuto modo di osservare

come sia possibile modificare un segnale attraverso un altro segnale. Inparticolare, un segnale di controllo è un segnale che richiede una riso-luzione temporale molto minore del segnale e la cui frequenza di situaal di sotto delle frequenze udibilei (“sub-audio range”). Un segnale dicontrollo tipicamente modifica un segnale audio. È a questo punto op-portuno riprendere ed espandere gli aspetti affrontati attraverso il modus

operandi più tipico di SC, il tempo reale.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 147/328

6.1–144

6 L’architetturaeilserver

6.1 L’architettura

Come si è avuto modo di osservare, scaricando il programma SC ci siporta a casa due componenti, di principio autonomi, un server e unclient. Il primo viene chiamato scsynth , il secondo sclang (SC-language).Il programma SC sfrutta cioè un’architettura client/server, separandodue funzioni, una di richiesta e l’altra di fornitura servizi, che comuni-cano attraverso una rete. In 6.1 è descritta una generica architettura direte: più client comunicano via rete con un server scambiando messaggi.In SC il client e il server comunicano attraverso la rete attraverso mes-

saggi scritti in un protocollo specifico, piuttosto usato nell’ambito del-le applicazioni multimediali (ad esempio, è implementato in Max/MS,PD, EyesWeb, Processing, etc.), che si chiama OSC.

http://www.cnmat.berkeley.edu/OpenSoundControl/

A scanso di equivoci, la rete di cui si parla è definita a livello astratto.Ciò vuol dire che client e server possono essere in esecuzione sulla stessamacchina: è ciò che avviene quando si manda in esecuzione l’applicazione

SC.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 148/328

6.1–145

client 1

client 2

client 3

Server

m  s   g   

msg 

 m s g

Rete 

Fig. 6.1 Architetturaclient/server generica.

In altre parole, aprendo SC si mandano in esecuzione due programmi,

scsynth e sclang. Il server è un motore per la sintesi audio, di basso livel-lo, potente, efficiente, e non molto intelligente (non ha molta capacità diprogrammazione). Il cliente di questo server è sclang: anche sclang è inrealtà due cose, un linguaggio di programmazione e insieme l’interpretedi questo linguaggio. L’interprete ha due funzioni:

1. è il client: in altre parole, è l’interfaccia che permette all’utente discrivere e spedire messaggi OSC al server. Per scrivere una letteraal server, è necessario avere un foglio di carta e un postino che laconsegni: sclang fa entrambe le cose.

2. è l’interprete del linguaggio: i messaggi OSC sono piuttosto macchi-nosi da scrivere, e condividono con il server la prospettiva di bassolivello. Il linguaggio sclang è invece un linguaggio di alto livello (ti-po Smalltalk). Il codice sclang viene allora tradotto in messaggi OSCdall’interprete e questi vengono così inviati al server. La poesia che

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 149/328

6.1–146

l’utente scrive in linguaggio sclang viene parafrasata in prosa OSCdall’interprete sclang per essere inviata al (prosaico) server.

La situazione è schematizzata in 6.2. La comunicazione tra lato cliente lato server avviene attraverso messaggi OSC che il client (tipicamen-te) spedisce al server. L’interprete sclang spedisce messaggi OSC in duemodi:

1. direttamente. In altre parole, sclang-inteprete è un buon posto per

l’utente da dove parlare al server al livello di quest’ultimo (da dovespedire messaggi OSC);

2. indirettamente. Il codice simil-Smalltalk dello sclang-linguaggio (adun livello più astratto) a disposizione dell’utente viene tradotto dall’interpreteautomaticamente in messaggi OSC (a livello server) per il server (èil cosidetto language wrapping).

Riassumendo, a partire dall’applicazione sclang-inteprete si può scrive-re in poesia affidandosi alla traduzione prosastica ad opera dello stes-so inteprete (che è traduttore e postino) o direttamente in prosa OSC(l’inteprete fa solo il postino). Ci si potrebbe chiedere perché complicar-si la vita con una simile architettura. I vantaggi sono i seguenti:

• stabilità: se il client sperimenta un crash, il server continua a funzio-nare (ovvero: l’audio non si ferma, ed è un fatto importante per unconcerto/installazione/performance) e viceversa.

• modularità: un conto è la sintesi, un conto il controllo. Separare ledue funzioni consente ad esempio di controllare scsynth anche daapplicazioni che non siamo sclang: l’importante è che sappiano spe-dire i giusti messaggi al server. Il server è democratico (tutti possono

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 150/328

6.1–147

ottenere servizi audio) e burocratico allo stesso tempo (l’importanteè rispettare il protocollo OSC).

• controllo remoto: la rete di cui si parla può essere sia interna al calco-latore, sia esterna. Quando ci si occupa esclusivamente di sintesi au-dio, tipicamente le due componenti lavorano sullo stesso calcolatoree usando l’indirizzo locale. Ma client e server potrebbero benissimotrovarsi via rete, anche ai due estremi opposti del globo e comunicarevia internet.

Gli svantaggi principali di una simile architettura sono due:

1. la circolazione dei messaggi introduce un piccolo ritardo (che puòessere di rilievo però vista la sensibilità temporale dell’audio);

2. in caso di alta densità temporale dei messaggi sulla rete, quets’ultimapuò essere sovraccaricata, e la gestione dei messaggi può indurre unritardo.

Va altresì notato che è decisamente raro incorrere in simili problemi.

s

.sendMsg

synthDefssynth

.play

func

.play

messaggi OSC

messaggi OSC

messaggi OSC

sclang

language wrapping

app.

esterna

app.

esterna

Client side Server side  

scsynth

livello messaggi OSCaltri livelli più astratti

Fig. 6.2 Architettura client/server di SC.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 151/328

6.2–148

Ad esempio, in 6.2 si distingue tra due “lati”, client e server side. Sul latoserver c’è scsynth. Su quello client ci possono essere un numero indefi-nito di applicazioni capaci di parlare via OSC al server (livello dei mes-saggi OSC). Dalla discussione precedente risulta infatti chiaro che sclangè soltanto uno dei possibili client di scsynth. Tuttavia, sclang, essendopensato esplicitamente per lavorare con scsynth, ne è in qualche modo ilclient privilegiato, ad esempio fornendo all’utente un linguaggio di altolivello (altri livelli più astratti) e traducendolo per lui in messaggi OSC.

6.2 Esempi

I due esempi seguenti illustrano l’utilità dell’architettura client/serverdi SuperCollider, che lo rendono particolarmente flessibile nell’interazionecon altri software. Si tratti di aspetti piuttosto complessi a livello intro-duttivo, ma che hanno il solo scopo di far intuire il funzionamento ge-nerale.

6.2.1 SwingOSC

Si è già osservato che SwingOSC è un server grafico in Java, che può es-sere controllato dall’interno di sclang. In sostanza, vale un ragionamen-to analogo a quanto visto per la comunicazione con scsynth. SwingOSCè un server e riceve messaggi via OSC da qualsiasi client che sia in gradodi inviarglieli. È esattamente lo stesso meccanismo visto in precedenza,tant’è che, analogamente a quanto visto per la relazione sclang/scsynth,è possibile inviare direttamente da sclang messaggi OSC a SwingOSC.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 152/328

6.2–149

Sono allora state predisposte dallo sviluppatore alcune classi che per-mettono dall’interno di sclang un controllo di più alto livello rispettoall’invio diretto di messaggi OSC. Si tratta delle classi già incontrate inprecedenza discutendo di interfacce grafiche. La situazione è raffiguratain 6.3.

scsynth

s.sendMsg

synth

.play

func

.play

messaggi OSC

messaggi OSC

sclang

language wrapping

app.esterna

Client side Server side  

livello messaggi OSCaltri livelli più astratti

SwingOSC

JSCWindow.

newg

.sendMsg

messaggi OSC

messaggi OSC

app.

esterna

Fig. 6.3 Architettura client/server: sclang, scsynth eSwingOSC.

Ad esempio, il codice sclang GUI.window.new crea un elemento GUI at-

traverso SwingOSC, una semplice finestra. Sclang interpreta il codice einvia gli opportuni messaggi a SwingOSC per la creazione dell’elementografico. Il caso più interessante è però quando si crea un elemento chenon è soltanto una “view” ma anche un “controller”: ad esempio unelemento-manopola la cui escursione permmetta di controllare un pa-rametro audio (ad esempio una manopola del volume). In fase di inizia-lizzazione (6.4 , 1) è necessario:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 153/328

6.2–150

1. istanziare un dispositivo di sintesi sul scsynth

2. istanziare un elemento GUI su SwingOSC

3. stabilire la relazione tra variabile di controllo dell’elemento GUI evariabile di controllo dell’elemento audio

In fase di esecuzione, il comportamento dell’utente viene intercettatoda SwingOSC (l’utente muove la manopola che è oggetto istanziato dal

server SwingOSC), il quale comunica di ritorno a sclang il nuovo valoredella manopola (6.4 , 2). Sclang a sua volta utilizza il valore ottenuto perinviare a scsynth un messaggio che indichi di modificare quel parametroaudio (6.4 , 3).

sclang

scsynth

SwingOSC1

1

2

3

Fig. 6.4 Creazione econtrollo di un elemento GUI.

Sebbene all’utente finale, soprattutto in Windows, la discussione pre-cedente possa sembrare troppo macchinosa, va ricordato che la consa-

pevolezza della architettura è l’unica strada per capire esattamente ilfunzionamento di SC. In altre parole, in SC, anche quando non si vedein alcun modo, se c’è segnale audio c’è sempre un server audio che perfunzionare ha bisogno di essere controllato via messaggi OSC.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 154/328

6.3–151

6.2.2 Graphista!

Un esempio abbastanza sofisticato di sfruttamento della architettura direte di SC è fornito in Figura 6.5. Graphista! è un programma con inter-faccia grafica per la composizione musicale algoritmica inizialmente in-teramente scritto nel linguaggio Python. Non pensato per il tempo reale,è stato ampliato per funzionare anche in RT utilizzando SC come motoreper la sintesi audio. La reimplementazione in SC dell’interfaccia grafica,piuttosto complessa, sarebbe stata complicata. Poiché esiste un modulodi Python che gestisce messaggi OSC, è stato allora possibile connetteredirettamente Graphista! a scsynth: l’utente controlla la sintesi attraver-so SC a partire dall’interfaccia grafica in Python di Graphista! (6.5 , a). Infase di implementazione, ci si è però resi conto che la precisione di Py-

thon per il controllo della generazione di eventi in tempo reale è piutto-sto limitata. La soluzione è consistita nel trattare anche sclang come unserver (6.5 , b). sclang infatti non solo invia, ma può ricevere messaggiOSC. Dunque, Graphista! invia messaggi OSC a sclang: i messaggi con-tengono frammenti di codice sclang. Quest’ultimo intepreta il codice e lotraduce in altri messaggi OSC per scsynth. In questa implementazionel’utente attraverso Graphista! controlla indirettamente scsynth attraver-so sclang (propriamente scsynth è inaccessibile a Graphista!).

6.3 Ilclientsclang

Come si è detto, sclang è soltanto uno tra i possibili client di scsynth. Manon è un cliente qualunque.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 155/328

6.4–152

synthDefs

Graphista!

OSC messages

Client side Server side  

SC scsynth

graph data

structures

User

init init  

event event 

init 

audio rate 

(Python)

synthDefsGraphista!

OSC messagesClient side  Server side 

SC scsynth

graph data

structures

User

init  init 

event  event 

init 

audio rate 

SC sclang

variables

update

OSC messages

(Python)

a. Prima ipotesi (progetto) b. Seconda ipotesi(implementazione)

Fig. 6.5 Graphista!: uso dell’architettura di rete

1. In primo luogo, sclang è l’interprete di un linguaggio di alto livelloche permette all’utente quasi di dimenticarsi della struttura client/servere di molto di quello visto fin’ora.

2. In secondo luogo, il privilegio maggiore di sclang sta nel fatto chepermette la definizione e l’invio al server delle synthDef. Le synth-Def devono risiedere sul server, ma come si fa a mettercele? Sclang

offre questa possiblità. Non è impossibile farlo da altri client, ma èmolto più complicato.

6.4 Unimpiantochimicoperlaproduzionediliquidie

unserveraudiointemporeale

Dunque scsynth è un motore di sintesi audio programmabile e control-labile in tempo reale. Non è agevole di primo acchito riuscire a tenerpresente le relazioni tra tutti gli elementi pertinenti per il server audioscsynth. Conviene perciò introdurre una quadro metaforico e pensareserver come ad un impianto chimico per la sintesi di liquidi. Nella di-scussione seguente si prenda in considerazione la figura 6.6.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 156/328

6.4–153

Dispositivo

Dispositivo

Dispositivo

Dispositivo

Dispositivo

Dispositivo

Dispositivo

Dispositivo

Macchinario

contenitorecontenitore

Impianto 

tubo di collegamento

tubo in uscita

tubo in entrata

Macchinario

Macchinario

tubo in uscita

Fig. 6.6 Il server audio come impianto chimico pergenerazione di liquidi di sintesi.

1. Per sintetizzare un liquido è necessaria un macchinario complesso

2. Un macchinario è costituito di dispositivi specializzati in cui i liquidi

subiscono trasformazioni. I dispositivi sono collegati attraverso tubiinterni.

3. Un macchinario deve essere progettato predisponendo le relazionitra dispositivi componenti. A partire da un progetto, può essere co-struito un numero indefinito di macchinari identici.

4. Una volta costruito, il macchinario non può essere modificato nellasua struttura interna

5. Ma un addetto può controllarne il comportamento dall’esterno at-traverso leve e comandi, così come monitorarne il funzionamento

6. Un impianto può comprendere più macchinari che lavorano in pa-rallello

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 157/328

6.4–154

7. Quando l’impianto è in funzione i liquidi scorrono lungo i tubi avelocità costante, senza mai potersi fermarsi.

8. I liquidi possono scorrere nei tubi a due velocità differenti (ma sem-pre costanti), in particolare a velocità di controllo e a velocità di sin-tesi

9. I liquidi possono però essere stoccati in quantità limitate dentro ap-positi contenitori, da cui è possibile attingere quando serve. Questi

liquidi di per sé non scorrono, ma, attraverso dispositivi specializza-ti, possono essere riversati in un liquido in scorrimento.

10. Tipicamente (anche se non necessariamente) un macchinario preve-de un dispositivo munito di un tubo che permette di far uscire illiquido all’esterno. Altre volte può avere anche dispositivo con untubo in entrata da cui ricevere un liquido che proviene da altri mac-chinari

11. La circolazione dei liquidi tra l’impianto e l’esterno (l’acqua dall’acquedottoin entrata, il prodotto sintetizzato in uscita) oppure tra i diversi mac-chinari nell’impianto avviene attraverso tubi speciali. I primi sonotubi di entrata/uscita, i secondi di collegamento. Attraverso quesiultimi, i liquidi possono così circolare nell’impianto e sono a dispo-sizione degli altri macchinari. Questi tubi permettono perciò di con-nettere diversi macchinari

12. I tubi di collegamento disperdono il loro liquido (che non è uscitoattraverso i tubi di uscita dell’impianto) negli scarichi dell’impianto.I liquidi non inquinano e la loro dispersione non è rilevante.

È possibile a questo punto riconsiderare i punti precedenti, sostituendoopportunamente i nomi di figura 6.6 con quelli di figura 6.7.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 158/328

6.4–155

UG UG UG

UG UG UG

UG UG

Synth

Synth

Synthbuffer buffer

SERVER 

bus

Out bus

In bus

Out bus

Fig. 6.7 Componenti del server audio.

Osservazione 1

Per sintetizzare un liquido è necessaria un macchinario complesso

Per sintetizzare un segnale audio è necessario un macchinario softwareche in SC prende il nome di Synth: un synth è appunto un sintetizzatoreaudio.

Osservazione 2

Un macchinario è costituito di dispositivi specializzati in cui i liquidisubiscono trasformazioni. I dispositivi sono collegati attraverso tubi in-terni

Per generare segnale audio un synth richiede di specificare quali algo-ritmi di elaborazione/sintesi del segnale da utilizzare. In SC, seguendola tradizione della famiglia di linguaggi Music N, gli algoritmi di ela-

 borazione/sintesi sono implementati in UGen (→ U nit Generator): unaUGen è semplicemente un dispositivo software che elabora o sintetizzasegnale audio. Ad esempio SinOsc è una UGen che genera segnali si-nusoidali: per avere un’idea è sufficiente eseguire questa riga di codice:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 159/328

6.4–156

{SinOsc.ar

}.play. Le UGen costituiscono i componenti di base di un

synth. Un synth è appunto un sintetizzatore, un dispositivo di sintesicostruito con componenti UGen.Le UGen possono avere più entrate, ma hanno sempre soltanto un’uscita.Una UGen può ricevere in entrata un’altra UGen: questo processo sichiama patching , e può essere tradotto (non letteralmente ma ad sensum)con “innesto”, così come to patch ha un buon equivalente in “innestare”.Un insieme di UGen innestate tra di loro formano uno UGen-graph, ungrafo di UGen, una struttura che rende conto delle relazioni tra UGen.Poiché le UGen generano segnali lo UGen-graph descrive il flusso deisegnali che dalle diverse sorgenti si “raccolgono” nel segnale. Lo UGen-graph è la cartina geografica di un fiume che raccoglie contributi di di-versi affluenti per poi terminare in mare.

Osservazione 3

Un macchinario deve essere progettato predisponendo le relazioni tra

dispositivi componenti. A partire da un progetto, può essere costruitoun numero indefinito di macchinari identici

Il client di SC chiede perciò al server di costruire e di far funzionareun synth per lui. Per soddisfare la richiesta il server deve sapere qualipezzi (UGen) utilizzare e in quali relazioni combinarli (patching in unoUGen-graph). Poiché è probabile che all’utente possano servire più voltegli stessi dispositivi, SC prevede un passaggio supplementare. L’utente

prima specifica al server una definizione di un synth (synthDef), unasorta di progetto dettagliato di come deve essere fatto il synth deside-rato, e quindi chiede al server di costruire un synth seguendo quel pro-getto. Una synthDef associa un nome n ad uno UGen-graph u , in modoche si possano creare synth di tipo n che generano segnali attraverso lerelazioni tra UGen previste da u. Una volta create, le synthDef possono

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 160/328

6.4–157

essere memorizzate in formato binario e restare perciò sempre disponi- bili all’utente. L’utente può in altre parole crearsi una libreria di synth-Def (intese come progetti o come stampi da cui creare synth) e, quandoè opportuno, chiedere al server di creare un synth a partire dalla synth-Def.In sostanza per usare SC come motore di sintesi è necessario compierealmeno passi:

1. definire una synthDef (definire il progetto del sintetizzatore)

2. istanziare un synth a partire da una synthDef (costruire il sintetizza-tore)

Osservazione 4

Una volta costruito, il macchinario non può essere modificato nella suastruttura interna

Una synthDef è un diagramma, uno schema: oggetto statico. Una vol-ta spedita al server, è immutabile. Se prevede due entrate, quelle avrà.D’altra parte, è sempre possibile spedire al server una nuova synthDefche prevede le modifiche desiderate.

Osservazione 5

Ma un addetto può controllarne il comportamento dall’esterno attraver-so leve e comandi, così come monitorarne il funzionamento Il proget-

to di un sintetizzatore è descritto in una synthDef attraverso lo UGen-Graph. Lo UGen-Graph è descritto sintatticamente attraverso una fun-zione (ed infatti è racchiuso tra parentesi graffe). Come ogni funzio-ne può prevedere argomenti in entrata: questi argomenti sono appun-to parametri per il calcolo, svolto dal corpo della funzione, del valore(l’ampiezza del segnale) che la funzione restituisce in uscita.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 161/328

6.4–158

Osservazione 6

Un impianto può comprendere più macchinari che lavorano in parallel-lo

Ogni macchinario dell’esempio idraulico rappresenta un synth, ovvero,musicalmente parlando, uno strumento -o in fondo anche una voce. Ilserver audio può gestire un numero indefinito di sintetizzatori in paral-lelo. In altre parole, il numero massimo degli strumenti -o delle voci- che

possono suonare contemporaneamente dipende esclusivamente dallerisorse hardware a disposizione.

Osservazione 7

Quando l’impianto è in funzione i liquidi scorrono lungo i tubi a velocitàcostante, senza mai potersi fermarsi

Si è detto che il liquido rappresenta il segnale audio. La scelta del liqui-

do dipende dal fatto che, poiché a questo punto non si sta parlando solodi segnali, ma di segnali in tempo reale, i segnali sono certo sequenze divalori di ampiezza secondo quanto visto finora, ma in più con il vinco-lo che tali campioni devono essere inesorbilmente calcolati ad un tassouniforme nel tempo (tipicamente, ma non necessariamente, nel caso disegnali audio 44.100 volte in un secondo). Ad ogni istante di tempo, unnuovo campione deve essere calcolato nella sequenza: ogni synth effet-tua tutti i calcoli previsti da tutte le UGen che lo compongono e resti-

tuisce un valore. In altre parole, ad ogni istante deve essere attraversatotutto lo UGen-Graph, indipendentemente dalla sua complessità. Atten-zione: se si considera l’esempio idraulico, ciò significa che se una gocciaentra da un tubo in entrata nell’istante x l’istante dopo (x + 1) deve es-sere già attraversato tutto l’impianto, ed essere in uscita. Ovvero: dentro

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 162/328

6.4–159

ogni macchinario, lo scorrimento del liquido lungo i tubi che connettonoi dispositivi è letteralmente istantaneo.

Osservazione 8

I dispositivi possono lavorare a due velocità differenti (ma sempre co-stanti), in particolare a velocità di controllo e a velocità di sintesi

Dunque ad ogni istante una nuova goccia deve uscire da un macchinario

dopo aver percorso tutto il complesso dei dispositivi. I dispositivi nonnecessariamente però aggiornano il loro comportamento ad ogni istan-te: possono modificare la loro azione soltanto una volta ogni n istanti.Un segnale di controllo è tipicamente un segnale che cambia meno neltempo di un segnale audio e che quindi può essere calcolato ad una ri-soluzione più bassa. Ad esempio, è inutile calcolare per ogni campioneaudio il valore di un inviluppo d’ampiezza. Se infatti si calcola un valoredell’inviluppo per il quale moltiplicare il segnale audio, e lo si mantiene

costante per 10 campioni audio, per poi ricalcolarlo all’undicesimo, dinuovo maneternlo costante per altri 10 , e così via, si ottiene un segna-le che è evidentemente più “scalettato” in ampiezza ad un’analisi dellaforma d’onda, ma che di fatto non è sensibilmente diverso da un segnalein cui l’inviluppo d’ampiezza sia stato calcolato per ogni campioni. Incompenso sono state risparmiate notevoli risorse computazionali. Unsegnale simile è un segnale calcolato non a tasso audio (audio rate), ma atasso di controllo (control rate). come si vedrà, le UGen generano segnali

nel momento in cui ricevano il messaggio .ar , o .kr: rispettivamenteil segnale risultante sarà aggiornato a tasso audio (audio rate) o a tassodi controllo ([k]ontrol rate). Si noti che si sta parlando di tasso di aggior-namento, e non di numero di campioni. SC genera un segnale audio in

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 163/328

6.4–160

tempo reale per forza a tasso audio: ma alcuni segnali che intervengononella sintesi sono aggiornati ad un tasso più basso di controllo.

Osservazione 9

I liquidi possono però essere stoccati in quantità limitate dentro appo-siti contenitori, da cui è possibile attingere quando serve. Questi liquididi per sé non scorrono, ma, attraverso dispositivi specializzati, possonoessere riversati in un liquido in scorrimento

Un buffer è una memoria temporanea che permette di conservare deidati audio richiesti da certi algoritmi di sintesi. Ad esempio, si considerila lettura di un file audio in funzione dell’elaborazione del suo contenu-to. Si potrebbe partire da un frammento di voce umana e costruire unsintetizzatore che intoni la voce sulle diverse altezze come rappresen-tate sui tasti di un pianoforte. Un simile sintetizzatore concettualmenteprevede due UGen.

• la prima elabora il frammento vocale rispetto all’altezza

• la seconda è responsabile della comunicazione con la scheda audio

Per poter elaborare il frammento, quest’ultimo deve essere disponibi-le alla prima UGen tutte le volte che questa ne ha bisogno: si pensi adeseguire una melodia a partire da quell’unico frammento trasformandoopportunamente l’altezza lungo la sequenza temporale delle note che

compongono la melodia. Il contenuto del file audio deve allora essereletto dall’hard disk e viene conservato in memoria temporanea. In SCun buffer è appunto una simile memoria che il server allocata su richie-sta. Il segnale audio contenuto nel buffer di per sé è statico: e tuttavia vi

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 164/328

6.4–161

può essere una UGen che legge il contenuto del buffer in tempo reale elo invia alla scheda audio.

Osservazione 10

Tipicamente (anche se non necessariamente) un macchinario prevedeun dispositivo munito di un tubo che permette di far uscire il liquidoall’esterno. Altre volte può avere anche dispositivo con un tubo in en-trata da cui ricevere un liquido che proviene da altri macchinari

Il segnale numerico sintetizzato deve essere inviato alla scheda audioin modo tale che quest’ultima lo converta in segnale elettrico e lo in-vii agli altoparlanti. Per questo compito esistono UGen specializzate,che prevedono entrate ma non uscite: infatti il segnale che entra non èpiù disponibile per la ulteriore elaborazione in SC, ma viene inviato allascheda audio. Tipico esempio è la UGen Out. Evidentemente UGen diquesto tipo occupano l’ultimo posto nello UGen-Graph che rappresen-

ta un synth. Se si omette una UGen di uscita il segnale viene calcolatosecondo quanto previsto dallae altre UGen nello UGen-Graph ma noninviato alla scheda audio (fatica mentale e computazionale sprecata). Sisupponga poi di collegare un dispositivo di entrata alla scheda audio, adesempio un microfono. Una UGen specializzata può rendere disponibi-le al synth tale segnale, in modo che possa essere elaborato (ad esempiosubire un qualche tipo di distorsione). A tal proposito SC prevede laUGen AudioIn.

Osservazione 11

La circolazione dei liquidi tra l’impianto e l’esterno (l’acqua dall’acquedottoin entrata, il prodotto sintetizzato in uscita) oppure tra i diversi mac-chinari nell’impianto avviene attraverso tubi speciali. I primi sono tubidi entrata/uscita, i secondi di collegamento. Attraverso quesi ultimi, i

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 165/328

6.4–162

liquidi possono così circolare nell’impianto e sono a disposizione de-gli altri macchinari. Questi tubi permettono perciò di connettere diversimacchinari

Si è già osservato come il server preveda una comunicazione con la sche-da audio, in entrata (“dal microfono”) e in uscita (“agli altoparlanti”).Questi canali di comunicazione prendono il nome di “bus”, secondo untermine che deriva dalla tecnologia dei mixer21. In effetti, rispetto a ”ca-nale” (che pure è il termine audio più vicino) il termine “tubo” può esse-

re meno fuorviante oltre mnemotecnicamente efficace. Il sistema dei busnon deve essere pensato come un sistema di tubi che connettono statica-mente i macchinari, ma come un sistema di tubi disponibili a cui i mac-chinari si raccordano. Ad esempio, tutti i synth che intendono elaborareun segnale che provenga dall’esterno possono raccordarsi al bus che èdeputato alla lettura dell’entrata della scheda audio (al tubo che immet-te un liquido dall’esterno). Tutti i synth, per inviano i segnali in uscitaalla scheda audio, si raccordano ai bus che gestiscono la comunicazione

con quest’ultima: i segnali sui bus in uscita semplicemente si sommano.I bus finora citati sono specializzati per segnali audio (audio busses), maesistono anche bus specificamente dedicati ai segnali di controllo control

busses. I bus sono indicati attraverso un numero progressivo, un indicea partire da 0. Per i bus di controllo, la numerazione è progressiva e nonci sono aspetti particolari da tener presenti. Per i bus audio, è invecenecessario ricordare che essi gestiscono la comunicazione con la sche-da audio. In particolare i primi bus audio (0, . . . , n) sono riservati alle

uscite della scheda audio, i secondi alle entrate (n + 1, . . . , o) (i tubi dientrata/uscita), seguono i bus ad uso interno (o +1, . . .) (i tubi di colle-gamento. Dunque, l’indicizzazione dipende dalla propria scheda audio.La configurazione standard con uscita stereo e ingresso microfono pre-vede i bus 0, 1 per i due canali stereo (i due altoparlanti) e il bus 2 per il

Il termine non sta per bus = mezzo di trasporto. Ed infatto pensare ad un bus audio21

come a un autobus è fuorviante.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 166/328

6.5–163

microfono. Dal 3 in avanti, i bus possono essere utilizzati internamen-te. Per farci cosa? Per connettere diversi synth. Ad esempio, un synthinstrada il segnale in uscita sul bus 4 da dove altri synth possono pren-derlo. Ovvero, idraulicamente un macchinario si raccorda ad un tubo inun punto e vi immette del liquido: più avanti lungo il tubo un secondomacchinario si raccorda e preleva il liquido immesso.

Osservazione 12

I tubi di collegamento disperdono il loro liquido (che non è uscito attra-verso i tubi di uscita dell’impianto) negli scarichi dell’impianto. I liquidinon inquinano e la loro dispersione non è rilevante

Una volta immessi su un bus, i segnali sono disponbili. Se non si scri-ve su un bus connesso alla scheda audio semplicemente non si ha unrisultato percepibile. In altre parole, inviare un segnale su un bus nonrichiede di sapere cosa altri potranno fare di quel segnale, e neppure se

mai qualche altro synth lo utilizzerà. Che cosa succede al segnale sul busè irrilevanet. Questo assicura una comunicazione possibile tra synth, masenza che questa diventi obbligatoria o prevista in anticipo.

6.5 Appetizer:unesempiodisintesiecontrollointempo

reale

L’esempio seguente serve per dare un’idea degli insieme degli elemen-ti fin qui citati. Senza scendere troppo nel dettaglio (scarso), ci si puòquantomeno fare un’idea generale di come funziona il tutto.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 167/328

6.5–164

1 s = Server.local.boot ; // first boot the server

3 (

4 // audio

5 SynthDef.new("sineMe", { arg out = 0, amp = 0.25, kfreq = 5 ;

6 Out.ar(out, SinOsc.ar(kfreq*50, mul: LFPulse.kr(kfreq, 0.25))*amp);

7 }).send(s);

8 )

10 (

11 // four vars12 var aSynth, window, knob1, knob2, button;

14 aSynth = Synth.new("sineMe"); // the synth

16 // GUI: creation

17 window = GUI.window.new("Knob", Rect(300,300,240,100));

18 window.front;

20 knob1 = JKnob.new(window, Rect(30, 30, 50, 50));

21 knob1.value = 0.25;

23 knob2 = JKnob.new(window, Rect(90, 30, 50, 50));

24 knob2.value = 0.3;

26 button = GUI.button.new(window, Rect(150, 30, 50, 50)) ;

27 button.states = [ // array of states

28 [ "stop", Color.black ], ["start", Color.red]] ;

30 // GUI: controlling audio

31 knob1.action_({arg v; aSynth.set("amp", v.value); });32 knob2.action_({arg v; aSynth.set("kfreq", v.value*15); });

33 button.action = ({ arg button;

34 var val = button.value.postln;

35 if (val == 1, { aSynth.run(false) }, { aSynth.run })

36 });

38 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 168/328

6.5–165

6.5.1 UnasynthDef 

In primo luogo, è necessario costruire lo strumento che generi il segnale.Un esempio minimale di synthDef è quello riportato di seguito.

1 SynthDef.new("bee",

2 { Out.ar(0, SinOsc.ar)}

3 ).send(s);

•SynthDef: è l’oggetto che interessa

• .new( … ): new è il metodo costruttore, che costruisce effettivamentela synthDef (restituisce l’oggetto synthDef). Il metodo new prevedeun certo numero di argomenti. Qui ne vengono specificati due, pergli altri è opportuno lasciare quelli predefiniti.

• "bee": il primo argomento è una stringa che rappresenta il nome del-la synthDef: il nome verrà associato allo UGen-graph. I synth gene-rati a partire da questa synthDef saranno dei “bee”, cioè dei synthdel tipo “bee”. Qui “bee” è una stringa, ma potrebbe anche essere unsimbolo (\bee).

• { Out.ar(0, SinOsc.ar)}: lo UGen-graph è racchiuso tra paren-tesi graffe. Tutto ciò che è tra graffe in SC è una funzione. Dunque,lo UGen-graph è descritto da una funzione. Lo UGen-graph è costi-tuito da due UGen, Out e SinOsc: questo fatto è reso esplicito dalmessaggio .ar che le due UGen ricevono. In generale ciò che rispon-de al messaggio .ar o .kr è una UGen. E perché una UGen generi

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 169/328

6.5–166

in tempo reale un segnale deve ricevere i messaggi .ar o .kr. Perchéuna funzione per descrivere le relazioni tra UGen? Si ricordi che unafunzione è un oggetto che restituisce un valore ogni qualvolta glielosi chiede. Un synth è allora descritto da una funzione perché ad ogniistante che passa gli viene chiesto di restituire un valore di ampiez-za, il valore del campione audio. Ad ogni istante viene calcolato ilvalore della funzione descritta dalla UGen-Graph.

SinOsc Out

Synth: "bee"

Out bus: 0SERVER 

Fig. 6.8 Schema di una synthdef minimale.

In Figura 6.8 è rappresentato, secondo le convenzioni precedenti, unsynth costruito a partire dalla synthDef “bee”. Come si vede il se-gnale risultante viene “raccordato” (inviato) sul bus 0. In manierapiù consueta lo UGen-Graph può essere descritto in forma di dia-gramma di flusso dal grafo di 6.922. Out è la UGen che si occupa diinviare alla scheda audio il segnale generato: senza Out non c’è co-municazione con la scheda audio, quindi non c’è suono udibile. Outprevede due argomenti. Il primo è l’indice del bus su cui inviare il

segnale in uscita, il secondo è il segnale stesso. Out riceve un segnalee lo spedisce al bus audio 0 , che indica, come già osservato, un cana-le della scheda audio (si ricordi: nei bus audio, prima gli output, poigli input). Il segnale che spedisce gli viene fornito da SinOsc: è uncaso di patching, di innesto di una UGen (SinOsc in un’altra (Out).SinOsc genera una segnale sinusoidale: laddove non si specifichino

Generato utilizzando le classi dot di Rohann Drape.22

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 170/328

6.5–167

la frequenza e la fase, queste varranno rispettivamente 440 (Hz) e 0.0(radianti).

SinOsc 440 0

 

Out 0

Fig. 6.9 Rappresentazionedello UGen-graph.

• .send(s): la synthDef, di per sé, non serve a nulla se non è carica-ta sul server. Il server è convenzionalmente assegnato alla variabile

globale s. Dunque il codice .send(s) chiama il metodo .send defi-nito per la synthDef, e dice alla synthDef di “spedirsi” al server s.Attenzione: tutto ciò che sta in una synthDef è costituito da specifi-che istruzioni per la sintesi del segnale.

Oltre a send , vi sono molti metodi definiti per la classe SynthDef , chepermettono ad esempio di scrivere la definizione su file (si tratta delmetodo writeDeFile): le synthDef così memorizzate verrano caricatead ogni accensione del server, e saranno perciò subito disponibili.

Tornando all’esempio, ora il server ha pronto il progetto “bee” per potercreare dei synth di tipo “bee”.

6.5.2 UGeneUGen-Graph

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 171/328

6.5–168

La definizione della synthDef dell’esempio originale è invece la seguen-te.

1 SynthDef.new("sineMe", { arg out = 0, amp = 0.25, kfreq = 5 ;

2 Out.ar(out, SinOsc.ar(kfreq*50, mul: LFPulse.kr(kfreq, width: 0.25))*amp);

3 }).send(s);

Si noti come in questo caso lo UGen-Graph preveda alcuni argomentiin entrata che ne permettono il controllo in tempo reale. Essi sono out,

amp, kfreq  , tutti dotati di valori predefiniti. Ogni synth di tipo “sineMe”

metterà a disposizione dell’utente i tre controlli equivalenti in entrata.La riga 2 descrive il patching tra UGen (Out, SinOsc, LFPulse). Si os-servi come quest’ultima aggiorni i propri valori ricalcolando il valorein uscita a tasso di controllo, secondo quanto previsto dal messaggio kr

inviato a LFPulse.

È opportuno ora soffermarsi di più su una UGen, in particolare su SinOsc.Per sapere come si comporta ci si può evidentemente rivolgere all’helpfile relativo. Un’altra opzione, utile in fase di studio almeno, consistenell’accedere alla definizione nel codice sorgente.

1 SinOsc : UGen {

2 *ar {

3 arg freq=440.0, phase=0.0, mul=1.0, add=0.0;

4 ^this.multiNew('audio', freq, phase).madd(mul, add)

5 }

6 *kr {

7 arg freq=440.0, phase=0.0, mul=1.0, add=0.0;

8 ^this.multiNew('control', freq, phase).madd(mul, add)

9 }

10 }

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 172/328

6.5–169

Si noti come SinOsc erediti da UGen , la sopraclasse generica di tutte leUGen. In più, definisce soltanto due metodi di classe, ar e kr. Lasciandoperdere l’ultima riga di ogni metodo, si nota come i metodi prevedanoun certo numero di argomenti a cui può essere passato un valore “dafuori”. Si noti anche come tutti gli argomenti tipicamente abbiano unvalore predefinito. Così

SinOsc.ar

è del tutto identico a

SinOsc.ar(freq: 440.0, phase: 0.0, mul: 1.0, add: 0.0)

ovvero a

SinOsc.ar(440.0, 0.0, 1.0, 0.0)

Gli ultimi due argomenti sono mul e add , e sono condivisi dalla mag-gior parte delle UGen: mul è un moltiplicatore del segnale mentre add

è un incremento (positivo o negativo) che viene sommato al segnale. Siconsiderino gli esempi seguenti

{SinOsc.ar(220, mul: 1, add:0)}.scope ;

{SinOsc.ar(220)}.scope ;

SinOscgenera una sinusoide a220Hz. Il segnale generato da una UGentipicamente è normalizzato, la sua ampiezza oscilla in [−1, 1] (altrevolte è compreso in [0, 1]). L’argomento mul definisce un moltiplica-tore che opera sull’ampiezza così definita, mentra add è un incrementoche si aggiunge allo stesso segnale. Nella prima riga il segnale è moltipli-cato per 1 e sommato a 0. Il segnale è cioè immutato. Si noti che i valorispecificati sono quelli predefinti, quindi si potrebbe scrivere la riga suc-cessiva ed ottenre esattamente lo stesso risultato. A scanso di equivoci,

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 173/328

6.5–170

“moltiplicare” e “aggiungere” significa che ogni campione del segnaleè moltiplicato e sommato per i valori specificati nei due argomenti.Invece in questo esempio

{SinOsc.ar(220, mul: 0.5, add:0)}.scope ;

il segnale risulta moltiplicato per 0.5 (e sommato a 0 , ma è irrilevante):la sua ampiezza sarà compresa in [−1.0, 1.0] × 0.5 = [−0.5, 0.5].Infine nell’esempio seguente

{SinOsc.ar(220, mul: 0.5, add:0.5)}.scope ;

il segnale precedente viene sommato a 0.5: la sua ampiezza sarà com-presa in [−1.0, 1.0] × 0.5 + 0.5 = [−0.5, 0.5 ] + 0.5 = [ 0.0, 1.0].L’assegnazione mul del valore costante 0.5 indica che ogni nuovo cam-pione verrà moltiplicato per 0.5. Si potrebbe pensare allora che mul siaun segnale costante. A tal proposito si può prendere in considerazionela UGen Line. Come dice l’help file:

“Line line generator

. . .Generates a line from the start value to the end value.”

I primi tre argomenti di Line sono start, end, dur: Line genera unasequenza di valori che vanno da start a adur in dur secondi. Nel codiceseguente

{SinOsc.ar(220)*Line.ar(0.5,0.5, 10)}.scope

Line genera per 10 secondi una sequenza di valori pari a 0.5 (cioè unaprogressione da 0.5 a 0.5). Il segnale in uscita dall’oscillatore SinOscviene moltiplicato per l’uscita di Line. Ad ogni istante di tempo il cam-pione calcolato dalla prima UGen viene moltiplicato per il campionecalcolato dalla seconda (che ha sempre valore 0.5). Si noti che il segnale

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 174/328

6.5–171

risultante è uguale a quello precedente. È chiaro che l’aspetto interessan-te nell’uso di Line sta proprio nel fatto che i valori che la UGen generanon sono costanti ma variano invece tipicamente secondo una progres-sione (lineare, appunto).Questo è un crescendo dal niente:

{SinOsc.ar(220)*Line.ar(0.0,1.0, 10)}.scopeIl patching è appunto l’innesto di una UGen in un argomento di un’altra

o il calcolo di un segnale a partire dal contributo offerto da più UGenin una qualche relazione reciproca (qui di moltiplicazione). L’esempiopermette di capire come gli argomenti possano essere descritti non dacostanti ma da variabili, cioè da alti segnali. In altre parole, i segnalipossono modificare qualsiasi aspetto controllabile di altri segnali.

out:0

Out bus channelsArray

amp:0.25

* a b

 

kfreq:5

* a b: 50

 

LFPulse freq iphase: 0.25 width: 0.5

 

SinOsc freq phase: 0

 

* a b

 

Fig. 6.10 Rappresentazione dello UGen-graph.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 175/328

6.5–172

Nella figura 6.10 è rappresentato il diagramma di flusso della synthDef"sineMe". Gli elementi neri descrivono il flusso a tasso audio, tutti glialtri le informazioni a tasso diverso (controllo/evento). LFPulse lavoraa tasso di controllo, mentre kfreq, amp, out vengono modificate a tassodi evento (ogni qualvolta un utente modifica i parametri). I blocchi “* a

 b” indicano blocchi di moltiplicazione. I valori di argomenti nelle UGennon specificati sono indicati attraverso i valori predefiniti.Il segnale moltiplicatore è prodotto da LFPulse , un generatore di ondequadre, con frequenza "kfreq" (quindi collegata alla frequenza dellasinusoide). Il segnale in uscita da LFPulse è unipolare, cioè compresonell’intervallo [0, 1]. Si può capire meglio la natura del segnale generatoattraverso:

{LFPulse.ar(100, mul: 0.5)}.scope

Come si vede, il segnale prevede solo due valori di ampiezze, 0.0 e 0.5(a causa dell’argomento mul), e oscilla da uno all’altro 100 volte al se-

condo. Utilizzando un segnale simile come moltiplicatore di un altrosegnale, si ha che, quando l’ampiezza è 0.0 , il segnale risultante ha am-piezza 0.0 (silenzio), quando l’ampiezza è 0.5 , in uscita si ha il segnaledi partenza scalato per 0.5. In sostanza, si produce una intermittenza.Dunque, la frequenza della sinusoide è correlata alla frequenza di inter-mitteza (più è acuta la frequenza, più frequentemente è intermittente).

6.5.3 Unsynth

Le righe 10 e 11 dell’esempio in discussione creano e mettono in funzio-ne un synth. In particolare

aSynth = Synth.new("sineMe")

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 176/328

6.5–173

assegna alla variabile aSynth un oggetto di tipo Synth inviando il co-struttore new alla classe. Il costruttore prevede come argomento una strin-ga che indica la synthDef da cui il synth viene fabbricato "sineMe".Nel momento in cui viene create attraverso new , il synth viene attivato(= suona). Questo comportamento è tipicamente utile, perché in realtàun synth può essere pensato come uno strumento (un sintetizzatore) maanche come un evento sonoro (una nota): a pensarlo così, diventa ovvioche la costruzione del synth equivale alla generazione di un evento so-noro.Il codice seguente assume che la synthDef precedente sia ancora dispo-nibile.

1 ~synth1 = Synth.new("sineMe", [\kfreq , 10]) ; // synth plays, array of

args

3 ~synth2 = Synth.newPaused("sineMe") ; // another synth

4 ~synth2.run(true) ; // start playing

6 ~synth1.set(\kfreq , 3) ; // set kfreq to 3

8 ~synth2.setn(\amp, [20, 0.1]) ; // set 2 args from amp

10 ~synth1.get(\kfreq , { arg val ; val.postln }) ; // get kfreq 

12 ~synth2.getn(\out, 3, { arg valArray ; valArray.postln }) ; // get 4

args from out

14 ~synth1.run(false) ; // stop playing15 ~synth2.run(false) ; // stop playing

17 ~synth1.free ; // free the synth

18 ~synth2.free ; // free the synth

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 177/328

6.5–174

La riga 1 crea un synth e lo associa alla variabile ~synth1. Dopo il no-me, viene specificato un array che contiene coppie composte da nomedell’argomento e valore (in questo caso una sola coppia, \kfreq e 10).Se si vuole costruire un synth senza renderlo immediatamente attivoè possibile usare il metodo newPaused , come avviene per il synth as-sociato a ~synth2. Il metodo run controlla attivazione/disattivazione(play/pause per così dire) del synth, attraverso un valore booleano true/false

(4, 14, 15). Il metodo set permette di controllare un argomento, passan-do nome e valore (6). Attraverso setn è possibile controllare più argo-menti, passando il nome del primo e un array che contiene i valori deglin argomenti successivi. Nell’esempio vengono impostati due argomentia partire da \amp (incluso), ovvero \amp e \kfreq (10). Simmetricamentei metodi get e getn consentono di recuperare i valori degli argomentidal synth. Il primo restituisce il valore di un singolo argomento, mentreil secondo un array di n valori (3 nell’esempio) a partire dal primo indi-cato (\out , ovvero i valori di \out, \amp, \kfreq ). I valori sono passaticome argomenti della funzione seguente, che, negli esempi di riga 10 e12, chiede semplicemente di stampare i valori stessi sulla post window.Una synth non più utilizzato può essere messo in pausa, ma in quel casocontinua ad essere residente in memoria, e dunque ad occupare inutil-mente risorse del calcolatore. Per eliminare dal server il synth. è suffi-ciente inviare all’oggetto synth il messaggio free (17, 18).

6.5.4 GUI econtroller

Sulla creazione di elementi GUI non c’è molto da dire. Si tratta di co-struire due manopole all’interno di una finestra, secondo una tecnicagià vista più volte. Di nuovo c’è la creazione di un pulsante a partire daGUI.button , secondo una sintassi del tutto analoga a quella di GUI.knob.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 178/328

6.5–175

La riga successiva definisce quanti stati ha il pulsante attraverso un ar-ray che contiene le proprietà di ognuno. Così lo stato 0 prevede la scritta”stop” in colore nero Color.black , mentre lo stato 1 prevede la scritta”start” in colore rosso Color.red.Più interessanti invece le azioni collegate alla variazione delle manopolee al pulsante. La riga

knob.action_(arg v; aSynth.set("amp", v.value);

definisce la connessione tra il controller GUIknob1 e sintesi audio. L’azioneè associata alla manopola (knob1.action_) è

aSynth.set("amp", v.value)

Ogni volta che cambia il valore della manopola viene chiamato sull’oggettoaSynth (il synth) il metodo set che assegna al parametro specificato("amp") un valore, qui v.value. Il parametro ("amp") viene allora aggior-nato dentro lo UGen-Graph. Esso indica il moltiplicatore che è posto in

fondo alla cascata delle UGen SinOSc e LFPulse: di fatto si comportacome un controllo del volume a cui viene attacata una manopola knob1.Quest’ultima genera valori nell’intervallo [0, 1] , cioè nell’escursione d’ampiezzadel segnale audio in forma normalizzata, e il segnale dunque varierà tra0 e il valore massimo in uscita dal patching precedente. Analogamente

aSynth.set("kfreq", v.value*15)

assegna al parametro "kfreq" il valore v.value*15. L’escursione di "kfreq"sarà perciò compresa in [0, 15]. Infine anche a button viene assegnataun’azione secondo una sintassi analoga a JKnob: l’argomento button in-dica appunto il pulsante, per cui button.valuepermette di accedere allostato del pulsante (ovvero l’indice dello stato nell’array degli stati but-ton.states). Ad ogni pressione del pulsante viene richiamata l’azione.L’azione valuta il lo stato del pulsante attraverso il costrutto condizio-nale (34). Se il valore val del pulsante è 1 viene chiamato il metodo

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 179/328

6.5–176

run(false) su aSynth , che mette in pausa il synth. Nel caso negativo(e dunque se val è 0) il synth viene attivatoaSynth.run. Quando si ese-gue il codice, il synth è attivo e lo stato è 0. Alla prima pressione lo statodiventa 1 , la GUI viene aggiornata e viene eseguito il ramo condizionaleche contiene aSynth.run(false).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 180/328

7.1–177

7 Controlliecanali

7.1 Inviluppi

Si è già discusso degli inviluppi d’ampiezza a proposito del calcolo di se-gnali in tempo differito. In particolare si era avuto modo di notare comela classe Env fosse specializzata nella generazione di “segnali” d’inviluppo.In realtà un oggetto di tipo Env non è un segnale, ma una sorta di stam-po del profilo temporale dilatabile (o comprimibile) a piacere. Tant’è cheper ottenere un segnale in tempo differito era stato necessario inviareil messaggio asSignal. In tempo reale un oggetto Env è una “forma”temporale a disposizione di una UGen specializzata che, leggendo il

contenuto di Env , genera un segnale: la UGen EnvGen è appunto spe-cializzata in questo compito. In effetti, l’argomento times del costrut-tore di Env , che richiede di specificare un array di durate, deve esse-re inteso non come una specificazione assoluta, quanto piuttosto pro-porzionale. Le durate specificate indicano cioè la proporzione tra partidell’inviluppo (si ricordi che le durate sono qui riferite agli intervalli tra

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 181/328

7.1–178

valori d’ampiezza), non necessariamente una indicazione cronometri-ca. Si consideri la definizione nel sorgente SC del metodo *ar di EnvGen(che è uguale, tasso a parte, a quella di *kr):

*ar { arg envelope, gate = 1.0, levelScale = 1.0, levelBias = 0.0,

timeScale = 1.0, doneAction = 0;}

Come specifica ulteriormente dall’help file relativo, l’argomento enve-

lope è un’istanza di Env. Gli argomenti levelScale, levelBias, ti-

 meScale sono tutti operatori che trasformano l’inviluppo passato comeprimo argomento. Si prenda come esempio l’inviluppo

1 e = Env.new(

2 levels:[0.0, 1.0, 0.5, 0.5, 0.0],

3 times: [0.05, 0.1, 0.5, 0.35]

4 ).jplot ;

• levelScale: moltiplica i valori d’ampiezza dell’inviluppo. Il valorepredefinito è 1.0 , che lascia i valori di levels in e immutati

• levelBias: viene sommato ai valori d’ampiezza. Se questi sono com-presi in entrata nell’escursione [0.0, 1.0] , in uscita essi saranno com-presi in [0 + levelBias, 1.0 + levelBias]. Anche qui il valore didefault (

0.0) non modifica i valori di e

• timeScale: moltiplica i valori di durata. La durata del nuovo invi-luppo sarà perciò timeScale × times. Il totale degli intervalliin e è pari a 1 , dunque la durata dell’inviluppo generato da EnvGen

sarà pari a 1 × timeScale. Come in precedenza, il valore prede-finito (1.0) non cambia i valori dell’inviluppo passato come primoargomento.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 182/328

7.1–179

Come si vede EnvGen può “stirare” la forma dell’inviluppo in lungo e inlargo. In effetti, conviene utilizzare come escursione sia per l’ampiezzache per la durata di un inviluppo Env l’intervallo normalizzato [0.0, 1.0].Si potrà poi agire sugli argomenti di EnvGen. Nell’esempio seguente vie-ne modificato un esempio tratto dall’help file. Qui l’inviluppo è il tipicoinviluppo percussivo senza sostegno, accessibile inviando a Env il mes-saggio perc

1 // explicit signal multiplication2 { EnvGen.kr(Env.perc, 1.0, doneAction: 0) * SinOsc.ar(mul: 0.1) }.play

;

4 // effect of timeScale

5 { EnvGen.kr(Env.perc, 1.0, timeScale: 10, doneAction: 0) * SinOsc.ar(mul:

0.1) }.play ;

7 // using mulAmp

8 { SinOsc.ar(mul: 0.1 * EnvGen.kr(Env.perc, 1.0, timeScale: 10, doneAction:

0) ) }.play ;

10 // gate = 0

11 { EnvGen.kr(Env.perc, 0.0, doneAction: 0) * SinOsc.ar(mul: 0.1) }.play

;

13 // controlling the gate

14 { EnvGen.kr(Env.perc, SinOsc.kr(4), doneAction: 0) * SinOsc.ar(mul:

0.1) }.play ;

16 JMouseBase.makeGUI ; // SwingOSC17 { EnvGen.kr(Env.perc, GUI.mouseX.kr(-1,1), doneAction: 0) * SinOsc.ar(mul:

0.1) }.play ;

Si confrontino i segnali risultanti dalle righe 2 e 5 di codice. Si noteràl’effetto di timeScale , che dilata gli intervalli temporali di un fattore 10.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 183/328

7.1–180

L’esempio di riga 3 illustra un’implementazione tipica dell’inviluppo: idue segnali vengono moltiplicati tra di loro ed, essendo un unipolare el’altro bipolare, il risultato sarà un segnale bipolare (la sinusoide invi-luppata, come si vede sostituendo a play il metodo jplot). L’altra im-plementazione tipica in SC (che produce lo stesso risultato) è illustratanella riga successiva in cui il segnale di inviluppo generato da EnvGen èil valore dell’argomento mul.Gli altri due argomenti sono:

• gate: l’argomento gate specifica un trigger. Un trigger è un segnaledi attivazione, è “qualcosa che fa partire qualcosa”. Per la precisione,un trigger funziona come una fotocellula: ogniqualvolta registra unpassaggio, invia un segnale. Tipicamente in SC il passaggio che fascattare il trigger è il passaggio dallo stato di partenza, che ha valore0 , ad uno stato con valore > 0. In sostanza, EnvGen genera al tassoprescelto un segnale d’ampiezza pari a 0 finché non riceve il trigger.A quel punto legge l’inviluppo. Nei tre esempi alle righe 1-7 il valore

di gate è 1.0 (che è anche quello di default): essendo superiore a 0 fascattare il trigger. L’attivazione del trigger dice alla UGen EnvGen dileggere l’inviluppo. Dunque, eseguendo il codice si ascolta il segnaleinviluppato. L’esempio successivo prevede come valore di gate 0 , eil trigger non scatta. Se si sostituisce ad una costante un segnale iltrigger viene attivato tutte le volte che viene sorpassato il valore disoglia 0. Nella riga 12 è una sinusoide con frequenza 4Hz che con-trolla il trigger gate. Tutte le volte che supera l’asse delle ascisse (en-

trando nel semipiano positivo sopra lo 0) il trigger viene attivato. Ciòavviene 4 volte al secondo. Infine, nell’esempio seguente gate è unsegnale generato daGUI.mouseX. L’asse orizzonatale della tavola gra-fica costruita da JMouseBase.makeGUI viene ripartito nell’intervallo[−1, 1]. Lo 0 è perciò a metà lungo l’asse. Tutte le volte che lo sisupera il trigger viene attivato.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 184/328

7.1–181

1 { EnvGen.kr(Env.perc, 1.0, doneAction: 0) * SinOsc.ar(mul: 0.1) }.play;

3 // –> SC works for you

5 (

6 SynthDef.new("sinePerc",

7 { Out.ar(0, EnvGen.kr(Env.perc, 1.0, doneAction: 2)

8 *

9 SinOsc.ar(mul: 0.1))

10 }).send(s);11 )

13 Synth.new("sinePerc") ;

• doneAction: un suono percussivo quale quello generato inviluppan-do una sinusoide, ad esempio con Env.perc , genera il tipico invilup-po percussivo senza sostegno. Ma che succede quando l’inviluppoè terminato? È necessario ricordare che nell’esempio di partenza, ri-portato qui sopra nella riga 1, SC svolge un lavoro oscuro ma sostan-ziale, che è riportato dalla riga 6 in avanti:

− crea una synthDef− istanzia da questa un synth e lo mette in funzioneSe si considera questo secondo blocco di codice, si può meglio ap-

prezzare il problema. Che fine fa il synth? Senza deallocazione espli-cita, resta attivo: EnvGen continua a generare un segnale d’ampiezzanulla, e un’altra UGen responsabile della sinusoide, SinOsc un altrosegnale. Spetta infatti all’utente rimuovere il synth un volta che que-sti ha generato il segnale percussivo richiesto. Una sequenza di 20suoni percussivi allocherebbe un numero analogo di synth, con in-tuibile spreco di RAM e di CPU. L’argomento doneAction permette

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 185/328

7.2–182

di evitare il lavoro di deallocazione, poiché esso viene preso in ca-rico direttamente da scsynth. L’argomento doneAction permette dispecificare che cosa scsynth debba fare del synth in questione unavolta terminata la lettura dell’inviluppo. I valori possibili sono at-tualmente 14. Ad esempio con doneAction = 0 scsynth non fa nullae il synth resta allocato e funzionante. Il valore più utilizzato è do-

neAction = 2 , che dealloca il synth. In sostanzia quel synth non c’èpiù e non c’è da preocuparsi della sua esistenza. Ovviamente il synthnon è più disponbile. Se si volesse generare un’altra sinusoide per-cussive sarebbe necessario costruire un altro synth dalla stessa syn-thDef. Si consideri l’esempio seguente in cui il mouse funziona comeun trigger. Se doneAction = 0 il synth è residente e ad ogni passag-gio del mouse può essere attivato grazie al trigger. Se doneAction

= 2 dopo la prima attivazione il synth è deallocato e il comporta-mento del mouse non può inviare alcun messaggio. Nell’interfacciagrafica del server è visibile il numero dei synth attivi: si nota alloral’incremento del numero quando è creato il synth (implicitamente)e il diverso comportamento (persitenza/decremento) in funzione didoneAction.

1 JMouseBase.makeGUI ; // SwingOSC

3 // after reading Env.perc synth is still resident

4 { EnvGen.kr(Env.perc, GUI.mouseX.kr(-1,1), doneAction: 0) * SinOsc.ar(mul:

0.1) }.play ;

6 // after reading Env.perc synth is freed

7 { EnvGen.kr(Env.perc, GUI.mouseX.kr(-1,1), doneAction: 2) * SinOsc.ar(mul:

0.1) }.play ;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 186/328

7.2–183

7.2 Generalizzazionedegliinviluppi

Sebbene l’uso degli inviluppi sia tipico (e sia stato originato) per l’ampiezza,va comunque ricordato che EnvGen è di fatto un lettore di tabelle. Unoggetto Env è in effetti del tutto analogo ad una cosiddetta tabella in cui

sono tabulati punti che descrivono un profilo.EnvGen

è allora un’unitàdi lettura di tabelle speciali (di tipo Env) il cui contenuto può essere uti-lizzato per controllare parametri di diverso tipo. Si consideri il codiceseguente:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 187/328

7.2–184

1 (2 SynthDef.new("sinEnv",

3 {

4 // defining an env

5 var levels, times, env ;

6 levels = Array.fill(50, { arg x ; sin(x)*x }).normalize ;

7 times = Array.fill(49, 1).normalizeSum ;

8 env = Env.new(levels, times) ;

9 // using it extensively

10 Out.ar(0,

11 Pan2.ar(12 SinOsc.ar(

13 freq: Latch.kr(

14 EnvGen.kr(env, timeScale: 50,levelScale: 100, levelBias:30

).poll

15 .midicps.poll,

16 LFPulse.kr(

17 EnvGen.kr(env, timeScale: 50, levelScale: 5, levelBias:

10))

18 ),

19 mul: LFPulse.kr(EnvGen.kr(env, timeScale: 50,levelScale: 10,levelBias: 15 )) ),

20 EnvGen.kr(env, timeScale: 50, levelScale: 2, levelBias: -1),

21 0.4

22 )

23 )

24 }).send(s) ;

25 )

27 Synth.new("sinEnv") ;

Alcune considerazioni sulla synthDef:

• InviluppoLe righe 5-9 definiscono un inviluppo env , costituito da 50 pun-ti d’ampiezza intervallati da 49 durate. In particolare levels è un

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 188/328

7.2–185

array che contiene un frammento di sinusoide che cresce progressi-vamente in ampiezza. La progressività è data dal moltiplicatore *x ,dove x è l’indice dell’elemento calcolato. Si provi:

Array.fill(50, { arg x ; sin(x)*x }).normalize.plot ;

Il metodo normalize scala i valori dell’array nell’intervallo [0.0, 1.0].

1 [1,2,3,4,5].normalize

3 [ 0, 0.25, 0.5, 0.75, 1 ]

Nell’esempio dalla post window l’intervallo in cui sono compresii valori del array sono riscalati tra [0.0, 1.0]. I punti d’ampiezzacalcolati per levels sono pensati come equispaziati. È per questoche la definizione di times produce semplicemente un array riem-pito dal valore 1. Il metodo normalizeSum restituisce un array ar-

ray/array.sum , dove a sua volta il metodo sum restituisce la sommadegli elementi dell’array in questione.

1 [1,2,3,4,5].sum

3 15

5 [1,2,3,4,5].normalizeSum

7 [ 0.066666666666667, 0.13333333333333, 0.2, 0.26666666666667,

0.33333333333333 ]

9 [1,2,3,4,5].normalizeSum.sum

11 1

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 189/328

7.2–186

Come si vede nell’esempio dalla post window, la somma degli ele-menti nell’array è 15 e dunque normalizeSum divide per 15 ognielemento dell’array. Poiché 5 dà un contributo pari a un terzo di 15 ,nell’array restituito da normalizeSum il valore relativo è pari ad unterzo di 1 (0.3 . . .). I due array levels e times sono allora nella for-ma normalizzata preferibile. L’idea alla base della synthDef è quel-la di utilizzare lo stesso inviluppo, opportunamente modificato, percontrollare aspetti diversi del segnale.Prima di addentrarsi nella descrizione delle relazioni tra le UGenconviene avere sottomano un diagramma di flusso che ne visualizzile relazioni, quale quello in Figura 7.1. Il diagramma è semplificatorispetto al codice, piché non vi sono rappresentati i valori numericidegli inviluppi (che altrimenti risulterebbero in un grafico illeggibi-le).

E nvGe n gat e: 1 l evel Sc al e: 10 0 l evel Bi as : 30 t im eS ca le : 50 doneA ct ion: 0 : 1 : 1 : -99 : -99 : 0 : 1 : 1 : 0

 

M ID IC PS a

 

Po ll tr ig i n la be l: -1 tr ig id : 12 : 85 : 71 : 101 : 110 : 40 : 69 : 110 : 118 : 71 : 101 : 110 : 41

 

P oll tr ig i n l abe l: -1 tr ig id : 17 : 8 5 : 7 1 : 101 : 110 : 40 : 85 : 110 : 97 : 114 : 12 1 : 79 : 112 : 85 : 7 1 : 101 : 110 : 4 1

 

L at ch i n t ri g

 

Impu lse freq: 10 phase: 0

 

Impu lse freq: 10 phase: 0

 

E nvGe n gat e: 1 l evel Sc al e: 5 l evel Bi as : 1 0 t im eS ca le : 50 doneA ct ion: 0 : 1 : 1 : - 99 : -99 : 0 : 1 : 1 : 0

 

LFPulse freq iphase: 0 width : 0 .5

 

S inOs c f re q pha se : 0

 

* a b

 

E nvGe n gat e: 1 l evel Sc al e: 2 l evel Bi as : 1 0 t im eS ca le : 50 doneA ct ion: 0 : 1 : 1 : -99 : -99 : 0 : 1 : 1 : 0

 

M ID IC PS a

 

LFPulse freq iphase: 0 width: 0.5

 

P an 2 i n p os l ev el : 0 .4

 

E nvGe n gat e: 1 l evel Sc al e: 2 l evel Bi as : - 1 t im eS ca le : 50 doneA ct ion: 0 : 1 : 1 : -99 : - 99 : 0 : 1 : 1 : 0

 

O ut b us : 0 c ha nnel sA rr ay n il

Fig. 7.1 Diagramma di flusso (semplificato).

• Out.ar(0, Pan2.ar(SinOsc.ar. . .Si consideri la Figura 7.2 che riporta l’ultima parte del diagramma di

flusso. In nero è rappresentato il flusso del segnale audio.Iniziando dal fondo, la UGen finale è Out che invia al bus 0 quan-to previsto dall’argomento successivo, Pan2.ar. Quest’ultima UGengestisce il panning stereo, ovvero la distribuzione tra due anali delsegnale: il suo metodo *ar è così descritto nel codice sorgente:

*ar { arg in, pos = 0.0, level = 1.0;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 190/328

7.2–187

 

Latch in trig

 

S inOsc freq phase: 0

 

* a b

 

MIDICPS a

 

LFPul se fr eq i pha se: 0 wid th: 0.5

 

Pan2 in pos level: 0.4

 

EnvGen gate: 1 levelScale: 2 levelBias: -1 t imeScale : 50 doneAct io

Out bus: 0 channelsArray nil

Fig. 7.2 Diagramma diflusso (semplificato): estratto.

Pan2 riceve cioè in entrata un segnale in e lo posiziona tra i due ca-nali attraverso l’argomento pos: se pos vale −1 allora il segnale ètutto sul canale sinistro, se pos vale 1 è tutto sul destro, se pos vale 0è ripartito tra i due in misura uguale. Ovviammente tutti i valori in-termedi sono possibili. L’argomento level permette di specifcare unmoltiplicare generale per cui vengono scalati entrambi i segnali pri-ma di andare in uscita. Dunque ad Out è richiesto attraverso Pan2 diinviare alla scheda audio una coppia di segnali ottenuta scalando inmodo “complementare” l’ampiezza del segnale in. Si noti come ven-ga specificato un unico bus (0), ma il segnale sia distribuito su duecanali (è stereo). Se ne discuterà più avanti, per ora si osservi come alpanner venga fornito in entrata un segnale generato da un oscillatoresinusoidale (opportunamente) scalato: ciò che avviene dunque è che

una sinusoide (opportunamente) elaborata viene (opportunamente)distribuita dal panner sui due canali. Nella synthDef, mentre level

vale 0.4 (riga 22), il primo uso dell’inviluppo env è nel controllo delpanning, cioè come argomento di pos (riga 21, cfr. 7.2). Qui EnvGenlegge env espandendolo temporalmente di un fattore 50 (timeSca-le), espandendone l’escursione dei valori dall’originario [0.0, 1.0]a [0.0, 2.0] (levelScale), aggiungendovi −1 (levelBias), così chel’escursione finale sia [−1.0, 1.0] , ovvero quella richiesta da Pan2.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 191/328

7.2–188

Il panning seguirà l’inviluppo env a sinusoide crescente, oscillandosempre di più sbilanciato tra i due canali.

• SinOsc.ar. . .Il blocco compreso tra le righe 13 e 20 contiene la definizione delsegnale che viene distribuito dal panner: si tratta di un oscillatoreSinOsc. Se si comincia dalll’argomento mul si nota come sia occu-pato da un generatore di onde impulsie a bassa frequenza, secondoun esempio già discusso in un altro caso. L’unica variante è che la

frequenza degli impulsi che modulano la sinusoide varia seguendoenv (20). In modo analogo a quanto visto sopra, il segnale generatoda EnvGen in questo caso varierà tra [15.0, 25.0] , sempre lungo 50secondi. Si noti che l’incremento della densità delle pulsazioni è cor-relato allo spostamento verso il canale destro (è lo stesso inviluppo).

• freq: Latch.kr. . .Se si osserva nuovamente la Figura 7.1 si nota come l’argomento freq 

di SinOsc sia controllato da una UGen, Latch. Dunque, la frequenzavaria in funzione del segnale generato da Latch. Quest’ultima imple-menta in SC un algoritmo classico, detto sample and hold. Si osservila sintassi del metodo *kr dal codice sorgente:

*kr { arg in = 0.0, trig = 0.0;

Il primo argomento, in , è un segnale da cui Latch preleva un valore.Il segnale in uscita da Latch è costituito da un valore costante pari alvalore campionato fino al prelievo successivo: di qui il nome tipicodi sample (campiona) and hold (tieni). Il campionamento dipende datrig: un segnale trigger che attiva il prelevamento ogni volta chesi ha passaggio da negativo a positivo. Si considerino i due esempiseguenti:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 192/328

7.2–189

1 // line going from 1 to 0 in 20 secs2 { Line.kr(1, 0, 20) }.scope

4 // sampled & held by a latch

5 { Latch.kr(Line.ar(1, 0, 20), SinOsc.ar(0.5)) }.scope

La prima funzione genera un segnale i cui valori diminuiscono li-

nearmente da 1 a 0 nell’arco di 20 secondi. La seconda campionaattraverso Latch il primo segnale “pescando” ad una frequenza chedipende dal trigger definito da SinOsc. Si ha triggering tutte le vol-te che il segnale passa da negativo a positivo: poiché la sinusoidecon i valori predefinti oscilla tra [−1, 1] un simile passaggio si hatutte le volte che la sinusoide inizia il ciclo (con valore 0). Atten-zione, il passaggio da positivo a negativo a metà del ciclo non fun-ziona come trigger. La frequenza della sinusoide è pari ad un ciclo

ogni due secondi. Dunque, il valore campionato da Latch verrà te-nuto per due secondi. Se si eseguono le righe di codice si nota comenella prima ci sia un decremento continuo nel tempo, mentre nellaseconda, che mostra l’output del Latch , si vede attraverso gli scattiche l’aggiornamento procede a frequenza 0.5Hz (una volta ognidue secondi, appunto). Nell’esempio di partenza Latch campionae mantiene il segnale in uscita da EnvGen (riga 15). Si noti time-Scale = 50 che dilata l’inviluppo env in un tempo di 50 secondi.

Per quanto concerne i valori d’ampiezza essi saranno compresi in[0, 1] × 100 + 30 = [30, 130]: env è infatti compreso tra [0, 1] ,ma viene prima moltiplicato per levelScale e quindi sommato a le-velBias. Tralasciando momentaneamente il messaggio poll si notiil messaggio successivo, midicps , che chiede di convertire i valori in

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 193/328

7.2–190

uscita da valori midi a frequenze (cps , o Hz: è quantitativamen-te lo stesso). Il valore midi del la sopra il do centrale è 69 , e la suafrequenza 440Hz. Dunque:

1 69.midicps

3 440

5 440.cpsmidi

7 69

In forma più complessa:

1 Array.series(7, 10,1).postln.midicps

3 [ 10, 11, 12, 13, 14, 15, 16 ]

4 [ 14.56761754744, 15.433853164254, 16.351597831287, 17.323914436055,18.354047994838, 19.44543648263, 20.601722307054 ]

Tornando all’escursione dell’esempio:

1 [30, 130].midicps

2 [ 46.249302838954, 14917.240368579 ]

Quest’ultima è l’escursione in Hz in cui si muove l’inviluppo. Que-st’inviluppo viene campionato a tasso variabile, poiché la frequenzadi campionamento di Latch è controllata da un generatore di impul-si, LFPulse , la cui frequena di pulsazione è a sua volta determinata da

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 194/328

7.2–191

un EnvGen a cui è fornito l’inviluppo env. Anche questo env è dilata-to in 50 secondi, mentre la sua escursione (la frequenza di LFPulse)si estende in [10, 15] (Hz).

• poll

L’architettura client/server di SC pone un problema di rilievo chespesso risulta nascosto. Il processo di sintesi è controllato dal client,ma è realizzato dal server. Il cliente dice cosa fare al fornitore di ser-vizi il quale svolge la sua azione ottemperando alle richieste. Come

però può sapere il client cosa succede dentro il server? Come si fa asapere se non si sono commessi errori di implementazione? Il solofeedback audio non è sufficiente (il fatto che il risultato sia interes-sante indipendentemente dalla correttezza dell’implementazione èsenz’altro positivo, ma la serendipità non aiuta il debugging . . .). Ilfeedback visivo (attraverso i metodi scope e plot ad esempio) non èanalitico, cioè non comunica direttamente cosa succede in termini dicampioni audio calcolati. Il metodo poll , definito sulle UGen, dice

al server di inviare indietro al client il valore di un campione audio,ad un tasso impostabile come argomento del metodo, e di stampar-lo sulla post window. Questo permette di monitorare cosa succedea livello campione nel server in uscita da ogni UGen. In sostanza, ilmetodo può essere concatenato dopo i metodi ar e kr. Ad esempio:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 195/328

7.3–192

1 {SinOsc.ar(Line.ar(50, 10000, 10).poll).poll}.play

3 Synth("temp__1198652111" : 1001)

4 UGen(Line): 50.0226

5 UGen(SinOsc): 0.00712373

6 UGen(Line): 149.523

7 UGen(SinOsc): -0.142406

8 UGen(Line): 249.023

9 UGen(SinOsc): -0.570459

10 UGen(Line): 348.523

11 UGen(SinOsc): -0.98286312 UGen(Line): 448.023

13 UGen(SinOsc): -0.616042

14 UGen(Line): 547.523

15 UGen(SinOsc): 0.676455

Per ogni UGen, poll stampa sullo schermo il valore del segnale inuscita. Si noti come SinOsc oscilli in [−1, 1] mentre Line inizi la pro-gressione lineare da 50 a 10000.La sequenza poll.midi.pollnell’esempio precedente stampa primail valore in uscita da EnvGen , quindi la sua conversione in Hz.

7.3 Sinusoidi&sinusoidi

L’ipotesi alla base dell’utilizzo di un inviluppo d’ampiezza sta nel con-trollo di un segnale da parte di un altro segnale in modo da ottenere unrisultato più “complesso”, “naturale”, “interessante” etc. Un segnale diinviluppo è un segnale unipolare, ma è evidentemente possibile utiliz-zare segnali bipolari. In particolare la sinusoide non è soltanto la formad’onda che produce lo spettro più semplice ma è anche la forma tipicache assume una variazione regolare intorno ad un punto di equilibrio.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 196/328

7.3–193

Dunque, una sinusoide descrive opportunamente un fenomeno di oscil-lazione intorno ad un valore medio. Si considerino due casi:

1 // minimal tremolo

2 { SinOsc.ar(mul: 0.5+SinOsc.kr(5, mul: 0.1)) }.play

4 // minimal vibrato

5 { SinOsc.ar(freq: 440+SinOsc.kr(5, mul: 5)) }.play

7 // with mouse control

9 JMouseBase.makeGUI ; // SwingOSC

11 // tremolo

12 { SinOsc.ar(mul: 0.5 + SinOsc.kr(

13 freq: GUI.mouseX.kr(0, 10),

14 mul: GUI.mouseY.kr(0.0, 0.5))) }.play

16 // vibrato

17 { SinOsc.ar(freq: 440 + SinOsc.kr(

18 freq: GUI.mouseX.kr(0, 10),

19 mul: GUI.mouseY.kr(0, 10))) }.play

• tremolo: in musica un tremolo è una variazione periodica della dina-mica, ovvero dell’ampiezza come dimensione percettiva. L’implementazione

di un tremolo è evidentemente semplice. È sufficiente sommare all’ampiezzadel primo oscillatore il segnale prodotto da un oscillatore di control-lo: l’incremento varierà periodicamente con frequenza pari a quelladell’oscillatore di controllo da 0 fino al massimo (l’ampiezza dellostesso oscillatore), discenderà a 0 e al massimo negativo per ritor-nare infine a 0. Nell’esempio l’argomento mul contiene una costante(0.5) a cui vine sommato il segnale in uscita da un oscillatore che

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 197/328

7.3–194

varia 5 volte al secondo nell’escursione [−

0.1, 0.1]. Dunque, conla stessa frequenza l’ampiezza dell’oscillatore portante (audio) va-rierà nell’intervallo [0.4, 0.6]. Il contributo dell’oscillatore di con-trollo è allora una variazione periodica dell’ampiezza del segnalecontrollato, variazione il cui periodo è specificato dalla frequenzadell’oscillatore di controllo. Il suono sintetico acquista così una ca-ratteristica tipica dell’esecuzione strumentale (per esempio, dei fiati).Nell’esempio alle righe 11-14 viene utilizzato il mouse per controlla-re i due parametri del tremolo.

[Lavori in corso: introducendo il mouse ricordare che l'origine

sulla tavola è in alto a sx]

• vibrato: se si applica il ragionamento svolto per il tremolo questa vol-ta non all’ampiezza ma alla frequenza, si ottiene un vibrato. Un oscil-latore di controllo controlla un incremento (minimo) della frequen-za dell’oscillatore principale. Supponendo che f 1,amp1, f 2,amp2

siano frequenza e ampiezza rispettivamente dell’oscillatore audio edi quello di controllo, la frequenza dell’oscillatore audio (f 1 , finoracostante) dopo l’incremento varia periodicamente (secondo la fre-quenza dell’oscillatore f 2 di controllo) tra f 1–amp2 e f 1 + amp2.Si ricordi che l’uscita del segnale di controllo è infatti sempre una va-riazione d’ampiezza ±amp2: questa variazione si somma in questocaso alla frequenza dell’oscillatore controllato f 1. Nell’esempio (5),la variazione di frequenza è data dalla somma alla costante 440 del

segnale di un oscillatore che 5 volte al secondo oscilla tra [−5, 5] (siveda mul): dunque per 5 volte al secondo la frequenza audio varieràtra [435, 445]. Analogamente a quanto visto per il tremolo, è for-nito anche un esempio in cui frequenza e ampiezza del vibrato sonocontrollabili via mouse. Il risultato musicale di una simile variazioneperiodica dell’altezza di una nota viene definito vibrato. Il periododel vibrato dipende dal periodo dell’oscillatore di controllo: si pensi

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 198/328

7.3–195

a un violinista che sposta di poco ma continuamente il suo dito at-torno alla posizione della nota prescelta. Ancora: nella tipica tecnicadel canto operistico si mettono in atto simultaneamente tremolo evibrato.

Un esempio riassuntivo è il seguente:

1 (

2 SynthDef("tremVibr",

3 { arg freq = 440, mul = 0.15,4 tremoloFreq = 5 , tremoloMulPercent = 5,

5 vibratoFreq = 10, vibratoMulPercent = 5 ;

6 var tremoloMul = mul*tremoloMulPercent*0.01 ;

7 var vibratoMul = freq*vibratoMulPercent*0.01 ;

8 var tremolo = SinOsc.kr(tremoloFreq, 0, tremoloMul) ;

9 var vibrato = SinOsc.kr(vibratoFreq, 0, vibratoMul) ;

10 var sinOsc = SinOsc.ar(freq+vibrato, 0, mul+tremolo) ;

11 Out.ar(0, sinOsc) ;

13 }).send(s) ;14 )

16 (

17 // pure sinusoid

18 var aSynth ;

19 aSynth = Synth.new("tremVibr", [ "tremoloMulPercent", 0, "vibratoMulPercent",

0]) ;

20 )

La synthDef "tremVibr"prevede argomenti per il controllo dell’oscillatoreaudio e di tremolo e vibrato (si noti come tutti abbiano valori predefi-niti). Sia di tremolo che di vibrato è possibile controllare la frequenzae l’incidenza. Le prima è in entrambi i casi descritta in termini assoluti,cioè attraverso i cicli al secondo (insomma, in Hz). Come si vede alle ri-ghe 8 e 9, tremolo e vibrato sono due segnali in uscita da due oscillatori

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 199/328

7.3–196

sinusoidali che hanno appunto come freq rispettivamente tremoloFreq e vibratoFreq . Più interessante la descrizione dell’incidenza dei due pa-rametri (ovvero di quanto variano il segnale audio). In entrambi i casil’incidenza è relativa alla stato del segnale da controllare. in altre parole,l’incidenza è proporzionale ed è descritta percentualmente. Si consideri

var tremoloMul = mul*tremoloMulPercent*0.01 ;

tremoloMul è calcolato assumendo che tremoloMulPercent , il parame-

tro controllabile dal synth, corrisponda ad una percentuale dell’ampiezzadel segnale. Se mul = 0.5 e tremoloMulPercent = 10 alloratremoloMul sarà pari al 10% di mul , cioè a 0.05. Dunque, il segna-le assegnato a tremolo sarà compreso nell’escursione [−0.05, 0.05]e l’ampiezza del segnale audio assegnato alla variabile sinOsc oscille-rà nell’intorno [0.45, 0.55]. Si ricordi che sinOsc è appunto una va-riabile, da non confondere con la UGen SinOsc): attraverso la variabi-le SinOsc il segnale viene passato come argomento ad Out. Un discor-

so analogo al calcolo del tremolo vale per il vibrato con il calcolo divibratoMul. Nell’esempio, viene quindi creato un synth aSynth in cuiviene annullato in fase di creazione il contributo di tremolo e vibrato as-segnando un valore pari a 0 ai due argomenti "tremoloMulPercent" e"vibratoMulPercent" (non c’è incidenza di tremolo e vibrato poiché idue segnali di controllo hanno ampiezza nulla).A partire da una simile synthDef è possibile costruire una interfacciagrafica per controllare gli argomenti di un synth. L’idea di partenza

è avere per ogni parametro un cursore e di visualizzarne il nome e ilvalore. Dato il numero esiguo di parametri si potrebbe semplicementecostruire l’interfaccia “artigianalmente”, definendo cioè singolarmentetutti i componenti GUI necessari. Vale la pena però sperimentare un al-tro approccio, più automatizzato, secondo quanto già visto nella primainterfaccia grafica realizzata, quella “inutile”. Le classi di elementi ne-cessarie sono due:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 200/328

7.3–197

1. GUI.slider: permette di costruire un cursore (in inglese, uno slider):la sintassi del costruttore (22) è piuttosto ovvia, giacché richiede unafinestra di riferimento (qui window23) e un rettagolo in cui viene dise-gnato il cursore.

2. GUI.staticText: è un campo di testo per la visualizzazione, che perònon prevede riconoscimento dell’input (scrive testo sullo schermoma non serve per immetterlo). La sintassi del costruttore è quellaconsueta, e definisce un riquadro ove verrà stampato sullo schermo

il testo. In più (17 e 28) viene chiamato sull’istanza così ottenuta ilmetodo string_ che definisce il testo da stampare.

Si tratta di definire un array che contenga i nomi degli argomenti, e apartire da questo di

1. generare gli oggetti grafici2. definire le azioni associate a questi ultimi

L’unica difficoltà sta nel fatto che nel connettere valori in uscita dal cur-sore e argomenti del synth è necessario tenere in conto di un mappingdisomogeneo. Ogni cursore ha un’estensione compresa in [0, 1]. La fre-quenza freq dell’oscillatore audio può avere un’escursione compresa in[50, 10000] , mentre la sua ampiezza mul è invece compresa in [0, 1] ,le frequenze di tremolo e vibrato sono tipicamente comprese in un regi-stro sub-audio, [0, 15] , mentre le due incidenze devono essere espres-se percentualmente, dunque in

[0, 100]. È perciò necessario un lavo-

ro di scalatura dei valori espressi da ogni cursore in quanto relativoad un preciso parametro. Non è opportuno passare i valori non scala-ti al synth includendo dentro la synthDef le operazioni necessarie alloscaling: in questo modo si verrebbe infatti a definire una dipendenza

Si noti come window sia resa più alta del richiesto aggiungendovi 30 × 2 pixel in al-23

tezza.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 201/328

7.3–198

della synthDef dall’interfaccia grafica. Nel lavoro con l einterfacce gra-fiche è invece bene assumere che il modello e i dati siano indipenden-ti dall’interfaccia di controllo/display. In questo modo, si può buttarevia l’interfaccia senza dover modificare il modello (qui, la synthDef).D’altra parte, nella definizione di un algoritmo di sintesi quale previ-sto dalla synthDef è del tutto fuori luogo prevedere elementi che in-vece concernono la GUI. La soluzione proposta dell’esempio prevedel’uso di un IdentityDictionary , ovvero di una struttura dati che as-socia in maniera univoca ad una chiave un valore, secondo il modellodel dizionario che prevede per ogni lemma (la chiave) una definizio-ne (il valore): controlDict associa ad ogni stringa-argomento un arrayche ne definisce l’escursione (secondo il modello [minVal, maxVal]). Laparte di codice compresa tra 13 e 30 definisce tre array che contengo-no un numero pari alla dimensione di controlDict rispettivamente di

 blocchi di testo per la visualizzazione del nome del parametro, cursori e blocchi di testo deputati alla visualizzazione del valore degli argomenti.Quindi viene istanziato un synth. Infine si tratta di definire la funziona-lità della GUI attraverso un ciclo su ognuno degli elementi contenuti incontrolDict. Nel ciclo value indica l’elemento di destra (l’escursione),ed a partire da questa si ottiene la chiave name attraverso l’invocazionedel metodo controlDict.findKeyForValue(value). Ad esempio, se va-lue è [50, 1000] , la chiave associata a name sarà "freq". Quindi vienecalcolata un’escursione range tra [0, 1] come differenza tra gli estremi(nell’esempio, 1000 − 50 = 950) e il minimo viene considerato comescarto di partenza (offset).

labelArr[index].string_(name)

assegna all’elemento di testo index in labelArr la stringa name che virisulta visibile (nell’esempio, "freq"). Infine

slidArr[index].action = . . .

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 202/328

7.3–199

assegna all’elemento index di slidArr un’azione attraverso il consue-to meccanismo di una funzione che viene valutata ogni qualvolta si re-gistra una variazione nello stato del cursore (un movimento della levagrafica). Nella funzione l’argomento (qui: theSlid) è come di consue-to l’istanza dell’elemento grafico su cui è definita la funzione. L’azionerealizza quattro comportamenti, ognuno descritto da un’espressione al-le righe 39-42.

1. dichiarando la variabile paramValue se ne calcola il valore. Nell’esempio

precedentemente relativo a "freq" , poiché theSlid.value è semprecompreso in [0, 1] ed essendo range = 50 , l’escursione varia ap-punto tra [0, 950] + 50 = [50, 1000]

2. la seconda azione consiste nello stampare sullo schermo il nome delparametro ed il suo valore

3. si tratta di controllare il synth impostando per l’argomento name il

valore paramValue (ovvero: aSynth.set(”freq” , 123.4567890)

4. infine il valore paramValue viene scritto nell’elemento di testo index

in valueArr.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 203/328

7.3–200

1 (2 var aSynth = Synth.new("tremVibr") ;

4 var controlDict = IdentityDictionary[

5 "freq" -> [50, 1000],

6 "mul" -> [0,1],

7 "tremoloFreq" -> [0, 15],

8 "tremoloMulPercent" -> [0, 50],

9 "vibratoFreq" -> [0, 15],

10 "vibratoMulPercent" -> [0, 50]

11 ];

13 var window = GUI.window.new("Control Panel",

14 Rect(30,30, 900, controlDict.size+2*30)) ;

16 var labelArr = Array.fill(controlDict.size, { arg index ;

17 GUI.staticText.new( window, Rect( 20, index+1*30, 200, 30 ))

18 .string_( 0 ) ;

19 }) ;

21 var slidArr = Array.fill(controlDict.size,22 { arg index ;

23 var slid = GUI.slider.new( window, Rect( 240, index+1*30, 340,

30 ));

24 slid ;

25 }) ;

27 var valueArr = Array.fill(controlDict.size, { arg index ;

28 GUI.staticText.new( window, Rect( 600, index+1*30, 200, 30 ))

29 .string_( 0 );

30 }) ;

32 controlDict.do({ arg value, index ;

33 var name = controlDict.findKeyForValue(value) ;

34 var range = value[1]-value[0] ;

35 var offset = value[0] ;

36 [value, index].postln;

37 labelArr[index].string_(name) ;

38 slidArr[index].action = { arg theSlid ;

39 var paramValue = theSlid.value*range + offset ;

40 [name, paramValue].postln ;41 aSynth.set(name, paramValue) ;

42 valueArr[index].string_(paramValue.trunc(0.001) ) ;

43 }

44 }) ;

46 window.front ;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 204/328

7.3–201

Si noti come l’interfaccia dipenda dal dizionario che connette la GUIal modello (la synthDef) definendo per ogni argomento il mapping op-portuno. Aggiornando la struttura dati per una nuova synthDef la GUIcambia di conseguenza. Nell’esempio che segue è stata definita una nuo-va SynthDef: per costruire un pannello di controllo è stato necessarioistanziare un synth con il nome della synthDef e aggiornare il control-Dict. Il resto del codice è stato omesso perché uguale a precedente.

1 (

2 SynthDef("resonantDust", { arg rlpfFreq = 300, dustFreq = 100,

3 rq = 0.01, mul = 10,

4 delay = 0, decay = 0 ;

5 Out.ar(0, CombL.ar(RLPF.ar(Dust.ar(dustFreq), rlpfFreq, rq, mul),

6 1, delay, decay))

7 }

8 ).send(s) ;

9 )

11 (

12 var aSynth = Synth.new("resonantDust") ;

14 var controlDict = IdentityDictionary[

15 "rlpfFreq" -> [50, 1000],

16 "mul" -> [0,20],

17 "dustFreq" -> [0, 300],

18 "rq" -> [0, 0.1],

19 "delay" -> [0, 10],

20 "decay" -> [0, 10]21 ];

23 […]

25 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 205/328

7.3–202

Un certo numero di informazioni potrebbero poi essere desunte dallastessa synthDef se assegnata a variabile. Nell’esempio seguente la syn-thDef "resonantDust" è assegnata ad a: se si invia il messaggio name ada quest’ultima restituisce il suo nome.

1 a = SynthDef("resonantDust", { arg rlpfFreq = 300, dustFreq = 100,

2 rq = 0.01, mul

= 10,

3 delay = 0,

decay = 0 ;4 Out.ar(0, CombL.ar(RLPF.ar(Dust.ar(dustFreq), rlpfFreq, rq,

 mul),

5 1, delay, decay))

6 }

7 ).send(s) ;

9 a.name ;

11 resonantDust

Si potrebbero allora desumere in automatico dalla synthDef i nomdi de-gli argomenti che costituiscono le chiavi di controlDict. In particolaregli argomenti di una UGen-Graph function prendono il nome di control

names.

1 a.allControlNames

3 [ ControlName P 0 rlpfFreq control 300, ControlName P 1 dustFreq control 100, ControlName P 2 rq control 0.01, ControlName P 3 mul

control 10, ControlName P 4 delay control 0, ControlName P 5 decay

control 0 ]

Dall’array restituito da allControlNames , che prevede una sintassi spe-cifica, non è allora difficile ottenere le stringhe necessarie per le chiavidi controlDict

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 206/328

7.3–203

1 a.allControlNames.do({ arg item ;2 item.postln ;

3 item.asString.split($ )[4].postln ;

4 "\n".postln

5 })

6 ControlName P 0 rlpfFreq control 300

7 rlpfFreq 

9 ControlName P 1 dustFreq control 100

10 dustFreq 

12 ControlName P 2 rq control 0.01

13 rq 

15 ControlName P 3 mul control 10

16 mul

18 ControlName P 4 delay control 0

19 delay

21 ControlName P 5 decay control 022 decay

Nel codice prima viene stampato item , cioè il nome intero. Nella rigasuccessiva, lo stesso è esplicitamente convertito in stringa (asString),quindi in suddiviso blocchi separati da un carattere di spaziatura ” ”: ladefinizione del carattere prevede l’uso del prefisso $, e il metodo resti-tuisce un array che contiene i singoli blocchi ottenuti come elementi. Ad

esempio:

1 "to be or not to be".split($ )

3 [ to, be, or, not, to, be ]

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 207/328

7.3–204

Dell’array così ottenuto si prende l’elemento numero 4 , ovvero il nomedel parametro, che viene scritto sulla post window. L’unico problema diun approccio simile è che il mapping tra domini numerici (tra escursionedi ogni cursore e escursione del parametro correlato) non può essereautomatizzato, ma deve essere definito caso per caso. Dunque, l’uso diun dizionario, oltre ad esemplificare la struttura dati, si rivela una sceltainteressante. L’unica controindicazione sta nel fatto che un dizionarionon è una struttura “ordinata”: nel ciclo, l’ordine in cui vengono lette lechiavi è infatti deciso internamente da SC (e, tra l’altro, varia per ogniesecuzione del codice). In effetti, modificando il codice, sarebbe forsepiù opportuno utilizzare un array di array così:

1 [

2 ["rlpfFreq", 50, 1000],

3 ["mul", 0,20],

4 ["dustFreq", 0, 300],

5 ["rq", 0, 0.1],

6 ["delay", 0, 10],7 ["decay", 0, 10]

8 ]

Infine, si può ristrutturare il problema. Ciò che è richiesto è una GUIautomatica a partire dalla synthDef che prevede un controllo per ogniargomento, la cui escursione deve essere impostabile dall’utente. Per in-tanto la synthDef può essere assegnata ad una variabile globale ~aDef ,

così da essere richiamata in seguito.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 208/328

7.3–205

1 (2 ~aDef = SynthDef("tremVibr",

3 { arg freq = 440, mul = 0.15,

4 tremoloFreq = 0 , tremoloMulPercent = 0,

5 vibratoFreq = 0, vibratoMulPercent = 0 ;

6 var tremoloMul = mul*tremoloMulPercent*0.01 ;

7 var vibratoMul = freq*vibratoMulPercent*0.01 ;

8 var tremolo = SinOsc.kr(tremoloFreq, 0, tremoloMul) ;

9 var vibrato = SinOsc.kr(vibratoFreq, 0, vibratoMul) ;

10 var sinOsc = SinOsc.ar(freq+vibrato, 0, mul+tremolo) ;

11 Out.ar(0, sinOsc) ;

13 }).send(s) ;

14 )

A questo punto (esempio successivo) è possibile istanziare subito unsynth a partire dal nome della synthDef (~aDef.name) (2). Recuperandoil codice già discusso in precendenza, a partire dalla lista dei controlNa- mes si definisce un controlArr: un array che contiene per ogni argomen-

to un array [nome dell'argomento, valore minimo, valore massimo].In fase di costruzione massimi e minimi sono impostati rispettivamen-te a 1 e a 0 (11). Viene quindi costruito un secondo array guiArr i cuielementi sono correlati uno ad uno con controlArr: è l’array che con-tiene gli oggetti GUI relativi a ciascun argomento della synthDef. Perogni elemento in controlArr viene creato un elemento in guiArr. Traquesti ci sono anche due campi numerici che accettano in entrata un va-lore impostabile dall’utente, due istanze di GUI.numberBox. La sintassi èpiuttosto intuitiva: si noti che viene loro assegnato il valore di massimoe minimo contenuto nel corrispettivo elemento di controlArr , attraver-so value_(item[. . .]) (22 3 24). Per ogni argomento c’è un elementonell’array controlArr che contiene

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 209/328

7.3–206

1. il nome2. il minimo3. il massimo

e c’è un elemento in guiArr che contiene (19-27)

1. un campo di testo dove scrivere il nome2. un campo numerico dove inserire il minimo3. un campo numerico dove inserire il massimo

4. un cursore di controllo5. un campo di testo dove scrivere il valore attuale dell’argomento

Creata l’interfaccia grafica, si tratta a questo punto di associare agli ele-menti le azioni opportune, secondo quanto avviene nelle righe 31-49.Per ognuno degli elementi di controlArr si recupera un elemento diguiArr (32-33). Questo elemento è un array che contiene tutti gli ogget-ti relativi all’argomento che è elemento di controlArr. La definizionedelle azioni concerne soltanto tre degli elementi grafici, quelli che devo-no rispondere all’interazine con l’utente. Questi deve poter muovere ilcursore dopo aver determinato massimi e minimi di ciascun argomento.

• L’azione collegata ai campi numerici (guiElement[1] e guiElement[2])assegna il valore immesso (value) dall’utente ai rispettivi campi dimassimo e minimo dell’elemento correlato in controlArr. Se dun-que l’utente imposta nei campi numerici relativi a "freq"] i valori20 e 10000 , l’elemento relativo in controlArr sarà ["freq", 20,

10000]

• Infine guiElement[3] è il cursore che controlla gli argomenti ipostan-doli sul synth. Il codice è uguale all’esempio precedente con un’unicadifferenza. Le variabili sono dichiarate all’interno della funzione checontrolla l’azione. Questo passaggio si rende necessario perché ran-

ge e offset dipendo dai massimi e dai minimi, e questi possono es-sere variati dall’utente. È necessario perciò che ad ogni movimento

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 210/328

7.3–207

del cursore si aggiornino i valori di massimo e minimo leggendolidall’array controlArr.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 211/328

7.3–208

1 (2 var aSynth = Synth.new(~aDef.name) ;

4 var controlArr = [], guiArr = [] ;

6 var window ;

8 ~aDef.allControlNames.do({ arg item ;

9 var name = item.asString.split($ )[4] ;

10 controlArr = controlArr.add([name, 0.0, 1.0])

11 }) ;

13 window = GUI.window.new(~aDef.name++" Control Panel",

14 Rect(30,30, 900, controlArr.size+2*30)).front ;

16 // GUI creation

17 controlArr.do({ arg item, ind ;

18 var index = ind + 1; // add some space

19 var guiElement = [

20 GUI.staticText.new( window, Rect( 20, 30*index, 200, 30 ))

21 .string_( item[0] ),22 GUI.numberBox.new( window, Rect( 240, 30*index, 50, 30 ))

23 .value_(item[1]),

24 GUI.numberBox.new( window, Rect( 300, 30*index, 50, 30 ))

25 .value_(item[2]),

26 GUI.slider.new( window, Rect( 370, 30*index, 340, 30 )),

27 GUI.staticText.new( window, Rect( 720, 30*index, 200, 30 ))

28 .string_( 0.0 ) ] ;

29 guiArr = guiArr.add(guiElement) ;

30 }) ;

32 // GUI action definition

33 controlArr.do({ arg item, index ;

34 var guiElement = guiArr[index] ;

35 guiElement[1].action = { arg minBox ;

36 item[1] = minBox.value ;

37 } ;

38 guiElement[2].action = { arg maxBox ;

39 item[2] = maxBox.value ;

40 } ;

41 guiElement[3].action = { arg slider ;42 var name = item[0] ;

43 var range = item[2].value - item[1].value ;

44 var offset = item[1].value ;

45 var paramValue = slider.value*range + offset ;

46 [name, paramValue].postln ;

47 aSynth.set(name, paramValue) ;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 212/328

7.4–209

7.4 Segnalipseudo-casuali

La discussione precedente in relazione al controllo di un oscillatore daparte di un altro oscillatore può essere intuibilemente estesa alla più ge-nerale prospettive del controllo di una UGen da parte di un altra UGen.I segnali di controllo precedenti erano sinusoidi: in particolare la formad’onda sinusoidale era appunto il profilo temporale della variazione in-dotta nel segnale. Un profilo di variazione può evidentemente assumereforme diverse. Negli esempi seguenti le prime funzioni contengono unsegnale di controllo che verrà impiegato per controllare il vibrato di unoscillatore (con frequenza sub-audio e a tasso di controllo) nelle seconde.Attraverso il metodo jscope è possibile visualizzre il profilo dei primisegnali di controllo (per comodità di visualizzazione la frequenza è sta-ta modificata a 1000 Hz). In generale le UGen che iniziano con LF sonospecializzate nella generazioni di segnali di controllo.

1 { SinOsc.ar(1000) }.scope ;

2 { SinOsc.ar(freq: 440+SinOsc.kr(2, mul: 50), mul: 0.5) }.play ;

4 { LFSaw.ar(1000) }.scope ;

5 { SinOsc.ar(freq: 440 + LFSaw.kr(2, mul: 50), mul: 0.5) }.play ;

7 { LFNoise0.ar(1000) }.scope ;

8 { SinOsc.ar(freq: 440 + LFNoise0.kr(2, mul: 50),mul: 0.5) }.play ;

10 { LFNoise1.ar(1000) }.scope ;

11 { SinOsc.ar(freq: 440 + LFNoise1.kr(2, mul: 50), mul: 0.5) }.play ;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 213/328

7.4–210

Si nota immediatamente la differenza tra i due segnali periodici, la si-nuoside e l’onda a dente di quadra, proprio in relazione al profilo udi-

 bile della variazione. Le due Altre UGen impiegate sono specializzatenella generazione di segnali pseudo-casuali. In particolare LFNoise0 ge-nerata ad una certa frequenza valori d’ampiezza che tiene per la duratadi ogni periodo (cioè, fino quando non calcola un un nuovo valore): sesi osserva la finestra attivata quando jscope è invocato sulla UGen sinota l’andamento a gradoni. Come LFNoise0 , LFNoise1 genera segnalipseudo-casali alla frequenza impostata, ma interpola tra gli estremi suc-cessivi. In altre parole, non salta da un valore al successivo, ma vi arrivagradualmente. L’esempio seguente è minimale ed il comportamento deidue generatori ne risulta chiaramente illustrato.

1 {SinOsc.ar(LFNoise1.ar(10, mul:200, add: 400))}.play

3 {SinOsc.ar(LFNoise0.ar(10, mul:200, add: 400))}.play

In entrambi i casi la frequenza dell’oscillatore è controllata da un gene-ratore di numeri casuali che aggiorna il suo stato 10 volte al secondo.In considerazione degli argomenti mul e add il segnale di controllo dellafrequenza varia casualmente allora nell’escursione [−1, 1] × 200 +

400 = [200, 600]. Con LFNoise0 si ha un  gradatum (di tipo scala-

re), con LFNoise1 un continuum (un glissando). Si potrebbe pensare aLFNoise0 come ad una versione di LFNoise1 sampled and held: si pren-de un campione di un segnale che interpola tra valori pseudo-casualiquale quello generato da LFNoise1 ad un ogni intervallo di tempo pre-stabilito e lo si tiene fino al prelevamento successivo. Come si è visto,un simile comportamento è realizzato da Latch. L’esempio seguente èuna variazione di un esempio dall’help file di Latch. In entrambi i casi il

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 214/328

7.4–211

segnale in uscita varia la sua frequenza ad un tasso di 9 volte al secondoscegliendo casualmente nell’intervallo [100, 900].

1 { SinOsc.ar(LFNoise0.kr(9, 400, 500), 4, 0.2)}.play

3 // the same but less efficient

5 { SinOsc.ar(Latch.ar(LFNoise1.ar, Impulse.ar(9)) * 400 + 500, 4, 0.2)

}.play;

Per la sua natura discreta LFNoise0 può essere utilizzato come compo-nente di un sequencer, cioè come generatore di sequenze discrete di va-lori. Due variazioni sul tema sono presentate nell’esempio seguente.

1 SynthDef("chromaticImproviser", { arg freq = 10 ;

2 Out.ar(0, SinOsc.ar(

3 freq: LFNoise0.kr(freq, mul:15, add: 60).round.midicps,4 mul: EnvGen.kr(Env.perc(0.05), gate: Impulse.kr(freq), doneAction:2)

)

5 )

6 }).play

8 SynthDef("modalImproviser", { arg freq = 10;

9 var scale = [0, 0, 0, 0, 3, 3, 4, 5, 5, 6, 6, 7, 7, 7, 10]+60 ;

10 var mode = scale.addAll(scale+12).midicps ;

11 var range = (mode.size*0.5).asInteger ;

12 Out.ar(0, SinOsc.ar(13 freq: Select.kr(LFNoise0.kr(freq,

14 mul: range,

15 add: range).round, mode),

16 mul: EnvGen.kr(Env.perc(0.05), gate: Impulse.kr(freq), doneAction:2)

)

17 )

18 }).play

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 215/328

7.4–212

I due “improvvisatori” generano sequenze casuali di altezze ad un tassopredefinito di 10 note al secondo. In entrambi i casi il generatore audioeè un oscillatore sinusoidale con un inviluppo percussivo.Il primo, vagamente hard bop , genera una sequenze di altezze cromatichecomprese tra in midi tra [45, 75]. Nel midi sono numerate linearmen-te le altezze, come se si trattasse di assegnare un indice ai tasti (bian-chi e neri) di un pianoforte. In notazione midi il do centrale è 60 , dun-que le altezze variano tra il quindiciesimo tasto che lo precede, corri-spondente al la al di sotto dell’ottava inferiore, e il quindicesimo ta-sto seguente, il mi bemolle al di sopra dell’ottava superiore. Infatti la fre-quenza dell’oscillatore audio è data dalla sequenza di valori in uscita daLFNoise0 , moltiplicati per 15 e sommati a 60 (secondo quanto previstoda mul, add). Per rappresentare i tasti del pianoforte sono utilizzati inmidi i numeri interi, mentre i valori intermedi corrispondono a frazionidi semitono. Siccome qui interessano le altezze temperate (trenta tastidi pianoforte), il segnale viene arrotondato all’intero tramite il metodoround (3).Il secondo gestisce le altezze in maniera diversa. In primo luogo scale

definisce una scala che comprende le altezze indicate nell’array. Si notiche all’array viene aggiunto 60 , dunque le altezze (in notazione midi)saranno:

1 [0, 0, 0, 0, 3, 3, 4, 5, 5, 6, 6, 7, 7, 7, 10]+60

2 [ 60, 60, 60, 60, 63, 63, 64, 65, 65, 66, 66, 67, 67, 67, 70 ]

ovvero do, mi bemolle, mi, fa, fa diesis, sol, sib , alcune delle quali ripetute.Il modo (cioè la sequenza effettiva) su cui il generatore improvvisa è de-finito come scale a cui viene aggiunta una copia di se stesso traspostadi un’ottava. Si ricordi che in midi il salto di ottava, pari ad un raddop-pio della frequenza, equivale ad un incremento di 12 (ovvero: 12 tastisul pianoforte). L’array mode viene quindi convertito in Hz attraverso

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 216/328

7.4–213

 midicps (10). La scelta della frequenza da generare è determinata dallaUGen Select , la sui sintassi prevede

*ar { arg which, array;

In sostanza, dato un array , Select ne restituisce l’elemento which. Ascanso di equivoci, si ricordi che, essendo una UGen, Select restitui-sce un segnale, cioè una sequenza, a tasso audio o di controllo, com-posta dall’elemento which di array. L’idea è quella di far selezionare

casualmente a Select una frequenza dall’array mode. Per fare ciò vieneutilizzato LFNoise0. Quest’ultimo, a frequenza freq  , genera un nume-ro compreso in [−range, +range] + range = [0, 2range] , dovela variabile range è definita come la metà intera di della dimensione di mode (11). Quindi, se mode.size = 26 , allora range = 13 , e LFNoise oscil-

lerà in [0, 26]. Essendo i valori in uscita da LFNoise0gli indici dell’arrayda cui Select legge, devono essere interi: di qui l’invocazione del me-todo round. Si è notato che mode contiene più volte gli stessi valori: è

un modo semplice (un po’ primitivo, ma efficace. . .) per fare in modoche certe altezze vengano scelte con frequenze fino a quattro volte su-periori ad altre. La scala enfatizza allora il primo, e poi il terzo minore,il quarto, il quarto aumentato e il quinto grado, ed è per questo (assai)vagamente blueseggiante. Infine, un’ultima annotazione sull’inviluppod’ampiezza. Il segnale in uscita dall’oscillatore è continuo e deve essereinviluppato ogni volta che si produce un cambiamento di altezza, ov-vero alla stessa frequenza di LFNoise0 , in modo tale da sincronizzare

altezze e ampiezza in un evento notale: per questo l’argomento gate ri-ceve come valore il segnale in usicta da Impulse , ovvero una sequenza diimpulsi che attivano l’inviluppo alla stessa frequenza freq di LFNoise0.Nell’esempio precedente l’utilizza di EnvGen richiede di specificare perl’argomento gate un trigger che operi alla stessa frequenza di LFNoise0:a tal fine è stata impiegata la UGen Impulse. Un segnale pseudo-casualespesso utilizzato come trigger è quello generato da Dust: quest’ultima

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 217/328

7.4–214

produce una sequenza di impulsi, nell’escursione [0, 1] , che è distri- buita irregolarmente (stocasticamente) nel tempo, alla densità media alsecondo definita dal primo argomento density.

*ar { arg density = 0.0, mul = 1.0, add = 0.0 ;

Se negli esempi precedenti si sostituisce a Impulse Dust , lasciando inal-terto il resto del codice, si ottien che gli inviluppi verrano generati in unnumero medio pari a freq al secondo, manon in una serie cronometrica-

mente regolare. Nell’esempio seguente le ascisse del mouse controllanola densità, che varierà nell’escursione [1, 500].

1 JMouseBase.makeGUI ; // SwingOSC

2 { Dust.ar(GUI.mouseX.kr(1, 500)) }.play

L’utilizzo di Dust come trigger è piuttosto diffuso in SC. L’esempio se-guente è tratto dall’help file di TRand , un altra UGen interessante: TRandgenera un valore pseudo-casuale compreso nell’escursione descritta daidue primi arogmenti:

*ar { arg lo = 0.0, hi = 1.0, trig = 0.0;

La generazione avviene ogni qualvolta il trigger cambia stato, passandoda negativo a positivo. Nell’esempio seguente la prima parte prevede

una come trigger Impulse: ad ogni nuovo impulso un Trand genera unnuovo valore utile alla frequenza di SinOsc. Si noti che è un altro modoper ottenere l’effetto sample & hold implementato con Latch. Se si sosti-tuisce Impulse con Dust , si ottiene una sequenza di impulsi (e dunquedi inviluppi) in una quantità media pari a freq .

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 218/328

7.5–215

1 (2 {

3 var trig = Impulse.kr(9);

4 SinOsc.ar(

5 TRand.kr(100, 900, trig)

6 ) * 0.1

7 }.play;

8 )

10 (

11 {12 var trig = Dust.kr(9);

13 SinOsc.ar(

14 TRand.kr(100, 900, trig)

15 ) * 0.1

16 }.play;

17 )

7.5 Espansioneeriduzionemulticanale

Nell’esempio relativo alla generalizzazione degli inviluppi si è fatto ri-

ferimento a Pan2 , che riceveva in ingresso un segnale mono e fornivacome output una coppia di segnali risultanti da una varia distribuzionedell’ampiezza del segnale. Un segnale stereo, come quello in uscita daPan2 , è in effetti una coppia di segnali che devono essere eseguiti in pa-rallello, tipicamente su due (gruppi di) altoparlanti. Tuttavia non è statonecessario specificare nella sintassi di Out una coppia di bus, bensì sol-tanto l’indice 0. Nella fattispecie, SC distribuisce automaticamente i due

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 219/328

7.5–216

segnali sul necessario numero di bus contigui (in questo caso 0 e 1). Que-st’operazione prende il nome di multichannel expansion. Più in generale,è importante sapere che SC opera una espansione multicanale tutte levolte che un argomento di una UGen è costituito da un array. Così nel-la prima synthdef dell’esempio seguente (”multi1”) l’argomento freq ècostituito non da un segnale o da un numero, ma da un array: dunqueSC genererà una coppia di sinuosodi con frequenza 100 e 1000 cheverrano inviate rispettivamente sui bus 0 e 1. In altre parole la synth-Def è identica nei risultati a quella successiva, ”multi2” , in cui esplicita-mente vengono inviati due segnali diversi ai due bus 0 e 1. Ma anche ilterzo esempio, ”multi3” , è equivalente: in esso Out riceve un array co-me valore dell’argomento channelArray , ed esegue di conseguenza unaespansione multicanale, secondo quanto esplicitamente prescritto nellasynthDef ”multi2”.

1 SynthDef( "multi1", {

2 Out.ar(0, SinOsc.ar([100, 1000]))

3 }).play ;

5 SynthDef( "multi2", {

6 Out.ar(0, SinOsc.ar(100))

7 + Out.ar(1, SinOsc.ar(1000))

8 }).play ;

10 SynthDef( "multi3", {

11 Out.ar(0,

12 [SinOsc.ar(100), SinOsc.ar(1000)])

13 }).play ;

. L’espansione multicanale avviene soltanto ed esclusivamente quandoagli argomenti di una UGen viene passato un oggetto di tipo , Array ,non per le sue sopraclassi né per le sue sottoclassi. A pensarci, questo

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 220/328

7.5–217

tipo di costrutto sintattico è estremamente potente. Si consideri quantoavviene nell’esempio seguente:

1 SynthDef("multi16", {

2 var bFreq = 100 ; // base freq 

3 var sigArr = Array.fill(16,

4 { arg ind ;

5 var index = ind+1 ;

6 SinOsc.ar(

7 freq: bFreq*index+(LFNoise1.kr(

8 freq: index,

9 mul: 0.5,

10 add: 0.5)*bFreq*index*0.02)

11 )

12 }) ;

13 Out.ar(0, sigArr)

14 }

15 ).play ;

Il diagramma di flusso è fornito in Figura 7.3 , mentre un dettaglio è ri-prodotto ingrandito in Figura 7.4.Partendo dal fondo del codice, e come si vede nelle Figure 7.3 e 7.4 ,si può osservare come Out riceva come argomento di channeslsArrayl’array sigArr , costituito da 16 segnali.

Out.ar(0, sigArr)

Quest’ultimo è ottenuto chiamando il metodo costruttore fill a cui vie-ne indicato un numero (16, il numero di posti dell’array) e una funzione.Ogni chiamata della funzione restituisce un oggetto SinOsc.ar , ovveroun segnale sinusoidale, in cui il valore dell’argomento freq è correlatoall’indice progressivo dell’array. Nell’esempio seguente sono aggiunticome commento i valori risultanti dai primi due cicli dell’array. Come si

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 221/328

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 222/328

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 223/328

7.5–220

1 SynthDef("multi16commented", {2 var bFreq = 100 ; // base freq 

3 var sigArr = Array.fill(16,

4 { arg ind ; // 0 1

5 var index = ind+1 ; // 1 2

6 SinOsc.ar(

7 freq: bFreq*index // 100 200

8 +(LFNoise1.kr( // +

9 freq: index, // freq: 1

10 mul: 0.5,

11 add: 0.5) // amp: 1 1 (fixed)12 *bFreq   // bFreq: 100 (fixed)

13 *index*0.02) // *1*0.02 = 2 *2*0.05 = 4

14 )

15 }) ;

16 Out.ar(0, sigArr)

17 }

18 ).play ;

Dunque, ogni elemento di sigArr è un oggetto SinOSc.ar , un segnalegenerato da una UGen SinOsc. Poiché Out riceve un array, alloca un nu-mero di bus pari alla dimensione dell’array, a partire da quello indicato,cioè da 0. Le 16 sinusoidi (dotate di diversi parametri) sono distribui-te dai bus consecutivi 0 − 15 in 16 canali audio: se la scheda audioè in grado di gestire 16 canali, allora ad ognuno di essi verrà inviata

una delle sinusoidi. Senza l’espansione multicanale, sarebbe necessariodescrivere esplicitamente attraverso il codice la struttura riprodotta daldiagramma di flusso di Figura 7.3 , un lavoro oneroso che invece SC faper l’utente, espandendo ogni elemento dell’array in un opportuno ra-mo del diagramma come meglio si vede in Figura 7.4. I rami hanno lastessa struttura, ma parametri differenti.Se si ascolta su un normale dispositivo stereo (quale quello di un pc) il ri-sultato della valutazione del codice precedente, saranno udibili soltanto

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 224/328

7.5–221

le due prime sinusoidi, quelle con frequenza fondamentale pari a 100 e

200Hz. A tal proposito SC mette a disposizione dell’utente una UGenspecializzata nella riduzione multicanale, ovvero nel missaggio di piùsegnali in un unico segnale: Mix. Quest’ultima semplicemente prevedecome argomento un array di segnali che restituisce missati in un unicosegnale. La versione seguente modifica l’esempio in discussione fornen-do ad Out un unico segnale, grazie all’intervento di Mix (riga 14). SI notiche quest’ultima UGen semplicemente somma l’output dei segnali checompongono l’array che riceve come argomento.

1 SynthDef("multi16mix", {

2 var bFreq = 100 ; // base freq 

3 var sigArr = Array.fill(16,

4 { arg ind ;

5 var index = ind+1 ;

6 SinOsc.ar(

7 freq: bFreq*index+(LFNoise1.kr(

8 freq: index,

9 mul: 0.5,10 add: 0.5)*bFreq*index*0.02) ,

11 mul: 1/16 ;

12 )

13 }) ;

14 Out.ar(0, Mix.new(sigArr))

15 }

16 ).play ;

Se tutte le sinusoidi hanno ampiezza normalizzata (come nel caso indiscussione), allora l’escursione del segnale in uscita da Mix sarà com-presa in [−1, 1] × 16 = [−16, 16] , dunque abbondantemente oltrel’escursione rappresentabile dell’ampiezza. È perciò opportuno scalarel’ampiezza di ognuno dei segnali sinusoidali per un fattore pari ad 1/n

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 225/328

7.5–222

(riga 11), dove n è il numero dei segnali (la dimensione dell’array), inmodo che l’ampiezza complessiva sia 1/n × n = 1.Attraverso Mix si è persa la spazializzazione ottenuta attraverso la distri-

 buzione nei 16 canali (ancorché inudibili), ottenendo un unico segnale(mono, per così dire). Si tratta ora di utilizzare le possibilità dell’espansionemulticanale per una distribuzione stereo. Nell’esempio seguente vienegenerato un array di 16 segnali come negli esempi precedenti. Si notiperò che SinOsc.ar è diventato il segnale in entrata di una UGen Pan2.Come si è visto, Pan2 distribuisce un segnale in entrata su un fronte ste-reo in funzione dell’argomento pos. Per ogni sinusoide, pos varia casua-lemente in [−1, 1] con una frequenza pari a index (riga 15). Dunque,più elevato è l’indice, più elevata è la frequenza dell’oscillatore, più ra-pidamente varia la distribuzione spaziale. Si noti che è stata utilizzatala UGen LFNoise1 , che interpola tra valori successivi, per evitare salti diposizione, simulando invece un progressivo movimento tra i valori as-sunti dalla distribuzione. In sostanza, l’array sigArr ora contiene 16 se-gnali generati da Pan2 , cioè sinusoidi la cui frequenza e la cui frequenzadi spostamento sul fronte stereo incrementa progressivamente in fun-zione dell’indice dell’array. Ma Pan2 restituisce in uscita una coppia disegnali. Ogni segnale è infatti stereo, cioè è costituito da una coppia disegnali la cui ampiezza varia in funzione di pos. Si può verificare quantoosservato aggiungendo un riga

sigArr.postln ;

prima di riga 16 nella synthDef "multi16commented". Si otterà stampatosulla post window:

1 [ a SinOsc, a SinOsc, a SinOsc, a SinOsc, a SinOsc, a SinOsc, a

SinOsc, a SinOsc, a SinOsc, a SinOsc, a SinOsc, a SinOsc, a SinOsc,

a SinOsc, a SinOsc, a SinOsc ]

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 226/328

7.5–223

Se si fa lo stesso con "multi16mixPan" , togliendo il marcatore di com-mento alla riga 18, si ottiene invece:

1 [ [ an OutputProxy, an OutputProxy ], [ an OutputProxy, an OutputProxy

], [ an OutputProxy, an OutputProxy ], [ an OutputProxy, an OutputProxy

], [ an OutputProxy, an OutputProxy ], [ an OutputProxy, an OutputProxy

], [ an OutputProxy, an OutputProxy ], [ an OutputProxy, an OutputProxy

], [ an OutputProxy, an OutputProxy ], [ an OutputProxy, an OutputProxy

], [ an OutputProxy, an OutputProxy ], [ an OutputProxy, an OutputProxy

], [ an OutputProxy, an OutputProxy ], [ an OutputProxy, an OutputProxy

], [ an O…etc…

La denominazione OutputProxy è il modo con cui SC chiama l’outputdi alcune UGen che hanno uscite multiple (come Pan2). A parte que-sto aspetto, qui irrilevante, è interessante osservare che ogni elementodell’array è a sua volta un array composto di due elementi, uno per ca-nale. Si consideri il prossimo esempio:

1 { Out.ar(0, Pan2.ar(SinOsc.ar, Line.kr(-1, 1, 10), 0.5)) }.play;

3 // only left channel (non multichannel expansion)

4 { Out.ar(0, Pan2.ar(SinOsc.ar, Line.kr(-1, 1, 10), 0.5)[0]) }.play;

6 // only right channel (non multichannel expansion)

7 { Out.ar(0, Pan2.ar(SinOsc.ar, Line.kr(-1, 1, 10), 0.5)[1]) }.play;

Alla riga 1 una sinusoide si sposta progressivamente dal canale sinistroa quello destro: pos è un segnale generato dalla UGen Line che linear-mente muove nell’arco di 10 secondi tra −1 e 1. Questo movimentosi traduce sul fronte stereo in decremento dell’ampiezza del segnale sulcanale sinistro e in un incremento della stessa sul canale destro. Le righe4 e 6 inviano ad Out soltano uno dei due canali, rispettivamente sinitro

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 227/328

7.5–224

e destro (dunque, non c’è espansione multicanale). Si noti la sintassi cheè quella per il recupero degli elementi in un array, attraverso [0] e [1]

chiamati sull’array restituito da Pan2. Lo spostamento sul fronte stereoè analiticamente scomposto in un crescendo del segnale a destra ed inun diminuendo a sinistra.Tornando a ”multi16mixPan” , la disposizione delgi elementi in sigArr

è perciò

[[sig0sx, sig0dx], [sig1sx, sig1dx], [sig3sx, sig3dx] . . ., [sig15sx,

sig15sx]]

Come già visto, chiamando il metodo flop (riga 19) si ottiene un nuovoarray con questa struttura

[[sig0sx, sig1sx, sig2, sx, sig3sx, . . ., sig15sx], [sig0dx, sig1dx,

sig2, dx, sig3dx, . . ., sig15dx]]

che è composta di due array, uno per canale, contenenti in contributidi ognuno dei segnali sinusoidali a quel canale. È allora possibile mis-sare ognuno dei due array ottenendo due singoli segnali, per il cana-le sinistro e per quello destro (righe 20 e 21), assegnati alle variabilileft, right. Inviando a Out l’array [left, right] si produce di nuovoun’espansione multicanale, per cui il primo (left) verrà inviato, attra-verso il bus 0 , all’altoparlante sinistro, il secondo (right), attraverso il

 bus 1 , all’altoparlante destro.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 228/328

7.5–225

1 SynthDef("multi16mixPan", {2 var bFreq = 100 ; // base freq 

3 var left, right ;

4 var sigArr = Array.fill(16,

5 { arg ind ;

6 var index = ind+1 ;

7 Pan2.ar(

8 in: SinOsc.ar(

9 freq: bFreq*index+(LFNoise1.kr(

10 freq: index,

11 mul: 0.5,12 add: 0.5)*bFreq*index*0.02) ,

13 mul: 1/16 ;

14 ),

15 pos: LFNoise1.kr(freq: index)

16 )

17 }) ;

18 // sigArr.postln ;

19 sigArr = sigArr.flop ;

20 left = Mix.new(sigArr[0]) ;

21 right = Mix.new(sigArr[1]) ;22 Out.ar(0, [left, right])

23 }

24 ).play ;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 229/328

8.1–226

8 Sintesi,II:tecnichedigenerazionedelsegna-leaudio

8.1 Oscillatorietabelle

Discutendo di algoritmi di sintesi del segnali non in tempo reale, piùvolte si è discusso della generazione del segnale a partire dal calcolo diuna funzione, tipicamente sin(x). Sebbene concettualmente elegante,il computo diretto della funzione si rivela assai poco efficiente dal pun-to di vista computazionale: costringe infatti l’elaboratore a calcolare ilvalore della funzione per un numero di volte al secondo pari al tassodi campionamento prescelta (cioè 44.100 nel caso di qualità CD, il tas-

so di campionamento predefinto in SC). È possibile però impiegare unaltro metodo, che ha una lunga tradizione in computer music: si trattacioè di costruire un oscillatore digitale. Finora il termine è stato impiegatosenza fornirene una definizione: si trtta ora di vedere più in dettaglioche cosa esso indichi. L’oscillatore digitale è un algoritmo fondamenta-le nella computer music, poiché non è soltanto impiegato per generaredirettamente un segnale ma è anche un’unità componente di molti altri

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 230/328

8.1–227

generatori di suono. Tornando al problema della generazione di una si-nusoide, e ragionando diversamente, si può osservare come un suonosinusoidale (ma in generale la parte stazionaria di ogni suono periodi-co) sia caratterizzato da una grande prevedibilità: esso si ripete ugua-le ad ogni periodo. Dato un periodo del segnale, si può allora pensaredi prelevarne il valore in n punti equidistanti. Questi valori campiona-ti possono essere immessi in una tabella di n punti: alla lista dei punticorrisponde un’altra lista con i valori della funzione. Una tabella di que-sto tipo prende il nome di wavetable (tabella dell’onda o forma d’ondatabulata).

Time (s)0 16

 –1

1

0

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Fig. 8.1 Forma d’onda campionata

Ad esempio il campionanamento di una sinusoide in ampiezza norma-

lizzata (Figura 8.1) dà origine alla seguente tabella:

[00] = 0.19509032 [08] = -0.19509032 [01] = 0.55557024 [09]

= -0.55557024

[02] = 0.8314696 [10] = -0.8314696 [03] = 0.98078525 [11]

= -0.98078525

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 231/328

8.1–228

[04] = 0.98078525 [12] = -0.98078525 [05] = 0.8314696 [13]

= -0.8314696

[06] = 0.55557024 [14] = -0.55557024 [07] = 0.19509032 [15]

= -0.19509032

L’algoritmo dell’oscillatore digitale prevede fondamentalmente il sem-plice svolgimento di due operazioni:

“leggi i valori della tabella dall’area di memoria in cui questa è con-servata”;

1. “arrivato all’ultimo indirizzo (il 15 nell’esempio), riparti dal primo(0)”. Quest’ultima operazione si definisce wrappping around.

Il metodo di sintesi descritto (Table Look-Up Synthesis) è estremamenteefficiente: la lettura di un dato dalla memoria è infatti un processo assaipiù veloce che non il calcolo del valore di una funzione. È agevole os-servare come una simile operazione di stoccaggio di una “forma” e suo

successivo reperimento sia tra l’altro lo stesso approccio preso in con-siderazione nel momento in cui si è discusso di una generalizzazionedegli inviluppi. La tabella costituisce infatti un modello (statico e cari-cato in fase di inizializzzione) della forma d’onda: sta all’utente deci-dere ampiezza e frequenza del segnale sintetizzato dall’oscillatore. Perquanto concerne l’ampiezza l’operazione è ormai ovvia. Ad esempio,se il segnale tabulato ha ampiezza compresa in [−1, 1] , moltiplicandonell’oscillatore tutti i valori della tabella per 0.5 , il segnale in uscita avrà

un’ampiezza dimezzata, che oscillerà nell’escursione [–0.5, +0.5]. Co-me ormai noto, moltiplicare un segnale per un numero k produce comerisultato un segnale in cui ognuno dei valori risulta moltiplicato per k.Quindi, ognuno dei valori del segnale in entrata (la forma d’onda tabu-lata) viene scalato per 0.5 (Figura 8.2).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 232/328

8.1–229

Time (s)0 16

 –1

1

0

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

0.5

 –0.5

Fig. 8.2 Scalatura dell’ampiezza

Passando all’implementazione in SC, si noti che, se il problema fossela generazione di una sinusoide, in SC sarebbe sufficiente utilizzare leUGen specializzate SinOsc e FSinOsc:

• SinOsc implementa l’algoritmo di table look-up, ma non richiededi specificare una tabella poiché la prevede internamente (di 8192punti)

• FSinOsc implementa un approccio diverso al problema della genera-zione di una sinusoide, in modo molto efficiente (di qui la F di Fast)seppur con qualche limitazione d’uso.

Tuttavia l’utilizo di tabelle non si limita evidentemente alla tabulazio-ne di una sinusoide e vale perciò la pena di soffermacisivi. Una delleUGen che si occupano esplicitamente di leggere da tabelle è Osc , il cuiprimo argomento è una tabella, la cui dimensione deve essere un mul-tiplo di 2 (per ragioni di ottimizzazione), e il secondo la frequenza allaquale l’oscillatore legge la tabella. Se la tabella rappresenta il periodo diun segnale, la frequenza indicherà la frequenza del segnale risultante.La tabella può essere fornita a Osc attraverso un buffer. Come si è visto

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 233/328

8.1–230

discutendo il server, un buffer è una locazione di memoria temporanea,allocata dal server nella RAM, in cui possono essere memorizzati dati:ogni buffer (come ogni bus) è indirizzato attraverso un numero interounivoco attraverso il quale vi si può far riferimento. SC implementa unaclasse Buffer che si occupa della gestione dei buffer. In altre parole conun buffer si dice al server di riservare un certo spazio per certi dati. Laclasse Buffer prevede alcuni metodi per allocare buffer, per leggervidentro un file audio, ma anche per riempire direttamente un buffer conspecifici tipi di segnali, di larga utilità.

1 (

2 var buf ;

4 buf = Buffer.alloc(s, 2.pow(10)) ;

5 buf.sine1([1]) ;

7 {Osc.ar(buf.bufnum, 440)}.play

8 )

10 (

11 var buf ;

13 buf = Buffer.alloc(s, 2.pow(10)) ;

14 buf.sine1( Array.fill(20, { 1.0.rand }) ) ;

16 buf.plot ;

18 {Osc.ar(buf.bufnum, 440, mul: 0.6)}.jscope

19 )

Il codice precedente contiene due esempi. Nel primo alla variabile buf

viene assegnato un oggetto Buffer ottenuto chiamando sulla classe ilcostruttore alloc. Il metodo dice al server s24 di allocare un buffer di una

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 234/328

8.1–231

certa dimensione. La dimensione è di per sé arbitraria: tuttavia nell’implementazionedegli oscillatori viene tipicamente richiesto (non solo in SC) per questio-ni di ottimizzazione che la dimensione della tabella sia una potenza di 2(2.pow(10)). Quindi viene inviato a buf il messaggio sine1 che riempieil buffer con una somma di sinusoidi armonicamente relate. La sintas-si è analoga al metodo waveFill della classe Array: l’array contiene leampiezze della armoniche. Nella fattispecie c’è solo una sinusoide (lafondamentale) con ampiezza unitaria. Osc richiede come primo argo-mento un indicativo del buffer da leggere (la tabella, appunto). Questoindicativo non può essere il nome della variabile perche è sconosciutaal server, risiedendo sul lato di sclang: deve invece essere l’indice del

 buffer assegnato dal server. Per ottenerlo è sufficiente inviare a buf ilmessaggio bufnum , che restituisce l’indice del buffer (7): in questo modol’utente non si deve preoccupare di ricordare esplicitamente quale sial’indicativo assegnato ad ogni buffer. La tabella memorizzata nel bufferviene quindi letta con una frequenza pari a 440 volte al secondo. Nel se-condo esempio, l’array di ampiezze è generato attraverso il metodo fill

invocato su Array , che restituisce un array di 20 numeri pseudo-casualicompresi in [0.0, 1.0]: essi rappresentano le ampiezze stocastiche delleprime 20 armoniche. Come si vede, è possibile visualizzare i dati conte-nuti nel buffer attraverso il metodo plot (16). È altresì possibile fare inmodo che Osc legga da una tabella che contiene un segnale audio resi-dente sul disco rigido. Nell’esempio seguente viene dapprima generatoun segnale attraverso la classe Signal , a cui viene inviato il messaggiosineFill , che genera la consueta somma di sinusoidi: si noti che la di-mensione dell’array (primo argomento di sineFill) è immediatamente

stabilita in una potenza di 2 , ovvero 216 = 65536 (riga 6). Inoltre,per poter essere letto da Osc , il segnale deve essere convertito in un for-mato apposito, quale quello previsto dalla classe Wavetable: di qui la

Si ricordi che alla variabile globale e è riservato per default il server audio24

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 235/328

8.1–232

conversione sig = sig.asWavetable (riga 7). la synthDef seguente sem-plicemente ingloba in una UGen Out una UGen Osc , prevedendo comeargomento bufnum: questo indica l’identificativo (numerico) del buffer,che serve per potervi far riferimento (è il “nome” del buffer). Quindi lasynthDef viene spedita al server (22). Infine, dopo aver memorizzato ilsegnale sotto forma di file audio (10-14), è possibile caricarlo in un buf-fer: la riga 30 utilizza il metodo readche alloca un buffer sul server s evi legge il file indicato dal percorso. Il buffer viene assegnato alla varia-

 bile buf. La dimensione del buffer (quanta memoria occupa) è inferitadirettamente da SC a partire dalla dimensione del file. Così, il nuovoSynth che viene generato (33) utilizza il buffer buf , il cui indentificativosul server è buf.bufnum.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 236/328

8.1–233

1 (2 var sig ;

3 var soundFile ;

5 //–> generating a signal

6 sig = Signal.sineFill(2.pow(16), [1]) ; // 65536

7 sig = sig.asWavetable ; // mandatory !

9 //–> writing an audiofile

10 soundFile = SoundFile.new ;

11 soundFile.headerFormat_("AIFF").sampleFormat_("int16").numChannels_(1);

12 soundFile.openWrite("sounds/signalTest.aiff") ;

13 soundFile.writeData(sig) ;

14 soundFile.close ;

15 )

17 (

18 //–> writing a synthDef

19 SynthDef("tableOsc",{ arg bufnum = 0, freq = 440, amp = 0.4 ;

20 Out.ar(0,21 Osc.ar(bufnum, freq, mul: amp))

22 }).send(s) ;

23 )

25 (

26 var freq = 440 ;

27 var buf, aSynth;

29 //–> allocating a buffer and directly reading in an audio file

30 buf = Buffer.read(s, "sounds/signalTest.aiff") ;

32 //–> a tableOsc synth readding the table from the buffer

33 aSynth = Synth.new("tableOsc", ["bufnum", buf.bufnum]) ;

34 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 237/328

8.1–234

La caratteristica precipua dell’oscillatore è soltanto quella di generarecampioni sulla base della lettura della tabella: la forma d’onda tabulatanon dev’essere necessariamente sinusoidale. È possible infatti tabularequalsiasi forma, come pure importare una forma d’onda da un qualsiasisegnale preesistente.Nell’esempio seguente la tabella è riempita con valori pseudo-casuali: inparticolare la riga 12 sceglie per ogni elemento dell’array (di tipo Signal)un valore-pseudocasuale tra [0.0, 2.0] − 1 = [−1.0, 1.0]: il risultatoviene quindi converito in una Wavetable. Il resto del codice assume lasynthDef precedente ( "tableOsc" e riprende quanto già visto nel casodella generazione di una sinusoide. Una variabile di rilievo è exp (11),l’esponente di 2 che determina la dimensione della tabella (riga 12). Unoscillatore che non si arresti dopo una lettura della tabella (nel qual casoil concetto di frequenza di lettura non avrebbe molto senso) produce perdefinizione un segnale periodico: infatti reitera la lettura della tabella econseguentementemente il segnale si ripete uguale a se stesso. Più la ta-

 bella è grande, maggiore è l’informazione sulla sua “forma” (il dettagliotemporale) più il segnale è rumoroso. Viceversa, tabelle di dimensioniridotte producono segnali il cui profilo temporale è più semplice (menovalori pseudo-casuali), e dunque maggiormente “intonati”. Si provi adesempio a variare exp nell’escursione [1, 20] , e a visualizzare il conte-nuto del buffer così ottenuto con jplot.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 238/328

8.1–235

1 /*2 Periodic/Aperiodic

3 oscillator reading from a pseudo-random filled table

4 */

6 (

7 var sig, exp ;

8 var soundFile;

10 // table generation

11 exp = 6 ; // try changing it bewteen [1, 20]12 sig = Signal.fill(2.pow(exp), {2.0.rand-1}).asWavetable ;

14 //–> writing the audio file

15 soundFile = SoundFile.new ;

16 soundFile.headerFormat_("AIFF").sampleFormat_("int16").numChannels_(1)

;

17 soundFile.openWrite("sounds/signalTest.aiff") ;

18 soundFile.writeData(sig) ;

19 soundFile.close ;

20 )

22 (

23 var buf, aSynth ;

24 buf = Buffer.read(s, "sounds/signalTest.aiff") ;

25 aSynth = Synth.new("tableOsc", ["bufnum", buf.bufnum, "amp", 0.1]) ;

26 )

Una modulazione della frequenza dell’oscillatore indica allora una va-riazione della velocità di lettura della tabella. La synthDef seguente pre-vede una variazione pseudo-casuale della frequenza con LFNoise0 , se-condo una modlaità abbondantemente descritta. In particolare, con unatabella sinusoidale la synthDef riproduce esempi già visti. Si noti invececome nel caso di una tabella che contenga valori pseudo-casuali la varia-zione di velocità produca una variazione dell’altezza percepita soltanto

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 239/328

8.2–236

entro certi limiti, approssimativamente entro exp = 10. Oltre a talesoglia, la variazione nella tabella non mantiene più l’identità del profilotemporale che la tabelle descrive.

1 (

2 // modulating the freq 

3 SynthDef("tableOsc",{ arg bufnum = 0, freq = 440, amp = 0.4 ;

4 Out.ar(0,

5 Osc.ar(bufnum, LFNoise0.ar(10, mul: 400, add: 400), mul: amp))

6 }).send(s) ;7 )

8.2 Campionamento

Il metodo di sintesi concettualmente più semplice è il campionamen-to. Fondamentalmente, con l’espressione ”prelevare un campione” siindica l’ottenimento di un segnale di breve durata o attraverso la regi-strazione diretta, oppure attraverso un’operazione di editing da un fileaudio. In ogni caso, nella sintesi per campionamento l’idea centrale è

quella del playback di materiale sonoro preesistente.

8.2.1 Campionamentosemplice

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 240/328

8.2–237

Nel campionamento semplice si ripropone l’idea che abbiamo incontra-to discutendo dell’oscillatore: la lettura di una tabella. Se però in quelcaso la forma d’onda, oltre a essere estremamente semplice (ma sarebbestato possibile costruire una forma qualsiasi), era tipicamente ridotta aun unico periodo, nel campionamento invece la forma d’onda tabulatarappresenta un suono complesso dotato di inviluppo, la cui durata di-pende soltanto dalle limitazioni imposte dall’hardware. Come intuibile,l’origine del campione (per registrazione diretta o per estrazione da unfile preesistente) non fa alcuna differenza. Una volta messo in memoria,il campione può essere richiamato ogni qualvolta l’utente lo desideriattraverso un dispositivo di controllo. Nonostante la semplicità concet-tuale, è evidente la potenza di un simile approccio, poiché si può avereagevolmente a disposizione una ricca tavolozza di suoni preregistrati:ad esempio un intero set di percussioni, così come molte altre librerie dicampioni25.Sebbene possa essere senz’altro possibile utilizzare un oscillatore comeOsc per leggere un file audio preventivamente caricato in un buffer, laUGen specializzata nella lettura di un buffer è PlayBuf. Essa non incorrenel limite di avere una tabella la cui dimensione sia multiplo di 2 , mapuò invece leggere un buffer di dimensioni qualsiasi.

Non è questo il luogo per una sitografia, ma vale la pena di segnalare una risorsa di25

grande interesse, The Freesound Project ,http://freesound.iua.upf.edu/

che mette a disposizione con licenza Creative Commons decine di migliaia di file au-dio, tutti indicizzati, scaricabili o ascoltabili on-line.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 241/328

8.2–238

1 (2 SynthDef("playBuf", { arg bufnum = 0, loop = 0;

3 Out.ar(0,

4 PlayBuf.ar(1, bufnum, loop: loop)

5 )

6 }).send(s)

7 )

9 (

10 var buf, aSynth ;

11 buf = Buffer.read(s,"sounds/a11wlk01-44_1.aiff") ;

13 aSynth = Synth("playBuf", ["bufnum", buf.bufnum, "loop", -1])

14 )

Nell’esempio precedente la synthDef “avvolge” semplicemente playBufdi cui dimostra tre argomenti, i primi due e l’ultimo.

• Il primo argomento indica il numero dei canali (tipicamente, monoo stereo): se il suo valore è 1 , allora il buffer è mono

• il secondo specifica l’indice del buffer, qui controllabilem come ar-gomento bufnum della synthDef.

• l’argomento loop indica la modalità di lettura e può avere due valori:0 indica un’unica lettura del buffer, 1 una lettura ciclica.

Nel seguito viene allocato un buffer buf che legge dal disco fisso, nellacartella sound dell’installazione locale di SC, il file a11wlk01-44_1.aiff.Si noti che il file è stato campionato ad un tasso di campionamento paria 44100Hz (come dice anche il nome). SC lo legge alla sua frequen-za di campionamento, predefinita a 44100Hz: essendo le due uguali,non c’è problema. Se invece fossero diverse sarebbe necessario tenerneconto.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 242/328

8.2–239

8.2.2 Resamplingeinterpolazione

La semplice lettura del buffer, secondo quanto descritto per PlayBuf ,riproduce il segnale tale e quale vi è stato memorizzato. Ripensandoal caso di Osc si può tuttavia notare come fosse specificabile una fre-quenza: questa frequenza indicava il numero di letture al secondo dellatabella contenuta nel buffer da parte dell’oscillatore. Se la tabella fossedi dimensione fissa, si potrebbe leggere più o meno velocemente la ta-

 bella, variando opportunamente il tasso di campionamento di scsynth.Ma poiché un buffer ha una dimensione fissa ma in compenso anche lasample rate non è modificabile, per poter variare la frequenza del segna-le uscente è necessario lavorare sulla tabella in un altro modo. Questolavoro è comune anche a PlayBuf e permette così di”intonare” ancheun suono campionato in una tabella. Il procedimento più usato a talescopo è usualmente definito resampling , che equivale, come indica il no-me, a un vero e proprio ricampionamento. Si consideri nuovamente latabella di Figura ?? , che rappresenta una forma d’onda. Se si leggonotutti i punti della tabella, si ottiene il segnale originale. Si supponga in-vece, allo stesso taso di campionamento, di leggere soltanto un puntoogni due. Si ottiene come risultato un segnale dalla frequenza doppiarispetto all’originale. Infatti, il segnale risultante risulta costituito di un

numero di campioni pari alla metà del segnale originale, e dunque ilsuo periodo è pari alla metà del periodo originale, T 2 = T 1/2. Data larelazione f  = 1/T  , ne consegue che f 2 = 1/T 2 , cioè 1/T 1/2: allorail rapporto R = f 2/f 1 è uguale al rapporto tra 1/T 1/2 e 1/T 1 , ov-vero R = 2. Si supponga di avere una tabella di 16 punti quale quelladi Figura ?? e che il tasso di campionamento sia di 44100 campioni alsecondo. Supponendo una semplice lettura della tabella sia che il pe-riodo T  (ovvero quanto dura un ciclo della forma d’onda tabulata) è

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 243/328

8.2–240

pari a T  = 16/44100 = 0.00036281179138322sec. Ciò indicache la frequenza del segnale risultante è f  = 1/T  = 2756.25Hz.Se invece si legge un campione ogni due, ovvero il passo di lettura è2 , allora il periodo del nuovo segnale è T  = 16/2 → 8/44100 =0.00018140589569161sec , e dunque la frequenza è → f  = 1/T  =5512.5Hz. ovvero il doppio della frequenza originale. Rispetto alla ta-

 bella la lettura procede come illustrato qui di seguito e produce il risul-tato visibile in Figura 8.3.

Tabella → Segnale

[00] = 0.19509032 → [00]

[01] = 0.55557024 → non utilizzato

[02] = 0.98078525 → [01]

[13] = -0.8314696 → non utilizzato

[14] = -0.55557024 → [07]

[15] = -0.19509032

→non utilizzato

Time (s)0 0.000362812

 –1

1

0

Time (s)0 0.000362812

 –1

1

0

Time (s)0 0.000362812

 –1

1

0

Time (s)0 0.000362812

 –1

1

0

Time (s)0 0.000362812

 –1

1

0

Time (s)0 0.000362812

 –1

1

0

Time (s)0 0.000362812

 –1

1

0

Fig. 8.3 Lettura conpasso = 2 della tabella.

In Figura 8.4(a) è rappresentato un segnale sinusoidale di 440Hz. Leg-gendo un punto ogni due, si ottiene il segnale di Figura 8.4(b-c): in (b) siosserva come nella stessa durata il numero di picchi e gole nel segnalerisultante raddoppi, mentre in (c) si può osservare come ogni ciclo del

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 244/328

8.2–241

segnale sottocampionato sia rappresentato da metà del numero di cam-pioni rispetto all’originale. Il segnale sottocampionato ha frequenza paria 880Hz e durata pari a metà del segnale originale, come si vede nelleFigure 8.4(d-e).

Time (s)0 0.02

 –1

1

0

Time (s)0 0.01

 –1

1

0

Time (s)0 0.02

 –1

1

0

Time (s)0 1

 –1

1

0

Time (s)0 1

 –1

1

0

Fig. 8.4 Sinusoide a 440 Hz (a), segnale sottocampiona-to leggendo un campione ogni due (b-c), segnale originalee sottocampionato rappresentati nella durata complessiva(d-e).

Ancora, se il passo di lettura è 4 allora T  = 16/4 → 4/44100 =0.00018140589569161sec , per una frequenza pari a f  = 1/T  =5512.5Hz. Musicalmente una rapporto 2 : 1 corrisponde a una tra-

sposizione all’ottava superiore, mentre 4 : 1 indica una trasposizionepari a quattro ottave.L’operazione fin qui descritta si chiama downsampling. L’upsampling èil procedimento simmetrico attraverso il quale è possibile diminuire lafrequenza del campione originario: a ogni punto della tabella vengo-no fatti corrispondere non uno, ma due campioni (nel senso di punti dicampionamento) nel segnale derivato.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 245/328

8.2–242

Tabella –> Array

[00] = 0.19509032 –> [00]

[01]?

[01] = 0.55557024 –> [02]

[03]?

[02] = 0.98078525 –> [04]

[15] = -0.19509032 –> [30]

[31]

In sostanza, è come se tra un campione e l’altro della tabella originalevenisse messo un nuovo campione. Rispetto alla tabella originale, ci saràtra ogni coppia di punti un punto intermedio in più, secondo quantoavviene in Figura 8.5.

Time (s)0 0.000362812

 –1

1

0

Time (s)0 0.000362812

 –1

1

0

Time (s)0 0.000362812

 –1

1

0

Time (s)0 0.000362812

 –1

1

0

Fig. 8.5 Lettura conpasso = 0.5 della tabella.

La frequenza risultante è la metà di quella originale, il che equivale mu-sicalmente a una trasposizione al grave di un’ottava. I valori dei campio-ni aggiunti non ci sono nella tabella originale e devono essere inferiti inqualche modo, intuibilmente a partire dai valori contigui. Tipicamenteciò avviene per per interpolazione tra i due valori originali che precedo-no e seguono ogni campione aggiunto. Intuibilmente se il primo valoreè 0 e il secondo 1 , il valore interpolato sarà 0.5. Se si osserva la Figura

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 246/328

8.2–243

8.6 si capisce come il ragionamento possa essere generalizzato attraver-so il ricorso alla proporzionalità tra triangoli. Nella Figura 8.6 sono noti(cioè, sono valori numerici dati):

• x0, y0, x1, y1, x.

Il problema è trovare y. Si osserva come siano omogenei i triangoli ABQe AP O , e dunque valga una relazione di omogeneità tra i lati.

• ABQ ∝ AP O → PO/BQ = AO/AQSosituendo ai termini i valori delle variabili si ottiene:

• (y − y0)/(y1 − y0 ) = (x − x0)/(x1 − x0)

ovvero

• y = (x−x0)/(y1−y0)(x1−x0) + y0

(x0, y0)

(x1, y1)

(x, y)

A

B

O

P

Q

Fig. 8.6 Interpolazione lineare comerelazione tra triangoli

Nel caso precedente, in cui un campione viene aggiunto “in mezzo” adue precedenti, rispetto alla figura si ha che i campiono noti sono rap-presentati dai punti A e B , che costituiscono i campioni 0 e 2 del nuovosegnale. Si tratta di calcolare il valore del campione con indice 1 , ovvero

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 247/328

8.2–244

del punto P  = (1, ?). Si hanno dunque le seguenti sostituzioni nume-riche rispetto alla formula:

• (x0, y0 ) = ( 0, 0)

• (x1, y1 ) = ( 2, 1)

• x = 1

E dunque:

• y = (1−0)/(1−0)(2−0) + 0 = 1

2 + 0 = 0.5

Questo tipo di interpolazione è detto “lineare” perché intuibilmente cer-ca sulla retta che connette i due punti noti A e B il valore ignoto corri-spondente alla ordinata della nuova ascissa26.L’utilizzo dell’interpolazione permette di determinare il valori di cam-pioni che avrebbero un indice frazionario: cioè, di poter prendere non

solo un campioni ogni due, tre etc, ma anche ogni 0.9 , 1.234 etc. Ciòsignifica poter trasporre il campione originale non solo all’ottava, ma atutte le altre frequenze corrispondenti alle altre note di una tastiera, peri quali è necessario considerare anche rapporti numerici non interi tra ilnumero dei punti iniziali e e quello finale. Poiché il rapporto tra due fre-quenze a distanza di semitono (sulla tastiera, tra due tasti consecutivi:

ad esempio, tra do e do♯) è12√ 

2 ≈ 1.06 , come si vede in SC calcolandoil rapporto tra le frequenze (si ricordi che in notazione midi 60 indica ildo e l’unità rappresenta il semitono):

Esistono altre forme di interpolazione, che qui non si discutono, ma che si basano sullo26

stesso principio geometrico di determinare una certa curva, non necessariamente unaretta, tra due punti e determinare il valore di una ordinata per una ascissa intermedianota.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 248/328

8.2–245

1 61.midicps/60.midicps2 1.0594630943593

Per ottenere una trasposizione di semitono sarebbe necessario preleva-re un punto ogni ≈ 1.06. Questa operazione è possibile calcolando perinterpolazione il nuovo valore. Infine ricordiamo che, poiché dal puntodi vista timbrico raddoppiare la frequenza è ben diverso da trasporrestrumentalmente all’ottava (vedi Capitolo 1), se si vuole fare della sin-

tesi imitativa è opportuno campionare tutte le diverse regioni timbriche(i registri) dello strumento prescelto. In un oscillatore come Osc l’idea èquella di fornire un periodo di un segnale e di poter controllare la fre-quenza del segnale risultante. La frequenza viene espressa in terminiassoluti, poiché indica il numero di volte in cui la tabella viene lettaal secondo, e dunque il numeroi di cicli per secondo. PlayBuf è inve-ce un lettore di buffer, impiegato tipicamente quando il buffer contienenon un ciclo ma un segnale complesso, di cui infatti non è necessario

conoscere la dimensione: la frequenza di lettura viene allora più util-mente espressa in termini di proporzione tra i periodi. Il rapporto viene

espresso in termini della relazione T 1T 2

 , dove T 1 è il numero di campioni

contenuti nel buffer e T 2 quello del segnale risultante. La stessa relazio-

ne può essere espressa in temrini di frequenza con f 2f 1

 , dove f 1 indica

la frequenza del segnale di partenza e f 2 quella del segnale risultante.PlayBuf permette di specificare un simile tasso attraverso l’argomentorate: se

rate = 1allora il buffer viene letto al tasso di campionamento

del server, se rate = 0.5 allora T 2 = 2 , cioè il buffer viene “stirato”su una durata doppia, e di conseguenza il segnale ha una frequenza f 2pari alla metà dell’originale, ovvero scende di un’ottava. Se rate è nega-tivo, allora il buffer viene letto in senso inverso, dall’ultimi campione alprimo. Nell’esempio seguente l’argomento rate è gestito da un segna-le che risulta dall’uscita di una UGen Line. Quest’ultima definisce un

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 249/328

8.2–246

segnale che decresce linearmente in [−

1, 1]. Questa progressione de-termina una lettura del buffer inizialmente senza modificazioni rispettoall’originale (rate = 1), a cui segue un progressivo decremento chesi traduce in un abbassamento della frequenza (e, si noti, in un incre-mento della durata) fino a rate = 0. Quindi il valore cresce ma consegno inverso: così fa la frequenza, ma il buffer viene letto all’inverso(dalla fine all’inizio). Il valore finale del segnale generato da Line è−1 ,che equivale ad una “velocità di lettura” pari a quella normale, ma alcontrario.

1 (

2 SynthDef("playBuf2", { arg bufnum = 0;

3 Out.ar(0,

4 PlayBuf.ar(1, bufnum, rate:

5 Line.kr(1, -1, 100), loop: -1)

6 )

7 }).send(s) ;

8 )

10 (

11 var buf, aSynth ;

12 buf = Buffer.read(s,"sounds/a11wlk01-44_1.aiff") ;

14 aSynth = Synth("playBuf2", ["bufnum", buf.bufnum]) ;

15 )

L’esempio seguente dimostra la potenza espressiva di SC (oltre alla suaefficienza) e riprende molti aspetti di un esempio già visto (che non siridiscuteranno). L’array source contiene 100 segnali stereo che risulta-no dalla spazializzazione attraverso Pan2 di PlayBuf. In ognuna delleUGen PlayBuf l’argomento rate è controllato da una UGen LFNoise0 ,così che l’escursione possibile dello stesso è [−2.0, 2.0] , ovvero fino

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 250/328

8.3–247

ad un’ottava sopra ed anche al contrario. I 100 Out leggono lo stesso buffer, ognuno variando pseudo-casualmente la velocità di lettura. I se-gnali stereo sono quindi raggruppati per canale (attraverso flop , riga13), missati (14-15) e inviati come array di due elementi a Out (16).

1 (

2 SynthDef("playBuf3", { arg bufnum = 0;

3 var left, right ;

4 var num = 30 ;

5 var source = Array.fill(num, { arg i ;6 Pan2.ar(

7 in: PlayBuf.ar(1, bufnum, rate:

8 LFNoise0.kr(1+i, mul: 2), loop: -1),

9 pos: LFNoise0.kr(1+i),

10 level: 1/num) ;

11 }) ;

13 source = source.flop ;

14 left = Mix.new(source[0]) ;

15 right = Mix.new(source[1]) ;16 Out.ar(0, [left, right])

17 }).send(s) ;

18 )

20 (

21 var buf, aSynth ;

22 buf = Buffer.read(s,"sounds/a11wlk01-44_1.aiff") ;

24 aSynth = Synth("playBuf3", ["bufnum", buf.bufnum]) ;

25 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 251/328

8.3–248

8.3 Sintesiadditiva

Il teorema di Fourier stabilisce che ogni segnale periodico per quantocomplesso può essere rappresentato come la somma di semplici segnalisinusoidali. L’idea alla base della sintesi additiva è quello di procedere

in senso inverso, ottenendo un segnale complesso a partire dalla som-ma di semplici segnali sinusoidali, ognuno dei quali dotato di un suoinviluppo d’ampiezza. La Figura 8.7 illustra un banco di oscillatori chelavorano in parallelo: essi generano n segnali, che vengono sommati eche risultano in un segnale complessivo spettralmente più ricco. Nellasintesi additiva classica gli oscillatori sono “intonati” a partire da unafrequenza fondamentale: le loro frequenze (f 2 . . . f n) sono cioè mul-tipli interi della frequenza fondamentale (f 1).

f 1

f 2 

f 3 

f 4 

Out

oscils harmonics 

f n 

Fig. 8.7 Banco di oscillatori.

Si tratta di uno dei metodi di sintesi in uso da più antica data proprioperché le due operazioni (sintesi di segnali sinusoidali e loro somma) so-no di implementazione molto semplice. Se in teoria del segnale si parladi “somma di segnali”, più tipicamente in ambito audio ci si riferiscealla stessa cosa in termini di missaggio (mixing, miscelazione). Come

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 252/328

8.3–249

si è visto, la UGen specializzata nel missaggio in SC è Mix , che riceve inentrata un array si segnali, li somma e restituisce un nuovo segnale (mo-no). Il missaggio in digitale è propriamente e banalmente una somma.Si comporta così

segnale 1: 0 - 1 - 2 - 3 - 2 - 1 - 1

segnale 2: 0 - 3 - 1 - 2 - 1 - 1 - 0

—————————————

 mix 1 + 2: 0 - 4 - 3 - 5 - 3 - 1 - 1

Per dirla in termini più vicini a SC, si consideri il seguente esempio:

1 (

2 a = Array.series(20).normalize*2-1 ; // ramp in [-1.0, 1.0]

3 b = Array.fill(20, { rrand(-0.5, 0.5) }) ; // rand in [-0.5, 0.5]

4 c = a + b ; // sum

6 // plot

7 [a, b, c].flop.flat.plot(numChannels:3, discrete:true, minval: -1, maxval:1)

8 )

I due array a e b contengono 20 valori. Il primo viene riempito di conuna serie che progredisce da 0 a 20 , viene normalizzato nell’escursione[0, 1] , quindi moltiplicato per 2 (l’escursione è ora [0.0, 2.0]), infine

sottraendo 1 i valori sono compresi in [−1.0, 1.0]. Il secondo contienevalori pseudo-casuali nell’intervallo [−0.5, 0.5]. Il terzo (c) contiene lasomma (valore per valore) dei primi due. Il risultato è visibile attraversola riga 7.Passando alla sintesi, l’esempio seguente –per quanto minimale– è istrut-tivo rispetto alla potenza espressiva di SC. Come si vede, la riga 3 in-troduce un oggetto Mix: esso deve riceve come argomento un array di

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 253/328

8.3–250

segnali che sommera restituendo un segnale unico. A Mix viene passa-to un array che contiene 20 segnali (generati da SinOsc. Si noti che i

è il contatore e viene utilizzato come moltiplicatore della frequenza de-gli oscillatori, che saranno perciò multipli di 200Hz. Poiché i è inizia-lizzata a 0 il primo oscillatore avrebbe una frequenza nulla (= assenzadi segnale), e dunque è necessario aggiungere 1 a i. Nel missaggio, lasomma dei segnali è lineare: ciò vuol dire che n segnali normalizzatinell’intervallo [−1.0, 1.0] verranno missati in un segnale risultante lacui ampiezza sarà compresa tra n

×[−

1.0, 1.0 ] = [−

n, n]: intuibil-mente, ciò risulta in un abbondante clipping. Nell’esempio, il problemaè risolto attraverso mul:1/20: ogni segnale ha al massimo ampiezza paria 1/20 , e dunque, pure nella circostanza in cui tutti i segnali sono simul-taneamente al massimo dell’ampiezza, il segnale missato non supera imassimi previsti.

1 (

2 {

3 Mix.new // mix

4 ( Array.fill(20, { arg i ; // 20 partials

5 SinOsc.ar(200*(i+1), mul: 1/20)}))

6 }.scope ;

7 )

Per verdere che cosa avviene a livello spettrale è sufficiente valutare:

1 s.freqscope // assuming that s is the server in use

Vista l’attitudine algoritmica di SC, il linguaggio mette a disposizione unmetodo fill definito direttamente sulla classe Mix. Il codice seguente èesattamente identico nei risultati al precedente.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 254/328

8.3–251

1 (2 {

3 // the same

4 Mix.fill(20, { arg i ;

5 SinOsc.ar(200*(i+1), mul: 1/20)})

6 }.scope ;

7 )

Negli approcci precedenti ogni sinusoide inizia il suo ciclo nello stessomomento. Questo determina un picco visibile nella forma d’onda, chesi traduce in una sorto di impulso. In generale, la fase è irrilevante nel-la parte stazionaria del segnale, mente assume importanza critica neitransitori e nelle discontinuità del segnale. Poiché quanto qui interessaè soltanto la relazione tra le componenti (in termini stazionari), è meglioevitare allineamenti di fase. Nell’esempio qui di seguito ogni oscillatorericeve una fase iniziale casuale attraverso 2pi.rand.

1 (

2 {

3 // avoiding phase sync

4 Mix.fill(20, { arg i ;

5 SinOsc.ar(200*(i+1), 2pi.rand, mul: 1/20)})

6 }.scope ;

7 )

Variando l’ampiezza delle armoniche componenti, si modifica eviden-temente il peso che queste hanno nello spettro. Qui di seguito, un se-gnale stereo che risulta dalla somma di 40 sinusoidi a partire da toHzviene modulata nell’ampiezza in modo differente sul canale destro e su

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 255/328

8.3–252

quello sinistro:nel primo caso l’ampiezza dei componenti varia casual-mente con una frequenza di 1 volta al secondo, nel secondo caso se-gue una oscillazione sinusoidale con frequenza casuale nell’intervallo[0.3, 0.5]Hz. Gli argomenti mul e add rendono il segnale unipolare(compreso nell’intervallo [0.0, 1.0]). L’ampiezza è divisa per 20: se-condo quanto vista prima, dovrebbe essere divisa per 40 , ma, a causadelle variazioni delle ampiezze dei segnali, una divisione (empirica) per20 è sufficiente ad evitare il clipping.

1 (

2 {

3 // stereo spectral motion

4 Mix.fill(40, { arg i ;

5 var right = { LFNoise1.kr(1, 1/20) } ;

6 var left = { SinOsc.kr(rrand(0.3, 0.5), 2pi.rand, mul: 0.5, add:

0.5) } ;

7 SinOsc.ar(50*(i+1), [2pi.rand, 2pi.rand], mul: [left/20, right]) })

8 }.scope ;

9 )

L’esempio seguente scala l’ampiezza di ogni componente in proporzio-ne inversa al numeto di armonica: più il numero è grande, minore èl’ampiezza, secondo un comportamente fisicamente comune negli stru-menti musicali. La variabile arr contiene prima una sequenza di interida 1 a 20 , il cui ordine viene invertito (attraverso il metodo reverse), ilcui valore viene normalizzato in modo che la somma di tutti i compo-nenti sia pari a 1. In altre parole, sommando tutti gli elementi dell’arrayarr si ottiene 1. QUesto vuol dire che se si usano gli elementi dell’arraycome moltiplicatori delle ampiezze non si incorre in fenomeni di clip-ping. La frequenza del’oscillatore è espressa in notazione midi (60 = docentrale), che viene quindi convertita in cicli al secondo ( midicps).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 256/328

8.3–253

1 (2 {

3 var arr = Array.series(20, 1).reverse.normalizeSum ;

4 Mix.new // mix

5 ( Array.fill(20, { arg i ; // 20 partials

6 SinOsc.ar(60.midicps*(i+1), 2pi.rand, mul: arr[i])}))

7 }.scope ;

8 )

Attraverso la sintesi additiva possono essere generate proceduralmentemolte forme d’onda di tipo armonico. Ad esempio, l’onda quadra puòessere descritta come una somma infinita di armoniche dispari la cuiampiezza è proporzionale all’inverso del numero d’armonica, secondola relazione f 1 × 1, f 3 × 1/3, f 5 × 1/5, f 7 × 1/7 . . .La Figura 8.8 confronta un’onda quadra (in alto) con la somma pesatadelle prime

3armoniche (al centro) e delle prime

10armoniche (in bas-

so), mentre la Figura 8.9 dimostra i cambiamenti nella forma d’onda (asinistra) e nello spettro (a destra, nel sonogramma) in relazione all’incrementodelle componenti armoniche.Come si nota, la ripidità degli spigoli nella forma d’onda è proporzio-nale al numero dei componenti. Dunque, l’arrotondamento indica un

 basso numero di componenti e, all’opposto, la presenza di transizioniripide un numero alto.

La discussione sulla sintesi additiva ha introdotto non a caso la classeMix , perché in effetti la sintesi additiva può essere generalizzata nei ter-mini di un micro-missaggio/montaggio in cui un insieme arbitrario dicomponenti viene sommato per produrre un nuovo segnale. Si parla inquesto caso di “somma di parziali”, intendendo come parziale un com-ponente di frequenza arbitraria in uno spettro (e che perciò non deve es-sere relata armonicamente alla fondamentale, e che può includere anchesegnali “rumorosi”). Restando nell’ambito dei componenti sinusoidali,

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 257/328

8.3–254

Time (s)0 0.03

 –1

1

0

Time (s)0 0.03

 –1

1

0

Time (s)0 0.03

 –1

1

0

Fig. 8.8 Onda quadra, prime 3 e prime 10 armoniche.

Time (s)0 1

 –1

1

0

Time (s)0 1

 –1

1

0

Time (s)0 1

 –1

1

0

Time (s)0 1

 –1

1

0

Time (s)0 1

 –1

1

0

Time (s)0 1

 –1

1

0

Time (s)0 6

0

2·104

   F  r  e  q  u  e  n  c

  y   (   H  z   )

Fig. 8.9 Progressione nelle componenti e approssimazione progressivaall’onda quadra

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 258/328

8.3–255

si può descrivere l’armonicità nei termini di un rapporto tra le frequen-ze delle componenti (ratio , in latino e in inglese). In caso di armonicità,si ha integer ratio tra fondamentale e armoniche (il rapporto è espres-so da un numero intero), nel caso di un parziale si ha non-integer ratio ,poiché parziale/f 1 non è intero. Nell’esempio seguente l’unica novità è lariga 10, che introduce un incremento casuale (e proporzionale al nume-ro di armonica) nelle frequenze delle armoniche. Dunque lo spettro saràinarmonico. Tra l’altro, una componente ridotta di inarmonicità è tipi-ca di molti strumenti acustici ed è di solito auspicabile (si parla alloradi quasi-integer ratio). Si noti che ogni volta che il codice viene valuta-to, nuovi valori vengono generati con conseguente cambiamento dellospettro.

1 (

2 // Varying envelopes with quasi-integer ratio

3 {

4 Mix.new( Array.fill(50,

5 { arg k ;6 var incr = 1 ; // quasi-integer. Try to increase to 2…5..10 etc

7 var env ;

8 i = k+1 ;

9 env = { LFNoise1.ar(LFNoise0.ar(10, add:1.75, mul:0.75), add:0.5,

 mul:0.5) };

10 SinOsc.ar(50*i

11 +(i*incr).rand,

12 mul: 0.02/i.asFloat.rand)*env })

13 )}.scope

14 )

Uno spettro di parziali può essere ottenuto per addizione di componentisinusoidali, in numero di 80 nell’esempio qui di seguito.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 259/328

8.3–256

1 (2 // A generic partial spectrum

3 {

4 var num = 80 ;

5 Mix.new( Array.fill(num, { SinOsc.ar(20 + 10000.0.rand, 2pi.rand, 1/num)

}) );

6 }.scope

7 )

È possibile sommare sinusoidi in un intervallo ridotto, intorno ai 500Hz:

1 (

2 // Sweeping around 500 Hz

3 {

4 Mix.new( Array.fill(20, { SinOsc.ar(500 + LFNoise1.ar(LFNoise1.ar(1,

add:1.5, mul:1.5), add:500, mul: 500.0.rand), 0, 0.05) }) );

5 }.scope

6 )

Infine, in relazione alla generalizzazione della tecnica in termini di mon-taggio/missaggio, nell’esempio seguente quattro segnali ottenuti contecniche di sintesi diverse (e diverse sono infatti le UGen coinvolte: SinOsc,Blip, HPF, Dust, Formant) sono correlate attraverso la stessa frequenza

(f): l’ampiezza di ognuno di essi è controllata da un generatore pseudo-casuale (le variabili a, b, c, d. Il segnale è poi distributio sul frontestereo attraverso Pan2.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 260/328

8.3–257

1 // Additive in a broad sense: 4 UGens tuned around a frequency andrandomly mixed down

2 // (and randomly panned around)

3 (

4 a = { LFNoise1.ar(1, add:0.15, mul:0.15) };

5 b = { LFNoise1.ar(1, add:0.15, mul:0.15) };

6 c = { LFNoise1.ar(1, add:0.15, mul:0.15) };

7 d = { LFNoise1.ar(1, add:0.15, mul:0.15) };

9 f = { LFNoise0.ar(LFNoise0.ar(0.5, add:0.95, mul: 0.95), add: 50, mul:50)

};

11 m = { Pan2.ar(

12 Mix.new([

13 { SinOsc.ar(f, mul:a) },

14 { Blip.ar(f, mul:b) },

15 { HPF.ar(Dust.ar(f*0.2), f, mul:c) },

16 { Formant.ar(f,mul:c) },

17 ])

18 , LFNoise1.ar(0.2, mul:1)

19 ) };20 m.scope;

21 )

La sintesi additiva si rivela particolarmente adatta per i suoni ad altezzadeterminata, in cui è sufficiente la definizione di un numero limitato diarmoniche particolarmente evidenti. In effetti, per costruire uno spigolo

(come quello di un’onda quadra, o di un onda triangolare o a dente disega) sono necessarie teoricamente infinite componenti sinusoidali. Atal proposito, SC prevede specifici generatori, ad esempio Pulse gene-ra onde impulseive (tra cui l’onda quadra) e Saw onde a dente di sega.Questi tipi di segnali sono spesso utilizzati come segnali di controllo edesistono perciò versioni LF di queste UGen, cioè versioni che sono spe-cializzate nel lavorare a tasso di controllo LFPulse, LFSaw27. Una somma

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 261/328

8.3–258

di sinusoidi, per quanto numerose esse possano essere, produce un se-gnale aperiodico, ma non “rumoroso”, ed è il risultato tipico è un effettodi “liquidità”.

1 (

2 // Filling the spectrum with sinewaves: frac of semitones

3 m = {

4 var comp = 500; // number of components. Increase as much as your CPU

can…

5 var res = 0.1;6 var base = 30 ; // 30 = rumble

7 Mix.new( Array.fill(comp,

8 { arg i;

9 SinOsc.ar(freq: (base+(i*res)).midicps // resolution: eg. interval

of 0.5 Hz

10 // Note that the resulting wave h as a pulse freq of reso-

lution

11 , phase: 2pi.rand, mul: 1.0/comp )}) // random phase

12 )}.scope

14 )

L’esempio crea 500 sinusoidi in parallelo (è un bel numero. . .): il nume-ro degli stessi è controllato da comp. La strategia di riempimento gestiscele frequenze attraverso la notazione midi. Questo assicura la possibilitàdi equispaziare in altezza (percepita) le componenti (e non in frequen-

za). La variabile res controlla la frazione di semitono che incrementa infunzione del contatore i a partire dalla altezza di base, base. Si noti co-me storicamente il principale problema della sintesi additiva sia stata lacomplessità di calcolo richiesta. Infatti un segnale complesso richiede ladefinizione di almeno 20 armoniche componenti, di ognuna delle quali

Ancora, Blip.ar(freq, numharm, mul, add) genera un numero numharm controllabile27

di componenti armoniche di un fondamentale freq  , dotate tutte della stessa ampiezza.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 262/328

8.4–259

è necessario descrivere l’inviluppo in forma di spezzata. Come si vede,il problema computazionale è ormai di scarso rilievo, anche perché SC èparticolarmente sufficiente. La sintesi di suoni percussivi, nello spettrodei quali si evidenzia una preponderante componente di rumore (cioèdi parziali non legate alla serie armonica di Fourier), richiederebbe (alfine di ottenere un risultato discreto) un numero di componenti elevatis-simo. In realtà, è necessario un altro approccio, quale ad esempio quellodella sintesi sottrattiva (cfr. infra).

8.4 Sintesigranulare

La sintesi granulare muove dal presupposto che il suono possa esserepensato non solo in termini ondulatori ma anche in termini corpusco-lari. È usuale il paragone con i procedimenti pittorici del pointillisme:la somma di frammenti sonori di dimensione microscopica viene perce-pita come un un suono continuo, come la somma di minuscoli punti dicolore puro origina la percezione di tutti gli altri colori. Si tratta alloradi definire grani sonori la cui durata vari tra 1 e 100ms , ognuno deiquali caratterizzato da un particolare inviluppo d’ampiezza, che influi-sce notevolmente sul risultato sonoro. Come intuibile, se per sintetizzareun secondo di suono sono necessari ad esempio 100 grani, non è pen-

sabile la definizione deterministica delle proprietà di ognuno di essi. Èperciò necessario ricorrere a un controllo statistico, che ne definisca i va-lori medi per i diversi parametri, ad esempio durata, frequenza, formad’onda, inviluppo: più complessivamente deve essere stabilita la densi-tà media dei grani nel tempo. La necessità di un controllo d’alto livellorispetto al basso livello rappresentato dai grani richiede così la definzio-ne di un modello di composizione: non a caso la sintesi granulare è unadelle tecniche che ha maggiormente stimolato un approccio algoritmico

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 263/328

8.4–260

alla composizione. Ad esempio si può organizzare la massa dei graniseguendo la legge di distribuzione dei gas perfetti (Xenakis), oppureattraverso una tipologia degli ammassi che deriva da quella meteoro-logica delle nuvole (Roads), o infine immaginare le sequenze di granicome dei flussi di particelle di cui determinare le proprietà globali tra-mite “maschere di tendenza” (Truax). In generale, va notato che per lasintesi granulare è richiesto al calcolatore un notevole lavoro computa-zionale per controllare i valori dei parametri relativi alla sintesi di ognisingolo grano. Esistono molti modi differenti di realizzare la sintesi gra-nulare, che rispondono a obiettivi anche assai diversi tra loro: in effetti,seppur con qualche approssimazione, può essere descritta come “sin-tesi granulare” ogni tecnica di sintesi che si basi sull’utilizzo di segnaliimpulsivi.

1 (

2 // sync granular synthesis

3 var baseFreq = { GUI.mouseX.kr(100, 5000, 1) };

4 var disp = { GUI.mouseY.kr } ;5 var strata = 10 ;

6 var minDur = 0.05, maxDur = 0.1 ;

7 var minRate = 10, maxRate = 50 ;

9 JMouseBase.makeGUI ; // if you use SwingOSC

11 {

12 Mix.fill(strata,

13 { SinOsc.ar( baseFreq + LFNoise0.kr(rrand(minRate, maxRate),

14 mul: baseFreq*disp*0.5), mul: 1/strata) }

15 //* LFPulse.kr(1/rrand(minDur, maxDur))

16 * SinOsc.ar(1/rrand(minDur, maxDur)*0.5).squared

17 )

18 }.freqscope

19 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 264/328

8.4–261

Nell’esempio precedente è implementato un approccio in sincrono allasintesi granulare. In sostanza, nell’algoritmo di sintesi una sinusoide èinviluppata in ampiezza da un’onda quadra, generata da LFPulse: poi-ché LFPulse genera un segnale unipolare (la cui ampiezza è inclusa in[0.0, 1.0]), quando l’ampiezza dell’onda quadra è > 0 , lascia passa-re il segnale, altrimenti lo riduce ad ampiezza 0. Il risultato è una “fi-nestrazione” del segnale. La durata di ogni finestra dipende dal ciclodell’onda quadra, ed è gestito da minDur e maxDur (le durate specificano

il periodo della finestra, dunque la frequenza di LFPulse sarà 1

T  , cioé

1/rrand(minDur, maxDur)). In questo caso, l’inviluppo del grano è ap-punto dato da un impulso (il ciclo positivo dell’onda quadrata). La ri-ga 16 (commentata) propone un altro inviluppo, ottenuto elevando alquadrato una sinusoide (cfr. supra). L’inviluppo avrà il doppio dei pic-chi nell’unita di tempo (attraverso il rovesciamento della parte negativadella sinusoide) e dunque la frequenza viene dimezzata attraverso *0.5.Si noterà che l’inviluppo a campana, meno ripido della sinusoide al

quadrato riduce l’ampiezza delle componenti più elevate dello spettro.Come si vede, attraverso Mix viene missato insieme un numero stra-

ta di segnali: in ognuno, baseFreq gestisce la frequenza di base a cuiviene aggiunto un valore pseudo-casuale disp , generato da LFNoise0 ,che rapprenta una percentuale normalizzata della frequenza di base (sebaseFreq = 100 e disp = 0.5 , allora la frequenza dell’oscillatorevarierà nell’intervallo [100 − 50, 100 + 50]). Il tasso di questa varia-zione è gestito da minRate e maxRate.

L’approccio precedente è implementabile in tempo reale, e parte dall’assuntodi convertire, per così dire, segnali continui, in segnali impulsivi a parti-re da una operazione di finestrazione. Un altro approccio possibile pre-vederebbe di pensare ad ogni singolo grano come ad un evento di taglia“compositiva”: lo si vedrà discutendo dello scheduling. Un uso tipicodelle tecniche granulari sfrutta la granularità non tanto per la sintesiab nihilo quanto piuttosto per l’elaborazione: tipicamente, l’operazioneè chiamata “granulazione”, e come intuibile consiste nel sottoporre a

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 265/328

8.4–262

scomposizione in grani e successiva ricombinazione un segnale preesi-stente. In qualche misura, l’operazione è intrinsecamente in tempo dif-ferito, perché è necessario avere a disposizione una parte di segnale perpoterla scomporre e ricomporre. Ciò vuol dire che, in tempo reale, ènecessario quantomeno riempire un buffer (una locazione di memoriatemporanea) per poterlo granulare.

1 (

2 b = Buffer.read(s, "sounds/a11wlk01-44_1.aiff");

4 SynthDef(\grainBuf, { arg sndbuf;

5 Out.ar(0,

6 GrainBuf.ar(2, Impulse.kr(10), 0.1, sndbuf,

7 LFNoise1.kr.range(0.5, 2),

8 LFNoise2.kr(0.1).range(0, 1),

9 2,

10 LFNoise1.kr(3)

11 ))

12 }).send(s);

13 )

15 x = Synth(\grainBuf, [\sndbuf, b])

L’esempio precedente è una semplificazione di quello proposto nel filedi help della UGen GrainBuf. Nel buffer b viene memorizzato il segnale

"sounds/a11wlk01-44_1.aiff" , sul quale GrainBuf opera. La sintassi diGrainBuf è la seguente:

GrainBuf.ar(numChannels, trigger, dur, sndbuf, rate, pos, interp,

pan, envbufnum, mul, add)

Il primo argomento specifica evidentemente il numero dei canali. Il se-condo il segnale di triggering che innesca un nuovo grano: nell’esempio

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 266/328

8.5–263

è una sequenza di impulsi con frequenza di 10Hz. Si provi a sostituirein Impulse.kr(10) il valore 10 con GUI.mouseX(1, 300) per verificarel’effetto della densità dei grani28. L’argomento dur determinata la dura-ta di ogni grano (costante a 0.1), il successivo il buffer (nello specifico,sarà b). Gli argomenti rate, pos, interp, pan, envbufnum controlla-no rispettivamente il tasso di lettura del campione (come in PlayBuf), laposizione di lettura del buffer (normalizzata tra [0.0, 1.0] , il metodo diinterpolazione per il pitchshifting dei grani (qui, 2 , ad indicare interpo-lazione lineare), la posizione sul fronte stereo (in caso di segnali stereo,come in Pan2), un buffer (opzionale) in cui è contenuto un inviluppoda utilizzare per inviluppare i grani. Alcuni argomenti sono controlli dageneratori LowFrequency. Alcune parole solo su ciò che non si è visto. Ilmetodo range permette di scalare un segnale all’interno dell’intervallospecificato dai due valori passati: è decisamente più intelligibile del la-voro (istruttivo. . .) con mul eadd29 La UGen LFNoise2 produce un ru-more a bassa frequenza con interpolazione quadratica tra un valore e ilsuccessivo, a differenza che nel caso di LFNoise1 in cui l’interpolazioneè lineare. Il risultato è un segnale molto “arrotondato”. Si provi ad ascol-tare e a guardare i seguenti segnali:

1 {LFNoise0.ar(200)}.scope

3 {LFNoise1.ar(200)}.scope

5 {LFNoise2.ar(200)}.scope

Senza dimenticare JMouseBase.makeGUI ; in caso si usi SwingOSC.28

Il metodo assume che il segnale sia nell’escursione normalizzata, quindi non funziona29

se gli argomenti mul e add vengono specificati.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 267/328

8.5–264

8.5 Sintesisottrattiva

Nella sintesi sottrattiva il segnale in input è generalmente un segnalecomplesso, dotato di uno spettro molto ricco. Questo segnale subisce unprocesso di filtraggio in cui si attenuano le frequenze indesiderate, enfa-

tizzando soltanto alcune regioni (più o meno estese) dello spettro. Più ingenerale, un filtro è un dispositivo che altera lo spettro di un segnale inentrata. Un filtro agisce cioè enfatizzando o attenuando determinate fre-quenze del segnale: una modifica dello spettro determina a livello per-cettivo un cambiamento nel timbro del suono. I parametri fondamentalidi un filtro sono: il tipo, la frequenza di taglio/centrale, l’ordine. Si rico-noscono usualmente quattro tipi di filtri: passa-basso (lowpass), passa-alto (highpass), passa-banda (bandpass) e elimina-banda (bandreject, o

notch). I quattro tipi sono schematizzati in Figura 8.10.

Fig. 8.10 Tipi di filtro. L’area grigia rappresenta l’intervallo di fre-quenze che il filtro lascia passare.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 268/328

8.5–265

In un filtro passa-basso o passa-alto ideali, data una frequenza di taglio,tutte le frequenze rispettivamente superiori o inferiori a questa dovreb-

 bero essere attenuate a 0. Allo stesso modo, in un filtro passa-banda oelimina-banda ideali, data una banda di frequenze, tutte le frequenzerispettivamente esterne o interne alla banda dovrebbero essere attenua-te a 0. La frequenza di taglio è perciò quella frequenza a partire dallaquale viene effettuato il filtraggio. Nei filtri passa- o elimina-banda sidefiniscono sia la larghezza di banda (bandwidth) che la frequenza cen-trale: data una regione dello spettro, la prima ne misura la larghezza, laseconda la frequenza al centro. Ad esempio, in un filtro che passa tut-te le frequenze nell’intervallo [100, 110]Hz , la larghezza di banda è10Hz , la frequenza centrale è 105Hz.La differenza tra mondo ideale e mondo reale è evidente se si valuta:

1 { LPF.ar(WhiteNoise.ar, freq: 1000) }.freqscope

La UGen LPF è un filtro passabasso (acronimo di “Low Pass Filter”), efreq indica la frequenza di taglio. Poiché la sorgente è un rumore bian-co (si noti il patching), il risultato visibile dovrebbe assomigliare allaFigura 8.10 , passabasso. In realtà, l’attenuazione è sempre progressiva,e proprio la ripidità della curva è un indicatore della bontà del filtro(intuibilmente, più l’inviluppo spettrale è ripido dopo la frequenza ditaglio, meglio è). Poiché i filtri che rispondano ai requisiti dell’idealitànon esistono, si considera come frequenza di taglio quella a cui il filtro

attenua di 3 dB il livello d’ampiezza massimo. Se perciò il passaggio trala regione inalterata e quella attenuata dal filtro è graduale, un ultimoparametro diventa rilevante: la pendenza della curva. Quest’ultima, mi-surata in dB per ottava, definisce l’ordine del filtro. Ad esempio, un filtrodel I ordine presenta una attenuazione di 6 dB per ottava, uno del II di12 dB, del III di 18 dB e così via.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 269/328

8.5–266

Se si pensa al caso discusso del rumore bianco, si nota come una par-te dell’energia (quella relativa alle frequenze “tagliate”) sia attenuata(idealmente a zero). Questa diminuzione riduzione dell’energia com-plessiva di un segnale risulta, nel dominio del tempo, in una modificadell’ampiezza del segnale, con una conseguente diminuzione del “vo-lume” del suono risultante. Tipicamente, più il filtraggio è consisten-te, maggiore è il decremento dell’energia. Ragion per cui spesso è ne-cessario incrementare in uscita l’ampiezza del segnale, compensandol’energia persa (un processo tipicamente detto balancing).Un altro parametro di rilievo in un filtro passabanda è il cosiddetto Q.Il Q intuitivamente, rappresenta il grado di risonanza di un filtro. Piùprecisamente:

Q = f centralelarghezzaBanda

Q è cioè il rapporto tra la frequenza centrale e la larghezza di banda.Esprimere il funzionamento del filtro attraverso Q permette di tene-

re in conto il problema della percezione della frequenza. Mantenere Qcostante lungo tutto lo spettro vuol dire infatti adeguare la larghezzadi banda all’altezza percepita (all’intervallo musicale). Ad esempio: sef centrale = 105; f acuta = 110Hz; f grave = 100Hz allora Q =

105110−100 = 10, 5. Se manteniamo Q costante, e incrementiamo la fre-

quenza centrale del nostro filtro a 10.500Hz , otteniamo come estremi11.000Hz e 10.000Hz. La larghezza di banda è passata da 10Hz a

1000Hz , conformente con la nostra percezione dell’altezza. Dunque,

Q ∝ risonanza , perché se Q è elevato, la banda è (percettivamen-te) stretta e diventa progressivamente percepibile un’altezza precisa. Ilparametro Q indica allora la “selettività” del filtro, la sua risonanza.Nella circostanza, usuale nella sintesi sottrattiva, in cui si impieghinopiù filtri, il filtraggio può avvenire in parallelo o in serie: nel primo casopiù filtri operano sullo stesso segnale simultaneamente (analogamentea quanto avveniva per il banco di oscillatori); nel secondo caso, i filtri

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 270/328

8.5–267

sono invece collegati in cascata, e il segnale in entrata passa attraversopiù filtri successivi. Seppur in termini non del tutto esatti, la sintesi sot-trattiva può essere pensata come un procedimento simmetrico a quellaadditiva: se in quest’ultima si parte generalmente da forme d’onda sem-plici (sinusoidi) per ottenere segnali complessi, nella sintesi sottrattivasi parte invece da un segnale particolarmente ricco per arrivare a unsegnale spettralmente meno denso. Come sorgenti possono essere uti-lizzati tutti i generatori disponibili, a parte evidentemente le sinusoidi.In generale, sono di uso tipico segnali spettralmente densi. Ad esempio,il rumore bianco, ma anche quello colorato, tendono a distribuire enere-gia lungo tutto lo spettro e ben si prestano ad essere punti di partenzaper una tecnica sottrattiva. In Figura 8.11 la larghezza di banda di quat-tro filtri (con frequenze centrali 400, 800, 1200, 1600 Hz) che operano inparallelo su un rumore bianco viene diminuita da 1000, a 10, fino a 1 Hz,trasformando il rumore in un suono armonico.

Time (s)0 10

0

5000

   F  r  e  q  u  e  n  c  y   (   H  z   )

Fig. 8.11 Filtraggio: da rumore bianco a spettro armonico

Per questioni di efficienza computazionale, le UGen specializzate nelfiltraggio prevedono come argomento in SC non Q ma il suo reciproco,indicato come rq . Intuibilmente, varrà allora la relazione per cui minoreè rq più stretto è il filtraggio (maggiore la risonanza). L’esempio seguen-te implementa la stessa situazione di filtraggio armonico in SC: a è un

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 271/328

8.5–268

array che contiene 10 valori da utilizzare come frequenze centrali per ilfiltro passabanda BPF. Poiché l’array viene passato come argomento aBPF ne consegue una espansione multicanale: ne risultano 10 segnali. Diessi, soltanto due sono udibili (nel caso la scheda audio sia stereo), quelliche risultano dal filtraggio a 100 e 200Hz.Attraverso scope si possonoosservare tutti i segnali e notare come il rumore bianco in entrata facciarisuonare ogni filtro intorno alla sua frequenza centrale. L’esempio suc-cessivo è uguale, ma invia i segnali ad un oggetto Mix: il segnale com-plessivo, che risulta dalla somma dei dieci filtraggi sul rumore biancole cui frequenze sono armoniche di 100Hz è udibile, e visibile comeforma d’onda e spettro (scope e freqscope).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 272/328

8.5–269

1 // Filtering results in a harmonic spectrum2 (

3 var sound = {

4 var rq;

5 i = 10; rq = 0.01; f = 100; // rq = reciprocal of Q –> bw/cutoff

6 w = WhiteNoise.ar; // source

7 a = Array.series(i, f, f); // array: [ 100, 200, 300, 400, 500,

600, 700, 800, 900, 1000 ]

8 m = BPF.ar(w, a, rq, i*0.5); // mul is scaled for i

9 m;

10 } ;11 sound.scope(10) ; // see 10 channels of audio, listen to first

2

12 )

14 (

15 var sound = {

16 var rq;

17 i = 10; rq = 0.01;f = 100; // rq = reciprocal of Q –> bw/cutoff

18 w = WhiteNoise.ar; // source

19 a = Array.series(i, f, f); // array: [ 100, 200, 300, 400, 500,600, 700, 800, 900, 1000 ]

20 n = BPF.ar(w, a, rq, i*0.5); // mul is scaled for i

21 m = Mix.ar(n); // mixDown

22 m;

23 } ;

24 sound.scope ; // mixdown: waveform

25 sound.freqscope ; // mixdown: spectrum

26 )

Un aspetto particolarmente interessante della sintesi sottrattiva sta nellasomiglianza che presenta con il funzionamento di molti strumenti acu-stici, nei quali una fonte di eccitazione subisce più filtraggi successivi.Ad esempio, la cassa armonica di una chitarra si comporta come un ri-sonatore: vale a dire, opera un filtraggio selettivo attenuando certe fre-quenze ed enfatizzandone altre. Un discorso analogo vale per la voce

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 273/328

8.6–270

umana, nella quale l’eccitazione glottidale passa attraverso il filtraggiosuccessivo di tutti i componenti del cavo orale: proprio per questo lasintesi sottrattiva è il metodo alla base della tecnica standard di simu-lazione artificiale della voce, la cosiddetta codifica a predizione lineare(Linear Predictive Coding). Nell’esempio successivo, è possibile confron-tare alcune sorgenti e verificare il risultato del filtraggio già discussoselezionando quella che interessa.

1 // Here we change sources

3 // sources

4 { w = Pulse.ar(100, 0.1, mul: 0.1) }.play

5 { w = Dust2.ar(100, mul: 1) }.play

6 { w = LFNoise0.ar(100, 0.1, mul: 1) }.play

7 { w = PinkNoise.ar(mul: 0.1) }.play

8 { w = WhiteNoise.ar(mul: 0.1) }.play

10 (

11 {12 i = 10; q = 0.01;f = 100;

13 //w = Pulse.ar(100, 0.1, mul: 0.1);

14 //w = Dust2.ar(100, mul: 1);

15 //w = LFNoise0.ar(100, 0.1, mul: 1);

16 //w = PinkNoise.ar;

17 w = WhiteNoise.ar;

18 a = Array.series(i, f, f);

19 n = BPF.ar(w, a, q, i);

20 m = Mix.ar(n)*0.2;

21 z = n.add(w).add(m);22 m;

23 }.scope // try .plot too

24 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 274/328

8.6–271

8.6 Analisierisintesi

Come si è visto, il momento fondamentale sia nella sintesi additiva chenella sintesi sottrattiva è il controllo dei parametri che determinano ri-spettivamente l’inviluppo delle componenti armoniche e le caratteristi-

che dei filtri impiegati. Nelle tecniche di sintesi basate su analisi e risin-tesi sono proprio i dati di controllo che vengono derivati dall’analisi diun segnale preesistente ad essere utilizzati nella fase di sintesi. Il pro-cesso viene usualmente scomposto in tre fasi:

1. creazione di una struttura dati contenente i dati ricavati dall’analisi;2. modifica dei dati d’analisi;3. risintesi a partire dai dati d’analisi modificati

Se questa è l’architettura generale, molte sono comunque le possibilitàdi realizzazione. Il caso del Phase Vocoder (PV) è particolarmente in-teressante e permette di introdurne l’implementazione in SC. Nel PV,il segnale viene tipicamente analizzato attraverso una STFT (Short Ti-me Fourier Transform). In un analisi STFT il segnale viene suddivisoin frame (finestre, esattamente nell’accezione di prima in relazione allasintesi granulare), ognuno dei quali passa attraverso un banco di filtripassabanda equispaziati in parallelo tra 0 e sr (la frequenza di campio-

namento). Il risultato complessivo dell’analisi di tutti i frame è, per ognifiltro, l’andamento di una componente sinusoidale di frequenza pari allafrequenza centrale del filtro stesso. La struttura di un frame può esseredescritta come segue:

FRAME 1 2 3 . . . bin: 1 freqval 1 freqval 2 freqval 3 . . .

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 275/328

8.6–272

ampval 1 ampval 2 ampval 3 . . . bin: 2 freqval 1 freqval 2 freqval 3 . . .

ampval 1 ampval 2 ampval 3 . . .. . . . . . . . . . . . . . .

 bin: 512 freqval 1 freqval 2 freqval 3 . . .ampval 1 ampval 2 ampval 3 . . .

In sostanza:

1. si scompone ogni frame del segnale originale in un insieme di com-ponenti di cui si determinano i valori di ampiezza e frequenza;

2. da queste componenti si costruiscono gli inviluppi relativi ad am-piezza e frequenza per tutti i segnali sinusoidali: l’ampiezza, la fasee la frequenza istantanee di ogni componente sinusoidale sono cal-colate interpolando i valori dei frame successivi

Gli inviluppi superano perciò i limiti del singolo frame. I due inviluppicosì ottenuti possono essere impiegati per controllare un banco d’oscillatoriche riproducono per sintesi additiva il segnale originale. Se il file d’analisinon viene modificato, la sintesi basata su FFT riproduce in maniera teo-ricamente identica il segnale originale, anche se in realtà si verifica nelprocesso una certa perdita di dati. Il PV sfrutta l’aspetto più interessantedell’analisi FFT: la dissociazione tra tempo e frequenza. È così possibi-le modificare uno dei due parametri senza per questo alterare l’altro.Più in generale è possibile modificare autonomamente i parametri dicontrollo di tutte le componenti. Un’altra possibilità di grande rilievo èl’estrazione degli inviluppi di soltanto alcune delle componenti.Essendo il passo di analisi necessariamente antecedente alla sintesi (ecostoso computazionalmente), le implementazioni classiche prevedo-no la scrittura su file dei dati d’analisi e la successiva importazion edelaborazioni dei dati per la risintesi. L’utilizzo in tempo reale richiedenell’implementazione in SC di allocare un buffer in cui vengono scritti

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 276/328

8.6–273

progressivamente i dati d’analisi. In particolare, la dimensione del buf-fer (che deve essere una potenza di 2) corrisponde alla dimensione dellafinestra d’analisi (il frame). In sostanza, ogni finestra prelevata sul se-gnale viene memorizzata nel buffer: ogni nuova finestra sostituisce laprecedente. I dati memorizzati nel buffer sono il risultato della conver-sione dal dominio del tempo al dominio della frequenza effettuata sullafinestra (detto un po’ approssimartivamente, lo spettro istantaneo dellafinestra, che conta come un’unica unità di tempo). Questa operazione èsvolta dalla UGen FFT , che effettua appunto una Fast Fourier Transformsulla finestra. I dati conservati nel buffer possono essere a quel puntomanipolati opportunamemte attraverso un insieme di UGen estrema-mente potenti, il cui prefisso è PV_ (Phase Vocoder). Tipicamente la ma-nipolazione lavora sullo stesso buffer, sostituendo i dati precedenti. Ma-nipolazti o meno, il buffer contiene comunque ancora dati che rappre-sentano il segnale (la finestra prelevata) nel dominio della frequenza. Peressere inviati in uscita, i dati devono perciò essere convertiti dal domi-nio della frequenza a quello del tempo (dallo spettro alla forma d’onda):l’operazione è svolta dalla UGen IFFT , ovvero Inverse Fast Fourier Tran-sform. In sostanza, l’intero processo prende la forma seguente:

segnale in entrata → FFT → PV_. . . → IFFT → segnale in uscita

L’elemento PV_ è in teoria opzionale, nel senso che i dati possono es-sere risintetizzati senza che siano stati rielaborati. Evidentemente unasimile situazione non è particolarmente utile, ma permette di spiegare

il processo:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 277/328

8.6–274

1 a = Buffer.alloc(s, 2048, 1) ;2 b = Buffer.read(s,"sounds/a11wlk01.wav") ;

4 (

5 SynthDef("noOperation", { arg fftBuf, soundBuf ;

6 var in, chain;

7 in = PlayBuf.ar(1, a.bufnum, loop:1) ;

8 chain = FFT(bufnum, in) ; // time –> freq 

9 Out.ar(out,

10 IFFT(chain) // freq –> time

11 );12 }).play(s,[\fftBuf, a, \soundBuf, b]) ;

13 )

Nell’esempio, il segnale in viene trasformato nel dominio della frequen-za dalla UGen FFT (si noti il nome tipico assegnato alla variabile, chain ,ad indicare che si tratta di un concatenamento di finestre in successio-

ne). I dati d’analisi vengono memorizzati nel buffer a (che è passatoall’argomento fftBuf), la cui dimensione è una potenza di 2 , 2048 =211. Quindi in uscita a Out viene semplicemente inviato il segnale risul-tante dalla trasformazione al contrario realizzata da IFFT. In un mondoideale, non ci sarebbe perdita di dati tra analisi e risintesi ed il segnale inuscita sarebbe una ricostruzione perfetta di quello in entrata: nel mondoreale si assite invece ad alcune trasformazioni del segnale indotte dallacatena di elaborazioni, tipicamente ridotte, ma potenzialmente impor-

tanti, soprattutto nel caso di segnali molto rumorosi.L’insieme delle UGen PV_ è molto esteso, e molto potente. Qui di se-guito verranno soltanto presentate un paio di applicazioni. Si consideril’esempio seguente: la synthDef realizza un noise gate, cioè lascia passa-re il segnale al di sopra di una cert ampiezza selezionabile con il mouse.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 278/328

8.6–275

1 c = Buffer.read(s, "sounds/a11wlk01-44_1.aiff") ;

3 SynthDef("noiseGate", { arg soundBufnum ;

4 var sig;

5 sig = PlayBuf.ar(1, soundBufnum, loop:1);

6 sig = sig.abs.thresh(GUI.mouseX.kr(0,1)) * sig.sign;

7 Out.ar(0, sig);

8 }).play(s, [\soundBufnum, c.bufnum]) ;

10 JMouseBase.makeGUI ;

12 // see what's going on

13 s.scope(1) ;

Il codice di rilievo è quello di riga 6. La parte negativa del segnale èribaltata in positivo attraverso abs , quindi tresh lascia inalterati i cam-pioni la cui ampiezza è superiore alla soglia (gestita da mouseX), mentre

restituisce il valore 0.0 se il campione è al di sotto della soglia (cioè: az-zera il segnale al di sotto di una certa soglia). In questo modo, tutta laparte di segnale inferiore ad un certo valore di soglia viene eliminata.Tipicamente ciò permette di eliminare i rumori di fondo, che si presen-tano come segnali con ampiezza ridotta e costante. Tuttavia, il segnale,che ora è unipolare, suono più o meno all’ottava superiore a causa delribaltamento. Il metodo sign restituisce −1 se il campione ha valorenegativo e 1 se positivo. Moltiplicando ogni campione per il segno del

campione originale la parte di segnale negativa ribaltata ritorna ad ave-re segno negativo. Vale la pena di osservare come, secondo prassi usualein SC, lo stesso risultato può essere ottenuto attraverso differenti imple-mentazioni30. Ad esempio:

Un suggerimento per la prima implementazione proviene da Nathaniel Virgo, la se-30

conda è stata proposta da Stephan Wittwer, entrambi attraverso la mailing list.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 279/328

8.6–276

1 c = Buffer.read(s, "sounds/a11wlk01-44_1.aiff") ;

3 SynthDef("noiseGate2", { arg soundBufnum = 0;

4 var pb, ir, mx;

5 mx = GUI.mouseX.kr;

6 pb = PlayBuf.ar(1, soundBufnum, loop: 1);

7 ir = InRange.ar(pb.abs, mx, 1);

8 Out.ar(0, pb * ir)

9 }).play(s, [\soundBufnum, c.bufnum]);

11 JMouseBase.makeGUI ;

13 // see what's going on

14 s.scope(1) ;

La UGen InRange.kr(in, lo, hi) restituisce 1 se il campione ha valoreincluso nell’intervallo [lo,hi] , 0 altrimenti. Nell’esempio, lo è gestito

da mouseX , mentre hi è pari a 1. Dunque, il segnale in uscita ir è unasequenza di 0 e 1 in funzione del valore assoluto del campione: se ilvalore assoluto (abs) è superiore a low–qui assegnata alla variabile mx–,allora l’output è 1. Il segnale sarà necessariamente uguale o inferiore a1 , che è il massimo nella forma normalizzata. Il segnale originale pb vie-ne moltiplicato per ir , che lo azzera se l’ampiezza è inferiore alla soglia mx (poiché lo moltiplica per 0) e lo lascia inalterato se è superiore alla

soglia (poiché lo moltiplica per 1).

Si noterà che, seppur efficace, il noise gate produce importanti “buchi”nel segnale. L’esempio seguente sfrutta un altro approccio e realizzaquello che si potrebbe definire un (noise) gate spettrale. La UGen PV_MagAbove

opera sui dati d’analisi assegnati alla variabile chain: lascia invariati ivalori d’ampiezza dei bin la cui ampiezza è superiore ad un valore disoglia (qui controllato dal mouseX), mentre azzera quelli la cui ampiezza

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 280/328

8.6–277

è inferiore. Come si nota, è possibile in questo modo eliminare comple-tamente lo sfondo rumoroso che le cui componenti si situano ad un am-piezza ridotta rispetto ad altri elemtni (la voce) in primo piano. Comesi nota, l’operazione è molto potente, ma non indolore, perché le stessecomponenti sono rimosse da tutto lo spettro (anche dalla figure in primopiano, per così dire).

1 (

2 // Allocate two buffers, b for FFT, c for soundfile

3 a = Buffer.alloc(s, 2048, 1);

4 b = Buffer.read(s, "sounds/a11wlk01-44_1.aiff");

5 "done".postln;

6 )

8 // A spectral gate

9 (

10 // Control with mouse spectral treshold

11 SynthDef("magAbove", { arg bufnum, soundBufnum ;

12 var in, chain;

13 in = PlayBuf.ar(1, soundBufnum, loop: 1);

14 chain = FFT(bufnum, in);

15 chain = PV_MagAbove(chain, JMouseX.kr(0, 100, 0));

16 Out.ar(0, 0.5 * IFFT(chain));

17 }).play(s,[\out, 0, \bufnum, a.bufnum, \soundBufnum, b.bufnum]);

19 JMouseBase.makeGUI ;// for SwingOSC

20 )

Un’altra applicazione che ha un suo corrispettivo nel dominio della fre-quenza è il filtraggio. Intuibilmente, se il segnale finestrato è scompo-sto in frequenza, è allora possibile eliminare i bin relativi alle frequen-ze che si vogliono filtrare (ad esempio, tutti quelli sopra una certa so-glia: filtro passa-basso, tutti quelli sotto: filtro passa-alto). Nell’esempio

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 281/328

8.6–278

seguente il mouse controlla l’argomento wipe di PV_BrickWall. Se wi-

pe è pari a 0 , non c’è effetto, se è < 0 la UGen lavora come un filtropassa-basso, se > 0 come un passa-alto. L’escursione possibile è com-presa nell’intervallo [−1.0, 1.0] (il che richiede di determinare empiri-camente il valore pari alla frequenza desiderata). Il filtro spettrale pren-de giustamente il nome di “brickwall” perché la ripidità in questo casoè verticale.

1 (2 // Allocate two buffers, b for FFT, c for soundfile

3 a = Buffer.alloc(s, 2048, 1);

4 b = Buffer.read(s, "sounds/a11wlk01-44_1.aiff");

5 )

7 (

8 // An FFT filter

9 SynthDef("brickWall", { arg bufnum, soundBufnum ;

10 var in, chain;

11 in = PlayBuf.ar(1, soundBufnum, loop: 1);12 chain = FFT(bufnum, in);

13 chain = PV_BrickWall(chain, JMouseX.kr(-1.0,1.0, 0));

14 // -1.0 –> 0.0: LoPass ; 0.0 –> 1.0: HiPass

15 Out.ar(0, IFFT(chain)*10);

16 }).play(s,[\bufnum, a.bufnum, \soundBufnum, b.bufnum]);

18 JMouseBase.makeGUI ; // for SwingOSC

19 )

Una delle applicazioni più tipiche del PV consiste nell’elaborazione del-la frequenza indipendentemente dal tempo. Tra le molte UGen dispo-nibili, l’esempio seguente sfrutta PV_BinShift. PV_BinShift(buffer,

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 282/328

8.6–279

stretch, shift) permette di traslare e di scalare tutti i bin, rispetti-vamente din un fattore shift e stretch. La traslazione (shift corri-sponde ad uno spostamento nello spettro: ad esempio, dato un spet-tro di tre componenti [100, 340, 450] , una traslazione +30 risulta in[130, 370, 480]. Nel codice seguente, l’argomento stretch riceve va-lore pari a 1 (nessuna trasformazione), mentre shift varia in funzio-ne di mouseX nell’intervallo [−128, 128]. Osservando lo spettro e –inparticolare– muovendo il mouse verso destra, si nota come l’intero spet-tro si sposti lungo l’asse delle frequenze.

1 (

2 a = Buffer.alloc(s,2048,1);

3 b = Buffer.read(s,"sounds/a11wlk01.wav");

4 )

6 (

7 SynthDef("fftShift", { arg bufnum, soundBufnum ;

8 var in, chain;

9 in = PlayBuf.ar(1, soundBufnum, loop: 1);10 chain = FFT(bufnum, in);

11 chain = PV_BinShift(chain, 1, MouseX.kr(-128, 128) );

12 Out.ar(0, 0.5 * IFFT(chain).dup);

13 }).play(s,[\bufnum, a, \soundBufnum, b]);

15 JMouseBase.makeGUI ; // for SwingOSC

17 s.scope ;

18 )

In maniera analoga, l’argomento stretch permette di moltiplicare il va-lore dei bin: come si vede osservando la visualizzazione dello spettronell’esempio seguente (in particolare muovendo progressivamente il mou-se da sinistra a destra), dalla variazione discalenell’intervallo [0.25, 4]

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 283/328

8.6–280

(con incremento esponenziale) consegue una progressiva espansione spet-trale.

1 (

2 a = Buffer.alloc(s,2048,1);

3 b = Buffer.read(s,"sounds/a11wlk01.wav");

4 )

6 (

7 SynthDef("fftStretch", { arg bufnum, soundBufnum ;

8 var in, chain;

9 in = PlayBuf.ar(1, soundBufnum, loop: 1);

10 chain = FFT(bufnum, in);

11 chain = PV_BinShift(chain, MouseX.kr(0.25, 4, \exponential) );

12 Out.ar(0, 0.5 * IFFT(chain).dup);

13 }).play(s,[\bufnum, a, \soundBufnum, b]);

15 JMouseBase.makeGUI ; // for SwingOSC

17 s.scope ;

18 )

Due note per concludere.Il metodo dup(n) , definito su Object , resituisce un array che contienen copie dell’oggetto stesso. Il valore di default di n è 2. Negli esempiprecedenti, dup inviato a IFFT restituisce un array [IFFT, IFFT] , chedunque richiede una espansione multicanale: essendo il valore predefi-nito di n = 2 , il segnale in uscita è stereo.Infine, si sarà notato come i valori di controllo per le UGen PV non sia-no espressi in Herz, ma alcune volte in forma normalizzata (è il caso diPV_BrickWall , altre in escursioni che dipendono dall’implementazionedelle UGen stesse (si pensi a [−128, 128] nel caso di PV_BinShift).In effetti, la situazione, per cui i valori dipendono fondamentalmente

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 284/328

8.7–281

dall’implementazione,non è chiarissima e deve tipicamente essere risol-ta in maniera empirica.

8.7 Modulazione

Si ha modulazione quando un aspetto di un oscillatore (ampiezza, fre-quenza, fase) varia continuamente in relazione a un altro segnale. Il se-gnale che viene trasformato si definisce “portante” (carrier), quello checontrolla la trasformazione “modulante” (modulator). Un oscillatore èdefinito da un’ampiezza e da una frequenza fisse: nella modulazionesi sostituisce uno dei due parametri con l’output di un altro oscillatore.Tremolo e vibrato costituiscono di fatto due esempi di modulazione, ri-spettivamente dell’ampiezza e della frequenza: due segnali di controllo(modulanti) che modificano periodicamente i segnali originali (portan-ti). Le implementazioni più semplici delle modulazioni di ampiezza efrequenza sono perciò analoghe a quelle del vibrato e del tremolo. Neicasi di tremolo e vibrato però la modulazione avviene al di sotto del-la soglia di udibilità (subaudio range), il segnale modulante ha cioè unafrequenza inferiore ai 20 Hz, e la modulazione viene percepita non co-me trasformazione timbrica, ma espressiva. Se invece la frequenza dellamodulante cade all’interno del campo uditivo, il risultato della modu-

lazione è un cambiamento spettrale che si manifesta percettivamentecome cambiamento qualitativo del timbro.In generale, il risultato di una modulazione è un nuovo segnale le cuicaratteristiche dipendono dalla combinazione dei due parametri fon-damentali: frequenza e ampiezza di portante e modulante. La modula-zione è una tecnica di larghissimo impiego perché è estremamente eco-nonomica in termini computazionali: contrariamente a quanto avviene

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 285/328

8.7–282

Time (s)0 15.343

0

5000

   F  r  e  q  u  e  n  c  y   (   H  z   )

Time (s)0 13.7314

0

5000

   F  r  e  q  u  e  n  c  y   (   H  z   )

Time (s)1 3

 –1

1

0

Time (s)1 1.1

 –1

1

0

Fig. 8.12 Incremento della frequenza di vibrato (destra) e di tremolo (sini-stra), sonogramma (alto) e forma d’onda (basso): dall’espressività al timbro.

per la sintesi additiva, che richiede la definizione di moltissimi parame-tri di controllo, attraverso la modulazione, anche impiegando soltantodue oscillatori come portante e modulante, è possibile creare spettri digrande complessità. Proseguendo nell’analogia con temolo e vibrato, lamodulazione può avvenire nell’ampiezza e nella frequenza.

8.7.1 Modulazioneadanelloed’ampiezza

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 286/328

8.7–283

Quando il segnale modulante (M) controlla l’ampiezza della portante(C), si possono avere due tipi di modulazione d’ampiezza, che dipen-dono dalle caratteristiche della modulante. Si ricordi che un segnale bi-polare si estende tra un massimo positivo e uno negativo, mentre unsegnale unipolare è invece compreso completamente tra valori positivi.

1 {SinOsc.ar}.scope ; // bipolar

2 {SinOsc.ar(mul: 0.5, add:0.5)}.scope ; // unipolar

Un segnale audio è tipicamente bipolare (in ampiezza normalizzata oscil-la nell’intervallo [−1.0, 1.0]). Come si vede, per trasformare un segna-le bipolare in uno unipolar è sufficiente moltiplicarlo e aggiungervi unoffset (nell’esempio: [−1.0, 1.0] → [−0.5, 0.5] → [0.0, 1.0]). Se ilsegnale modulante è bipolare si ha una modulazione ad anello (Ring Mo-

dulation , RM), se è unipolare si ha quella che viene definita per sineddo-che modulazione d’ampiezza (Amplitude Modulation , AM). Supponen-do che portante e modulate siano due sinusoidi di frequenza rispettiva-mente C e M  , il segnale risultante da una modulazione ad anello ha unospettro complesso formato da due frequenze, pari a C − M e C + M  ,chiamate bande laterali (side-bands). Se C  = 440Hz e M  = 110Hz , ilrisultato della modulazione ad anello è un segnale il cui spettro è dotatodi due componenti armoniche, 330 e 550Hz. Se invece la modulanteè unipolare, e si ha una modulazione d’ampiezza, lo spettro del segna-le risultante conserva anche la componente frequenziale della portante,

oltre a somma e differenza di portante e modulante. Mantenendo tut-ti i parametri identici, ma realizzando una AM attraverso l’impiego diun segnale unipolare, si avranno perciò C − M  , C  , C + M : tre com-ponenti pari a 330 , 440 , 550Hz. Nel caso in cui la differenza risulti disegno negativo si ha semplicemente un’inversione di fase: il che equiva-le a dire che la frequenza in questione comunque si “ribalta” al positivo:ad esempio, un risultante di −200Hz sarà presente come frequenzadi 200Hz. L’esempio seguente mostra due possibili implementazioni,

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 287/328

8.7–284

del tutto identiche nei risultati, ma utili come esempio di patching. Nel-le prime implementazioni (3, 7) la modulante controlla l’argomento mul

della portante. Nelle seconod, si ha moltiplicazione diretta dei segna-li.L’argomento mul definisce il valore per cui ogni campione deve esseremoltiplicato: il moltiplicatore è fornito dal valore del segnale modulan-te. La moltiplicazione di segnali fa la stessa cosa: ogni nuovo campionedella portante viene moltiplicato per un nuovo campione della modu-lante.

1 // better to select log display for frequencies

2 // RM

3 { SinOsc.ar(440, mul: SinOsc.ar(110))}.freqscope ;

4 { SinOsc.ar(440)*SinOsc.ar(110) }.freqscope ; // the same

6 // AM

7 { SinOsc.ar(440, mul: SinOsc.ar(110, mul: 0.5, add:0.5))}.freqscope ;

8 { SinOsc.ar(440)*SinOsc.ar(110, mul:0.5, add:0.5) }.freqscope ;

8.7.2 Modulazioneadanellocometecnicadielabora-

zione

La sintesi per modulazione d’ampiezza (AM) nasce come tecnica percostruire spettri più complessi a partire da sinusoidi. La modulazionead anello ha invece un’origine e un lungo passato analogico31 non tantocome tecnica di generazione ab nihilo ma come tecnica di elaborazione

Lo stesso nome deriva dalla configurazione “ad anello” dei diodi usata per approssi-31

mare la moltiplicazione nelle implementazioni in tecnologia analogica.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 288/328

8.7–285

di segnali complessi32. In primo si può pensare di modulare un segnalecomplesso (ad esempio di origine strumentale) con un segnale sinusoi-dale. Un segnale complesso avrà uno spettro composto di un insieme dicomponenti “portanti” C n:

C  = C 1, C 2, C 3 . . . , C  n

Data una sinusoide M  , una modulazione ad anello C ×M risulta alloranella somma e differenza di tra ogni componente C e M . Se il segnale

modulante è unipolare, anche le componenti C  saranno presenti nellospettro:

C 1 − M, (C 1), C 1 + M ; C 2 − M, (C 2), C 2 + M , . . . C  n − M, (C n), C n + M 

Se M  è ridotto, allora C n − M  e C n + M  saranno vicini a C n: adesempio, con uno spettro inarmonico Cn = 100, 140, 350, 470,etce M  = 10 , si avrà 90, 110, 130, 150, 340, 360, 460, 480,etc −M,etc

+M . Sostanzialmente l’inviluppo spettrale non cambia, ma

raddopia di densità. Quando invece M  è elevato, allora si realizza unaespansione spettrale. Nell’esempio precedente, se M  = 2000 allora lospettro risultante sarà 1900, 2100, 1860, 2140, 1650, 2350, 1730, 2470,etc−M,etc+M . La situazione è rappresentata in Figura 8.13 (tratta da Puc-kette cit.).Nell’esempio seguente un file audio è modulato da una sinusoide la cuifrequenza incrementa esponenzialmente tra 0 e 10000Hz nell’arco di

30secondi. Si noti all’inizio l’effetto di “raddopio” intorno alle frequen-

ze dello spettro e la progressiva espansione spettrale, che porta, nel fina-le, all’emergenza della simmetria spettrale intorno alle frequenze dellasinusoide.

Alcuni riferimenti e figure da Miller Puckette, Theory and Techniques of Electronic Music ,32

http://www-crca.ucsd.edu/~msp/techniques.htm

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 289/328

8.7–286

frequency

amplitude

(a)

(b)

(c)

Fig. 8.13 Influenza di M  sull’inviluppo spet-trale: segnale originale, addensamento edespansion (da Puckette cit.).

1 (

2 b = Buffer.read(s,"sounds/a11wlk01.wav"); // buffering the file

4 { PlayBuf.ar(1, b.bufnum, BufRateScale.kr(b.bufnum), loop: 1)

5 *

6 SinOsc.ar(XLine.kr(1, 10000, 30))

7 }.freqscope

8 )

Lo stesso approccio può essere esteso ai casi in cui M  è complesso: èquanto avveniva tipicamente nell’uso analogico dell’RM, in cui spessodue segnali strumentali venivano modulati tra loro33. Nel caso allora in

Ad esempio, in alcuni importanti lavori di K.H.Stockhausen (dal vivo): Kontakte , Hym-33

nen , Mikrophonie , Prozession

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 290/328

8.7–287

cui C  e M  siano complessi, si ha addizione/sottrazione reciproca ditutte le componenti, così che, se C  e M  hanno rispettivamente i e kcomponenti spettrali, C × M  avrà i × k componenti, un risultato fi-nale evidentemente di grande complessità. L’esempio seguente utilizzalo stesso file audio predefinito in SC. Il primo segnale modulante è unacopia del medesimo file, la cui velocità di lettura è modificata attraversoun generatore di segnale esponenziale da 0.1 a 10.0 (si può ascoltarevalutando le righe 5-9). Come si vede, il segnale risultante dalla RM (ri-ghe 11-19) presenta un inviluppo spettrale molto complesso, in cui pureresta traccia percettiva dei due segnali di partenza.

1 (

2 b = Buffer.read(s,"sounds/a11wlk01.wav"); // buffering the file

3 )

5 ( // the modulating signal

6 { PlayBuf.ar(1, b.bufnum,

7 XLine.kr(0.1, 10.0, 30, doneAction:0),

8 loop: 1) }.play ;

9 )

11 (

12 { PlayBuf.ar(1, b.bufnum, BufRateScale.kr(b.bufnum), loop: 1)

13 *

14 PlayBuf.ar(1, b.bufnum,

15 XLine.kr(0.1, 10.0, 30, doneAction:0),

16 loop: 1)

17 *5

18 }.freqscope

19 )

Nel secondo esempio, lo stesso segnale dal file audio è moltiplicato perun onda quadra la cui frequenza incrementa in 30sec da 1 a 10.000Hz.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 291/328

8.7–288

Si noti che finché la frequenza è nel registro subaudio (freq <≈

20), ilsegnale modulante opera propriamente come un inviluppo d’ampiezza.

1 // modulating signal

2 { Pulse.ar(XLine.kr(1, 10000, 30))}.play ;

4 (

5 b = Buffer.read(s,"sounds/a11wlk01.wav"); // buffering the file

7 { PlayBuf.ar(1, b.bufnum, BufRateScale.kr(b.bufnum), loop: 1)

8 *

9 Pulse.ar(XLine.kr(1, 10000, 30))

10 }.freqscope

11 )

Un altro esempio interessante di applicazione della RM si ha quando ilsegnale portante è un segnale complesso armonico con frequenza fonda-

mentale C  , mentre la modulante è una sinusoide con frequenza M  =C 2 . Lo spettro risultante è armonico con frequenza M =C 

2  , e compren-de soltanto armoniche dispari. In sostanza, si tratta dello spettro delsegnale portante abbassato di un’ottava, secondo un’elaborazione cheprende il nome in ambito pop/rock di octaver. Ad esempio, se C 1−n =100, 200, 300, . . . n e M  = 50 , allora il segnale modulato avrà que-ste componenti: 100 − 50, 100 + 50, 200 − 50, 200 + 50, 300 −50, 300 + 50 = 50, 150, 150, 250, 250, 350, 350. Si tratta delle ar-

moniche dispari (raddoppiate) di C 2 . I rapporti Tra frequenze risultantisono infatti 1, 3, 5, 7, . . .. Per recuperare le armoniche pari (altrimentiil segnale è più “vuoto” rispetto all’originale), è sufficiente sommare ilsegnale originale.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 292/328

8.7–289

1 //RM octaver2 (

3 SynthDef.new("RmOctaver", {

4 var in, freq ;

5 in = SoundIn.ar(0) ; // audio from soundcard

6 Pitch.kr(in)[0].poll ; // the retrieved freq 

7 Pitch.kr(in)[1].poll ; // is the in sig pitched?

8 freq = Pitch.kr(in)[0] ; // the pitch freq 

9 Out.ar(0, SinOsc.ar(freq: freq*0.5)*in+in);

10 // RM freq/2 + source

11 }).send(s) ;12 )

14 Synth.new("RmOctaver") ;

La synthDef "RmOctaver" riceve in input il segnale dall’ingresso dellascheda audio (il microfono, tipicamente), attraverso la Ugen SoundIn.

Nella UGen, il primo argomento indica il bus richiesto: per convenien-za l’indice 0 rappresenta sempre il primo ingresso. La UGen Pitch in-vece è una UGen di analisi, che estrae un segnale di controllo che rap-presenta la frequenza fondamentale ( pitch in inglese) del segnale ana-lizzato. Pitch fornisce in uscita un array che comprende due segnali. Ilprimo è costituito dai valori di frequenza rilevati, il secondo da un se-gnale che può avere valore binario [0, 1] , ad indicare rispettivamenteassenza/presenza di frequenza fondamentale rilevabile. Le righe 6 e 7

chiamano sui due segnali che compongono l’array in uscita da Pitch ilmetodo poll che stampa sullo schermo il valore del segnale. La frequen-za freq ÷2 viene utilizzata per controllare un oscillatore34 che moltipli-ca il segnale in , infine in viene sommato al segnale risultante.In modo analogo è poi possibile utilizzare una modulante con M  =

Si moltiplica per 0.5 per questioni di efficienza computazionale. Le divisioni costano34

al calcolatore molto di più delle moltiplicazioni.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 293/328

8.7–290

C . In questo caso si ha un incremento delle componenti superioridello spettro del segnale portante. Se M  = n × C  si ha un “ribatti-mento” delle armoniche. Si consideri: C  = 100, 200, 300, n × 100 eM  = 200(n×2). Lo spettro risultante sarà: 100−200 = 100, 100+200 = 300, 200 − 2 0 0 = 0, 200 + 200 = 400, . . ..

8.7.3 Modulazionedifrequenza

Nella modulazione di frequenza (FM) è la frequenza della portante cheviene modificata dalla modulante. Si coinsiderino due oscillatori cheproducano due sinusoidi di frequenza C e M . Alla frequenza C dell’oscillatoreportante viene sommato l’output dell’oscillatore modulante. In questomodo la frequenza C subisce una serie di variazioni che la fanno deviareverso l’acuto (quando l’output di

M è positivo,

C viene incrementata)

e verso il grave (inversamente, quando l’output di M è negativo, C de-crementa). Con il termine frequenza di deviazione di picco ( peak frequen-

cy deviation) – o semplicemente deviazione (D) – si indica l’escursionemassima, misurata in Hz , subita dalla frequenza della portante, che di-pende dall’ampiezza della modulante.La differenza fondamentale tra FM da una parte e RM e AM dall’altrasta nel fatto che con la FM non si producono solo 2 o 3 bande laterali, ma

una serie teoricamente infinita data da tutte le frequenze C ±n×M . SeC  = 220 e M  = 110 , si ha con n = 1: 330 e 110; con n = 2: 440 e 0;con n = 3: 550 e 110 (–110 invertito di fase), e così via. Valgono a pro-posito le considerazioni sugli spettri già svolte per la AM. Con la FM siapre allora la possibilità di creare spettri anche molto complessi attraver-so una tecnica di grande semplicità computazionale. Proprio per questomotivo la FM è diventata la prima tecnica di sintesi digitale di gran-dissimo successo commerciale, grazie a una serie, fortunatissima negli

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 294/328

8.7–291

anni ‘80, di sintetizzatori della Yamaha (soprattutto il celebre DX7). LaFM è stata usata dall’inizio ‘900 nelle telecomunicazioni (come noto, è diuso comune la locuzione “radio in modulazione di frequenza”): sul fini-re degli anni ’60, all’università di Stanford, John Chowning sperimentainizialmente con rapidissimi vibrato, implementa quindi una versionedigitale, e ne esamina a fondo le possibilità (1973).Turenas (1972) è il pri-mo brano ad usare estensivamente la FM, anche se il primo tentativo inassoluto è Sabelithe del 1966, completato nel 1988. Chowning ottiene condue oscillatori risultati timbrici pari all’uso di 50 oscillatori in sintesi ad-ditiva. Quindi, la Yamaha compra il brevetto (ancora adesso quello piùredditizio per Stanford...) e applica la tecnica sui sintetizzatori.Dunque, la FM si caratterizza per la ricchezza timbrica. In realtà, del-le infinite bande teoricamente presenti, poche sono quelle significative:per determinarne il numero approssimativo è utile il cosiddetto indicedi modulazione I . La relazione che lega deviazione, frequenza modu-lante e indice di modulazione è la seguente: I  = D

M . In questo sen-so, D rappresenta la “profodità” della modulazione. Il valore dato daI + 1 viene considerato un buon indicatore del numero approssimativodi bande laterali “significative”. L’utilità della formula sta in questo: sesi considerano D e M costanti (poiché dipendono da modulante e por-tante), l’indice fornisce una misura della ricchezza in bande laterali dellospettro. Dalla relazione precedente discende che l’ampiezza della modu-lante è data dalla relazione: D = I × M . Se I  = 0 , non c’è deviazio-ne, poiché l’incremento fornito dalla modulante alla portante (la devia-zione) è nullo, e il segnale portante non viene modulato. L’incrementodell’indice di modulazione indica un incremento della ricchezza dellospettro.Riassumendo: nella FM, la natura dello spettro generato (cioè, la posi-zione delle bande laterali) è determinata dalla relazione tra la portante ela modulante, mentre la ricchezza dello spettro (cioè, il numero di bandelaterali) è proporzionale all’ampiezza del segnale modulante.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 295/328

8.7–292

Frequency (Hz)0 22050

   S  o  u  n   d

  p  r  e  s  s  u  r  e

   l  e  v  e   l   (   d   B          /   H  z

   )

20

40

60

Frequency (Hz)0 22050

   S  o  u  n   d

  p  r  e  s  s  u  r  e

   l  e  v  e   l   (   d   B          /   H  z

   )

20

40

60

Frequency (Hz)0 22050

   S  o  u  n   d

  p  r  e  s  s  u  r  e

   l  e  v  e   l   (   d   B          /   H  z

   )

20

40

60

Fig. 8.14 I  = 1, 3, 7

Nell’esempio seguente, il mouse controlla frequenza e ampiezza del se-gnale modulante M  , mentre C  , ch è costante, è pari a 1000Hz. Posi-zionando il mouse nell’orgine (si ricordi che è l’angolo in alto a sinistra),

il contributo di M è pari a 0 (l’ampiezza del segnale è nulla): dunque, siascolta soltanto la sinusoide C  a 1000Hz. Spostando leggermente in

 basso il mouse (incrementando l’ampiezza della modulante) e mouven-dosi verso destra si ascolta e si osserva nello spettro il contributo datoda M  la cui frequenza incrementa da 0 a 1000. Come si nota aumentala distanza tra le bande laterali in relazione alla formula C ± M . Spo-stando verso il basso il mouse, aumenta invece l’energia associata alle

 bande laterali (i picchi diventano più prominenti, lo spetto più ricco).

1 JMouseBase.makeGUI // required on SwingOSC

3 (

4 { SinOsc.ar(

5 1000 // C freq 

6 + SinOsc.ar( // modulator

7 freq: GUI.mouseX.kr(0, 1200), // M freq 

8 mul: GUI.mouseY.kr(0, 10000) // M amp

9 ),10 mul: 0.3

11 )}.freqscope

12 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 296/328

8.7–293

8.7.4 C:M ratio

Oltre all’ampiezza della modulante, l’altro fattore che va tenuto in con-siderazione nello studio delle caratteristiche spettrali del segnale risul-tante da una modulazione è il rapporto tra le frequenze di portante emodulante. Tale fattore è di particolare rilievo per la modulazione difrequenza o nella modulazione ad anello di segnali complessi: in en-trambi casi, a differenza di quanto avviene nella AM o RM in cui C  eM  siano sinusoidali, il segnale in uscita risulta costituito da numerosecomponenti, e non soltanto da due (RM) o tre (AM). Il rapporto tra lefrequenze dei due segnali viene usualmente definito come C:M ratio (diqui in poi: cmr). Poiché le frequenze componenti lo spettro del segna-le comprendono somma e differenza di C e M  , se cmr è un intero lospettro sarà armonico, comprendendo due multipli del massimo comundivisore tra C e M . Ad esempio, se C  = 5000Hz e M  = 2500Hz(cmr = 2 : 1), si avranno (in AM) 2500 , 5000 e 7500Hz: uno spettroarmonico formato da fondamentale (2500) e dalle prime due armoni-che (i multipli 5000 e 7500Hz). Due casi interessanti in RM e in FMsi hanno quando cmr = 1 : 2 e C  : Mratio = 1 : 1. Nel pri-mo caso sono presenti soltanto le armoniche dispari: con C  = 1000e M  = 2000 , si ha in RM (−)1000, 3000 , a cui si aggiungono in

FM: (−)3000, 5000, (−)5000, 7000 , ecc. Nel secondo caso, tutte learmoniche sono presenti nel segnale modulato: con C  = M  = 1000 ,si ha in RM 0, 2000 , e in FM 0, (−)1000, 3000, (−)2000, 4000 ecc.Se la frazione ha denominatore 1 (come nell’esempio precedente), al-lora le frequenze ottenute sono multipli della modulante, che diven-ta fondamentale del segnale generato. Se il denominatore è maggio-re di 1 , è il massimo comun divisore tra C  e M  a diventare la fon-damentale del segnale risultante dalla modulazione: con C  = 3000

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 297/328

8.7–294

e M  = 2000 (cmr = 3 : 2) la nuova fondamentale è il massi-mo comun divisore, ovvero 1000Hz , lo spettro essendo composto da1000 Hz (3000 − 2000), cui si aggungono (in AM) 3000Hz (C ), e5000Hz (3000+2000). A differenza di questo caso, la fondamentalepuò anche essere apparente. Ad esempio, se C  = 5000 e M  = 2000 ,(cmr = 5 : 2) la nuova fondamentale è sempre 1000Hz (il MCD tra5000 e 2000), ma lo spettro è composto da 3000Hz (5000 − 2000),5000 (in AM), e 7000 (5000 + 2000). La fondamentale 1000Hz èapparente perché può essere ricostruita dall’orecchio, pur non essen-do presente fisicamente nel segnale, come la fondamentale di cui so-no presenti le armoniche III, V e VII. La fondamentale viene ricostruitadall’orecchio se cade nel campo di udibilità e se sono presenti un nu-mero sufficiente di armoniche. Quest’ultima considerazione vale per lamodulazione di frequenza, poiché in RM e AM semplici (dove C e M sono segnali sinusoidali) le bande laterali sono rispettivamente sem-pre solo 2 e 3. Nell’esempio precedente, sempre con C  = 5000Hzma con M 

= 2000 , si avranno (in AM) frequenze risultanti pari a

3000, 5000, 7000Hz: terzo, quinto, settimo armonico di 1000Hz.La C:M ratio è perciò un’indicatore della “armonicità” dello spettro: piùè semplice la frazione (cioè minore è il prodotto C  × M ), più vicinisono gli armonici risultanti. Se la C:M ratio è quasi intera (ad esempio,2.0 0 1 : 1) si ottiene un suono che non solo viene ancora percepito comearmonico, ma che risulta invece meno artificiale proprio perché simulale inarmonicità presenti negli strumenti acustici.In generale, si ha che ratio pari a

N  : 1, 1 : N riproducono lo stesso

spettro. Il numero dei parziali può essere calcolato a partire dai compo-nenti della ratio. Ad esempio, se la ratio è 2 : 3 , si ha allora |2±3×n| =1, 2, 4, 5, 8, 11 . . .. Se C > 1 , allora ci sono bande laterali inarmo-niche (o “fondamentale mancante”). Ad esempio, se cmr = 2 : 5 ,lo spettro risultante sarà 2, 3, 7, 8, 12, 13 . . .: come si vede, manca lafondamentale (la componente 1) e molte armoniche. In più, lo spettrosi allontana all’acuto.Si consideri cmr = 5 : 7: si produce uno spettro

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 298/328

8.7–295

distintamente inarmonico: 2, 5, 9, 12, 16, 19, 23, 26, . . ..La synthDef seguente permette di controllare una modulazione di fre-quenza utilizando, oltre la frequenza di base freq  , ovvero C  , i parametriderivati dalla cmr , ovvero c, m, a. I primi due indicano numeratore edenominatore della cmr , il terzo l’ampiezza della modulante.

1 (

2 SynthDef("cm", { arg f = 440, c = 1, m = 1, a = 100, amp = 0.3 ;

3 Out.ar(0,

4 SinOsc.ar(5 f // base freq 

6 + SinOsc.ar( // modulator

7 freq: f * m / c, // M freq 

8 mul: a // M amp

9 ),

10 mul: amp)

11 )

12 }).send(Server.local) ;

13 )

L’interfaccia grafica seguente permette di controllare i parametri f, c, m, a attraverso cursori e campi d’inserimento numerico.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 299/328

8.7–296

1 (2 var w = GUI.window.new("C:M player", Rect(100, 100, 250, 420)).front ;

3 //sliders

4 var sl1 = GUI.slider.new(w, Rect(10, 10, 50, 350)) ;

5 var sl2 = GUI.slider.new(w, Rect(60, 10, 50, 350)) ;

6 var sl3 = GUI.slider.new(w, Rect(110, 10, 50, 350)) ;

7 var sl4 = GUI.slider.new(w, Rect(160, 10, 50, 350)) ;

8 // numberboxes

9 var nb1 = GUI.numberBox.new(w, Rect(10, 360, 40, 20)) ;

10 var nb2 = GUI.numberBox.new(w, Rect(60, 360, 40, 20)) ;

11 var nb3 = GUI.numberBox.new(w, Rect(110, 360, 40, 20)) ;12 var nb4 = GUI.numberBox.new(w, Rect(160, 360, 40, 20)) ;

13 // labels

14 var l1 = GUI.staticText.new(w, Rect(10, 390, 40, 20)).string_("freq")

;

15 var l2 = GUI.staticText.new(w, Rect(60, 390, 40, 20)).string_("c") ;

16 var l3 = GUI.staticText.new(w, Rect(110, 390, 40, 20)).string_("m") ;

17 var l4 = GUI.staticText.new(w, Rect(160, 390, 40, 20)).string_("a") ;

19 /* to be continued… */

Si tratta ora di creare un synth e di stabilire alcuni valori di riferimento

1 /* …here… */

2 var cmsynth = Synth("cm") ;

3 var freq = 2000 ; // f: 0-2000 Hz

4 var num = 30 ; // range for c:m

5 /* …still to be continued…*/

Infine, la parte di codice che segue è piuttosto lunga (come tipico con leinterfacce grafiche), ma cioò che fa è semplicemente associare ad ognielemento grafico l’azione di controllo sul synth (cmsynth.set) e aggior-nare l’elemento correlato (cambiando il valore del cursore, cambia anche

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 300/328

8.7–297

quello del campo numerico, e viceversa). Il codice in un blocco unito (edeseguibile direttamente) è accessibile qui:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 301/328

8.7–298

1 /* …here*/2 // base freq 

3 sl1.action = { arg sl ;

4 var val = sl.value*freq ;

5 cmsynth.set("f", val) ;

6 nb1.value = val ;

7 } ;

9 nb1.action = { arg nb ;

10 var val = nb.value ; // 0-1000 Hz

11 cmsynth.set("f", val) ;12 sl1.value = val/freq ;

13 } ;

15 // C

16 sl2.action = { arg sl ;

17 var val = (sl.value*(num-1)).asInteger+1 ;

18 cmsynth.set("c", val) ;

19 nb2.value = val ;

20 } ;

22 nb2.action = { arg nb ;

23 var val = nb.value.asInteger ;

24 cmsynth.set("c", val) ;

25 sl2.value = val/num ;

26 } ;

28 // M

29 sl3.action = { arg sl ;

30 var val = (sl.value*(num-1)).asInteger+1 ;

31 cmsynth.set("m", val) ;32 nb3.value = val ;

33 } ;

35 nb3.action = { arg nb ;

36 var val = nb.value.asInteger ;

37 cmsynth.set("m", val) ;

38 sl3.value = val/num ;

39 } ;

41 // a42 sl4.action = { arg sl ;

43 var val = sl.value*10000 ;

44 cmsynth.set("a", val) ;

45 nb4.value = val ;

46 } ;

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 302/328

8.7–299

In conclusione, le tecniche per modulazione hanno dalla loro parte la ca-pacità di creare spettri di grande complessità unitamente ad un’estremaeconomicità in termini computazionali: si pensi alla complessità spet-trale ottenuta ad esempio in FM a partire da due sinusoidi. D’altra par-te, non è ovvia la relazione tra controllo e risultato. In più, le tecnicheper modulazione scontano una inapplicabilità analitica: è estremamen-te difficile l’estrazione funzionale dei parametri controllo dall’analisi dimateriale sonoro preesistente.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 303/328

9.1–300

9 Suonoorganizzato:(minimal)schedulinginSC

9.1 Serverside:attraversoleUGen

Il controllo dell’informazione e dei suoi processi, attraverso il linguag-gio SC, e la sintesi del segnale, attraverso la gestione delle UGen nellesynthDef, sono due momenti fondamentali che devono essere integrati:mutuando un’espressione di Edgar Varèse, si tratta di arrivare al “suo-no organizzato”. La locuzione è interessante perché unisce il lavoro sul-la materia sonora alla sua organizzazione temporale: ne consegue unadefinizione in fondo molto generale di musica e composizione, come

un insieme di eventi sonori. In termini molto generali, lo scheduling èappunto l’assegnazione di risorse per la realizzazione di un evento inun certo momento35. Come usuale, in SC esistono potenzialmente modidiversi di realizzare lo scheduling. Una opzione, che potrebbe derivare

Ad esempio, http://en.wikipedia.org/wiki/Scheduling. Un termine italiano possi-35

 bile è “programmazione”, nel senso di gestione nel tempo delle risorse, ma in generaleil termine italiano è molto meno specifico.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 304/328

9.1–301

da sintetizzatori analogi, è quella di gestire il sequencing (la messa insequenza) degli eventi attraverso segnali. L’esempio seguente, pur nel-la sua banalità, dimostra un aspetto che si è già discusso: un inviluppoapplicato ad un segnale continuo lo può trasformare in un insieme dieventi discreti.

1 (

2 SynthDef.new("schedEnv", {

3 Out.ar(0,

4 Pan2.ar( // usual panner5 InRange.ar(LFNoise2.ar(10), 0.35, 1).sign

6 *

7 Formant.ar(LFNoise0.kr(1, mul: 60, add: 30).midicps, mul:0.5),

8 LFNoise1.kr(3, mul:1) ) // random panning

9 )

10 }).send(s) ;

11 )

13 Synth.new("schedEnv") ;

In questo caso, alla UGen Formant (si veda il file di help) genera un se-gnale che viene inviluppato dal segnale descritto dal codice di riga 4.Si è già visto in precedenza il funzionamento di InRange , che restitui-sce un segnale il cui valore dipende dall’inclusione o meno del valoredel campione in entrata nell’intervallo specificato (qui

[0.35, 1]). Se il

valore è incluso, InRange restituisce il valore stesso, altrimenti restitui-sce 0. Il metod sign restituisce 1 se il segnale è positivo, 0 se è pari a0. Dunque, il segnale in uscita sarà composto da 1 o 0 in funzione ri-spettivamente del superamento o meno della soglia di 0.35. Un similesegnale d’inviluppo “buca” il segnale audio tutte le volte che vale 0 , difatto trasformando un segnale continuo in un insieme di eventi. Si valutiquanto segue per capire cosa succed in 10 secondi.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 305/328

9.1–302

{InRange.ar(LFNoise2.ar(10), 0.35, 1).sign

}.plot(10)

L’effetto di generazione di eventi è sottolineato nel caso di istanziazionemultipla di più synth36. L’esempio, già conosciuto, chiarisce un puntogenerale in relazione allo scheduling: il parallelismo (voci, strati, comeli voglia chiarire) è gestito da SC semplicemente istanziando più synth,esattamente come quando si valuta il codice interattivamente.

1 (

2 SynthDef.new("schedEnv", {3 Out.ar(0,

4 Pan2.ar( // usual panner

5 InRange.ar(LFNoise2.ar(10), 0.35, 1).sign

6 *

7 Formant.ar(LFNoise0.kr(1, mul: 60, add: 30).midicps, mul:0.5),

8 LFNoise1.kr(3, mul:1) ) // random panning

9 )

10 }).send(s) ;

11 )

13 (

14 100.do({

15 Synth.new("schedEnv") ;

16 })

17 )

Si è già discussa la UGen Select.kr(which, array) , che implementaa livello server una funzione tipica del sequencing: a tasso di control-lo, ogni volta che calcola un nuovo valore selezione un elemento which

dell’array array. Vale la pena di riprendere la discussione. Il codice se-guente è tratto dal file di help.

Il clicking, che produce una solta di polvere di sfondo rispetto agli altri oggetti sonori36

quasi vocali, dipende da un’applicazione dell’inviluppo che non si cura delle transi-zioni. Nel singolo synth non era particolarmente evidente.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 306/328

9.2–303

1 (2 {

3 var a, cycle;

4 a = Array.fill(32, { rrand(30,80) }).postln.midicps;

5 cycle = a.size * 0.5;

6 Saw.ar(

7 Select.kr(

8 LFSaw.kr(1.0, 0.0, cycle, cycle),

9 a

10 ),

11 0.212 );

13 }.play;

14 )

L’array a contiene 32 frequenze, a caso tra le altezze 30 e 80 in notazioneMIDI (riga 4). La riga 7 specifica che il segnale in uscita sarà un onda a

dente di sega, la cui ampiezza sarà pari a 0.2 (riga 12). La frequenza ègestita invece da Select. All’argomento array è passato a ,cioè le altez-ze prescelte proverrano dall’array precedentemente creato. La parte piùinteressante è la riga 9, che determina quale sarà l’indice dell’elementodi a da prelevare. La riga 6 ha assegnato a cycle valore pari a metà del-la dimensione di a , ovvero 16. La UGen LFSaw genera un’onda a dentedi sega, con frequenza 1 nell’esempio: in sostanza, una volta al secon-do la forma d’onda incrementa linearmente tra −1.0 e 1.0. Senonché

l’argomenti mul e add valgono cycle. Dunque, il segnale è una retta cheincrementa tra 0 e 31 , e il valore del campione (convertito internamentein intero) è utilizzato da Select come indice dell’elemento da seleziona-re in a37. L’utilizzo di segnali simili (ramp , “a rampa”) è tipico nei synth

Un’altra UGen che permette di generare eventi discreti in maniera analoga è Stepper.37

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 307/328

9.2–304

analogici38 , in cui spesso lo scheduling è gestito attraverso segnali con-tinui opportunamente generati.

9.2 Serverside:leUGenDemand

Un approccio allo scheduling molto peculiare è implementato nelle UGendi tipo Demand, o “demand rate”, secondo una locuzione –come si vedrà–significativa. La UGen Demand.ar(trig, reset, [..ugens..]) operain relazione ad un trigger (trig). Ogni qualvolta un segnale di trigger èricevuto39 , la UGen richiede un valore ad ognuna delle altre UGen inclu-se nell’array [..ugens..]. Queste UGen devono essere di tipo speciale,ovvero di tipo Demand: sono infatti delle UGen che generano un valore(ed uno solo) a richiesta. Nell’esempio seguente, il segnale di trigger perDemand è generato dalla UGen Impulse. Ogni impulso prevede una tran-sizione tra minimo (0) e massimo (qui 1), e dunque un trigger. Inutilediscutere della sintesi (riga 7), salvo notare che la frequenza di Pulse ègestita da freq . La riga 6 assegna a freq attraverso una UGen Demand.Ogni qualvolta un trigger è ricevuto, Demand chiede il prossimo valo-re nell’array demand a. Quest’ultimo è riempito da Dseq (riga 4), cheproduce una sequenza di valori quale quella prevista nell’array fornitocome primo argomento ([1,3,2,7,8]), ripetuta –in questo caso– per 3

volte. Ascoltando il risultato, ci si accorge come la sequenzaa

sia ap-punto costituita dalla ripetizione per 3 volte di un segmento: quando ilsegmento è concluso, Demand restituisce l’ultimo valore della sequenza.

L’implementazione più usuale prende il nome di “phasor”: si veda la UGen omonima38

in SC.Si ricordi che si ha un evento di triggering ogni qualvolta si verifica una transizione39

da 0 ad valore positivo.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 308/328

9.2–305

1 (2 {

3 var a, freq, trig;

4 a = Dseq ([1, 3, 2, 7, 8]+60, 3);

5 trig = Impulse.kr(4);

6 freq = Demand.kr(trig, 0, a.midicps);

7 LPF.ar(Mix.fill(10, { Pulse.ar(freq+5.rand)}), 1500) * 0.1

9 }.play;

10 )

Come si vede, in sostanza le UGen di tipo Demand sono generatori divalori a richiesta, e si differenziano tra loro per i pattern che possonoprodurre. Ad esempio, come si è visto Dseq genera sequenze di valo-ri costruite iterando n volte un array. Invece, una UGen come Drand

riceve due argomenti: il primo è un array di valori, il secondo un un nu-mero che rappresenta il numero di valori pescati a caso nell’array for-nito. Nell’esempio, l’array è lo stesso del caso precedente, mentre freq 

è una sequenza di durata inf di valori prelevati pseudo-causalmentesullo stesso array a40.

1 (

2 {

3 var a, freq, trig;

4 a = Drand([1, 3, 2, 7, 8]+60, inf);

5 trig = Impulse.kr(10);6 freq = Demand.kr(trig, 0, a.midicps);

7 LPF.ar(Mix.fill(10, { Pulse.ar(freq+5.rand)}), 1500) * 0.1

9 }.play;

10 )

Inoltre la frequenza di triggering è stata incrementata da 4 a 10.40

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 309/328

9.2–306

La potenza espressiva delle UGen di tipo Demand sta nella possibilità diinnesto ricorsivo. L’esempio seguente è del tutto analogo al primo casoqui discusso. senonché uno degli elementi dell’array su cui opera Dseq 

è Drand.

1 (

2 {

3 var freq, trig, reset, seq;

4 trig = Impulse.kr(10);5 seq = Dseq (

6 [42, 45, 49, 50,

7 Dxrand([78, 81, 85, 86], LFNoise0.kr(4).unipolar*4)

8 ], inf).midicps;

9 freq = Demand.kr(trig, 0, seq);

10 RLPF.ar(Pulse.ar(freq + [0,0.7])* 0.1, 1500, 0.01);

11 }.play;

12 )

Ciò che avviene è che seq è una sequenza che ripete infinite volte (inf)un pattern costituito dai numeri 42, 45, 49, 50 , e da un quinto ele-mento definito da Dxrand: analogamente a Drand , quest’ultima UGenpesca a caso nell’array fornito ([78, 81, 85, 86]), ma la sequenzain uscita non prevede ripetizioni dello stesso elemento. La dimensio-ne della sequenza in uscita è controllata da LFNoise0: in sostanza, varia

pseudo-casualmente nell’escursione [0, 4]. Nel primo caso, il contribu-to di Dxrand è nullo, nel secondo consiste in tutti e quattro i valori, inordine pseudo-casuale.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 310/328

9.2–307

1 (2 SynthDef("randMelody",

3 { arg base = 40, trigFreq = 10;

4 var freq, trig, reset, seq;

5 var structure = base+[0, 2, 3, 5, 6, 8] ;

6 trig = Impulse.kr(trigFreq);

7 seq = Dseq (

8 structure.add(

9 Dxrand(structure+12, LFNoise0.kr(6).unipolar*6))

10 , inf).midicps;

11 freq = Demand.kr(trig, 0, seq);12 Out.ar(0, LPF.ar(

13 Mix.fill(5, {Saw.ar(freq +0.1.rand + [0,0.7])* 0.1}), 1500));

14 }).send(s);

15 )

17 (

18 15.do({ arg i ;

19 Synth.new("randMelody",

20 [\base, 20+(i*[3, 5, 7].choose), \trigFreq , 7+(i/10) ])

21 })22 )

Nell’esempio precedente una synthDef costruita in maniera analoga alcaso precedente prevede come argomenti base e trigFreq : il primo rap-prsenta la frequenza di base in notazione MIDI, il secondo la frequenzadi triggering. Il ciclo successivo sovrappone dieci voci: in ognuna la fre-

quenza di base è incrementata di i per un valore a scelta tra [3, 5, 7].In più la frequenz di triggering incrementa di una quantità pari a i/10.Quest’ultimo aspetto permette di realizzare un progresivo dephasing: itempi degli strati sono cioè lievemente differenti, e il sincronismo ini-ziale si disperde progressivamente.L’idea alla base delle UGen che si basano sul meccanismo Demand è

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 311/328

9.3–308

quella di fornire la possibilità di annidare all’interno delle synthDef aspet-ti tipicamente di più alto livello. In più, la possibilità dell’incassamentodi una UGen nell’altra è estremamente potente. Ma in realtà forse è con-cettualmente più lineare separare due aspetti, che lavorano tipicamentea tassi di aggironamento diverso: la sintesi (ad audio rate) e lo schedu-ling (a event rate). Non a caso, le UGen Demand sono strettamente rela-te con i cosidetti “Pattern”, strutture per il controllo compositivi di altolivello sul lato del linguaggio. In qualche modo, le UGen Demand co-stituiscono una sorta di versione sul lato server dei Pattern. Al di là deiPattern, su lato del linguaggio lo scheduling si basa fondamentalmentesulle Routine.

9.3 Langside:Routines

In effetti, il modo più usuale (e forse più sensato) per effettuare lo sche-duling degli eventi consiste nel gestirlo dal lato del linguaggio. La strut-tura di controllo fondamentale in proposito in SC è la routine. Di per se,le routine sono strutture di controllo che estendono il funzionamentodelle funzioni, e il loro uso non è limitato allo scheduling. In realtà, loscheduling è soltanto una delle applicazioni possibili delle routine, an-che se la più tipica. L’esempio seguente mostra una routine minimale.

Come si vede, la routine riceve come argomento una funzione. La fun-zione contiene un ciclo che per 10 volte stampa “rallentando”, quindiassegna a time valore apri a i*0.1. L’unico messaggio non conosciutoè wait , ricevuto da i , che è un numero a virgola mobile. Intuibilmente,wait concerne lo la gestione del tempo, cioè lo scheduling. La routiner definisce cioè una programmazione che deve essere eseguita, in cui ilmessaggio wait ricevuto da un numero indica un tempo di attesa (pa-ri al ricevente del messaggio) prima di proseguire nell’esecuzione della

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 312/328

9.3–309

espressione successiva. La gestione del compito nel tempo è affidata adun orologio, nella circostanza SystemClock , cioè ad una classe specializ-zata nel “tenere il tempo” alla massima precisione possible. Al’orologioè chiesto di eseguire (play) una routine (r). L’orologio interpreta gli og-getti che ricevono il messaggio waitco,q quantitaà temporali in cui so-spendere l’esecuzione della sequenza di esperessioni. Quando questa ri-prende, le espressioni successivi sono valutate il più in fretta possibile.Nella circostanza, la routine r attende un tempo time che cresce pro-gressivamente. Realizzato il ciclo, r prescivere di attendere 1 secondo edi scrivere ”fi”, poi un altro secondo e di scrivere ”n”.

1 (

2 // Minimal routine

3 r = Routine.new(

4 { var time ;

5 10.do ({ arg i ;

6 "rallentando".postln ;

7 time = (i*0.1).postln ;

8 time.wait ;

9 }) ;

10 1.wait ;

11 "fi".postln ;

12 1.wait ;

13 "ne".postln ;

14 }

15 ) ;

16 )

18 SystemClock.play(r)

Si noti che la routine “ricorda” il suo stato interno: se si valuta nuova-mente SystemClock.play(r) si ottiene di ritorno l’oggetto SystemClock ,poiché la routine è ormai terminata.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 313/328

9.4–310

1 SystemClock.play(r)

3 SystemClock

Per riportare lo stato interno della routine alla condizione iniziale è ne-cessario inviarle il messaggio reset.

1 r.reset

3 a Routine

A questo punto è possible rieseguire da capo la routine. Una sintassi al-ternativa è fornita dal metodo play definito direttamente per le routine,che riceve come argomento un orologio.

1 // the same:

2 r.play(SystemClock)

4 rallentando

5 0

6 [etc]

È chiaro come una routine costituisca la base per la gestione di processitemporali. Semplificando, quando si vogliono eseguire espressioni se-

condo una certa progressione temporale è sufficiente avviluparle in unaroutine ed inframezzare opportunamente espressioni del tipo n.wait.

9.4 Orologi

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 314/328

9.4–311

Il prossimo esempio discute la generazione di una GUI che funziona dasemplice cronometro, e permette di introdurre alcuni elementi in piùnella discussione sullo scheduling. Una volta eseguito il codice, si apreuna piccola finestra che visualizza l’avanzamento del tempo a partire da0: il cronometro parte e viene interrotto nel momento in cui la finestraviene chiusa.

1 (

2 var w, x = 10, y = 120, title =�"Tempus fugit" ; // GUI var

3 var clockField ;

4 var r, startTime = thisThread.seconds ; // scheduling

6 w = GUI.window.new(title, Rect(x, y, 200, 60)) ;

7 clockField = GUI.staticText.new(w, Rect(5,5, 190, 30))

8 .align_(\center)

9 .stringColor_(Color(1.0, 0.0, 0.0))

10 .background_(Color(0,0,0))

11 .font_(GUI.font.new("Century Gothic", 24));

12 r = Routine.new({

13 loop({

14 clockField.string_((thisThread.seconds-startTime)

15 .asInteger.asTimeString) ;

16 1.wait }) // a clock refreshing once a second

17 }).play(AppClock) ;

18 w.front ;

19 w.onClose_({ r.stop }) ;

20 )

Le prime righe dichiarano le variabili. Come si vede, fondamentalmen-te il codice prevede due tipi di elementi: elementi GUI (righe 2, 3) e ele-menti che si occupano di gestire l’aggiornamento dei valori temporali. Inparticolare, la riga 4 assegna a startTime il valore di thisThread .se-

conds: thisThread è un oggetto particolare, una pseudo-variabile checontiene una istanza della classe Thread , che tiene il conto di di quanto

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 315/328

9.4–312

tempo è passato dall’inizio della sessione dell’interprete. Se si valuta unpaio di volte la riga seguente si noterà come il valore restituito dal meto-do seconds incrementi di conseguenza (e corrisponda ai secondi passatida quando si è avviata l’applicazione).

1 thisThread.seconds

Dunque, startTime contiene un valore che rappresenta il tempo in cui

il codice viene valutato (il momento 0 del cronometro). Inutile dilun-garsi analiticamente sulla costruzione dell’interfaccia grafica che nonha nulla di particolare. Si noti soltanto lo stile tipico di programmazio-ne nelle GUI che prevede il concatenamento dei messaggi (righe 8-11)per impostare le diverse proprietà grafiche. Le righe 12-17 definisconoinvece la routine che si occupa ogni secondo di calcolare il nuovo valo-re del cronometro e di aggiornare il campo dell’elemento GUI. La fun-zione contenuta nella routine contiene un ciclo infinito (si ricordi che

loop è un sinonimo di inf.do) che esegue due espressioni: la primaaggiorna il campo dell’ora impostando la proprietà string di clock-Field (righe 13-14), la seconda richiede di attendere un secondo pri-ma di ripetere il ciclo (1.wait , riga 16). Il nuovo valore del tempo davisualizzare vience calcolato in tre passi. In primo luogo viene chiestoall’interprete il valore attuale del tempo passato attraverso una chiama-ta di thisThread.seconds: ad esso viene sottratto il tempo di partenzastartTime per ottenere la differenza. Quindi il risultato viene converti-

to in numeri interi (qui non interessano i valori decimali): dunque nelnumero intero di secondi pasasati da quando il cronometro è esistito.Infine, il metodo, definito per la classe SimpleNumber , asTimeString re-stituisce una stringa nella forma ore:minuti:secondi. Ad esempio:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 316/328

9.4–313

1 20345.asTimeString

3 5:39:05

Il metodo play riceve come argomento un oggetto di tipo Clock , ma nonè SystemClock: infatti, quest’ultimo non può essere utilizzato nel casodi GUI. AL suo posto deve essere utilizzato AppClock. La soluzione èobbligata perché dipende dalla gestione delle priorità: nel caso di sche-

duling, i messaggi al server audio hanno la priorità su altre funzioanlità,GUI inclusa. Questo non permetterebbe di gestire da una stessa routi-ne il controllo di un synth e di un elemento GUI: una simile operazioneè possibile utilizzando all’interno della routine il metodo defer imple-mentato dalle funzioni. In sostanza, nella routine le espressioni che con-cernono la GUI vengono raccolte all’interno di una funzione (racchiusetra parentesi graffe) a cui viene inviato il messaggio defer che permettedi differire il risultato della loro valutazione nel momento in cui vi siano

risorse computazionali disponibili (ovvero: senza sottrarne alla compu-tazione audio). Infine, la riga 19 definisce una proprietà della finestra w:onClose prevede come valore una funzione che viene eseguita nel mo-mento in cui w è chiusa. La funzione contiene r.stop: la routine r vieneciò arrestata alla chiusura della finestra. Il codice seguente è una variantedel precedente che dimostra le ultime considerazioni. L’aggiornamentodella GUI è racchiuso in una funzione a cui è inviato defer (riga 14-17):dunque, è possibile utilizzare SystemClock (riga 18). È stata poi rimossa

l’assegnazione della funzione onClose e un messaggio postln permet-te di stampare l’aggiornamento del tempo sulla post window. Se ora sichiude la finestra, la routine continua ad essere operante (all’infinito),come si vede dalla post window. Inoltre, la routine r chiede di impo-stare la stringa che contiene l’ora nel campo grafico: poiché questo nonesiste più (la GUI è stata chiusa), la post window segnala un errore.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 317/328

9.5–314

1 (2 var w, x = 10, y = 120, title =�"Tempus fugit" ; // GUI var

3 var clockField ;

4 var r, startTime = thisThread.seconds ; // scheduling

6 w = GUI.window.new(title, Rect(x, y, 200, 60)) ;

7 clockField = GUI.staticText.new(w, Rect(5,5, 190, 30))

8 .align_(\center)

9 .stringColor_(Color(1.0, 0.0, 0.0))

10 .background_(Color(0,0,0))

11 .font_(GUI.font.new("Century Gothic", 24));12 r = Routine.new({

13 loop({

14 {

15 clockField.string_((thisThread.seconds-startTime)

16 .asInteger.asTimeString.postln) ;

17 }.defer ;

18 1.wait }) // a clock refreshing once a second

19 }).play(SystemClock) ;

20 w.front ;

21 )

9.5 Sintetizzatori/eventi

L’approccio precedente permette a tutta evidenza di essere esteso all’audio.Se si eccettua il problema della priorità, non c’è infatti niente di peculia-re alle interfacce grafiche nella gestione dello scheduling discussa pre-cedente. La synthDef seguente si basa su una sequenza di impulsi didensità density (riga 7), che vengono filtrati da un filtro risonante pas-sabasso RLPF (righe 6-9), riverberate attraverso la UGen FreeVerb (ri-ghe 5-10), e infine distributie sul fonte streo attraverso Pan2 (righe 4-12).

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 318/328

9.5–315

Prevede come argomenti la densità degli impulsi (density), la frequen-za di taglio del filtro (ffreq ), il reciproco di Q (rq ) e um moltiplicatored’ampiezza (amp).

1 (

2 SynthDef("filtImp", { arg density = 30, ffreq = 200, rq = 0.1, amp =

1;

3 Out.ar(0,

4 Pan2.ar(

5 FreeVerb.ar(6 RLPF.ar(

7 Impulse.ar(density),

8 ffreq,

9 rq 

10 ), room:1

11 )*amp*5,

12 LFNoise1.ar(2))

13 )

14 }).send(s)

15 )

Una volta costruito il synth (synth), lo scheduling è gestito attraversouna routine infinita (loop), che ad ogni iterazione imposta (synth.set)i valori degli argomenti del synth. La routine sfrutta abbondantementevalori pseudo-casuali: ad esempio, la densità degli impulsi che mettonoin risonanza il filtro varia nell’escursion [5, 20]. Più interessante il cal-

colo di ffreq  , che seleziona un numero casuale in [70, 80] e lo moltipli-ca per un fattore pari a 0.75 , quindi converte da valori midi a frequen-za. Ogni valore midi prescelto sarà perciò un multiplidi 0.75 semitoni,

ovvero lungo una scala di 38 di tono. Anche il tempo in secondi che inter-

corre tra una iterazione e la successiva è generato pseudo-casualmentenell’intervallo [0.1, 1.0].

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 319/328

9.5–316

1 (2 var synth = Synth(\filtImp) ;

4 Routine.new({

5 loop ({

6 synth.set(

7 \density, rrand(5, 20),

8 \ffreq , (rrand(70, 80)*0.75).postln.midicps,

9 \rq , rrand(0.001, 0.005),

10 \amp, 0.5.rand + 0.5

11 ) ;12 rrand(0.1, 1).wait ;

13 }) ;

14 }

15 ).play(SystemClock)

16 )

Nell’esempio precedente l’idea fondamentale è quella di costruire un

syntt (uno strumento) e controllarlo attraverso una routine. La synth-Def seguente permette di introdurre un secondo approccio. Essa preve-de una semplice sinusoide a cui è aggiunto un vibrato ed un inviluppod’ampiezza. I parametri di entrambi sono controllabili dall’esterno: a,b, c rappresentano punti dell’inviluppo, vibrato e vibratoFreq i dueparametri del vibrato.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 320/328

9.5–317

1 (2 SynthDef("sineMe1",{ arg out = 0, freq = 440, dur = 1.0, mul = 0.5,

pan = 0,

3 a, b, c,

4 vibrato, vibratoFreq;

6 var env;

7 env = Env.new([0, a, b, c, 0],[dur*0.05, dur*0.3,dur*0.15,dur*0.5],

'welch');

8 Out.ar(out,

9 Pan2.ar(10 SinOsc.ar(

11 freq: freq+SinOsc.kr(mul:vibrato, freq: vibratoFreq),

12 mul:mul

13 ) * EnvGen.kr(env, doneAction:2)

14 ), pan)

16 }).send(s);

17 )

L’inviluppo d’ampiezza è utilizzato da una UGen EnvGen , il cui argo-mento doneAction riceve un valore 2. Ciò significa che, una volta con-cluso l’inviluppo, il synth viene deallocato sul server. Questo implicache il synth non esiste più: esso si comporta perciò non tanto come unostrumento ma come un evento. Si osservi cosa avviene nello routine:

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 321/328

9.5–318

1 (2 var r = Routine.new({

3 inf.do({ arg i ;

4 var env, dur = 0.5, freq, end, mul, pan, vibrato, vibratoFreq ;

5 a = 1.0.rand ;

6 b = 0.7.rand ;

7 c = 0.5.rand ;

8 pan = 2.0.rand-1 ;

9 freq = ([0, 2, 3, 5, 6, 8, 10, 12, 13, 15, 16, 18].choose+70).midicps;

10 // 13 pitches on a non-8ving modal fragment

11 dur = rrand(0.015, 0.5);12 mul = rrand(0.05, 0.8);

13 vibrato = (dur-0.015)*100;

14 vibratoFreq = dur*10;

15 Synth.new("sineMe1", [

16 "vibrato", vibrato,

17 "vibratoFreq", vibratoFreq,

18 "a", a,

19 "b", b,

20 "c", c,

21 "freq", freq,22 "dur", dur,

23 "mul", mul,

24 "env", env]

25 ) ;

26 end = 0.15.rand;

27 (dur+end).wait;

28 });

29 });

31 SystemClock.play(r);32 )

Ad ogni iterazione del ciclo viene istanziato un synth che si dealloca nelmomento in cui l’inviluppo è concluso (dunque non è neppure neces-sario chiamare il metodo free). In questo secondo esempio, l’oggetto

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 322/328

9.6–319

synth non è trattato come uno strumento, cioè come un dispostivo per-sistente (una tromba, un basso, un fagotto) il cui comportamento va con-trollato in funzione del presentarsi di nuovi eventi. Piuttosto, qui il synthdiventa un evento sonoro, l’equivalente di una nota musicale.Nuovamente, la synthDef fa largo uso di valori pseudo-casuali, che of-frono alla sinusoide una qualità tipicamente “fischiata”. L’unico aspettodi rilievo è il controllo della frequenza (riga 9). L’array definisce una se-quenza di altezze che descrivono un modo non ottavizante di 13 altezze,ne seleziona una stocasticamente, e vi aggiunge 70.

9.6 Routine/Task

Le routine possono essere riportate nella condizione iniziale attraversoil messaggio reset e interrotte attraverso il messaggio stop.

1 (

2 r = Routine({

3 inf.do({ arg i ; i.post; ": going on".postln; 2.wait})

4 }).play

5 )

7 // wait a bit

8 r.reset

10 // had enough

11 r.stop

13 // start again

14 // first reset

15 r.reset

16 //then

17 r.play

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 323/328

9.6–320

Tuttavia, nel momento in cui ricevono il messaggio stop , per poter es-sere di nuovo attivate devono prima ricevere il messaggio reset che leriporta nella condizione di partenza. Questo aspetto costituisce una li-mitazione potenzialmente importante allo uso musicale. La classe Task

implementa questo comportamento: è un processo “che può essere mes-so in pausa” ( pauseable process).

1 (

2 t = Task({

3 inf.do({ arg i ; i.post; ": going on".postln; 2.wait})

4 }) ;

5 )

7 // start

8 t.play

10 // pause: internal state is stored

11 t.pause

13 // start from last state

14 t.resume

16 // reset to 0

17 t.reset

19 // stop: the same as pause

20 t.stop

22 // the same as resume

23 t.play

Come si vede, i metodi stop/pause , e play/resume si comportano esat-tamente nello stesso modo. L’esempio seguente mette in luce le diffe-renze tra task e routine. La synthDef "bink" utilizza un filtro risonanteResonz , sollecitato da un rumore bianco. Il tutto è inviluppato da un in-viluppo percussivo e distribuito sul fronte stereo attraverso Pan2.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 324/328

9.6–321

1 (2 SynthDef("bink", { arg freq, pan = 1;

3 Out.ar(0,

4 Pan2.ar(

5 EnvGen.kr(Env.perc, doneAction:2)*

6 Resonz.ar(WhiteNoise.ar, freq, 0.001)),

7 LFNoise1.kr(pan)

8 )

9 }).send(s) ;

10 )

12 (

13 var pitch ;

14 var arr = Array.fill(8, { arg i ;

15 Task({

16 inf.do({ arg k ;

17 pitch = (i*[3, 5, 7].choose+(k*0.5)+40).clip2(200) ;

18 Synth(\bink, [\freq , pitch.midicps,

19 \pan, pitch/50 ]) ;

20 ((9-i)/8).wait ;

21 })22 })

23 }) ;

25 var isPlaying ;

27 arr.do({ |t| t.play}) ; // play all

29 // first time evaluate until up here

31 8.do({ arg ind ;32 isPlaying = true ;

33 Routine({

34 inf.do({

35 if (isPlaying)

36 { arr[ind].pause; isPlaying = false }

37 { arr[ind].play; isPlaying = true } ;

38 (Array.series(6, 0, 1/6).choose).wait

39 })

40 }).play

42 })

44 )

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 325/328

9.7–322

Alla variabile arr è assegnato un array che contien 8 task. Ognuno diessi permette di generare uno voce in cui le altezze dipendono dal con-tatore (in sostanza le voci tendono a differenziarsi per registro). Il task sceglie un valore tra [3, 5, 7] , lo moliplica per l’indice (il registro dellavoce, per così dire) e incrementa progressivamente di un quarto di to-no l’altezza. Il punto di partenza è la nota 40, e la progressione viene

 bloccata al valore 200. Ogni strato ha un suo tasso di sviluppo autono-mo: il più grave si muove più lentamente, il più acuto più velocemente,nell’intervallo di [0.125, 1] secondi. Si noti che si tratta di una quantiz-zazione ai trentaduesimi con tempo pari a 60. La progressione procedeinesorabilmente se si valuta il codice fino alla riga 27. Fino a qui l’utilizzodei task è in fondo accessorio: sarebbe stato perfettamente possibile usa-re routine. La riga 31 introduce un nuovo processo di scheduling. Il cicloseleziona progressivamente gli indici dei task contenuti in arr. Quindiesegue una routine che modifica lo stato del task selezionato valutandola variabile isPlaying (la quale è reinizializzata per ogni task, riga 32). Insostanza, la routine verifica se il task è in esecuzione: se così è, lo arresta(e aggiorna isPlaying), se è fermo, lo fa ripartire (e aggiorna isPlay-

ing). Infine attende per una durata scelta a caso tra le frazioni multipledi un sesto di secondo (appositamente: in modo da essere asimmetricorispetto alla suddivisione binaria precedente).

9.7 Micro/macro

L’utilizzo delle routine e dei task permette di chiarire meglio l’utilità del-la classi di tipo Demand. In effetti, rispetto allo scheduling, esse non sonoalternative alle classi appena discusse. Piuttosto permettono di gestire

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 326/328

9.7–323

quello che potrebbe essere definito come micro-scheduling: uno sche-duling interno al synth. L’opzione è particolarmente interessante se unsimile micro-scheduling viene incassato in uno scheduling, si potrebbedire macro-, gestito da una routine o da un task. La synthDef seguen-te è una variazione di un esempio già discusso. Qui density gestisce lafrequenza di un segnale impulsivo che fa da trigger per una Demand (ri-ghe 9-10). Queste ultime ciclano su dFreq a cui è assegnata una UGenDrand , la quale, a sua volta, genera una sequenza infinita di elementiselezionati casualmente dall’array fornito. Quest’ultimo utilizza un in-sieme di intervalli a quarti di tono che vengono trasposti in funzionedell’argomento midinote. Gli stessi valori, convertiti in frequenze, con-trollano sia la frequenza del generatore di impulsi (riga 9) che la frequen-za di taglio del filtro (riga 10). In assenza della riga 13, un synth di tipofiltImp2 genera una sequenza continua: ma la presenza di EnvGen e deisui argomenti Env.perc e doneAction:2 , in seguito all’applicazione diun inviluppo percussivo, libera il synth. Ne consegue un oggetto sono-ro composito, che prevede una variabilità interna, in questo caso unavariazione del profilo melodico, ma che resta un singolo oggetto.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 327/328

9.7–324

1 (2 SynthDef("filtImp2", { arg density = 5, midinote = 90, rq = 0.1, amp

= 1;

3 var trig = Impulse.kr(density) ;

4 var dFreq = Drand([0, 2, 3.5, 5, 6, 6.5, 11.5, 12]+midinote, inf) ;

5 Out.ar(0,

6 Pan2.ar(

7 FreeVerb.ar(

8 RLPF.ar(

9 Impulse.ar(Demand.kr(trig, 0, dFreq.midicps)),

10 Demand.kr(trig, 0, dFreq.midicps),11 rq  

12 ), room:1

13 ) * EnvGen.kr(Env.perc, doneAction:2) * amp,

14 LFNoise1.ar(density*0.25))

15 )

16 }).send(s)

17 )

L’esempio seguente utilizza una routine per gestire lo scheduling di og-gettifiltImp2. L’esempio è anche interessante perché utilizza l’argomentocontatore i della funzione associata alla routine per definire una tra-sformazione progressiva, attraverso le variabili correlate j e k. Inoltre,realizza un parameter mapping , una associazione tra i diversi parametri:in sostanza, per ogni nuovo synth, i valroi degli argomenti dipendonosempre da i, j, k.

5/16/2018 Super Collider Guida Prd tSCIRMA a5 - slidepdf.com

http://slidepdf.com/reader/full/super-collider-guida-prd-tscirma-a5 328/328

1 (2 var j, k ;

4 Routine.new({

5 inf.do({ arg i;

6 k = i.clip2(40) ;

7 j = i.clip2(60) ;

8 [i, k, j].postln ;

9 Synth(\filtImp2, [

10 \density, rrand(5, 15)+(k/4),

11 \midinote, rrand(40, 50)+j,12 \rq , rrand(0.001, 0.005)-(k/20000),

13 \amp, 0.1.rand + (((60-j)/60)*0.5)

14 ]

15 ) ;

16 (rrand(0.1, 0.3+(60-j*0.05))).wait ;

17 }) ;

18 }

19 ).play(SystemClock)

20 )