User:Ssstephen/take-the-entrain

From XPUB & Lens-Based wiki

this room for sound residency will be an exploration of tying digital connections and using them as an instrument. connexion used to be spelled with an x which shows the origin of the word: a binding or joining together. opening a network connexion creates a string of data which can and will be plucked. a work in the form of a net: strings interwoven and interconnetted. starting from short strings inside a single computer, over the two weeks this network will expand to cover the entire universe.

This is a two week residency in the Willem de Kooning Academy's Room for Sound, from 16th to 27th January 2023. I will be experimenting with networked music, in particular I plan to use some ESP32 boards and a Raspberry Pi to send and receive RTP-MIDI over LAN and hopefully WAN, and to translate this MIDI data to and from audio (via microphones, sensors, buzzers, speakers, etc). I would like to get other people involved in this process as well as getting the machines to interact: the machines could be not just musicians but also instruments.

Pseudocode

Get the computers to entrain to eachother dynamically, clap with eachother

While
    Countup++ per ms
    If(hearbeep) or (countup= random ~ 200ms)
        If(countup >40ms)
            Wait(countup ms)
            Sendbeep
            Countup=0

Day 1

Get the computers to sing

Today I am working with two Seeed Studios Xiao ESP32-C3 and some buzzers. Writing Arduino (C++) scripts for them to make beeps and also blinkenlights because they're fun.

/**
 * Singing 
 *
 * Plays predefined tones in a predefined order from a buzzer on pin D9.
 * Also flashes an LED on pin D8 just for fun.
 */
#include "Arduino.h"
// #include "pitches.h"

// Define some pitches of beeps, a basic time unit, a status
int dt1=200;
int dt2=90;
int dt3=360;
int dt4=400;
int duration=50;
int ledstatus=0;

void beep(int tone1,int length) {
  //this part switches the LED status
  if(ledstatus==0){
    digitalWrite(D8,HIGH);
    ledstatus=1;
  }else{
    digitalWrite(D8,LOW);
    ledstatus=0;
  }
  //This part pulses the buzzer.
   for (int tonecounter=1;tonecounter<=length;tonecounter=tonecounter+1){
     analogWrite(A0,127);
     delayMicroseconds(tone1);
     analogWrite(A0,0);
     delayMicroseconds(tone1);
   }
  //Or you could for more exact tones and lengths but no analog
  //tone(D9, tone1, length);
}

void setup()
{
  // initialize LED digital pin as an output.
  pinMode(D8, OUTPUT);
  pinMode(A0, OUTPUT);
}

void loop()
{
  //A sequence of buzzes
  beep(dt1,duration*2);
  beep(dt2,duration);
  beep(dt1,duration*2);
  beep(dt2,duration*2);
  beep(dt1,duration);
  beep(dt2,duration*4);
  beep(dt1,duration*2);
  beep(dt2,duration);
  beep(dt1,duration*2);
  beep(dt3,duration);
  beep(dt1,duration*2);
  beep(dt4,duration*4);
}

Someone else sending data from arduino xto ChucK

Get the computers to clap

Some tweaks to that code (tweaks only below) gave me two buzzers that beep at predefined tempi (metronomes I guess). They can make nice polyrhythms together. Timing is tricky!

int notelength=20;
int bpm = 100;
unsigned long delay1=(60000000/bpm) - (1000 * notelength);

void clap(int tone1,int bpm) {
  tone(A0, tone1, notelength);
  delayMicroseconds(delay1);
}

void loop()
{
  //A clapping speed
  clap(dt3,180);
}

How do you embed audio on the wiki? Here's a link instead.

Day 2

Get the computers to listen

To sound or to digital signals? If they're digital I probably need them to listen more generally to wifi or bluetooth first. But I dont have any microphones for the C3's today so if its audio input I'll need to use another board.

The ESP32-A1S: Audio Inputs

How to work this board. First I am following the instructions here. Installing ESP-IDF and ESP-ADF. (IoT and Audio Development Frameworks). Actually I'm going to give up on this and use Arduino. I found a video tutorial and a library that look good. Hmm this board is actually quite tricky to get going. I have installed another library to work with this exact board but failing to upload after compile (A fatal error occurred: Could not open COM70, the port doesn't exist). I have been experimenting with the platformio.ini file below but still no luck. I think I'll give up on this part for today.

; PlatformIO Project Configuration File for arduino-audiokit-hal
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps = https://github.com/pschatzmann/arduino-audiokit-hal

	c:\Users\user\Downloads\arduino-audio-tools-main.zip
lib_ldf_mode = deep+
build_flags = -DCORE_DEBUG_LEVEL=5 -DAUDIOKIT_BOARD=5 
monitor_speed = 115200

(Also this serial plotter looks cool)

Explore timbre

I didnt expect to be so interested in the tone of the buzzers but they are very cool. The digitalWrite function (and analogWrite, and delay) seem interesting to explore further to see what happens. Can you keep a constant pitch and change tone to explore what is possible? Two first attempts at playing with tone by varying the pulse length and gap:

void beepdown(int tone1,int length) {
  //This part pulses the buzzer.
  for (int tonecounter=1;tonecounter<=length;tonecounter=tonecounter+1){
    analogWrite(A0,250);
    delayMicroseconds(tone1*((length-tonecounter+1)/10));
    analogWrite(A0,0);
    delayMicroseconds(tone1*(tonecounter/10));
  }
}
void beepup(int tone1,int length) {
  //This part pulses the buzzer.
  for (int tonecounter=1;tonecounter<=length;tonecounter=tonecounter+1){
    analogWrite(A0,250);
    delayMicroseconds(tone1*(tonecounter/10));
    analogWrite(A0,0);
    delayMicroseconds(tone1*((length-tonecounter+1)/10));
  }
}

They came out very squealy and uncomfortable sounding in the recording, but interesting tones for sure.

Listen here

Day 3

ESP32C3 Listening

Ok back to the ESP32-C3, today I want to get WiFi or Bluetooth working on these, maybe sending MIDI data over these channels, bluetooth first because I'm scared of the network here (although the ESP32 could be a wifi access point which may be interesting too). I'm kinda following this tutorial. First I copied a bluetooth scanner that prints to the serial port. Success! Then a different script that sets it as a bluetooth server, and I managed to send some data (text) from my phone. Now I'll tweak this and see if the ESP will play a sound when my phone sends data. Yesssss it does indeed.

/**
 * Sing for me 
 *
 * Plays tones from a buzzer on pin A0 when bluetooth commands are received.
 * Also flashes an LED on pin D8 just for fun.
 */

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
 
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
 
#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

// Define some pitches of beeps, a basic time unit, a status
int dt1=400;
int dt2=360;
int dt3=480;
int dt4=400;
int dt5=960;
int dt6=200;
int duration=50;
int ledstatus=0;
int notelength=14;
int bpm = 240;
unsigned long delay1=(60000000/bpm) - (1000 * notelength); 
 
 
// functions for making sounds

void ledSwitch(){
  //this part switches the LED status
  if(ledstatus==0){
    digitalWrite(D8,HIGH);
    ledstatus=1;
  }else{
    digitalWrite(D8,LOW);
    ledstatus=0;
  }
}

void beep(int tone1,int length) {
  ledSwitch();
  //This part pulses the buzzer.
  for (int tonecounter=1;tonecounter<=length;tonecounter=tonecounter+1){
    analogWrite(A0,250);
    delayMicroseconds(tone1);
    analogWrite(A0,0);
    delayMicroseconds(tone1);
  }
}

void clap(int tone1) {
  tone(A0, tone1, notelength);
  delayMicroseconds(delay1);
}

void beepsweep(int tone1,int length, int direction) {
  ledSwitch();
  //This part pulses the buzzer.
  for (int tonecounter=1;tonecounter<=length;tonecounter=tonecounter+1){
    analogWrite(A0,250);
    delayMicroseconds(tone1*(abs((1-direction)*length-tonecounter+1)/10));
    analogWrite(A0,0);
    delayMicroseconds(tone1*(tonecounter/10));
    delayMicroseconds(tone1*(abs(direction*length-tonecounter+1)/10));
  }
  ledSwitch();
}

// Class for BLE interaction

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();
 
      if (value.length() > 0) {
        Serial.println("*********");
        for (int i = 0; i < value.length(); i++)
          Serial.print(value[i]);
        Serial.println();
        Serial.println("*********");

        beepsweep(stoi(value),duration*2, 1);
      }
    }
};


 
void setup() {
  Serial.begin(115200);

  // initialize LED digital pin as an output, and buzzer analog pin.
  pinMode(D8, OUTPUT);
  pinMode(A0, OUTPUT);
 
  BLEDevice::init("Bzzzzzzzt");
  BLEServer *pServer = BLEDevice::createServer();
 
  BLEService *pService = pServer->createService(SERVICE_UUID);
 
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );
 
  pCharacteristic->setCallbacks(new MyCallbacks());
 
  pCharacteristic->setValue("Hello World");
  pService->start();
 
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}
 
void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
}