Beam Beats is an interactive and tangible rhythm sequencer that translates the geometry of beacons on the ground into rhythms and polyrhythms thanks to a rotating laser beam. This experimental MIDI instrument is about investigating self-similarities in polyrhythms, as described in this post.
Update: Here’s the video of a demo at Dorkbot at La Gaité Lyrique in Paris
Before I report more on this project with demos and videos, here are some pictures to illustrate the work currently in progress, thanks to lasercutting techniques in particular:
The brand new laser-cut acrylic structureThe prototype laser head and retro-reflection light sensorThe Arduino to detect the light variations and convert them into MIDI notesVery early design of beacons each with their own light sensor
This prototype works, here’s a picture of the laser beam rotating:
I’ve been working on the Arduino source code to add the ability to send MIDI clock in order to sync Beam Beats to other MIDI devices.
Now I mostly need to conclude on the design for the active beacons(sensors stands) and the passive (retroreflective adhesive stands) beacons, and find out what to play with this sequencer…
On a Sunday afternoon, fifteen friends, all non musicians but two amateur musicians, joined the machines set in turn, around 8 at a time, to improvise electro or hip-hop rhythmic grooves. Of course there were food and drinks as well.
The goal was to introduce music making in an attractive way: no pressure, no constraint, no reason to be shy, just have fun!
Don’t be shy
Some arrived saying “no no no I will never sing in the mike”, but ended up doing the mike to record voice loops into the Kaoss Pad… Other spent time to figure out how to play something musical from machines they were touching for the first time. It was amazing how everybody got into it!
Here is a time lapse overview, unfortunately silent:
The machine set was primarily composed of an Akai MPC500 with various programs (drums, stabs, acapella chops, etc.), a Korg Kaoss Pad 3 with an Shure SM58 mike and a Korg microKorg, all MIDI clock-ed together, and all mixed into a Yamaha MG12/4 with a Boss SE-70 reverb send. There were also a 49-keys Casio keyboard and a Yamaha SHS10 mini handheld keyboard, both used as MIDI controllers to drive an EMU Turbo Phatt. Various circuit-bent toys were also pre-mixed and then fed into the Kaoss Pad as well, to get the best out of them.
Every machine has its own appeal: the Kaoss Pad 3 is the most appealing at first, but then it gets more difficult to master. The microKorg, thanks to its sync-ed arpeggiator and its modulation wheel is also rewarding very quickly. The MPC is somehow harder since you must be rather accurate when playing for the rhythm to sound good. The EMU Phatt is very easily rewarding, especially when using the Beats programs or other programs made of several sounds laid over the keyboard.
Fun or accurate: this is the question
One note about loops, either on the Kaoss Pad or in the MPC: if they help to improve the accuracy of the music (repeats perfectly each time), they also kill a lot of fun out of it since you only have to play once, record, and then you are done! On the other end, playing repeatedly the same thing (or at least trying to) helps to get warmer and warmer!
Thanks all for joining us for this party, and see you for next time!
Following my ongoing work on a theory of rhythms and a corresponding physical instrument using lasers, here is a version of the same idea implemented into an Arduino: a generative sequencer. The idea is to generate rhythms, and perhaps melodies, from one rhythm seed, then use mutated copies of it to create something more interesting, all this in realtime using knobs and buttons.
This is not ‘yet another step sequencer’, but really a generative music device, that builds a real time MIDI loop based on an underlying theory described in a previous post.
This is work in progress, and is shown ‘as is’ for the sake of getting feedback.
Approach
The approach is to generate a “seed” of rhythm that is then copied a few times into “instances”, each instance being distorted in its own way. The controls for the human player (or programmer) are therefore all about adjusting the deformations (transforms actually) to apply to each instance, and of course defining the seed.
Eventually each instance is wired to a MIDI note, channel etc. to remote control a synthesizer or a drum machine or any MIDI setup, to generate actual sounds.
Principle: one seed, many transformed instances
The maths
Given a seed of rhythm of lengh length composed of pulses, each of duration m, then:
for each instance k of the seed, each pulse i,
pulse(k, i) happen at time t = phase(k) + i . m . stretch(k), t < length
where phase(k) and stretch(k) are the phase and stretch settings for the instance k.
Realtime control of the sequencer is therefore all about setting the phase and stretch values for each instance, once the pulse number and the pulse duration of the seed have been globally set.
Inversely, for a given instance k, at time t, we have a pulse if:
there exists an i, such as t = phase(k) + i * m * stretch(k)
i.e. i = (t - phase(k))/(m * stretch(k))
Thinking in MIDI ticks (24 per quarters), in 4/4, for 1 bar, length = 4 * 24, phase is in [-24 .. 24] and stretch is in [4:1 .. 1:4] and m in [12 .. 48] by steps of 12 ticks.
The implementation is the very simple: for each instance of the seed, and given its phase and stretch settings, whenever the modulo condition above is true, then we emit its MIDI note, with the set velocity on the set MIDI channel.
As usual, the pace of the loop is primarily based on the value from the Tempo potentiometer.
Overview of the circuit, with the switches and the knobs
Adding some swing
8th note swing
The EMU SP-1200, early Linn machines, Roland 909, Akai MPC and many other machines are famous for their swing quantize, a feature that delays every other note by a certain amount in order to create a groovy feeling (see Swung Note).
Different machines express the swing factor in different ways, we will stick to the MPC format, expressed in percent from 50% (no swing, play straight) to 75% (hard shuffle).
For a swing for 8th notes, this swing factor represents the ratio of the period of the first 8th note over the period of the second 8th note, in percent.
In the Arduino code of our generative sequencer, we chose to do a fixed swing for 8th notes only.
A big constraint is that we are limited to a resolution of 24 ticks per quarter note, which is not a lot! By contrast, MPC have a 96 ppq resolution. Because a hard swing of 70% translates into hardly 2 MIDI ticks at 24 ppq, doing the swing on top of the ticks will not be accurate at all!
The only solution is to vary the internal tempo before and after each 8th note. The drawback (or advantage) is that the MIDI clock being sent will also move, reflecting the same swing. Since the Swing knob value is actually between 0 and 25 (to be read from50% to 75%), the tempo before (t-) and the tempo after (t+), are given by:
t+/- = (50 +/- swing) * t / 50
where t is the base loop period without swing
Video Demo
Here is a video demo. There are only 3 instances, selected by the switches 1, 2 and 3; the first switch selects the GLOBAL settings: step duration (quarter, 8th etc.), swing factor, tempo. Each instance can be set its Phase, Stretch, MIDI note, velocity and MIDI channel. Here I have preset the MIDI channels, instance 1 on channel 1 (the microKorg) and instances 2 and 3 on channel 2 (the MPC with a drum kit).
The goal is to build a simple beat by only adjusting the parameters.
Please note that some parts of the code are not used any more, such as the big constant arrays, and some comments are not up to date (e-g no prime number anymore).
All analog inputs are wired to simple knobs. Digital inputs 8, 9, 10 , 11 are the four buttons used to switch pages. Digital output 12 is the activity LED (showing when the knob is active within the knob pagination). MIDI out is on the Tx pin.
/*
* Generative rhythm sequencer, more details at: http://cyrille.martraire.com
*
* Knob mapping according to a grid 2^n . prime^m, against the MIDI 24 ticks/quarter.
*
* Knob pagination to multiplex the knobs several times with LED to show activity.
*
* Memory-less event handling thanks to maths relationships.
*
* MIDI note on output on every 16 channel and MIDI clock according to tempo.
//---------- USER INPUT AND PAGINATION -----------
#define PAGE_NB 4
#define KNOB_NB 6
#define FIRST_PAGE_BUTTON 8
#define PROTECTED -1
#define ACTIVE 1
#define SYNC_LED 12
// the permanent storage of every value for every page, used by the actual music code
int pageValues[PAGE_NB][KNOB_NB];
// last read knob values
int knobsValues[KNOB_NB];
// knobs state (protected, enable...)
int knobsStates[KNOB_NB];
// current (temp) value just read
int value = 0;
// the current page id of values being edited
int currentPage = 0;
// signals the page change
boolean pageChange = false;
//temp variable to detect when the knob's value matches the stored value
boolean inSync = false;
int maxValue = 890;
int scaleLen = 15;
int *scale = scale3;
int step = 60;
int center = 30;
int coeff = 10;
//---------- GENERATIVE MUSIC CODE ---------
unsigned int cursor = 0;
int bars = 1;
int length = bars * 4 * 24;
// INPUTS
int PHASE = 0;
int STRETCH = 1;
//int DIRECTION = 2;
int NOTE = 2;
int DURATION = 3;
int VELOCITY = 4;
int CHANNEL = 5;
// GLOBAL KNOBS (seed and global settings)
int seedDuration = 24;
int seedTimes = 8;
int instanceNb = 4;
int swing = 0;//0..25% (on top of 50%)
//
int loopPeriod = 125/6;//120BPM
int actualPeriod = loopPeriod;
//instance i
int phase = 0;
int stretch = 1;
int note = 48;
int duration = 24;
int velocity = 100;
int channel = 1;
// custom map function, with min value always 0, and out max cannot be exceeded
long mapC(long x, long in_max, long out_min, long out_max)
{
if (x > in_max) {
return out_max;
}
return x * (out_max - out_min) / in_max + out_min;
}
// for each instance, and for the given cursor, is there a pulse?
boolean isPulse(byte phase, byte stretch){
int num = cursor - phase;
int denum = seedDuration * stretch / 4;
return num % denum == 0;
}
// Sends a MIDI tick (expected to be 24 ticks per quarter)
void midiClock(){
Serial.print(0xF8, BYTE);
}
// plays a MIDI note for one MIDI channel. Does not check that
// channel is less than 15, or that data values are less than 127:
void noteOn(char channel, char noteNb, char velo) {
midiOut(0x90 | channel, noteNb, velo);
}
// plays a MIDI message Status, Data1, Data2, no check
void midiOut(char cmd, char data1, char data2) {
Serial.print(cmd, BYTE);
Serial.print(data1, BYTE);
Serial.print(data2, BYTE);
}
// read knobs and digital switches and handle pagination
void poolInputWithPagination(){
// read page selection buttons
for(int i = FIRST_PAGE_BUTTON;i < FIRST_PAGE_BUTTON + PAGE_NB; i++){
value = digitalRead(i);
if(value == LOW){
pageChange = true;
currentPage = i - FIRST_PAGE_BUTTON;
}
}
// if page has changed then protect knobs (unfrequent)
if(pageChange){
pageChange = false;
digitalWrite(SYNC_LED, LOW);
for(int i=0; i < KNOB_NB; i++){
knobsStates[i] = PROTECTED;
}
}
// read knobs values, show sync with the LED, enable knob when it matches the stored value
for(int i = 0;i < KNOB_NB; i++){
value = analogRead(i);
inSync = abs(value - pageValues[currentPage][i]) < 20;
// enable knob when it matches the stored value
if(inSync){
knobsStates[i] = ACTIVE;
}
// if knob is moving, show if it's active or not
if(abs(value - knobsValues[i]) > 5){
// if knob is active, blink LED
if(knobsStates[i] == ACTIVE){
digitalWrite(SYNC_LED, HIGH);
} else {
digitalWrite(SYNC_LED, LOW);
}
}
knobsValues[i] = value;
// if enabled then miror the real time knob value
if(knobsStates[i] == ACTIVE){
pageValues[currentPage][i] = value;
}
}
}
Here is an example of how to use the same knobs (e-g. 6 knobs easy to connect to the 6 Arduino analog inputs) several times to adjust several parameters spread over several “pages”.
This enables to “multiplex” the same knobs many times, in a safely fashion thanks to the protection mecanism: after changing the active page, every knob is in protected mode (turning the knob does not change the value of the parameter) not to force a sudden jump of value. On turning a knob, the LED lights on when the knob’s value matches the stored value, and then the knob becomes fully active (at least till the next page switch).
This mecanism is inspired and similar to that of the microKorg synth edit knobs. As they say about it in Wikipedia:
“In the Edit mode, however, every knob makes the LED panel display the current value associated with the knob position. To change the current value of a given parameter, the user must pass through the original value before being able to modify anything. When one that original value, the Original Value LED will light on, and the value displayed on the LED panel will stop flashing. This avoids the user from passing from a small to a high value immediately, so there’s no big margin in the change of the parameters (a useful function for live performances).” The microKorg Edit panel, with 5 knobs and 22 pages = 120 parameters to control
In Arduino
Console output printing the 4 pages of 6 parameters and the currently active page
To do this in Arduino is not very difficult.We first need a 2-dimension array to store the value of each parameter:
// the permanent storage of every value for every page, used by the actual application code
int pageValues[PAGE_NB][KNOB_NB];
We also need an array to store the state of each knob: whether it is PROTECTED or ACTIVE, and yet another array to keep track of the value of each knob in the previous loop, in order to detect when a knob is being turned:
// last read knob values
int knobsValues[KNOB_NB];
// knobs state (protected, enable...)
int knobsStates[KNOB_NB];
Then we begin to read the digital switches to select the current active page. In case the selected page has changed, every knob has its state set to PROTECTED. We then read the analog value for each knob, detect changes, find out when the knob value is in sync with the stored value for the parameter to light the LED and set its state to ACTIVE.
Only when the state is set to ACTIVE we copy the current value of the knob to the actual parameter stored for the current page.
In my experiment I have 4 digital buttons connected to digital inputs 8 to 11, and 6 knobs (pots) connected to the 6 analog inputs:
The Arduino board, the 4 page buttons, the 5 + 1 knobs and fader and the LED
Here is the full code below:
/*
* Handles a pagination mecanism, each page can use the same knobs;
* Digital switches select the current active page.
*
* This enables to "multiplex" the same knobs many times, safely thanks to the protection mecanism.
*
* After changing the active page, every knob is protected, not to force a jump in value.
* On turning a knob the LED lights up when the knob's value matches the stored value, and then
* the knob becomes active till next page switch.
*
* This mecanism is inspired and similar to that of the microKorg synth edit knobs.
*
* Copyleft cyrille martraire cyrille.martraire.com
*/
//---------- USER INPUT AND PAGINATION -----------
#define PAGE_NB 4
#define KNOB_NB 6
#define FIRST_PAGE_BUTTON 8
#define PROTECTED -1
#define ACTIVE 1
#define SYNC_LED 12
// the permanent storage of every value for every page, used by the actual music code
int pageValues[PAGE_NB][KNOB_NB];
// last read knob values
int knobsValues[KNOB_NB];
// knobs state (protected, enable...)
int knobsStates[KNOB_NB];
// current (temp) value just read
int value = 0;
// the current page id of values being edited
int currentPage = 0;
// signals the page change
boolean pageChange = false;
//temp variable to detect when the knob's value matches the stored value
boolean inSync = false;
void setup() {
pinMode(13, OUTPUT);
Serial.begin(19200);
setupPagination();
}
void setupPagination(){
pinMode(SYNC_LED, OUTPUT);
for(int i=0; i < KNOB_NB; i++){
knobsValues[i] = analogRead(i);
knobsStates[i] = ACTIVE;
}
}
// read knobs and digital switches and handle pagination
void poolInputWithPagination(){
// read page selection buttons
for(int i = FIRST_PAGE_BUTTON;i < FIRST_PAGE_BUTTON + PAGE_NB; i++){
value = digitalRead(i);
if(value == LOW){
pageChange = true;
currentPage = i - FIRST_PAGE_BUTTON;
}
}
// if page has changed then protect knobs (unfrequent)
if(pageChange){
pageChange = false;
digitalWrite(SYNC_LED, LOW);
for(int i=0; i < KNOB_NB; i++){
knobsStates[i] = PROTECTED;
}
}
// read knobs values, show sync with the LED, enable knob when it matches the stored value
for(int i = 0;i < KNOB_NB; i++){
value = analogRead(i);
inSync = abs(value - pageValues[currentPage][i]) < 20;
// enable knob when it matches the stored value
if(inSync){
knobsStates[i] = ACTIVE;
}
// if knob is moving, show if it's active or not
if(abs(value - knobsValues[i]) > 5){
// if knob is active, blink LED
if(knobsStates[i] == ACTIVE){
digitalWrite(SYNC_LED, HIGH);
} else {
digitalWrite(SYNC_LED, LOW);
}
}
knobsValues[i] = value;
// if enabled then miror the real time knob value
if(knobsStates[i] == ACTIVE){
pageValues[currentPage][i] = value;
}
}
}
void loop() {
poolInputWithPagination();
printAll();
delay(100);
}
void printAll(){
Serial.println("");
Serial.print("page ");
Serial.print(currentPage);
//Serial.println("");
//printArray(knobsValues, 6);
//Serial.println("");
//printArray(knobsStates, 6);
for(int i = 0; i < 4; i++){
Serial.println("");
printArray(pageValues[i], 6);
}
}
void printArray(int *array, int len){
for(int i = 0;i< len;i++){
Serial.print(" ");
Serial.print(array[i]);
}
}
Now we want to put that into practice to build a musical instrument. Let’s consider we want to do something inspired by the Theremin, but simpler to play and more funny to look at while easier to build as well.
Requirements
Here is now a case study: We want to build an instrument that must be:
Playable by friends that know very little in music: in other words really easy to play
Attractive for friends that enjoy the fun of playing and jamming together: must be expressive
Suitable for groovy electronic music (house, hip-hop, electro, acid-jazz, trip-hop and a bit of techno)
Able to participate within a small band among other instruments, mostly electronic machines
With a funky look and visually attractive when performing
Design and justification
The finished instrument
Based on these requirements, and after some trials and error we go for the following:
Finger physical guidance, because it is too hard to keep hands in the air at the same position (req. 1)
Bright leds plus light sensor as a primary way of playing, for the funky look and visually attractive performance (req. 5)
Discrete pitch as primary way of playing, with pitch quantization against a pentatonic scale, easy, good sounding (but coupled to one fixed tonality unless putting configuration buttons) (req. 1)
Expression on the pitch when a note is pressed send pitch bend events to modulate the pitch as on a guitar or real theremin; this only happen after a note is pressed, not to conflict with the primary pentatonic scale (req. 2)
Allows for additional expression using a distinct light sensor mapped to a Midi Continuous Controller (controller 1: modulation wheel) (req. 2)
Continuous rhythm control to start the project simply, plan to quantize it on 16th notes according to a midi clock later (tradeoff to keep simple right now, should be even simpler due to req. 1)
MIDI controller rather than integrated synthesizer to allow for very good sounds generated from external professional synthesizers (req. 3)
Internal scale setup within the range between C3 and C5, to dedicate the instrument to play solo on top of an electronic rhythm (req. 4)
Arduino implementation (easy to implement pitch quantization logic and expression controls)
Construction
The very simple circuitThe Arduino board
An aluminium rail (from a DIY shop) is fixed to an empty salt box as the body (hence the name “Salty Solo”)
The main sensor and the expression sensor are two simple LDRs connected through a voltage divider to two Arduino analog inputs
Two buttons are simply connected to two Arduino digital inputs.
The MIDI out DIN plug is connected to the Arduino Tx pin.
The rest is in the Arduino software!
I have decorated the salt box with adhesive stuff…
Playability and fixes
At first try, playing the Salty Solo is not that easy! A few problems happen:
Reaction time (or “latency”) is not good
Moving the light with the left hand is not very fast, hence impedes playing a melody that sounds like one.
Also there is a kind of conflict between the note quantization that does a rounding to the closest accurate note, and the expression control that allows to “bend” notes.
The first problem has been solved by increasing the Arduino loop frequency down to 100Hz (wait period = 10ms); to prevent sending MIDI continuous controller and MIDI pitch bend too often we therefore needed to send them (when needed) once out of a few loops.
For the second problem a workaround has been done by using the second button to trigger the next note in the scale, and pressing both buttons together triggers the second next note in the scale. Basically, in the (almost) pentatonic scale we use this usually means jumping to the third or to the fifth. This kind of jump is very common when playing guitar or bass guitar thanks to their multiple strings, and it does help play faster while moving the left hand much less. With two buttons like this it is much easier to play melodic fragments.
The last problem has been solved a bit randomly: because of a bug in the code, the pitch bend only happen when on the highest note: this saves the most useful case of playing the guitar hero on a very high note while bending it a lot. On the other notes, sliding the left hand descend or ascend the scale instead. Further playing and external opinions will probably help tweak this behaviour over time.