The Granular Patchbay

 

Rationale

A few years ago I attended a lecture at Harvard given by composer Jean Claude Risset. He accounted his experiences with early computing systems such as RCA/Princeton synthesizer and other punch-card devices, commenting that back in those days while waiting a week to get your reels back, just to find that there was a mistake, you had to think.


Although composers today have access to unprecedented computing resources, the onward march towards commercializable tools have left a severe imprint on how we make digital music. The spirit and attention to detail of the predecessors has been lost. Although new research continues to unearth fascinating synthesis techniques (scanned synthesis, granular synthesis), composers hardly take advantage of them in favor of speed and interface accessibility as epitomized by dp4, or various native instruments softwares.


Additionally, in the heyday of analog synths composers had their hands in it. Composers romantically harken back to the day when they could tweak knobs and work around patchbays in their noisy old moog devices. These systems were remarkable and novel in how one was able to rely on physicality to move complex sound parameters around a physically attractive and acoustically complex space.


This project tries to incorporate these criticisms into the development of an interface between an Arp2600 synthesizer and csound.

 

 

 

Tools

Csound
a syntax based totally free software synthesis programming environement.
People diss it because its text based and they cant handle it. The good news is that with such an open-ended and powerful tool, you can realize complex and beautiful sounds not otherwise possible. Especially useful for granular synthesis, with precise control over many parameters.

Max/MSP
Ubiquitous in the music controller community is Max/MSP. You have objects that perform functions. By graphically connecting objects you map out a "patch" that performs some flow control over audio, midi, and matrix data. Some people will tell you that this is much like patching in analog systems. Its total BS. It shouldn't be called patching at all. The Max/MSP interface is devoid of any of the patching nuance of analog systems. Although, it undeniably useful for control.

Arduino
Realizing that you know nothing about microcontrollers is a drag. The Arduino board is the way to go. It's a simple dev kit for programming the ATMega8 out of a java IDE that is much like Processing. It is becoming a favorite in the hacker/controller community for its ease of interfacing to hardware, especially for sensors, switches and motors. It interfaces with Max.

Arduino2Max
Grabs serial data from the arduino. Its best to mess with the baud rate.


csound~
Compiles csound in realtime as an object in max/msp

 

 

 

Circuits

circuits blabla

The board

The Arp2600

Diagram

 

 

 

Max/msp


Here are some of the critical parts of the Max patch.
Ripped from Arduino2Max. I deleted all the digital read loops in both the arduino code and the max code to get more speed when reading the ADC.
A bank of zmaps grab the 8bit arduino intergers and scale to midi range. Note the many extra zmaps are there to eventually be used by a muxing AVR. The 6 analog pins on the Arduino board get used up too fast.The csound core of the thing. I get the 0-127 values from my bank of zmaps into these variable messages, that look like midi to csound. Inside csound these are going to granular parameters.

 

 

 

 

Arduino

The arduino code is adapted directly from the SimpleMessageSystem code found off the Arduino2Max instructions. It scans input pins and sends serial.


#include <SimpleMessageSystem.h>
/* Analog/Digital inputs to MAX/MSP trigger
* ------------
* send serial values to MAX/MSP to trigger something
*/
char firstChar;
char secondChar;
void setup()
{
Serial.begin(115200);
}void loop()
{ if (messageBuild()) { // Checks to see if the message is complete
firstChar = messageGetChar(); { // Gets the first word as a character
if (firstChar = 'r') { // Checking for the character 'r'
secondChar = messageGetChar(); // Gets the next word as a character
if (firstChar = 'd') // The next character has to be 'd' to continue
messageSendChar('d'); // Echo what is being read
for (int i=0;i<=5;i++) {
messageSendInt(analogRead(i)); // Read analog pins 0 to 5
}
messageEnd(); // Terminate the message being sent
delay(5);
}
}
}
}

 

 

 

csound

The grain opcode in csound defines all of the parameters required to produce granular synthesis with various constraints.

grain kamp, ipitch, kdens, kampoff, kpitchoff, kgdur, igfn, iwfn, imgdur, igrnd

amplitude of the each grain, grain pitch, grain density, random offset range for grain amplitude, offset range for pitch, grain duration, grain function, grain amplitude envelope, maximum grain duration, and a flag for randomly reading from different start points at each grain excitation.


The complete code is below, with large sections commented out as I tried to get the conditional stuff working to switch between grain and window functions in realtime, and Im not sure if it does.


< CsoundSynthesizer>
< CsInstruments>
;Adam Boulanger
;adamb@media.mit.edu
;Midified grain instrument for testing grainsynth interface
garvb init 0
;ctrlinit 1, 10, x, 11, x, 12, x, 13, x
ctrlinit 1, 14, 12, 15, 0
ctrlinit 1, 16, 0, 17, .16, 18, 0, 19, .8, 20, 4000
ctrlinit 1, 21, 0, 22, 0, 23, 5, 24, 0, 25, 1
instr 3
;midi variable assignment block
;iwfna midic7 10, x, x
;iwfnd midic7 11, x, x
;iwfns midic7 12, x, x
;iwfnr midic7 13, x, x
imgdur midic7 19, .01, .8 ;;init = .8
igrnd midic7 22, 0, 1 ;;init = 0
kdens_gross midic7 14, 6, 100 ;;init = 12
kdens_fine midic7 15, -5, 5 ;;init = 0
kampoff_gross midic7 16, 0, 3000 ;;init = 0
kgdur_gross midic7 17, .01, .8 ;;init = .16
kgdur_fine midic7 18, -.007, .007 ;;init = 0
kamp_gross midic7 20, .00001, 6000 ;;init = 4000
kpitchoff_gross midic7 21, -800, 800 ;;init = 0
kpitch_gross midic7 23, 3.00, 13.0 ;;init = 5.0
kpitch_fine midic7 24, -.5, .5 ;;init = 0
ksel_gfn midic7 25, 0, 5
;grain control block::::::::::::::::::::::::::
;;grain function multi-position switch
if (ksel_gfn <= 1.0) kgoto selfn2
if (ksel_gfn <= 2.0) kgoto selfn3
if (ksel_gfn <= 3.0) kgoto selfn4
if (ksel_gfn <= 4.0) kgoto selfn5
if (ksel_gfn <= 5.0) kgoto selfn6
selfn2:
igfn = 5
koutme = 1 ;debug outme to test conditional
goto end_gfn_sel
selfn3:
igfn = 3
koutme = 2
goto end_gfn_sel
selfn4:
koutme = 3
igfn = 4
goto end_gfn_sel
selfn5:
igfn = 5
goto end_gfn_sel
selfn6:
igfn = 6
goto end_gfn_sel
end_gfn_sel:
;outvalue "maxmsp", koutme
iwfn = 1
;imgdur in i midic7 block
;igrnd in i midic7 block
kamp = kamp_gross
kampoff = kampoff_gross
ipitch cpsmidi
kpitchoff = kpitchoff_gross
kdens = kdens_fine + kdens_gross
kgdur = kgdur_gross
kcut = 500
asig grain kamp, ipitch, kdens, kampoff, kpitchoff, kgdur, igfn, iwfn, imgdur, igrnd
alp butterlp asig, kcut
out alpendin
< /CsInstruments>
< CsScore>
f 1 0 4096 1 "a50.aif" 0 4 1
f 2 0 4096 20 6 ;gauss
f 3 0 4096 20 9 ;sync
f 4 0 4096 20 8 ;rectangle
f 5 0 4096 20 5
f 6 0 4096 20 7
f0 600</CsScore>
< /CsoundSynthesizer>
< MacOptions>
Version: 3
Render: Real
Ask: Yes
Functions: ioObject
WindowBounds: 68 136 671 768
Options: -b128 -A -s -m7 -R
< /MacOptions>
< MacGUI>
ioView background {60108, 65535, 63132}
ioListing {75, 280} {562, 166}
ioGraph {163, 38} {472, 230}
ioSlider {76, 39} {34, 229} 20.000000 2000.000000 559.351990 pitch
< /MacGUI>

 

 

 

contact: adamb [at] media.mit.edu

copyright @ 2006 Adam Boulanger. MIT Media Lab. All rights reserved.