ACTAM - Advanced tools for embedded music programming

12/12/2024

Goals: Introduce two new tools

  1. Arduino
  2. SuperCollider

What is Arduino?

Available Boards

https://www.arduino.cc/en/hardware

  • Arduino Uno: Basic board, good for simple audio projects
  • Arduino Due:
    • 12-bit DAC (Digital to Analog Converter)
    • Higher processing power (84 MHz)
    • Ideal for complex audio synthesis
  • Arduino Mega: More I/O pins for multiple controllers/sensors

How can I program it?

Get started with this IDE

Arduino as MIDI Controller

void setup() {
  Serial.begin(9600);
}
void loop() {
  int sensorValue = analogRead(A0);
  // Map sensor to MIDI values (0-127)
  byte midiValue = map(sensorValue, 0, 1023, 0, 127);
  Serial.write(midiValue);
  delay(10);
}

Basic tone generation

const int speakerPin = 9;
void setup() {
  pinMode(speakerPin, OUTPUT);
}

void loop() {
  tone(speakerPin, 440, 500);
  delay(1000);
}

Basic DAC generation

For example on Arduino Due:

const int dacPin = DAC1; 

void setup() {
  // No need to set pinMode for DAC pins
  // here we could precompute sine wave values scaled to DAC
}

// SAWTOOTH
void loop() {
  for (int value = 0; value <= 4095; value += 100) { 
    analogWrite(dacPin, value); 
    delay(10);
  }
}

// SQUARE 
void loop() {
  analogWrite(dacPin, 0);       
  delay(500);                   
  analogWrite(dacPin, 4095);    
  delay(500);                   
}

Arduino with Web Audio API

// Receiving Arduino data via Web Serial API
async function connectArduino() {
  const port = await navigator.serial.requestPort();
  await port.open({ baudRate: 9600 });

  const reader = port.readable.getReader();
  while (true) {
    const { value, done } = await reader.read();
    if (value) {
      oscillator.frequency.value = value * 10;
    }
  }
}

What's SuperCollider? Isn't SonicPi enough?

  • lower level language (SCLang)
  • real-time audio server (spectral analysis, manipulation, and resynthesis with FFT)
  • can define your own synthesis algorithms

Basic SuperCollider Syntax

(
SynthDef(\simpleSine, {
    arg freq = 440;
    var sig = SinOsc.ar(freq, 0, 0.5);
    Out.ar(0, sig); //  precise channel mapping
}).add;
)

// Play the synth
x = Synth(\simpleSine);
x.set(\freq, 880);
x.free; // Stop

SuperCollider getting Arduino Data

SerialPort.listDevices; // List available ports

p = SerialPort.new("/dev/ttyACM0", 9600);

// Read incoming data
r = Routine({
    var byte;
    loop {
        byte = p.read;
        // Map byte to frequency (example)
        {SinOsc.ar(byte * 10)}.play;
        0.01.wait;
    }
}).play;

Arduino code for SuperCollider

Same as for web audio api

const int sensorPin = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(sensorPin);
  Serial.write(map(sensorValue, 0, 1023, 0, 255));
  delay(10);
}

Project Ideas & Applications

  • Interactive sound installations
  • Gesture-controlled synthesizers
  • Real-time audio effects processors
  • Sensor-based music generators
  • Interactive performance tools