Lab 3: Sensors and Physical Interface Design

The goal of this lab is to control Faust synthesizers with sensors connected to the Teensy. Various mapping strategies are also introduced.

Electronic Basics

Sensors and Teensy Basics

void setup() {
  Serial.begin(9600); // initializing serial port
}

void loop() {
  int sensorValue = analogRead(A0); // retrieving sensor value on Analog pin 0
  Serial.println(sensorValue);
  delay(30); // wait for 30ms
}
#include <Audio.h>
#include "FaustSawtooth.h"

FaustSawtooth faustSawtooth;
AudioOutputI2S out;
AudioControlSGTL5000 audioShield;
AudioConnection patchCord0(faustSawtooth,0,out,0);
AudioConnection patchCord1(faustSawtooth,0,out,1);

void setup() {
  AudioMemory(2);
  audioShield.enable();
  audioShield.volume(0.1);
}

void loop() {
  int sensorValue = analogRead(A0);
  float frequency = sensorValue + 50;
  faustSawtooth.setParamValue("freq",frequency);
}

Exercise: Controlling Multiple Synth Parameters

Discrete Events

Looping Through Notes

The goal of this section is to make an instrument with the following behavior:

First, add a button to your circuit. The buttons provided in your kits have 4 pins (2 sets of 2 pins connected to each other). Place the button as follows on the breadboard:

Then connect one of the 2 pins to power and the other pin to the digital input 0 of your Teensy. You should add a pull-down resistor to this pin too. Note that an analog input could have been used as in the previous examples, but since we’re retrieving a discrete signal it doesn’t really make sense.

import("stdfaust.lib");
freq = hslider("pitch",60,0,127,1) : ba.midikey2hz;
gate = button("gate");
process = os.sawtooth(freq)*gate;
#include <Audio.h>
#include "FaustSawtooth.h"

FaustSawtooth faustSawtooth;
AudioOutputI2S out;
AudioControlSGTL5000 audioShield;
AudioConnection patchCord0(faustSawtooth,0,out,0);
AudioConnection patchCord1(faustSawtooth,0,out,1);

int notes[] = {60,60,60,62,64,62,60,64,62,62,60}; // the melody
int cnt = 0; // index to loop through the notes
bool change = true; // did the note status changed?
bool on = false; // what is the note status?

void setup() {
  pinMode(0, INPUT); // configuring digital pin 0 as an input
  AudioMemory(2);
  audioShield.enable();
  audioShield.volume(0.1);
}

void loop() {
  if (digitalRead(0)) { // button is pressed
    if(!on) change = true; // did the status of the button changed
    on = true;
  } 
  else {
    if(on) change = true; // did the status of the button change?
    on = false;
  }

  if(change){ // if the status of the button changed
    if(on){ // if the button is pressed
      faustSawtooth.setParamValue("gate",1);
      faustSawtooth.setParamValue("pitch",notes[cnt%11]);
      cnt++; // next note
    }
    else{
      faustSawtooth.setParamValue("gate",0);
    }
    change = false; // status changed
  }
}

Notes are saved in an integer array as MIDI note numbers. When digital pin 0 receives a signal, the on variable is set to true and vice versa. The change variable is used to make sure that we only send messages when necessary.

Exercise

Continuous parameters can be controlled in parallel of this button/looping mechanism. Add a lowpass filter to your sawtooth oscillator, e.g.,:

process = os.sawtooth(freq)*gate : fi.resonlp(ctFreq,5,0.5);

and control the value of the cutoff frequency with the photoresistor on your circuit. Spend some time thinking about the mapping of the cutoff frequency: what works best in this context?

Hint:

The min and max functions are often useful when mapping a sound synthesis parameter to a sensor. For instance, you probably noticed that the photoresistor doesn’t “fully exploit” the 0-1023 range offered by the 10bits converter. A common practice is to normalize the sensor output so that you can fully take advantage of its range. For example, say that you see that the output range of your sensor is 500-900, you could normalize its output with something like:

normSens = min(1023,max(0,sens - 550)*3.3);

Here subtracting 550 to the raw sensor output (sens) and then comparing that to 0 with max will make sure that the lowest value of the sensor is 0. Multiplying the result of this operation by 3.3 and comparing the result to 1023 with min will ensure that the highest value of the sensor is 1023.

Assignment (Due on Jan. 29, 2020)

Submissions

  • Raul Altosaar
  • Monica Ngozi Anuforo
  • Noah Louis Bailyn
  • Andrea Baldioceda
  • Noah Nathan Berrie
  • Hannah Lee Choi
  • Engin Daglik
  • Richard Chaffin Givhan
  • David Mendoza
  • Nolan Ashvin Miranda
  • John Mistele
  • Mike Robert Mulshine
  • Jeremy Thomas Raven
  • Samantha Elinon Silverstein
  • Kathlynn Marie Simotas
  • Jan Stoltenberg
  • Kangrui Xue