Βασικές Κυματομορφές & Εισαγωγή στο SuperCollider

Ημιτονοειδής Κυματομορφή | Sinusoidal Waveform

Για να παραγάγουμε ήχο στο SuperCollider πρέπει πρώτα να ξεκινήσουμε (να «μπουτάρουμε») τον διακομιστή (server). Ο server είναι ένα ξεχωριστό πρόγραμμα εντός του SuperCollider που παίρνει τις εντολές που γράφουμε στη γλώσσα (language) και τις μετατρέπει σε ήχο. Φαντάσου τον server σαν ένα συνθεσάιζερ που πρέπει πρώτα να πατήσεις το κουμπί του προτού να παίξεις. Το μπουτάρισμα γίνεται μόνο μία φορά όταν ανοίγουμε το SuperCollider. Αν είσαι σε MacOS μπορείς να μπουτάρεις πατώντας ταυτόχρονα [cmd και b], ενώ στα Windows η συντόμευση είναι [ctrl και b], σε κάθε περίπτωση μπορείς να πας από το Μενού > Language > Boot Server. Αν η κάρτα ήχου είναι σωστά ρυθμισμένη στο σύστημά σου τότε στο post-window θα τυπωθούν μερικά ακαταλαβίστικα πράγματα και ανάμεσά τους και μία πρόταση που θα λέει ότι ο server είναι έτοιμος, ... κάτι σαν "SuperCollider server ready". Μπορούμε να συνθέσουμε την πρώτη μας κυματομορφή.

Χαμήλωσε την ένταση!

Σου προτείνω να ακούς πάντα σε χαμηλή στάθμη ώστε να προστατεύεις τα αυτιά από αναπάντεχα δυνατούς ήχους. Χαμήλωσε επομένως την ένταση στα ηχεία και σε μία κενή γραμμή στον editor γράψε την επόμενη εντολή:

{ SinOsc.ar(440) }.play

Πρόσεξε τα γράμματα S και O να είναι με κεφαλαία, ενώ όλα τα υπόλοιπα να είναι με μικρά. Ο υπολογιστής δεν είναι πολύ ευφυής και θα καταλάβει την εντολή μόνο αν τη γράψουμε ακριβώς όπως την ξέρει! Για να την τρέξεις άφησε τον κέρσορα πάνω στην ίδια γραμμή και πάτησε [cmd και return] στο Mac, [ctrl και return] στα Windows, ή από το Μενού > Language > Evaluate Selection, Line or Region. Επιτυχία! Δημιούργησες μία ημιτονοειδή κυματομορφή στα 440 Hz. Μην ανησυχείς που ακούγεται μόνο από το αριστερό ηχείο, θα καταλάβεις αργότερα γιατί συμβαίνει αυτό και πώς λειτουργεί η στερεοφωνία. Όταν χορτάσεις από ημίτονο (που δεν είναι και ο πιο ευχάριστος ήχος) πάτησε [cmd και .] για να σταματήσει στο Mac, [ctrl και .] στα Windows, ή πήγαινε στο Μενού > Language > Stop.

Ας δούμε σιγά-σιγά τι ακριβώς σημαίνει αυτό που έγραψες. Το SuperCollider αποτελείται από αντικείμενα (objects). Τα αντικείμενα εκείνα που παράγουν ή επεξεργάζονται σήματα ονομάζονται UGens (Unit Generators). Κάθε UGen, ανάλογα με τη λειτουργία του, έχει συγκεκριμένα ορίσματα (arguments) που μας επιτρέπουν να καθορίζουμε τις τιμές των παραμέτρων του. Το αντικείμενο που φτιάχνει ένα ημίτονο είναι το SinOsc (Sine Oscillator). Πρόκειται για μία ψηφιακή γεννήτρια ήχου που ταλαντώνεται περιοδικά με τέτοιο τρόπο ώστε να παράγει μία ημιτονοειδή κυματομορφή. Στον κώδικά μας έχουμε θέσει εντός παρένθεσης την τιμή 440. Αυτό είναι ένα όρισμα του SinOsc που καθορίζει τη συχνότητα που θα παραγάγει ο ταλαντωτής. Πρόσεξε ακόμη ότι μεταξύ του SinOsc και του (440) παρεμβάλλεται το μήνυμα ar μετά από τελεία. Το ar είναι σύντμηση του audio rate (συνώνυμο του sample rate) και αναφέρεται στη συχνότητα που ο υπολογιστής επεξεργάζεται τα δείγματα ήχου. Το sample rate το θέτουμε από το πάνελ της κάρτας ήχου του υπολογιστή μας πριν ξεκινήσει το SuperCollider. Με το μήνυμα ar ζητάμε από τον ταλαντωτή μας να φτιάξει τόσα δείγματα το δευτερόλεπτο όσα και η συχνότητα δειγματοληψίας της κάρτας ήχου. Αν δουλεύουμε στα 44.1 KHz, θα παραγάγει 44,100 δείγματα το δευτερόλεπτο (που είναι πολλά) στην προσπάθειά του να παίξει επαναλαμβανόμενα ένα ημίτονο στα 440 Hz.

Το SinOsc.ar(440) δημιουργεί την κυματομορφή που θέλουμε αλλά δεν είναι ικανό από μόνο του για να την ακούσουμε. Ο πιο απλός τρόπος για να παράγουμε ήχο από τα ηχεία είναι τυλίγοντας τη γεννήτρια ήχου μέσα σε άγκιστρα { } και στέλνοντας το μήνυμα play. Τα δύο άγκιστρα ορίζουν μία συνάρτηση (function), ενώ το play που μπαίνει μετά τη συνάρτηση επιτρέπει εύκολα να φτιάξουμε ένα συνθεσάιζερ ήχου και να το παίξουμε. Ίσως κάποια από αυτά σου φαίνονται λίγο δυσνόητα, μην ανησυχείς, όσο προχωράμε θα ξεδιαλύνουν.

Αν θέλεις να δεις παράλληλα αυτό που δημιουργεί το SinOsc στο πεδίο του χρόνου μπορείς να στείλεις το μήνυμα scope αντί για play. Γράψε σε μία νέα γραμμή τον ακόλουθο κώδικα και τρέξε τον.

{ SinOsc.ar(220) }.scope

Θα πρέπει να προβληθεί ένα παράθυρο που εμφανίζει την κυματομορφή γραφικά σε πραγματικό χρόνο. Όταν χορτάσεις για μία ακόμη φορά από τον ήχο του ημιτόνου κάνε κλικ κάπου πάνω στον Editor ώστε να φύγεις απ' το παράθυρο του stethoscope και πάτα [cmd και .] σε Mac ή [ctrl και .] σε Windows για να σταματήσει.

Η χρήση του scope μας επιτρέπει να δούμε την παραγόμενη ημιτονοειδή κυματομορφή.

Για να κατανοήσεις γρήγορα τη σύνταξη του SuperCollider σου συστήνω να αρχίσεις να χρησιμοποιείς τα αρχεία βοήθειας (help-files) που είναι προσβάσιμα από το παράθυρο του help-browser. Αν έχεις έστω βασική γνώση της αγγλικής γλώσσας δε θα αντιμετωπίσεις κανένα πρόβλημα. Σε Mac και Windows καταλαμβάνει το επάνω δεξί μέρος της οθόνης. Για να δούμε πώς συντάσσεται ένα αντικείμενο μπορούμε να το επιλέξουμε από τον Editor κάνοντας διπλό κλικ πάνω του και να πατήσουμε [cmd και d] στο Mac ή [ctrl και d] στα Windows.

Δοκίμασε τώρα να δεις το αρχείο βοήθειας του SinOsc. Επίλεξε τη λέξη και πάτα τη συντόμευση ανάλογα με το λειτουργικό σύστημα που χρησιμοποιείς. Το αρχείο περιέχει μία περιγραφή του SinOsc, τις μεθόδους (methods) που μπορούμε να χρησιμοποιήσουμε και τα ορίσματα (arguments) που δέχεται. Στην ουσία κάθε μήνυμα (message) που στέλνεται σε ένα αντικείμενο αντιστοιχεί σε μία μέθοδο που έχει το ίδιο ακριβώς όνομα. Αυτό ακούγεται μπερδεμένο, είναι όμως ένα τεχνικό ζήτημα που δεν θα πρέπει να σε απασχολήσει. Συγκράτησε μόνο ότι κάθε φορά που ανοίγεις ένα αρχείο βοήθειας ενός αντικειμένου και διαβάζεις για τις μεθόδους του, ότι αυτές πρακτικά αντιστοιχούν στα μηνύματα που μπορείς να στείλεις στο συγκεκριμένο αντικείμενο.

Εστίασε την προσοχή σου στη γραμμή που περιγράφει τη μέθοδο ar.

*ar (freq: 440, phase: 0, mul: 1, add: 0)

Η γραμμή μας δείχνει ότι η συγκεκριμένη μέθοδος έχει 4 ορίσματα που είναι τα freq, phase, mul, add. Στο help-file υπάρχει επεξήγηση για κάθε ένα. Θα στα εξηγήσω με τη σειρά.

Το όρισμα freq μας επιτρέπει να αλλάξουμε τη συχνότητα που παράγει ο ταλαντωτής. Επειδή είναι το πρώτο όρισμα μπορούμε αν θέλουμε να παραλείψουμε το όνομά του. Έτσι αν θέλεις να φτιάξεις ένα ημίτονο με συχνότητα 261 Hz, δεν έχεις παρά να τρέξεις τον κώδικα:

{ SinOsc.ar(261) }.play

... που είναι ισάξιος με τον ακόλουθο:

{ SinOsc.ar(freq: 261) }.play

Με το όρισμα phase μπορούμε να καθορίσουμε την αρχική φάση της κυματομορφής, δηλαδή από ποιο σημείο του κύκλου θα ξεκινήσει. Δε θα ασχοληθούμε αυτή τη στιγμή με τη φάση διότι για να γίνει αντιληπτή η επίδρασή της χρειάζεται να έχουμε τουλάχιστον δύο κυματομορφές. Αν όμως θέλεις να αλλάξεις τη φάση μπορείς να γράψεις κάτι τέτοιο:

{ SinOsc.ar(freq: 261, phase: 0.5) }.play

Το όρισμα mul μας επιτρέπει να μεταβάλλουμε το πλάτος της ταλάντωσης, άρα να αλλάξουμε την ένταση του ήχου. Είναι βασικά ένας πολλαπλασιαστής (multiplier) που πολλαπλασιάζει με μία σταθερά το πλάτος του σήματος κατά την έξοδό του. Προς το παρόν θα δίνουμε δεκαδικές τιμές μεταξύ 0 και 1. Όταν η τιμή είναι 0 δεν ακούμε τίποτα, όταν η τιμή είναι 1 τότε η κυματομορφή έχει το μέγιστο πλάτος και άρα έχουμε τη μέγιστη ένταση.

Αν ανατρέξεις στο προηγούμενο κεφάλαιο και δεις την αναπαράσταση της κυματομορφής στο πεδίο του χρόνου θα παρατηρήσεις ότι το πλάτος στον κάθετο άξονα παίρνει τιμές μεταξύ -1 και 1. Το SinOsc, αν δε θέσουμε συγκεκριμένη τιμή στο mul, δημιουργεί ένα σήμα με εύρος πλάτους από το -1 στο 1. Η δουλειά του mul λοιπόν είναι να πολλαπλασιάσει κάθε μία από αυτές τις τιμές με μία σταθερά, σταθμίζοντας κατ' αυτόν τον τρόπο το πλάτος του σήματος.

Δοκίμασε να συγκρίνεις το ηχητικό αποτέλεσμα στις παρακάτω περιπτώσεις τρέχοντας κάθε γραμμή ξεχωριστά, μία τη φορά. Θα παρατηρήσεις ότι η κυματομορφή στην πρώτη περίπτωση ηχεί δυνατότερα, έχοντας μεγαλύτερο πλάτος ταλάντωσης από τη δεύτερη.

{ SinOsc.ar(freq: 261, mul: 0.6) }.scope

{ SinOsc.ar(freq: 261, mul: 0.2) }.scope

Είναι χρήσιμο να θυμάσαι ότι η ένταση του ήχου είναι ένα υποκειμενικό μέγεθος που εξαρτάται από διάφορους παράγοντες, όπως π.χ. η συχνότητα και η διάρκεια. Το ανθρώπινο αυτί είναι περισσότερο ευαίσθητο σε συχνότητες στη μεσαία περιοχή του φάσματος, μεταξύ 2 KHz έως 4 KHz, κάτι που είναι αναμενόμενο εφόσον αυτή είναι η περιοχή που χρησιμοποιούμε στην ανθρώπινη ομιλία. Το πλάτος λοιπόν της ταλάντωσης επηρεάζει την αντίληψή μας για την ένταση του ήχου, παρότι δεν είναι ο μόνος παράγοντας.

Τέλος, με το όρισμα add μπορούμε να προσθέσουμε μία σταθερά. Τη χρησιμότητά του θα την αντιληφθείς αργότερα. Προς το παρόν για να δεις την επίπτωσή του στο παραγόμενο σήμα τρέξε τις επόμενες γραμμές, μία κάθε φορά, σταματώντας τον ήχο της προηγούμενης.

{ SinOsc.ar(freq: 261, mul: 0.2) }.scope

{ SinOsc.ar(freq: 261, mul: 0.2, add: 0.5) }.scope

Το ημίτονο που έχουμε καταφέρει να φτιάξουμε είναι η πιο απλή κυματομορφή, πρόκειται για έναν τεχνητό ήχο που μπορεί να δημιουργηθεί μόνο ηλεκτρονικά. Δεν μπορούμε να βγούμε βόλτα στην παραλία και να ακούσουμε ημίτονα. Ο ήχος θεωρείται απλός διότι δε διαθέτει καθόλου αρμονικές, δεν έχει δηλαδή άλλες συνιστώσες πλην της θεμελιώδους συχνότητας που ορίζουμε. Έτσι, σίγουρα δεν είναι ό,τι πιο ενδιαφέρον μπορούμε να φτιάξουμε. Είναι όμως μία αρχή.

Σύντομη Εισαγωγή στη Γλώσσα του SuperCollider

Πριν προχωρήσουμε στα διαφορετικά είδη κυματομορφών είναι χρήσιμο να αντιληφθείς τον τρόπο λειτουργίας του SuperCollider και τη σύνταξή του. Οι επόμενες παράγραφοι είναι λίγο στρυφνές καθώς πραγματεύονται προγραμματιστικά θέματα, ευτυχώς όμως είναι σύντομες.

Το SuperCollider περιέχει μέσα του δύο προγράμματα: Τη γλώσσα (language) που είναι το μέρος που γράφουμε τις εντολές, και τον διακομιστή (server), που δέχεται τις εντολές της γλώσσας και τις μετατρέπει σε ήχο. Έχουμε ήδη δει ότι για να δημιουργήσουμε ήχο πρέπει πρώτα να ξεκινήσουμε τον server ως ξεχωριστό πρόγραμμα. θυμήσου αυτή τη διάκριση μεταξύ lanuage και server γιατί είναι σημαντική για την κατανόηση του τρόπου λειτουργίας του SuperCollider.

Ας δούμε κάποια πράγματα που σχετίζονται με τη σύνταξη της γλώσσας, με το μέρος του λογισμικού δηλαδή που γράφουμε τις εντολές. Πολλές φορές όταν προγραμματίζουμε βοηθάει να γράφουμε σχόλια, δηλαδή επεξηγηματικές παρατηρήσεις πάνω στον κώδικα, οι οποίες όμως δεν εκτελούνται. Χρησιμοποιούμε σχόλια για να βοηθήσουμε στην καλύτερη κατανόηση του προγράμματος μας και μπορούμε να τα εισάγουμε μετά τα σύμβολα // ή μεταξύ /* και */.

{ SinOsc.ar(440) }.play; // generates a sine wave at 440 Hz

{ SinOsc.ar(220) }.scope; /* generates a sine wave at 220 Hz viewing its waveform through an oscilloscope */

Όταν θέλουμε να τυπώσουμε χαρακτήρες στο post-window τους βάζουμε μέσα σε διπλά αγγλικά εισαγωγικά " " και χρησιμοποιούμε το μήνυμα postln.

"this text will be printed on the post window".postln

Για να τρέξουμε ταυτόχρονα πολλές γραμμές κώδικα πρέπει στο τέλος κάθε εντολής να χρησιμοποιήσουμε το ελληνικό ερωτηματικό ; (στα αγγλικά είναι η άνω τελεία). Αν δεν έχουμε επιλέξει συγκεκριμένες γραμμές τότε όταν πατήσουμε [cmd και return] στο Mac ή [ctrl και return] στα Windows το πρόγραμμα θα τρέξει μόνο τη γραμμή πάνω στην οποία βρίσκεται ο κέρσορας.

// select the following 3 lines together and evaluate
"one".postln;
{ SinOsc.ar(freq: 261, mul: 0.2) }.play;
"two".postln;

Στο IDE για Mac και Windows ένας βολικός τρόπος για να επιλέξουμε γρήγορα μεγάλο μέρος κώδικα είναι να τον κλείσουμε μέσα σε παρένθεση. Πατώντας διπλό κλικ πάνω στην παρένθεση επιλέγουμε τις εσωτερικές γραμμές και τις τρέχουμε όπως ξέρουμε.

// double click before the parenthesis to select the lines
(
"one".postln;
{ SinOsc.ar(freq: 261, mul: 0.2) }.play;
"two".postln;
)

Επίσης, δε θα υπήρχε πρόβλημα αν τοποθετούσαμε τις παραπάνω εντολές στην ίδια γραμμή.

// this is equivalent to the previous
"one".postln; { SinOsc.ar(freq: 261, mul: 0.2) }.play; "two".postln;

Όμως το επόμενο δε θα τρέξει διότι έχουμε ξεχάσει να βάλουμε τα ερωτηματικά στο τέλος κάθε postln.

"one".postln "two".postln "three".postln // ERROR: syntax error

Από αυτό το σημείο και στο εξής θα χρησιμοποιούμε πάντα το ερωτηματικό στο τέλος κάθε εντολής ως δικλίδα ασφαλείας. Η παράληψή του είναι συνηθισμένο λάθος όταν γράφουμε πολλές γραμμές εντολών.

Στο SuperCollider χρησιμοποιούμε τους αριθμητικούς τελεστές για να κάνουμε πράξεις: + (πρόσθεση), - (αφαίρεση), * (πολλαπλασιασμό), / (διαίρεση), ** (ύψωση σε δύναμη).

3 - 2; // prints 1
( 3 * 2 ) / 2; // prints 3
2**4; // prints 16

Προσοχή όμως, οι πράξεις τελούνται όπως εμφανίζονται από τα αριστερά προς τα δεξιά (όχι όπως έχουμε συνηθίσει στα μαθηματικά που προηγείται ο πολλαπλασιασμός από την πρόσθεση και την αφαίρεση). Επομένως όταν απαιτείται μία πράξη να τελεστεί πριν από κάποια άλλη τότε εσωκλείεται σε παρένθεση.

3 * 2 + 5; //   prints 11
5 + 3 * 2; //   prints 16 (strange ?)
5 + (3 * 2); // prints 11

Οι τελεστές ==, =!, <, >, >=, <= χρησιμοποιούνται για να κάνουμε συγκρίσεις μεταξύ δύο πραγμάτων. Αν η μαθηματική έκφραση είναι αληθής τότε η γλώσσα επιστρέφει τη σταθερά true, αν είναι ψευδής επιστρέφει false.

3 == 3; // prints true, 3 is equal to 3
3 != 2; // prints true 3 is not equal to 2
5 < 1;  // prints false, 5 is not less than 1
10 > 2; // prints true, 10 is greater than 2
4 >= 2; // prints true, 4 is greater than OR equal to 2
4 <= 2; // prints false, 4 is not less than OR equal to 2

Το ίσον = χρησιμοποιείται για ανάθεση. Μπορούμε π.χ. να αναθέσουμε στη μεταβλητή a την τιμή 384403, που είναι η μέση απόσταση της Γης απ' το φεγγάρι της!

a = 384403; // assigns the value of 384403 to the variable a
a; // prints 384403, the value of a

Και ένα τελευταίο. Χρησιμοποιώντας αγκύλες [ ] μπορούμε να ορίσουμε έναν πίνακα (Array). Οι πίνακες είναι πολύ χρήσιμα αντικείμενα γιατί μας επιτρέπουν να συλλέγουμε και να οργανώνουμε διάφορα είδη δεδομένων. Στον επόμενο κώδικα αναθέτουμε στη μεταβλητή q έναν πίνακα που περιέχει 5 στοιχεία. Αργότερα θα δούμε ότι τα στοιχεία που βρίσκονται μέσα σε πίνακες μπορούν να χρησιμοποιηθούν με ποικίλους τρόπους, όπως π.χ. να αποτελέσουν συχνότητες για μια γεννήτρια ήχου.

q = [200, 300, 450, 600, 800]; // define the array
q; // q is an Array containing 5 elements

Τριγωνική Κυματομορφή | Triangle Waveform

Η τριγωνική κυματομορφή είναι πιο σύνθετη απ' την απλή ημιτονοειδή. Αποτελείται από τις περιττές (δηλαδή τις μονές) αρμονικές με σχετικά πλάτη αντιστρόφως ανάλογα του τετραγώνου της αντίστοιχης αρμονικής. Με απλά λόγια αυτό σημαίνει ότι οι υψηλότερες αρμονικές έχουν μικρότερο πλάτος. Αν π.χ. η θεμελιώδης (1η αρμονική) έχει πλάτος 1, τότε η 3η αρμονική θα έχει πλάτος 1/9, η 5η αρμονική θα έχει πλάτος 1/25, η 7η αρμονική θα έχει πλάτος 1/49 κ.ο.κ.

Στο επόμενο διάγραμμα φαίνεται το θεωρητικό σχήμα μιας τριγωνικής κυματομορφής στο πεδίο χρόνου (αριστερά) και στο πεδίο συχνοτήτων (δεξιά). Παρατήρησε ότι αυτό το διάγραμμα χρησιμοποιεί έναν εναλλακτικό τρόπο παρουσίασης του σήματός μας στο πεδίο συχνοτήτων. Πρόκειται για ένα στατικό δισδιάστατο γράφημα όπου στον οριζόντιο άξονα απεικονίζουμε τις αρμονικές και στον κάθετο τα πλάτη τους. Ένα τέτοιο διάγραμμα παρέχει πληροφορίες για τις συχνοτικές συνιστώσες που βρίσκονται στο σήμα, αλλά δεν μπορεί να μας δείξει την εξέλιξή τους στον χρόνο.

Η τριγωνική κυματομορφή στο πεδίο χρόνου και συχνοτήτων.

Αν θέλεις να φτιάξεις μια τριγωνική κυματομορφή στο SuperCollider μπορείς να χρησιμοποιήσεις το UGen LFTri που είναι ένας τριγωνικός ταλαντωτής. Η σύνταξή του είναι παρόμοια με του SinOsc.

{ LFTri.ar(150) }.play; // carefull this may be loud!

Για να μάθεις παραπάνω για το LFTri επίλεξέ το και κάλεσε το αρχείο βοήθειας. Θυμήσου ότι μπορείς να εμφανίσεις την κυματομορφή καλώντας τη μέθοδο scope καθώς και να αλλάξεις την ένταση χρησιμοποιώντας το mul.

{ LFTri.ar(freq: 150, mul: 0.2) }.scope;

Ας δούμε έναν απλό τρόπο που μας επιτρέπει να ελέγχουμε τη συχνότητα του ταλαντωτή με την κίνηση του ποντικιού. Στον επόμενο κώδικα τη θέση της συχνότητας έχει πάρει ένα νέο αντικείμενο που συνοδεύεται από τα δικά του ορίσματα και το μήνυμα kr. Τρέξε τον κώδικα για να ακούσεις το αποτέλεσμα και θα σου εξηγήσω τι γίνεται.

{ LFTri.ar(freq: MouseX.kr(100, 500), mul: 0.2) }.scope;

Εδώ, το MouseX.kr(100, 500) έχει αντικαταστήσει τη σταθερή τιμή 150. Το MouseX είναι ένα UGen που μας δίνει την οριζόντια θέση του κέρσορα στην οθόνη. Γενικά, μπορούμε να αντιστοιχίσουμε την τιμή του κέρσορα σε οποιαδήποτε παράμετρο. Στη συγκεκριμένη περίπτωση επηρεάζουμε τη συχνότητα του τριγωνικού ταλαντωτή. Οι δύο τιμές μέσα στην παρένθεση (100, 500) ορίζουν την ελάχιστη και τη μέγιστη τιμή που θα δώσει το MouseX στα δύο άκρα της οθόνης. Επομένως, όταν ο κέρσορας βρίσκεται στο αριστερό άκρο ο ταλαντωτής παίζει μία τριγωνική κυματομορφή στα 100 Hz, όταν βρίσκεται στο δεξιό άκρο παίζει στα 500 Hz και οπουδήποτε αλλού παράγει μία ενδιάμεση συχνότητα.

Η μέθοδος kr που καλείται μετά το MouseX δηλώνει ότι το συγκεκριμένο UGen παράγει τιμές σε συχνότητα ελέγχου (control rate). Τη διάκριση μεταξύ του audio rate που έχουμε ήδη συζητήσει και του control rate που βλέπουμε εδώ είναι χρήσιμο να την καταλάβεις διότι αυτές οι έννοιες συναντώνται σε πολλά προγραμματιστικά περιβάλλοντα ήχου.

Ένα UGen που λειτουργεί σε συχνότητα ήχου (audio rate) δημιουργεί πάρα πολλά δεδομένα το δευτερόλεπτο. Για την ακρίβεια παράγει όσα ορίζονται από τη συχνότητα δειγματοληψίας της κάρτας ήχου, συνήθως τουλάχιστον 44,100. Το LFTri φτιάχνει μία τριγωνική κυματομορφή δημιουργώντας 44,100 δείγματα ανά δευτερόλεπτο. Γενικά όσα αντικείμενα δημιουργούν ή επεξεργάζονται ήχο δουλεύουν σε audio rate εφόσον χρειαζόμαστε υψηλή ανάλυση ώστε να έχουμε καλή ποιότητα ήχου. Ορισμένα αντικείμενα όμως δε χρειάζεται να δουλεύουν τόσο σκληρά εφόσον δε σχετίζονται με την παραγωγή ήχου. Αυτά τα αντικείμενα (όπως το MouseX) λειτουργούν σε συχνότητα ελέγχου (control rate) που είναι χαμηλότερη της συχνότητας ήχου και αφορούν λειτουργικές διαδικασίες. Χρησιμοποιούνται μόνο για να ελέγχουμε άλλες παραμέτρους. Ο λόγος λοιπόν που κάποια αντικείμενα τρέχουν σε control rate είναι για εξοικονόμηση υπολογιστικής ισχύος σε περιπτώσεις που δεν απαιτείται υψηλή ανάλυση.

Η διαδικασία της ένθεσης ενός μέρους κώδικα μέσα σε άλλον, όπως έγινε με την τοποθέτηση του MouseX.kr(100, 500) στη θέση της συχνότητας του LFTri, ονομάζεται nesting. Αυτόν τον τρόπο οργάνωσης των αντικειμένων σε περισσότερο σύνθετες δομές κώδικα θα τον χρησιμοποιούμε συχνά.

Δες και το επόμενο παράδειγμα. Χρησιμοποιεί ένα MouseY που επιτρέπει τον έλεγχο του πλάτους ταλάντωσης ανάλογα με τη θέση του κέρσορα στον κάθετο άξονα της οθόνης.

{ LFTri.ar(freq: MouseX.kr(100, 500), mul: MouseY.kr(0, 0.2)) }.scope;

Πριονωτή Κυματομορφή | Sawtooth Waveform

Η πριονωτή κυματομορφή περιέχει όλες τις αρμονικές, περιττές και άρτιες, με σχετικά πλάτη αντιστρόφως ανάλογα του αύξοντα αριθμού των αρμονικών. Αν δηλαδή η θεμελιώδης (1η αρμονική) έχει πλάτος 1, τότε η 2η αρμονική έχει πλάτος 1/2, η 3η αρμονική έχει πλάτος 1/3, κ.ο.κ.

Η πριονωτή κυματομορφή στο πεδίο χρόνου και συχνοτήτων.

Στο SuperCollider ένας τρόπος να δημιουργήσουμε μία πριονωτή κυματομορφή είναι χρησιμοποιώντας το UGen LFSaw.

{ LFSaw.ar(freq: 231, mul: 0.2) }.scope; // non-band-limited sawtooth oscillator

Πρέπει να σου πω ότι η κυματομορφή που φτιάχνει το LFSaw αφορά μία μαθηματική συνάρτηση που αντιστοιχεί σε ένα τέλειο πριόνι όπως στο παραπάνω διάγραμμα. Δυστυχώς στην πράξη αυτό το σχήμα πάσχει από aliasing. Αναδιπλώνει δηλαδή όσες συχνότητες ξεπερνούν τη συχνότητα Nyquist (sample-rate/2) στο μέρος του φάσματος που ακούμε, δημιουργώντας τελικά παραμόρφωση. Η λύση για να αποφύγουμε αυτό το πρόβλημα είναι να χρησιμοποιούμε ταλαντωτές που προσεγγίζουν το θεωρητικό σχήμα αλλά δημιουργούν συχνότητες μέχρι τη συχνότητα Nyquist και ονομάζονται «ταλαντωτές περιορισμένου εύρους» (band-limited oscillators) εν αντιθέσει με τους «ταλαντωτές μη-περιορισμένου εύρους» (non-band-limited oscillators).

Στην πράξη λοιπόν αρκετές φορές προτιμούμε να μη χρησιμοποιούμε το UGen LFSaw όταν παράγουμε ήχο, αλλά αντ' αυτού το Saw διότι το τελευταίο δεν υποφέρει από aliasing.

{ Saw.ar(freq: 231, mul: 0.2) }.scope; // band-limited sawtooth oscillator

Για να αντιληφθείς την επίδραση του ανεπιθύμητου θορύβου που δημιουργεί ένας ταλαντωτής μη-περιορισμένου εύρους όπως το LFSaw μπορείς να συγκρίνεις τα Saw και LFSaw ως προς το παραγόμενο φάσμα χρησιμοποιώντας έναν αναλυτή συχνοτήτων (frequency analyser). Το αντικείμενο FreqScope μας βοηθάει να δούμε το φάσμα σε κάθε περίπτωση.

FreqScope.new // This brings up a frequency analyser

/* evaluate the following line and observe the spectrum */
{ Saw.ar(10000, mul: 0.2) }.scope // this is a band-limited sawtooth oscillator
/* stop your audio */

/* evaluate the following line and observe the spectrum */
{ LFSaw.ar(10000, mul: 0.2) }.scope // this is a non-band-limited sawtooth oscillator
/* stop your audio */

Τετραγωνική Κυματομορφή | Square Waveform

Η τετραγωνική κυματομορφή αποτελείται από τις περιττές αρμονικές με σχετικά πλάτη αντιστρόφως ανάλογα των αντίστοιχων αρμονικών. Αν η 1η αρμονική έχει πλάτος 1, τότε η 3η αρμονική θα έχει πλάτος 1/3, η 5η θα έχει πλάτος 1/5, η 7η θα έχει πλάτος 1/7 κ.ο.κ. Στο επόμενο διάγραμμα φαίνεται το θεωρητικό σχήμα της τετραγωνικής κυματομορφής στο πεδίο χρόνου και στο πεδίο συχνοτήτων.

Η τετραγωνική κυματομορφή στο πεδίο χρόνου και συχνοτήτων.

Ο ταλαντωτής περιορισμένου εύρους που μπορεί να δημιουργήσει μία τετραγωνική κυματομορφή στο SuperCollider είναι το Pulse. Το UGen LFPulse μπορεί επίσης να φτιάξει μία τετραγωνική κυματομορφή χρησιμοποιώντας όμως τη μαθηματική συνάρτηση που αντιστοιχεί στο προηγούμενο διάγραμμα και είναι μη-περιορισμένου εύρους, δημιουργώντας aliasing.

{ Pulse.ar(150, mul: 0.2) }.scope; // this is a band-limited pulse oscillator

{ LFPulse.ar(150, mul: 0.2 ) }.scope; // this is a non-band-limited pulse oscillator

Εν γένει, η σύντμηση LF μπροστά από ένα UGen σημαίνει Low Frequency και δηλώνει ότι το συγκεκριμένο αντικείμενο είναι καλύτερα να χρησιμοποιείται για πολύ χαμηλές συχνότητες.

Για να αρχίσεις να αντιλαμβάνεσαι πώς διαφορετικά αντικείμενα του SuperCollider μπορούν να συνδυαστούν μεταξύ τους, σου παραθέτω έναν εναλλακτικό τρόπο δημιουργίας μιας τετραγωνικής κυματομορφής: Υπάρχει ένα αντικείμενο που ονομάζεται Clip και ο στόχος του είναι να περιορίζει το πλάτος ενός σήματος μεταξύ μιας ελάχιστης και μιας μέγιστης τιμής. Στο αρχείο βοήθειας θα δεις ότι δέχεται τρία ορίσματα: το εισερχόμενο σήμα (in), την ελάχιστη τιμή (lo) και τη μέγιστη τιμή (hi), *ar (in: 0, lo: 0, hi: 1).

Αν ένα σήμα υπερβεί το κατώφλι της μέγιστης τιμής προς τα πάνω (ή της ελάχιστης προς τα κάτω) τότε το Clip ψαλιδίζει τις ακραίες τιμές του σήματος μεταξύ των ορίων που έχουμε θέσει. Οι τιμές 0 και 1 για τα lo και hi αντίστοιχα είναι οι προεπιλεγμένες τιμές (default values) που χρησιμοποιεί το αντικείμενο αν δε θέσουμε εμείς κάτι διαφορετικό. Έτσι, αν φτιάξουμε ένα ημιτονοειδές σήμα με πολύ μεγάλο πλάτος χρησιμοποιώντας το SinOsc (π.χ. ένα σήμα που κινείται στο [-200, 200]) κι εν συνεχεία το ψαλιδίσουμε μεταξύ δύο ορίων χρησιμοποιώντας το Clip (έστω μεταξύ [-0.2, 0.2]) τότε το αποτέλεσμα θα προσεγγίζει μια τετραγωνική κυματομορφή μη-περιορισμένου εύρους.

Όταν κάνεις τέτοια πειράματα σου συνιστώ να ακούς σε χαμηλή ένταση για να προστατεύεις τα αυτιά από πιθανές υψηλές εντάσεις που μπορεί να προκληθούν λόγω σφάλματος στον κώδικα. Χαμήλωσε λοιπόν λίγο τα ηχεία και τρέξε τον επόμενο κώδικα.

// clipping a sine wave produces a square wave which is not band-limited
{ Clip.ar(in: SinOsc.ar(200, mul: 200), lo: -0.2, hi: 0.2) }.scope; 

Σύνθεση Σταθερής Κυματομορφής | Fixed Waveform Synthesis

Αν κάποια στιγμή αποφασίσεις να εμβαθύνεις στη σύνθεση ήχου και σκεφτείς να προγραμματίσεις το δικό σου UGen τότε θα χρειαστείς να ξέρεις θεωρητικά πώς δουλεύει ένας ψηφιακός ταλαντωτής. Για να δημιουργήσουμε μία κυματομορφή θα μπορούσαμε να χρησιμοποιήσουμε τη μαθηματική της συνάρτηση, που όμως δεν είναι ο πλέον ενδεδειγμένος τρόπος καθώς απαιτεί επαναλαμβανόμενους υπολογισμούς που καταναλώνουν μεγάλη υπολογιστική ισχύ. Στην πράξη, τις περισσότερες φορές ακολουθούμε μία διαφορετική προσέγγιση. Αρχικά αποθηκεύουμε τις τιμές ενός μόνο κύκλου της κυματομορφής σε έναν πίνακα που ονομάζεται πίνακας κυματομορφής (wavetable). Στη συνέχεια φτιάχνουμε έναν αλγόριθμο που μας επιτρέπει να σαρώνουμε επαναλαμβανόμενα τα στοιχεία του πίνακα ώστε να παραγάγουμε μία περιοδική κυματομορφή. Ένα wavetable είναι στην ουσία μία περιοδική συνάρτηση που μας δίνει το σχήμα της κυματομορφής αρχίζοντας και τελειώνοντας στο μηδέν. Για να αλλάξουμε τη συχνότητα απλώς διαβάζουμε τον πίνακα κυματομορφής με διαφορετική ταχύτητα, που επιτυγχάνεται παραλείποντας κάθε φορά κάποια στοιχεία του πίνακα.

Ρίξε μία ματιά στο αρχείο βοήθειας του SinOsc. Η περιγραφή του UGen αναφέρει ότι πρόκειται για ένα sine wavetable oscillator, δηλαδή για έναν ημιτονοειδή ταλαντωτή που χρησιμοποιεί πίνακα κυματομορφής. Αυτός ο πίνακας περιέχει 8192 θέσεις για να αναπαραστήσει 1 κύκλο από την ημιτονοειδή συνάρτηση.

Εκτός από τις βασικές κυματομορφές που παρουσιάζονται σε αυτό το κεφάλαιο, το SuperCollider περιέχει πληθώρα γεννητριών ήχου τις οποίες μπορείς να ανακαλύψεις από το παράθυρο βοήθειας: Help Window > Browser > UGens > Generators > Deterministic.

Για να έχεις φτάσει μέχρι αυτό το σημείο σημαίνει ότι έχεις πάρει ζεστά το θέμα και είσαι αποφασισμένος/αποφασισμένη να μάθεις σύνθεση ήχου. Δε σου κρύβω ότι τα πιο ενδιαφέροντα πράγματα αρχίζουν σταδιακά από τα επόμενα κεφάλαια. Έχεις κάνει ήδη αρκετή υπομονή, κρατήσου.


Χωρίς σχόλια. Επίλεξε ό,τι είναι μέσα στην παρένθεση, τρέξε και άκου.

(
{
    var sig, noiseLfo;
    noiseLfo = LFNoise1.kr(5);
    sig = Mix.ar(LFTri.ar(freq: [80, 120, 300, 1200], mul: LFPulse.ar(freq: noiseLfo.range(0.5,15), width: 0.2)));
    sig = LPF.ar(sig, noiseLfo.range(120, 1200));
    sig = FreeVerb.ar(sig);
    Out.ar(0, Pan2.ar(sig, noiseLfo.range(1,-1)) * 0.2);
}.play;
)