Schillinger Rhythm Generator

Interactive web-based sequencer, applying rhythmic theory for creative and educational use.

Stack

  • HTML/CSS
  • JavaScript
  • p5.js
  • p5.sound

Code & Docs

Schillinger Rhythm Generator home page

The purpose

Working in collaboration with a composer, teacher and specialist in the Schillinger System of Musical Composition, the aim of this project is to develop an application which can generate rhythms based on a numerical user input. It can serve as a tool for sparking creative inspiration, while teaching key elements of Joseph Schillinger's rhythmic theory, which can have many creative uses for composers and songwriters.

To demonstrate that varied and effective rhythms can be created mathematically from almost any series of numbers, the app is designed to take user input in the form of a sequence of digits, which could be entered manually (e.g. 1240652) or come from a less manual/predictable 'in-world' source, such as a barcode. You really can create a rhythm from a can of beans (without needing to hit it)!

User-generated beats are represented in the sequencer, against a consistent 'pulse' rhythm. The interaction between this regular pulse and the irregular (or regular) user-generated pattern is key to the Schillinger rhythm system - the 2 patterns will go in and out of phase, or sync, but return to their original relationship at certain intervals. Schillinger calls these 'interference patterns', referring to the relationship between simultaneous rhythmic patterns. We hear many of these rhythms in nature, and this method is therefore an interesting way of conceptualising it and applying it to musical composition.

How are the numerical patterns generated? Each individual number in the sequence defines the 'length' of a beat - for example:

The pattern is translated into a pattern in the app's drum sequencer, an interface which should be immediately familiar to many musicians. This can then be edited dynamically by the user to experiment with different patterns, adding or removing beats for each instrument/sample.

Once the pattern has been created, the app will ultimately allow the musician to alter it in a number of interesting and idea-inspiring ways, or 'mutations' (to be added). Schillinger's 'interference patterns' work with symmetry, so the ability to convert a pattern into a symmetrical one will be a key feature, alongside further 'preset' tweaking options:

Schillinger Rhythm Generator features

Features

  • Drum sequencer - can be used like a regular sequencer. Clicking any cell will add or remove a beat
  • Numerical input for users - creates a beat against the pulse
  • Tempo slider for adjusting BPM
  • User-adjustable pattern length (default is 16 beats, or the total length of the user-input beat if entered)
  • Regular/irregular pattern selection

Web Stack & Tech

The app was written in JavaScript, with p5.js for drawing the sequencer grid. The goal, working with my client, was to make the app simple and accessible while building out its core features, thereby shortening the production cycle and making this quickly available for testing - therefore, web/browser-based tools were chosen.

For audio, I identified p5.sound as the most compatible tool, as it extends p5 with Web Audio functionality. Most importantly, it includes useful and flexible methods for handling playback of samples in the form of sequences or patterns.

Schillinger Rhythm Generator tech

Challenges

Inconsistent playback speed - for a rhythm-based app this could be quite an issue! By default, the grid-based patterns do not play back 'on beat' but rather slow down or speed up erratically, like a drunken drummer. I therefore needed to pass in a scheduled delay time to produce a clock time that would be consistent with the sample rate. I also added some artificial latency to the visual playhead so that this was in sync with the speed of audio playback.

The Web Audio API, which is used for audio playback in the browser, comes with some policy restrictions - understandably, auto-playback is restricted and the API therefore expects some form of explicit user interaction in order to allow permission to play audio. In practice, finding a way to consistently 'suspend' audio playback on page load across browsers (and therefore avoid error which break the app) was unexpectedly challenging, but I was able to find a method that mimics Google's autoplay policy.

Working with patterns of differing lengths (i.e. a user-defined sequence length which is longer or shorter than the length of the numerical input pattern) - the 'interference' between the two is core to what makes Schillinger rhythms interesting, but also introduces some very complex logic. If the two differ, the visual sequencer pattern would also need to update dynamically on each 'cycle'. This involves accounting for a number of scenarios and design decisions:

  • If the sequence length is set to be longer than the input pattern, the pattern itself needs to cycle within the longer sequence, while the sequence display needs to update on each cycle of the playhead. A simpler alternative would have been to add rests to the pattern to 'fill' the remainder of the sequence, so that the same pattern repeats on each cycle - but this is far less interesting and doesn't take full advantage of the variation in 'interference patterns'.
  • If the sequence length is set to be shorter than the original input pattern, the sequence on display needs to be 'refreshed' more frequently. A simpler alternative would be to truncate the pattern, but again this limits variation.
  • If the sequence length is much longer than the input pattern, this requires multiple cycles within a sequence, adding further complexity.

For more detail, and to see more development challenges (and solutions), see the GitHub docs.

Schillinger Rhythm Generator challengesSchillinger Rhythm Generator challengesSchillinger Rhythm Generator challenges

Lessons

This has been a great experience in collaboration, working together to understand the aims and ideas of the client, and communicating with them the technical challenges or steps needed to translate these into functioning code. I set out a plan covering the features that were in scope for the project, and laid out the development stages needed to build a successful app, working through them iteratively.

One key takeaway from this project has been that there are many ways that a user can 'break' an app or interact with it in unexpected ways, so creating a robust UI/UX that allows for flexible interaction is really important. This made me think about the importance of usability in any application - making it simple and intuitive, while not forcing the user to overthink. There are some key principles in Steve Krug's Don't Make Me Think, Revisited: A Common Sense Approach to Web and Mobile Usability (strongly recommended!) which I intend to implement in future iterations of this app, including:

  • Don't make the user think - use of the app should be self-evident and a new user should be able to explore it intuitively, without friction or confusion.
  • Avoid instructions, or keep them short and simple. I have initially kept detailed instructions on the app's front page for ease of development and demonstration, but these will be replaced with UI features and a clearer visual hierarchy to highlight the app's most important features.
  • Regular usability testing - this helps to challenge development assumptions when used in the 'real world,' and continuous testing allows for continuous improvement.

Other Projects

YelpCamp

Direct Debit Date Calculator