DEV Community

Aravind Mohandas
Aravind Mohandas

Posted on

Adding sequences to Tidal Cycles and listening to Konnakol - GSoC '22 Update 3

As the official coding period of the Google Summer of Code 2022 come to an end, I will be talking about the progress that I have made since the last blog post. I shall also talk about how I fared against my own expectations, major learnings and what I plan to do after the Official Coding Period ends.

Generating Konnakol using Tidal Cycles

In the previous blog post, I had talked about generating audio samples using Konnakol in Tidal Cycles. I spent a few days ironing out the finer details of this audio generation, by having functions to figure out the ideal speed at which compositions need to be generated, and fixing missing audio samples.

Now, one can listen to a Konnakol composition, with a few extra sounds and effects by using just a few lines of code as follows:

do
  resetCycles
  d1 $ jux rev $ fast 2 $ (tidalK Chaturasra thriputa Chaturasra (mkStdGen 23)) # gain 2

d2 $ sound "bd sd <bd ~> [sd sd sd]" # gain 1.2

d5 $ sound "arpy(<3 5>, 8)" # gain 1.2
Enter fullscreen mode Exit fullscreen mode

One thing that should be noted here is that changing the value under mkStdGen entirely changes the composition that is generated. Hence, this offers a great range of variety Konnakol compositions, and two different values will most probably give two entirely different compositions.

I then had the privilege of presenting my progress in front of the Tidal Cycles community on the 11th of August 2022. The response was encouraging, and there were several suggestions on how to make it better. One of the suggestions was first enumerating syllables during generation of compositions, and then using these enumerations to generate the same pattern but
for different set of audio samples. I was instantly hooked to the idea, and spent the next couple days to get it to work.

Now, if you use the following code, you will get a Konnakol composition along with an enumerated composition on the piano.

do
  resetCycles
  d1 $ fast 2 $ numK Tisra rupaka Khanda (mkStdGen 12123) "lydian"  # sound "superpiano" # legato 3
  d2 $ fast 2 $  tidalK Tisra rupaka Khanda (mkStdGen 12123) # gain 3
Enter fullscreen mode Exit fullscreen mode

I have tried recording a couple such samples, one can find these samples in the Konnakol repository.

Adding Sequences to Konnakol

After I was done with the Konnakol part of my project, the next (and final) objective was to develop a system within Tidal Cycles to deal with beat-wise composition. Currently Tidal Cycles is cycle-based, and a pattern in Tidal is a function of time, instead of a sequence of beats.

After a lot of brainstorming, my mentor (Alex McLean) and I decided to create a new datatype called Sequence, which would be able to deal with sequences.

data Sequence a = Atom Rational a
                | Gap Rational
                | Sequence [Sequence a]
                | Stack [Sequence a]
              deriving (Show, Eq)
Enter fullscreen mode Exit fullscreen mode

The recursive tree-like structure of a sequence would allow one to have sequences within sequences. For representing aligned sequences, we have the Stack [Sequence a], which actually consists of a list of sequences with the same duration. The idea was to describe functions for sequences which had the same type signatures as the ones for patterns.

In order to do this, the first major problem that we had to solve was to develop functions which could align sequences(This would play a significant role in applying sequences of functions to sequences). To align sequences, we found there were multiple possible ways, somewhat similar to aligning text (read more about the various possible strategies here).

So, the first step in defining functions for sequences was defining the various alignment methods. In total, 9 different alignment methods were defined. After this, the instances of Functor, Applicative Functor, and Monad were defined for Sequences. A general method was also defined to apply a sequence of functions to a sequence. A couple of methods were also defined to help simplify a sequence of sequences, and to remove redundant values (such as a Gap 0).

After doing all this groundwork, the next objective was to start picking functions defined for patterns, and to define them with respect to sequences. Functions such as fast and slow were easy to implement, whereas functions such as euclid, iter and every took some brainstorming, since there was the initial challenge of understanding what their implementation would mean for a sequence.

As I kept adding on to and expanding sequences, we worked on creating a way to handle function calls with the same name for sequences as well as patterns. A method was also defined which could convert a sequence into a pattern (for now, it is a one-way street, but we might try to get it done the other way pretty soon).

All this modification was performed in Tidal-1.9.0, which then threw some errors when I tried to get it build on Windows. This helped us discover that there actually was a bug for Windows users, which was then resolved. However, the dependencies of Tidal-1.9.0 had a lot of conflicts with Konnakol, and so I defined a Konnakol program within the Tidal package, which contained all the necessary function for generating compositions.

Hence, the current system is capacitated to deal with sequences as well as patterns, and is capable of producing audio output as well. One can try implementing more than a handful of functions on sequences, and the results are often quite surprising, depending on the alignment strategy that has been chosen.

Future work on Tidal Cycles

Over the last 12 weeks, I was able to accomplish everything (and maybe a bit more) that I had initially proposed. The overall process of coming up with creative and efficient solutions to challenging problems has helped me evolve as a programmer.

The Official Coding period of the Google Summer of Code might be coming to a close, but it surely does not mark the end of my contribution to Tidal Cycles. I absolutely loved the community and the challenging problems that I encountered here.

The next thing that we are planning to do is rewriting Tidal to accommodate sequences and patterns (which we're planning to rename to signals), in a way that removes a lot of redundancy. We have already begun our work on this (repository has been linked below), and one can read more about the ideas that we have for this here.

References

To view the Konnakol repository, visit here.

To view all the progress that has been made on Sequences, visit this branch.

To view the exciting rewrite of Tidal, visit here.

Top comments (0)