Routines [1]

{RK; SC meeting; 20-Jan-2018} 

We know what a function is, right? A function is just something that per braces you put a series of messages, separated by semicolons, and it does something. It’s like a little packet of logical score. You define a sequence of commands and execute it from beginning to end. A routine is a kind of expansion of the capabilities of functions. What a routine does is, it allows the function to be defined, and here’s the thing that happens. When you read a lot of SC documentation, focus is more on how it’s used, than how things are being defined. And there’s all of this complexity in the interaction between how things are defined and how they’re used, the moment we get into any kind of notion of concurrency. So, in the case of a routine, yield means “Done! I stop execution. The function is over”. But then when I call the function again, it goes on from where it left off. This is unbelievably cool for music, because now the function is a little bit like a performance for a musical score, it’s like “I’m gonna do this. Wait. Now I’m gonna do this”. I don’t wanna do it all at once, I wanna do it in sequence. The fundamental cool thing about routines is that they allow this sequentiality. In the history of live computer music, the first thing people did was having time procedure call. So you could have a function that would run and would schedule software activations. [In a way, it could be said that in the Scala world that time procedure call turns out to be kind of an implementation, a way to do things.] It’s just a way to quickly have some kind of time. The problem was that the whole world of computer programming had no interest in time. Time was an annoyance, I just want it to be faster!



The third SuperCollider meeting took place in the CUBE at the Institute for Electronic Music and Acoustic, Graz. 

Ron Kuivila, Hanns Holger Rutz and Daniel Mayer presented their sc-related work. In particular, Ron and Hanns Holger discussed the implementation and usage of the pattern library, and elaborated the distinction between functional and imperative paradigms in music composition.

{HHR; SC meeting; 20-Jan-2018}

Ron’s piece has a meta-structure to control something, patterns that are more like functional. Functional in the sense of a description that we could look at as if it was a static structure. Of course it would be turned into a stream, into something that performs. But we can reason about it as something that is just there as an object, and then we add the temporal dimension through another abstraction.





On software biasing

{HHR; SC meeting; 20-Jan-2018}

Software systems preconfigure the way we approach an artistic object, because we have this background layer, we know how these systems work. So they interfere with the way we conceive a specific piece. That’s obvious when you think about a structure like the pattern system, it preconfigures a specific way of thinking about how you could formalize your piece or how you could work with it. 

So then one interesting experiment could be to take a specific thing that has this history with it, for example a pattern system, and see what happens when you transport that to another system that doesn’t have an equivalent abstraction, or it has other abstractions. How you find other abstractions that compensate for that particular abstraction or how could you add that abstraction to it.

Ron was working with this little sketch of the parallel structure of the melodies and he’s working in particular with this pattern system in sc. I have developed another system which is based on SuperCollider, but is a different system called Mellite. And so, one question could be what happens when you try to describe this approach in the other system. What does that reveal about the underlined tacit knowledge or about the assumptions that to undergo change.

About the translation process

{HHR; SC meeting; 20-Jan-2018}

Two main steps are involved:

1. Understanding how a pattern system could work in Scala [language in which soundProcesses is wrtitten].

2. Understanding how that then could integrate within my computer music framework [Mellite].


I departed from one of the first sketches Ron made in October. I started with very simple things, I tried to understand how actually this all pattern system works. I copied and pasted some small patterns to see how they evaluate, what do they actually do and how does this all behaves. I wanted to undertand how does this wrapper, that takes the functional pattern system into a more imperative, a more bottom-up system, work. 


I tried to eliminate the procedures, everything that is somehow in curly braces. Each of the functions now is printing out the inputs and the outputs. I translated these little functions one by one, to see how easy was that. It turned out that, because both are general programming language and this has nothing to do with temporality yet, this is quite straightforward.

SuperCollider Meeting

20th January 2018, IEM, Graz

Further strategies

{HHR; SC meeting; 20-Jan-2018}

As Ron already mentioned, the routines don’t exist directly in Scala. Therefore a co-routine is really a tricky structure. Basically the concept in Scala is that if you can do it in the library, do it in the library, not in the language. If you want to have a co-routine, that is a sort of function that you can suspend, it returns something and then is able to pickup the work at a later point, that is actually quite difficult to implement as a library. So I decided to skip that part of the patterns system that is based on routines altogether. 


I eliminated all the indeterministic behavior by putting the seeds value of the number generators all to the same value. And this proved that there are some implied things: for example, when you have an unordered set of numbers, you could say that conceptually they are the same, even if the numbers have different orderings, because the idea of a set is that there is no order. But then you need to iterate the set, so it would either put 1,2,3,4 or 1,4,2,3, depending on how the set structure is implemented, if it is a hash set, how the hash is calculated, and so forth. So in order to compare the two, you have first of all to make them completely deterministic.



{RK; SC meeting; 20-Jan-2018}

It’s easier for me to think about a pattern as a routine. And this is again a part of the interesting conversation with Hanns, because in Scala world you really don’t want to use routines. In fact the whole Scala language group has banished routines! So it’s very interesting for me, because this is the way I think about this stuff in SuperCollider, and it would be really cool to discover an entirely different approach within Scala. 



Pattern thinking

{RK; SC meeting; 20-Jan-2018}

So, about my work with the pattern library. The basic idea is to say: I want to take every distinct subgrouping of pitches from a specific musical phrase. Let’s take three notes. I’ll take every distinct different one. And then I’ll find how to play every one of those notes in combination with that group. So these are in essence just some little extracted sub melodies from the larger sequence.

It just turns out that, in order to do this in SuperCollider, you need a bunch of coding. Because, even though array manipulations are certainly great, they’re not necessarily set up to do exactly this. This kind of idea is atemporal. You don’t want to do it in a sequential fashion. You want to take an array and generate all this possibilities. This is a kind of question that probably turns out to be much nicer to do within a functional programming language.



About collections

{HHR; SC meeting; 20-Jan-2018}

The way you work with collections of numbers are not the same. For example in SC something that takes a collection returns another collection by applying a function to each element. This is called .collect. In Scala I used .map, which is more akin to what most functional programming languages use for something that is called a monadic operation: you map over the elements and return the same structure, or with .flatMap you map from one element to a collection and then flatten the result. So in this case is two steps against one. The style of working is kind of different, in the sense that the Scala collections have a more ‘functional touch’. You usually don’t loop and then say add something to a list. You just compose more the structure.



Data types

{HHR; SC meeting; 20-Jan-2018}

One big difference that makes it also difficult, especially for patterns, is that Scala, as opposed to SC, is a statically typed language. That means that every object you have has a type attached to it. That’s also the case for SC, something is a string, or a number or an array of something. But in statically typed language there’s two steps involved in executing a program: one is to compile it and one is to run it. The compilation step is not part of a dynamically typed language, where these two steps coincide. That means that in this language I have to observe the types, before I can actually run the program, otherwise the compiler would complain, because for instance you cannot add a number to a string. That’s something very very simple in SC, because these types don’t get in your way. Patterns are an interesting example because they are abstractions over element of arbitrary type. In general you have two prototypical patterns, you have a value pattern and then you have the event patterns, which are patterns of dictionaries of things that become descriptions of a sound with a pitch, an envelope and so forth. The most difficult part in modeling the pattern is understanding how we could still create this kind of expressiveness of the patterns in SC, which allow you to arbitrary nest things with their types and so forth, without them getting in your way.



Routines [2]

{RK; SC meeting; 20-Jan-2018}

A function is evaluated with a value message,  and then it returns itself. Routine is kind of like that, but now I can have a more complicated function that actually changes what it does, each time it is called. Stream is just an object that returns sequence of values. You say ‘next’ and you get the next value. It could be like that’s my score, so that’s the next event to play. The class object defines next and reset. Most thing in the language are streams, in the nerd sense. Streams become a terminological tool for thinking about sequences of values, and routines have this convenient way of defining streams. In sc it’s actually a little deeper than that, which is: what routines also do is they allow you to define one stream out of other streams. In particular, I can define a stream and embed it in the stream of another routine. I have this little piece of stream, I want it to run in my stand and then I want the control back once it gets done. I could have [1,2,3,4] as my little score, but sometimes I want [1] to be [1,0,1,0]. And that’s what .embedInStream does for you. And here’s the thing. The class object defines embedInStream to simply yield the object and this is the profound connection between defining streams in sc and routines. Every object that isn’t a stream object can be streamed, because it knows that when it’s being streamed inside a routine it can just yield itself. The fundamental design trick is: I want most objects to have this funny double behavior. When they’re viewed as stream on their own, they’re unended. When they’re viewed as stream within a definition of another stream, they only happen once. And that is the fundamental structural trick in sc.