
Tofu Time: A Solid Block of Extra Firm Time and a Very Sharp Knife
“How does time function in postmodern music? Postmodernism is profoundly temporal, but it uses, rather than submits to time. Its music shapes time, manipulates time. Time, like tonal sounds and diatonic tunes and rhythmic regularity and textual unity, becomes no longer context but malleable material.” ~ Jonathan D. Kramer, Postmodern Music, Postmodern Listening 2016, p. 152.
Most drum machines build a beat from the sample up. Some, like the Roland 808, allow you to press buttons to determine the position of samples in a left to right sequence. Others, like the Akai MPC-1000, allow you to set an empty loop length and trigger a sample as your previously triggered samples loop endlessly until you fill up the loop space. Both drum machines work from the bottom up to build a beat.
This isn’t that drum machine. This is a drum machine that approaches beatmaking from the top down — a postmodern drum machine. Instead of building a beat by adding samples, this drum machine lets you build a beat by dividing time down. This is a drum machine that treats time like tofu, a big block of extra firm tofu.
The Postmodern Drum Machine uses the standard Arduino and breadboard circuit described here. In the video below, it is turned on its side to show the potentiometers in action.
In this implementation, the first four potentiometers are set to a value of 1 to 8, a knife sharp enough to cut tofu. A value of 1 cuts the big block of tofu into very thin slices. A value of 8 cuts it into 8 pieces of time. Eight is a convenient maximum because the total clock ticks in this block are 96 (24*4), so cutting the time by 1 to 8 produces some nice and clean — and some nasty and jagged — slices of time. The fifth potentiometer is the length of time between the notes within the sequence of four in milliseconds. The sixth potentiometer is the length of time between the sequence of four in milliseconds.
In the code, two main variables control the size of the block of time and how precisely it can be cut:
int MAX_CLOCK_TICK = 24 * 4; // sets maximum ticks in the loop
int MAX_CLOCK_DIVISOR = 8; // sets maximum divisor for triggers
MAX_CLOCK_TICK is the numerator and MAX_CLOCK_DIVISOR is the divisor. Even with MAX_CLOCK_TICK set to 96, some unusual rhythms emerge due to the fact that we are testing the result to see if there is a remainder. 96/8 = exactly 12, no remainder. Divide the total time into 12 equal parts. 96/4 = exactly 16, no remainder. Divide the time into 16 equal parts. Nice cuts. But 96/5 = 19.2 and 96/7 = ~13.714. The final remainder at the end of the block of time is whatever slice is still left. Nasty cuts. And yet, each of the sounds assigned to the four potentiometers plays on in its own time, oblivious to the other sounds. Even the remaining nasty cut at the end of the block will repeat as a fresh block of tofu time is cut again.
But this is not assembling a beat from samples or picking out a pattern of buttons. With the Postmodern Drum Machine, the composer/performer is not playing the sounds assigned to the potentiometers; the composer/performer is playing with time. Turning and twisting time. As Kramer said, “Rhythmic regularity… becomes…malleable material.”
There are three videos that demonstrate the circuit in action. The first uses four standard drum sounds from general MIDI. From left to right: Kick, Snare, Ride, and, of course, Cowbell. The second video uses pitched percussion with four notes, a delightfully discordant tone row. From left to right: C, F#, B, Eb. The third video is a Raga in D Minor on a stringed instrument. From left to right: D, A, F, D. All sounds were produced using the MIDI out of the circuit connected to an Alesis NanoSynth. Videos first, then code.
Postmodern Drum Machine with Trap Drum Kit
Postmodern Drum Machine with Pitched Percussion
String Raga in D Minor (Postmodern Drum Machine)
Postmodern Drum Machine Code
/* A POSTMODERN DRUM MACHINE This program demonstrates how to control the timing of multiple midi events triggered from a master clock, i.e, a BEATBOX or DRUM MACHINE. The program assumes a General MIDI mapping of drums. A list of standard drum assignments appears the bottom of this program for convenience. This program reads up to 10 digital switches (not used here, but left for future use) and 6 ADC sensors. It reads an ON/OFF switch connected to pin D12. It allows for both HAIRLESS MIDI (software serial connection) and CLASSIC MIDI (hardware connection) through a standard 5-pin connector with output via the TX pin (D1). Note that the appropriate baud rate (speed) of midi transmission should be adjusted in the setup function. For more on this circuit and programs, see: www.amateurmusicology.com Elliot Inman Spring 2016 */ // Create variables to use throughout the program // Create a Master Clock to Rule All Time int CLOCK_TICK = 0; // counts ticks int MAX_CLOCK_TICK = 24 * 4; // sets maximum ticks in the loop int MAX_CLOCK_DIVISOR = 8; // sets maximum divisor for triggers // Digital switches connected to pins D2 to D11 int switch1, switch2, switch3, switch4, switch5, switch6, switch7, switch8, switch9, switch10; // Six ADC sensors connected to A0 to A6 int clock_divisor1, clock_divisor2, clock_divisor3, clock_divisor4; int time_to_play; int time_between_notes; // SETUP the Arduino with a baud rate and tell // it what to do with various pins void setup() { // Set MIDI baud rate for HAIRLESS MIDI: // Serial.begin(115200); // If using CLASSIC MIDI: Serial.begin(31250); // Not used in this program, but left here for convenience pinMode(2, INPUT_PULLUP); // breadboard button input pinMode(3, INPUT_PULLUP); // breadboard button input pinMode(4, INPUT_PULLUP); // breadboard button input pinMode(5, INPUT_PULLUP); // breadboard button input pinMode(6, INPUT_PULLUP); // breadboard button input pinMode(7, INPUT_PULLUP); // breadboard button input pinMode(8, INPUT_PULLUP); // breadboard button input pinMode(9, INPUT_PULLUP); // breadboard button input pinMode(10, INPUT_PULLUP); // breadboard button input pinMode(11, INPUT_PULLUP); // breadboard button input pinMode(12, INPUT); // ON/OFF Switch input pinMode(13, OUTPUT); // Use LED to indicate running } // LOOP that will cycle endlessly. void loop() { // At start, set LED to OFF digitalWrite(13, LOW); // At start, set CLOCK_TICK to 0 CLOCK_TICK = 0; // Check to see if the ON/OFF switch is on. // If so, proceed. Otherwise, keep checking. while (digitalRead(12) == HIGH) { // Turn LED on to indicate running digitalWrite(13, HIGH); // Collect all sensor data // Because these are INPUT_PULLUP switches, // pressed = LOW or 0 and Not Pressed = HIGH or 1 switch1 = digitalRead(2); switch2 = digitalRead(3); switch3 = digitalRead(4); switch4 = digitalRead(5); switch5 = digitalRead(6); switch6 = digitalRead(7); switch7 = digitalRead(8); switch8 = digitalRead(9); switch9 = digitalRead(10); switch10 = digitalRead(11); // Gather ADC sensor data and map from 0 to 1023 to // 1 to MAX_CLOCK_DIVISOR to use to divide // the time from our master clock to trigger events clock_divisor1 = map(analogRead(A0), 0, 1023, 1, MAX_CLOCK_DIVISOR); clock_divisor2 = map(analogRead(A1), 0, 1023, 1, MAX_CLOCK_DIVISOR); clock_divisor3 = map(analogRead(A2), 0, 1023, 1, MAX_CLOCK_DIVISOR); clock_divisor4 = map(analogRead(A3), 0, 1023, 1, MAX_CLOCK_DIVISOR); // 5th and 6th ADC sensors mapped to 5 to 500 time_to_play = map(analogRead(A4), 0, 1023, 1, 500); time_between_notes = map(analogRead(A5), 0, 1023, 1, 500); // play a note using the function defined below // Notice that there is a bit of random variance added to the attacks // with the minimum set at 80 and an additional emphasis 0 and 40 if (CLOCK_TICK % clock_divisor1 == 0) noteOn(0x99, 38, 80+random(40)); // Kick if (CLOCK_TICK % clock_divisor2 == 0) noteOn(0x99, 45, 80+random(40)); // Snare if (CLOCK_TICK % clock_divisor3 == 0) noteOn(0x99, 53, 80+random(20)); // Ride if (CLOCK_TICK % clock_divisor4 == 0) noteOn(0x99, 62, 80+random(20)); // Cowbell delay(time_to_play); if (CLOCK_TICK % clock_divisor1 == 0) noteOn(0x99, 38, 0); // Kick if (CLOCK_TICK % clock_divisor2 == 0) noteOn(0x99, 45, 0); // Snare if (CLOCK_TICK % clock_divisor3 == 0) noteOn(0x99, 53, 0); // Ride if (CLOCK_TICK % clock_divisor4 == 0) noteOn(0x99, 62, 0); // Cowbell delay(time_between_notes); CLOCK_TICK = CLOCK_TICK + 1; if (CLOCK_TICK == MAX_CLOCK_TICK) CLOCK_TICK = 0; } } /* noteOn function to play a MIDI note COMMAND 0x99 sends NOTE ON on Channel 10, a channel that is often reserved for general MIDI drums. PITCH is the note from 0 to 127 with 60 as middle C. Keep in mind that some MIDI instruments may not sound outside of their normal real acoustic range. VELOCITY is how hard the note is struck (from 0 to 127), but is often perceived as volume. Using 0 for velocity is the same as turning a note OFF, so that is often used instead of a note OFF command. */ void noteOn(int command, int pitch, int velocity) { Serial.write(command); Serial.write(pitch); Serial.write(velocity); } /* General MIDI Drum Notes Key# Drum Sound 35 Acoustic Bass Drum 36 Bass Drum 1 37 Side Stick 38 Acoustic Snare 39 Hand Clap 40 Electric Snare 41 Low Floor Tom 42 Closed Hi Hat 43 High Floor Tom 44 Pedal Hi-Hat 45 Low Tom 46 Open Hi-Hat 47 Low-Mid Tom 48 Hi-Mid Tom 49 Crash Cymbal 1 50 High Tom 51 Ride Cymbal 1 52 Chinese Cymbal 53 Ride Bell 54 Tambourine 55 Splash Cymbal 56 Cowbell 57 Crash Cymbal 2 58 Vibraslap 59 Ride Cymbal 2 60 Hi Bongo 61 Low Bongo 62 Mute Hi Conga 63 Open Hi Conga 64 Low Conga 65 High Timbale 66 Low Timbale 67 High Agogo 68 Low Agogo 69 Cabasa 70 Maracas 71 Short Whistle 72 Long Whistle 73 Short Guiro 74 Long Guiro 75 Claves 76 Hi Wood Block 77 Low Wood Block 78 Mute Cuica 79 Open Cuica 80 Mute Triangle 81 Open Triangle */
Heat your wok until the metal begins to shine. Ginger, garlic, green onions, and soy. It’s tofu time.
~ WEI 2017
You must be logged in to post a comment.