TUTORIAL DE SUPERCOLLIDER 3 - PARTE 2 Rodrigo F. Cadiz, basado en apuntes de Gary S. Kendall Northwestern University El lenguaje SuperCollider (SC) sclang: - Orientado al objeto - Bastante similar al lenguaje SmallTalk - Sintaxis es similar a C++. Sentencias Las sentencias SC son terminadas por un punto y coma ";" Literales Los literales son valores que tienen una representacion sintactica directa Numeros Un entero es una serie de digitos precedidos opcionalmente por un signo menos. Ejemplos : -13 666 2112 96 Un numero real (float, de punto flotante) esta compuesto por digitos seguidos por un punto decimal despues del cual hay mas digitos. Deben haber digitos a ambos lados del punto decimal. Por ejemplo: 0.0 3.1415 -0.5 Esto distingue numeros reales de expresiones como: 8.rand Tambien se puede utilizar notacion exponencial. 1.2e4 1e-4 La constante pi se puede agregar a un numero para crear una constante de punto flotante: 2pi 0.5pi -0.25pi Valores especiales Las instancias singulares de las clases True, False, Nil y Infinitum se escriben: true, false, nil y inf. True y False son valores booleanos (Boolean). x = true; y = false; z = nil; n = inf; Variables Identificadores Los nombres de variables (y muchas otras cosas) empiezan con un caracter alfabetico en minusculas seguido de cero o mas caracteres alfanumericos. Las variables son "case sensitive": estaesmivariable no es lo mismo que estaEsMiVariable Por convencion, los nombres de variables usan la siguiente convencion: unaCosa, otraCosa Las variables se declaran con la clave 'var': var abc, z123, func; Las variables pueden ser inicializadas de la siguiente manera: var abc=3, z123=6; SuperCollider define las letras del alfabeto automaticamente como variables y, por lo tanto, pueden ser utilizadas sin ser declaradas. Esto es conveniente para demostraciones rapidas de codigo, pero no es aconsejable para codigo real. Alcance (scope) de variables Los programas SC se organizan ente pares de parentesis. Las variables se definen y son entendidas entre un par de parentesis, pero no afuera de ellos. algoAqui ( var miNumero, myOtroNumero; miNumero = miOtroNumero; /* Estas variables son reconocidas aqui */ ); miOtroNumero = miNumero; /* Pero no aqui!!! */ Nombres de clases Algunas palabras usadas en programas son asociadas con una parte del lenguaje llamada "clases". Los nombres de clases siempre empiezan con una letra mayuscula. Las "unidades de generacion" (Unit Generators o UGen) que modifican y crean audio son todas clases. Object Point Synth Osc Reson Comentarios Los comentarios son lineas de codigo que no son tomadas en cuenta por el interprete (o compilador) Empiezan con // y terminan en el final de la linea. Tambien pueden ser delimitados con /* y */. Ejemplos: // comentarios de una linea /* comentario multi linea */ /* A diferencia de C, se pueden tener comentarios /* anidados */ */ Expresiones Las expresiones son combinaciones de literales, variables y operadores que producen un resultado. Los operadores pueden ser operaciones aritmeticas comunes. Ejemplos de operadores 1 + 2 // suma de uno y dos a - b // diferencia de a y b Precedencia de operadores No hay. Todos los operadores tienen el mismo nivel de precedencia y se asocian de izquierda a derecha. Por ejemplo, la expresion: x = a * b + c * d; es equivalente a: x = ((a * b) + c) * d; y no: x = (a * b) + (c * d); Por lo tanto, bueno utilizar parentesis en las expresiones. Asignaciones Asignacion simple. Una asignacion simple asigna el valor de una expresion en el lado derecho a una variable en el lado izquierdo. Una asignacion simple tiene la forma: <variable> = <expresion>; Ejemplo: c = a + b; cup = java; resultado = esto * aquello + mas; signal = SinOsc.ar(800, 0, 0.1); Una asignacion no es lo mismo que el signo igual. Una asignacion transfiere algo del lado derecho al izquierdo. Objetos, Mensajes - SuperCollider es un lenguaje orientado al objeto. - Todas las entidades del lenguaje son objetos. - Un objecto es algo que tiene datos que representan el estado del objeto y un set de operaciones que se pueden aplicar a el. - Todos los objetos son instancias de alguna clase que describe la estructura del objecto y sus operaciones. - Los objectos en SuperCollider incluyen numeros, cadenas de caracteres, colecciones, unidades generadoras, ondas de audio, puntos, rectangulos, etc. El estado interno de un objecto es capturada por sus variables instanciadas. - Las operaciones sobre los objectos son invocadas mediante mensajes. - Un mensaje es un requerimiento por un objecto, llamado el receptor (receiver) que ejecutan alguno de sus metodos instanciados. - El metodo a ejecutar depende de la clase que define al objeto. - Objetos de clases distintas pueden implementar el mismo mensaje de formas distintas. - Por ejemplo, las clases de unidades generadoras responden al mensaje "ar" y "kr". - "ar" provoca al objeto ejecutar procesamiento de audio a la tasa de audio y "kr" a la tasa de control. Notacion de objetos Para acceder o cambiar el valor de una variable de objecto se usa la notacion de punto. miInstrumento.freq = 440.0; // setear la variable freq del objecto miInstrumento s = Server.default; // accesar una instancia de variable, en este caso de una Clase Notacion de mensajes - Un mensaje consiste de un selector de mensaje, que nombra el tipo de operacion, una receptor al cual el mensaje es enviado y en algunos casos una lista de argumentos que otorgan informacion adicional relacionada a la operacion en cuestion. - Un mensaje siempre produce un resultado. - El tipo de resultado depende del tipo de mensaje. Por ejemplo, las unidades generadoras retornan senales de auio. - Los mensajes pueden ser escritos usando operadores (como los matematicos), notacion funcional o de receptor. Notacion funcional - El selector de mensaje precede la lista de parentesis. - El primer argumento en la lista es el receptor. - Las operaciones pueden ser unarias o binarias. Ejemplos: sin(x) // sino of x----unaria max(a, b) // maximo entre a y b----binaria Notacion de receptor - Una llamada a un metodo en notacion funcional se puede convertir a notacion de receptor al poner el receptor antes del nombre del metodo seguido por un punto (notacion de punto). 1.25.sin es equivalente a sin(1.25) x.cos es equivalente a cos(x) -1.max(3) equivale a max(-1,3) f(a, b) equivale a a.f(b) Los mensajes de las UGen se escriben siempre en notacion de receptor: Osc.ar(800.0, 0.0, 0.4) SuperCollider tiene una gran coleccion de operadores unarios y binarios, muchos de los cuales son especificos para audio. Operadores unarios (ver [SimpleNumber]) ampdb dbamp reciprocal cpsmidi midicps cpsoct octcps midiratio ratiomidi abs ceil floor frac sign neg sqrt squared cubed distort softclip sin cos tan asin acos atan sinh cosh tanh exp log log2 log10 isNegative isPositive isStrictlyPositive x.rand x.rand2 Operadores binarios (ver [SimpleNumber]) + - * / ** % div pow max min thresh trunc amclip clip2 round scaleneg excess fold2 wrap2 difsqr sumsqr sqrsum sqydif absdif atan2 hypot hypotApx ring1 ring2 ring3 ring4 x.rand(y) x.exprand(y) Argumentos claves - Los argumentos (parametros) para metodos pueden ser especificados por el nombre mediante el cual son declarados en una clase. - Tales argumentos son llamados argumentos claves (keyword arguments). - Si un argumento clave y un argumento posicional especifican el mismo argumento, el argumento clave tiene preferencia, - Por ejemplo, el metodo 'ar' de la clase SinOsc toma los argumentos freq, phase, mul, and add, en ese orden. Todos los ejemplos siguientes son llamadas validas para ese metodo SinOsc.ar(800, pi, 0.2, 0); {SinOsc.ar(800, pi, 0.2, 0)}.play; // freq = 800, mul = 0.2, others get default values. SinOsc.ar(800, mul: 0.2); // freq = 800, phase = pi, mul = 0.. SinOsc.ar(phase: pi, mul: 0.2, freq: 800); // 1200 predomina por sobe 800 SinOsc.ar(800, freq: 1200); SinOsc.ar(zorg: 999); // argumento invalido Argumentos por defecto - Se pueden llamar a metodos con menos argumentos definidos en la clase correspondiente. - Si esto sucede, dichos argumentos se inicializan envalores por defecto, si es que estos estan definidos en la clase, o si no se les asigna el valor nulo (nil). - Si se pasan argumentos en exceso, generalmente se coleccionan en un arreglo (Array) o son ignorados. - Si se llama a un metodo sin argumentos, los parentesis pueden ser omitidos. // x es declarada para tomar dos argumentos, a y b son valores por defecto de 1 y 2. // Retorna la suma de los argumentos x = { arg a=1, b=2; a + b }; z = x.value; // z vale 3. (a = 1, b = 2) z = x.value(10); // z vale 12. (a es 10, b = 2) z = x.value(10, 5); // z vale 15. (a es 10, b es 5) z = x.value(10, 5, 9); // z vale 15. (a es 10, b es 5, 9 es ignorado)