User:Ssstephen/take-the-entrain: Difference between revisions
(→Day 5) |
|||
Line 332: | Line 332: | ||
==Day 5== | ==Day 5== | ||
[[File:Room-for-sound-week-1.jpg|frameless|right|alt=room-for-sound-week-1|room-for-sound-week-1]] | |||
===The day I get the ESP32 to send more interesting data=== | ===The day I get the ESP32 to send more interesting data=== |
Revision as of 20:43, 26 January 2023
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.
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); }
I also strapped a little flat buzzer to the window and sent bluetooth notes to it from across the building. Couldnt get it to work from the building next door though, is it because of the wind? Or the windowpane? Or the windy staircase? Anyway strapping it to the window is very interesting, these buzzers are really weak and the sound comes through so quietly I really like it.
So that works great for BT signals in and serial out but I need to introduce the two machines to eachother, so make a connection and send BLE messages.
Wifey
Tutorial I'm trying. So first I'm making one ESP32C3 a wifi access point (like a hotspot on a phone). It works and I can connect to it on my phone or laptop. Now I'll try to set up the other module to connect to this network.
Day 4
La La LAN
Today: connect ESP32-C3s directly to eachother. On Wifi. On bluetooth. Lets try WiFi first, still using yesterday's tutorial. Connecting to the other ESP32 network: all works good. I also set up the connecting chip to have a webserver that turns on an LED, and plays a buzzer.
Also managed to connect to eduroam. No cert needed here, just login credentials. So I can connect both ESPs to the eduroam wifi at the same time. I can ping them and have given them Wifi status LED's that flash if WiFi is connected. But I cant get a webserver running on eduroam hmmm. Maybe I should try to open a port, or maybe it wont be possible to use this network.
Now they need to have a little chat with eachother.
Day 5
The day I get the ESP32 to send more interesting data
This playlist gives me some information on how to MIDI on Arduino. But actually that is for MIDI over DIN, so maybe for a different day. This library does lots of MIDI stuff including MIDI over serial and BLE, and can later be expanded with this to do rtpMIDI.
Also tried MIDIUSB where I learnt that an ESP32 does not in fact have USB communication, rather a serial port going down a USB wire. Interessant.
First I'm getting the ESP32 to send MIDI over BLE, using this script and this BLE MIDI driver. The code below sends a 150bpm drum pattern over MIDI, while playing a melody itself on a buzzer. I really like how the synchronisation is all messed up, this is what I was hoping for. Next week the plan is to play with this effect some more and get it happeing on different networks. I am working with microsecond delays for the moment, but this is probably not the most accutate way to count time. Or maybe it is. The processor is 160Mhz so I'm not sure if I need to account for that, more likely I think it is to do with bluetooth latency (does bluetooth MIDI have strict timing? I doubt it).
#include <Arduino.h> #include <BLEMIDI_Transport.h> #include <hardware/BLEMIDI_ESP32.h> BLEMIDI_CREATE_INSTANCE("Bammm",MIDI); // Define some pitches of beeps, a basic time unit, a status int melody[16] = {400, 360, 480, 400, 960, 200, 400, 360, 480, 400, 960, 200, 400, 360, 480, 400}; int melodyPos = 0; int ledstatus=0; int tempo = 100000; //a 16th note in 150bpm // 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 clap(int tone1) { ledSwitch(); tone(A0, tone1, 100); delayMicroseconds(tempo-10000); ledSwitch(); } void setup() { // initialize LED digital pin as an output, and buzzer analog pin. pinMode(D8, OUTPUT); pinMode(A0, OUTPUT); MIDI.begin(10); } void loop() { for (int i =0; i<16; i++){ if((i%4==0)||(i==14)){ MIDI.sendNoteOn(36, 100, 10); MIDI.sendNoteOff(36, 0, 10); } MIDI.sendNoteOn(44, 100, 10); MIDI.sendNoteOff(44, 0, 10); if(i%3==0){ clap(melody[melodyPos%16]); melodyPos++; }else{ delayMicroseconds(tempo); } } }
Next week: rtpMIDI, receiving MIDI data to make sounds on the ESP, buttons, two ESPs communicating (via some sort of MIDI).
Day 6
The day that rtpMIDI finally happens
Today is the day. This library let me send MIDI on the internet. I also used this program to do rtpMIDI on windows. So I am sending rtpMIDI over a wifi port and tomorrow I should finally be able to build the program from the pseudocode at the start wooo.
Listen to it here.
#include <Arduino.h> #include <WiFi.h> #include <WiFiClient.h> #include <WiFiUdp.h> #define SerialMon Serial #include <AppleMIDI.h> // #-------------------------------eduroam stuff------------------ #include "esp_wpa2.h" //wpa2 library for connections to Enterprise networks //Identity for user with password related to his realm (organization) //Available option of anonymous identity for federation of RADIUS servers or 1st Domain RADIUS servers #define EAP_ANONYMOUS_IDENTITY "**********" //anonymous@example.com, or you can use also nickname@example.com #define EAP_IDENTITY "***********" //nickname@example.com, at some organizations should work nickname only without realm, but it is not recommended #define EAP_PASSWORD "********" //password for eduroam account //SSID NAME const char* ssid = "eduroam"; // eduroam SSID int ledstatus=0; void ledSwitch(){ //this part switches the LED status if(ledstatus==0){ digitalWrite(D8,HIGH); ledstatus=1; }else{ digitalWrite(D8,LOW); ledstatus=0; } } 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(); } unsigned long t0 = millis(); int8_t isConnected = 0; APPLEMIDI_CREATE_DEFAULTSESSION_INSTANCE(); // ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void setup() { AM_DBG_SETUP(115200); delay(3000); AM_DBG(F("Booting")); pinMode(D8, OUTPUT); pinMode(A0, OUTPUT); // Serial.begin(115200); Serial.print(F("Connecting to network: ")); Serial.println(ssid); WiFi.disconnect(true); //disconnect form wifi to set new wifi connection WiFi.mode(WIFI_STA); //init wifi mode WiFi.begin(ssid, WPA2_AUTH_PEAP, EAP_ANONYMOUS_IDENTITY, EAP_IDENTITY, EAP_PASSWORD); //without CERTIFICATE // while (WiFi.status() != WL_CONNECTED) { // delay(500); // Serial.print(F(".")); // } // Serial.println(""); // Serial.println(F("WiFi is connected!")); // Serial.println(F("IP address set: ")); // Serial.println(WiFi.localIP()); //print LAN IP // ledSwitch(); // WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500); AM_DBG(F("Establishing connection to WiFi..")); } AM_DBG(F("Connected to network")); ledSwitch(); AM_DBG(F("OK, now make sure you an rtpMIDI session that is Enabled")); AM_DBG(F("Add device named Arduino with Host"), WiFi.localIP(), "Port", AppleMIDI.getPort(), "(Name", AppleMIDI.getName(), ")"); AM_DBG(F("Select and then press the Connect button")); AM_DBG(F("Then open a MIDI listener and monitor incoming notes")); AM_DBG(F("Listen to incoming MIDI commands")); MIDI.begin(); AppleMIDI.setHandleConnected([](const APPLEMIDI_NAMESPACE::ssrc_t & ssrc, const char* name) { isConnected++; AM_DBG(F("Connected to session"), ssrc, name); }); AppleMIDI.setHandleDisconnected([](const APPLEMIDI_NAMESPACE::ssrc_t & ssrc) { isConnected--; AM_DBG(F("Disconnected"), ssrc); }); MIDI.setHandleNoteOn([](byte channel, byte note, byte velocity) { AM_DBG(F("NoteOn"), note); }); MIDI.setHandleNoteOff([](byte channel, byte note, byte velocity) { AM_DBG(F("NoteOff"), note); }); AM_DBG(F("Sending NoteOn/Off of note 45, every second")); } // ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void loop() { // Listen to incoming notes MIDI.read(); yield(); if (WiFi.status() == WL_CONNECTED) { delay(4000); Serial.println(""); Serial.println(F("WiFi is connected!")); Serial.println(F("IP address set: ")); Serial.println(WiFi.localIP()); //print LAN IP AM_DBG(F("Add device named Arduino with Host"), WiFi.localIP(), "Port", AppleMIDI.getPort(), "(Name", AppleMIDI.getName(), ")"); ledSwitch(); } // send a note every second // (dont cáll delay(1000) as it will stall the pipeline) if ((isConnected > 0) && (millis() - t0) > 1000) { t0 = millis(); byte note = 45; byte velocity = 55; byte channel = 1; Serial.println(F("MIDI Sending")); MIDI.sendNoteOn(note, velocity, channel); MIDI.sendNoteOff(note, velocity, channel); beepsweep(600,120,1); } }
And I also received MIDI on the ESPs
That was pretty straightforward.
Day 7
Latent Rhythms
Today I sent rtpMIDI over the internet from one ESP32 to another, via some routing on my computer. The code below is one of a pair of programs that plays a beep after it receives a MIDI note, and sends a MIDI note back. If it doesnt hear a note at all for 2000ms, it beeps anyway. The latency was way more irregular than I expected making some really interesting rhythms. You can hear the network, and the network itself is making the music interesting not the individual performers.
Other ways to use this
What happens if there are more than two devices
What else can the MIDI control
What happens if replies send in the next MIDI channel up, but resets always send in channel one.
Can the 2000ms reset be adapted: trusting the other performers more and more if the latency is low.
Can you send CV gate from MIDI in using these ESP32s
What happens if a modular synth gets involved
Can it work on WAN as well as LAN
#include <Arduino.h> #include <WiFi.h> #include <WiFiClient.h> #include <WiFiUdp.h> #define SerialMon Serial #include <AppleMIDI.h> // #-------------------------------eduroam stuff------------------ #include "esp_wpa2.h" //wpa2 library for connections to Enterprise networks //Identity for user with password related to his realm (organization) #define EAP_ANONYMOUS_IDENTITY "????????????????" //anonymous@example.com, or you can use also nickname@example.com #define EAP_IDENTITY "!!!!!!!!!!!!!!" //nickname@example.com, at some organizations should work nickname only without realm, but it is not recommended #define EAP_PASSWORD "££££££££££££" //password for eduroam account const char* ssid = "$$$$$$$$$$$"; // eduroam SSID // Other variables int ledstatus=0; int melodyPos=0; int melody[16] = {63, 66, 65, 68, 65, 62, 61, 63, 65, 63, 57, 61, 63, 66, 65, 62}; float a = 660; unsigned long t0 = millis(); int8_t isConnected = 0; APPLEMIDI_CREATE_DEFAULTSESSION_INSTANCE(); // Functions // #------------------------------------- void ledSwitch(){ //this part switches the LED status if(ledstatus==0){ digitalWrite(D8,HIGH); ledstatus=1; }else{ digitalWrite(D8,LOW); ledstatus=0; } } void beepsweep(int tone1,int length, int direction) { long delay = (500000/tone1); ledSwitch(); AM_DBG(F("Delay in microseconds is "), delay); //This part pulses the buzzer. for (int tonecounter=1;tonecounter<=length;tonecounter=tonecounter+1){ analogWrite(A0,250); delayMicroseconds(delay); analogWrite(A0,0); delayMicroseconds(delay); } ledSwitch(); } // Running stuff // #------------------------------------------------------------------------- void setup() { AM_DBG_SETUP(115200); delay(3000); AM_DBG(F("Booting")); pinMode(D8, OUTPUT); pinMode(A0, OUTPUT); // Serial.begin(115200); Serial.print(F("Connecting to network: ")); Serial.println(ssid); WiFi.disconnect(true); //disconnect form wifi to set new wifi connection WiFi.mode(WIFI_STA); //init wifi mode WiFi.begin(ssid, WPA2_AUTH_PEAP, EAP_ANONYMOUS_IDENTITY, EAP_IDENTITY, EAP_PASSWORD); //without CERTIFICATE while (WiFi.status() != WL_CONNECTED) { delay(500); AM_DBG(F("Establishing connection to WiFi..")); } AM_DBG(F("Connected to network")); ledSwitch(); AM_DBG(F("OK, now make sure you an rtpMIDI session that is Enabled")); AM_DBG(F("Add device named Arduino with Host"), WiFi.localIP(), "Port", AppleMIDI.getPort(), "(Name", AppleMIDI.getName(), ")"); AM_DBG(F("Select and then press the Connect button")); AM_DBG(F("Then open a MIDI listener and monitor incoming notes")); AM_DBG(F("Listen to incoming MIDI commands")); MIDI.begin(); AppleMIDI.setHandleConnected([](const APPLEMIDI_NAMESPACE::ssrc_t & ssrc, const char* name) { isConnected++; AM_DBG(F("Connected to session"), ssrc, name); }); AppleMIDI.setHandleDisconnected([](const APPLEMIDI_NAMESPACE::ssrc_t & ssrc) { isConnected--; AM_DBG(F("Disconnected"), ssrc); }); MIDI.setHandleNoteOn([](byte channel, byte note, byte velocity) { if (channel == 3){ t0 = millis(); byte note = melody[melodyPos%16]; byte velocity = rand() % 63 + 63; byte channel = 1; Serial.println(F("MIDI Received! Now sending")); MIDI.sendNoteOn(note, velocity, channel); beepsweep((a / 32) * pow(2, ((note - 9) / 12.0)),100,1); MIDI.sendNoteOff(note, velocity, channel); melodyPos++; } }); } // ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void loop() { // Listen to incoming notes MIDI.read(); yield(); if (WiFi.status() == WL_CONNECTED) { ledSwitch(); } // send a note every second // (dont call delay(1000) as it will stall the pipeline) if ((isConnected > 0) && (millis() - t0) > 2000) { t0 = millis(); byte note = melody[melodyPos%16]; byte velocity = rand() % 63 + 63; byte channel = 1; MIDI.sendNoteOn(note, velocity, channel); beepsweep((a / 32) * pow(2, ((note - 9) / 12.0)),60,1); MIDI.sendNoteOff(note, velocity, channel); melodyPos++; } }
Day 8
Day eight was a holy day of rest
Day 9
Consonance and Dissonance
One computer wants to play more consonant intervals, and the other one wants to play more dissonant intervals. They tell eachother what they played last over rtpMIDI. C++ is a pain in the hoop everything is so complicated with it. The buzzers are attempting to play the correct notes, and the MIDI is also driving two software synths on my computer.
Then I added a little rand()omness for whether the new note is above or below the previous one. Remember randomness on a computer is not real, each ESP is deciding which notes to play through the knowledge of consonance and dissonance I gave them and their pseudorandom number generation that was programmed by someone else. They are deciding when to play based on each other, some limits set by me, and the latency created by the network.
byte intervals[7] = {0,5,2,4,3,6,1}; //this is half an octave of intervals, in order of consonance byte lastnote = 63; //This is a function that plays a (roughly) more dissonant note than the current interval byte dissonate(byte note, byte lastnote){ AM_DBG(F("The old notes were: "), note, lastnote); int currentInterval = min(abs(note%12 - lastnote%12), abs(lastnote%12 - note%12)); AM_DBG(F("The old interval is: "), currentInterval); if (currentInterval == 1){ AM_DBG(F("The new note is also: "), lastnote); return lastnote; } for (int i=0; i<7; i++) { if (currentInterval == intervals[i]) { int sign = random() & 1 ? 1 : -1; byte newnote = note + (sign * intervals[i+1]); AM_DBG(F("The new interval is: "), intervals[i+1]); AM_DBG(F("The new note is: "), newnote); return newnote; break; } } }
//This is a function that plays a (roughly) more consonant note than the current interval byte consonate(byte note, byte lastnote){ AM_DBG(F("The old notes were: "), note, lastnote); int currentInterval = min(abs(note%12 - lastnote%12), abs(lastnote%12 - note%12)); AM_DBG(F("The old interval is: "), currentInterval); if (currentInterval == 0){ AM_DBG(F("The new note is also: "), lastnote); return lastnote; } for (int i=0; i<7; i++) { if (currentInterval == intervals[i]) { int sign = random() & 1 ? 1 : -1; byte newnote = note + (sign * intervals[i-1]); AM_DBG(F("The new interval is: "), intervals[i-1]); AM_DBG(F("The new note is: "), newnote); return newnote; break; } } }