• Junkbox Junkie Blog
  • About
  • Contact
  • Arty Schematics
  • Audio Samples
  The Junkbox Junkie Official Home

4): Random thoughts I

8/2/2015

0 Comments

 
Now that we have a test unit – an Arduino Uno Rev 3 clone with the Arty Bridge MIDI out – we can start looking at what makes aleatory tick. As we discussed, the word aleatory comes from the Latin for 'dice player'. So, we need to teach the Arduino (or any computer that will generate music) how to throw the dice.

Unfortunately, that's a bit more difficult than one might imagine.

Simply put, a random number sequence is supposed to be a group of numbers in which the order is not predictable. So a sequence of, say {2,4,6,8,10} would not be considered as being random since there is a common difference of 2 between each number. The set {1,8,13,14,34,99} is more than likely a random set of numbers. However, it could be that there is a relationship: it just may not be readily apparent. That is, by and large, one of the problems with randomness. When you don't want it, it rears its ugly head. When you want it, it makes itself scarce. I'm not exactly a math whiz, but I'm pretty sure there's a point at which a sequence of numbers can be considered as 'random enough'.

In our case, we have to settle with what the Arduino has, which is actually a pseudo-random number generator. For our purposes, it is 'random enough'. And if it isn't, we will pretend it is.

One aspect of the pseudo-random number is called the random seed number. We're going to follow the simple suggestion found on the Arduino reference pages and use an initializer based on looking at the value of an unconnected analog port.

I've added some things to the previous test_MIDI code. First, a global variable called noteVal, to hold our randomly chosen MIDI note. Secondly, in setup(), a call to seed the random number generator. Finally, the loop() code now sends out random notes with a random loudness at a random interval over the MIDI cable, rather than the linear 0 to 127 notes at a constant velocity (loudness) and tempo. You can spend half a day playing with all these random settings and get some output that almost entirely but not quite exactly sound like something that may approach being a distant cousin to something akin to a musical melody.

Picture
/*
+-------------------------------------------------+
| Arty The Aleatoric Arduino: random gaze 0       |
| Part I of the Arty series                       |
| Perambulations in the Field                     |
|                   of Artifical Music Generation |
| Brought to you by "Junkbox Junkie, the Musical" |
+-------------------------------------------------+
Copyright © 2015 by Bill L. Behrendt

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include <stdio.h>
#include <SoftwareSerial.h>

//software serial port pins for MIDI
#define MIDI_OUT 11
#define MIDI_IN 12 //unused

//MIDI cmd
#define CMD_NOTE_ON 0x90 //channel 1
#define CMD_NOTE_OFF 0x80 //channel 1

//global variables
SoftwareSerial MIDI(MIDI_IN, MIDI_OUT); // RX, TX
byte noteVal;

void flashWorkLED(char start) {
  if (start == 1) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(250);
    digitalWrite(LED_BUILTIN, LOW);
    delay(250);
  }
  for (char tm = 0; tm < 5; tm++) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(125);
    digitalWrite(LED_BUILTIN, LOW);
    delay(75);
  }
}

void sendMIDI(unsigned char cmd, unsigned char data1, unsigned char data2)
{
  MIDI.write(cmd);  //note on or note off
  MIDI.write(data1); //MIDI note 0-127
  MIDI.write(data2); //velocity (loudness) of note
}

void audioBootTest(void) {
  sendMIDI(CMD_NOTE_ON,36,64);
  sendMIDI(CMD_NOTE_ON,60,64);
  sendMIDI(CMD_NOTE_ON,64,64);
  sendMIDI(CMD_NOTE_ON,67,64);
  sendMIDI(CMD_NOTE_ON,72,64);
  flashWorkLED(1);
  delay(1000);
  flashWorkLED(0);
  sendMIDI(CMD_NOTE_OFF,36,64);
  sendMIDI(CMD_NOTE_OFF,60,64);
  sendMIDI(CMD_NOTE_OFF,64,64);
  sendMIDI(CMD_NOTE_OFF,67,64);
  sendMIDI(CMD_NOTE_OFF,72,64);  
}

void allNotesOff(void) {
   for (int anoff = 0; anoff < 16; anoff++) {
    sendMIDI(0xB0 + anoff, 0x7B, 0x00);
  } 
}

void setup() {
  Serial.begin(115200); // for looking at debug things
  MIDI.begin(31250); // our software serial MIDI connection
  //turn all notes off, all channels
  allNotesOff();
  audioBootTest();
  //get a random seed from an unattached analog pin
  randomSeed(analogRead(0));
}

void loop() {
  //trying out the Arduino pseudo-random nature
  noteVal=random(12,96); //change range to limit spread of notes do things like random(30,72)%random(60,96)
  Serial.println(noteVal);
  sendMIDI(CMD_NOTE_ON,noteVal,32+random(64)); // or use random(32,96)
  //delay(130+random(130));  //a tempo of sorts or use random(130,260)
  delay(random(130,260)); //another way to limit the tempo variation
  sendMIDI(CMD_NOTE_OFF,noteVal,64);
}
It's worth mentioning that the sound source of your destination MIDI device may not handle all notes from 0 to 127. So, in some cases, you may experience 'drop out' which means that you sent a command to turn on a note that your sound source doesn't support. Just write it off as a musical rest. Generally, you can use random(36,96) which I would think is a range supported by most MIDI devices of the last 100 years or so.

I am a proponent of modularizing code whenever possible, so I am going to present a second code listing. This will also be a framework for the future as we discover more and more ways to make Arty sing. The main change is adding a function called getARand(). This function will replace having to type in random(0,127) and allow you to experiment more freely with randomness of your own choosing. I've added three random functions and used #defines to name them RND_0 through RND_2. I've added a global variable array to hold a previous value for each random function. So, if you add your own RND_X functions, you'll also need to add a #define entry and a value in the initialized array for each addition.

The parameters passed to getARand() are a required 'rType' – which is where the #defined names come in handy. There are also two optional parameters to allow any of the functions added to be more flexible. So, getARand(RND_0), getARand(RND_0,36) and getARand(RND_0,36,96) all work because the RND_0 function is created with 'random(loVal, hiVal)'. So, in the first case, the end result of getARand(RND_0) is the same as random(0,127), because the default values are used when no values are supplied. getARand(RND_0,36,96), however, is the same as random(36,96) because both of the optional values were supplied. Finally, getARand(RND_0,36) is the same as random(36,127), with the supplied 36 overriding the default 0. Sadly, getARand(RND_0,,55) will not work and will generate an 'expected primary-expression' compiler error. The rule being, you must supply optional values from the first to the last (from left to right) without skipping over any of them.
/*
+-------------------------------------------------+
| Arty The Aleatoric Arduino: random gaze 1       |
| Part I of the Arty series                       |
| Perambulations in the Field                     |
|                   of Artifical Music Generation |
| Brought to you by "Junkbox Junkie, the Musical" |
+-------------------------------------------------+
Copyright © 2015 by Bill L. Behrendt

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include <stdio.h>
#include <SoftwareSerial.h>

//software serial port pins for MIDI
#define MIDI_OUT 11
#define MIDI_IN 12 //unused

//MIDI cmd
#define CMD_NOTE_ON 0x90 //channel 1
#define CMD_NOTE_OFF 0x80 //channel 1

//random types
#define RND_0 0
#define RND_1 1
#define RND_2 2

//global variables
SoftwareSerial MIDI(MIDI_IN, MIDI_OUT); // RX, TX
byte prevVal[] = {72, 60, 96}; // for use in getARand() function
byte noteVal;

byte getARand(byte rType, byte loVal=0, byte hiVal=127) {
  //get random stuffs
  byte retVal = 0;

  switch (rType) {
    case RND_0:
      retVal = random(loVal,hiVal);
      break;
    case RND_1:
      retVal = random(loVal,hiVal)+prevVal[rType];
      break;
    case RND_2:
      retVal = random(loVal,hiVal)%(prevVal[rType]*3);
      break;
    default:
      retVal=random(0,127);
  }
  prevVal[rType] = (retVal & 127);
  return prevVal[rType];
}
//----- end random functions

void flashWorkLED(char start) {
  if (start == 1) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(250);
    digitalWrite(LED_BUILTIN, LOW);
    delay(250);
  }
  for (char tm = 0; tm < 5; tm++) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(125);
    digitalWrite(LED_BUILTIN, LOW);
    delay(75);
  }
}

void sendMIDI(unsigned char cmd, unsigned char data1, unsigned char data2)
{
  MIDI.write(cmd);  //note on or note off
  MIDI.write(data1); //MIDI note 0-127
  MIDI.write(data2); //velocity (loudness) of note
}

void audioBootTest(void) {
  sendMIDI(CMD_NOTE_ON,36,64);
  sendMIDI(CMD_NOTE_ON,60,64);
  sendMIDI(CMD_NOTE_ON,64,64);
  sendMIDI(CMD_NOTE_ON,67,64);
  sendMIDI(CMD_NOTE_ON,72,64);
  flashWorkLED(1);
  delay(1000);
  flashWorkLED(0);
  sendMIDI(CMD_NOTE_OFF,36,64);
  sendMIDI(CMD_NOTE_OFF,60,64);
  sendMIDI(CMD_NOTE_OFF,64,64);
  sendMIDI(CMD_NOTE_OFF,67,64);
  sendMIDI(CMD_NOTE_OFF,72,64);  
}

void allNotesOff(void) {
   for (int anoff = 0; anoff < 16; anoff++) {
    sendMIDI(0xB0 + anoff, 0x7B, 0x00);
  } 
}

void setup() {
  Serial.begin(115200); // for looking at debug things
  MIDI.begin(31250); // our software serial MIDI connection
  //turn all notes off, all channels
  allNotesOff();
  audioBootTest();
  //get a random seed from an unattached analog pin
  randomSeed(analogRead(0));
}

void loop() {
  //rather than changing the random functions here, use getARand()
  // RND_0, RND_1 and RND_2
  noteVal=getARand(RND_2);
  sendMIDI(CMD_NOTE_ON,noteVal,64);
  delay(200);  //a tempo of sorts
  sendMIDI(CMD_NOTE_OFF,noteVal,64);
}
There are a wealth of things you can do, aside from adding your own functions. Initially, it might help to get a feel for the random numbers by listening to the differences in the default sounds. Do this by simply changing the parameter to getARand(). First, noteVal=getARand(RND_0); then noteVal=getARand(RND_1); and finally noteVal=getARand(RND_2);.

We will be adding other functions soon. In the meantime, here are a few ideas to play with.
noteVal = getARand(RND_0,12,36)+getARand(RND_1,36,60);

Recursive calls:
noteVal=getARand(RND_0, getARand(RND_1), getARand(RND_2));

Change the velocity (loudness):
sendMIDI(CMD_NOTE_ON,noteVal,64+getARand(RND_2, 0, 32));
sendMIDI(CMD_NOTE_ON,noteVal,getARand(RND_0, 64, 96));


Change the tempo / interval between notes:
delay(getARand(RND_0) + 150);

Have fun until next time! :)
Picture
Picture
Picture
Copyright © 2015 by Bill L. Behrendt
Copyright © 2015 by Bill L. Behrendt
0 Comments



Leave a Reply.

    Picture
    The Dusty And Rusty Show!
    ISLA Instruments

    Author

    Junkbox Junkie is an electronics and computer hobbyist who delights in reuse of electronics things.
    Currently working on Arty, The Aleatoric Arduino -- a project / quest to create a music composing computer.

    Copyright © 2015 by Bill L. Behrendt

    Artificial Music
    Artificial Music
    SOUNDCLOUD

    Archives

    June 2020
    January 2018
    August 2017
    January 2016
    August 2015
    July 2015

    Categories

    All
    Aleatory
    Arduino
    Artificialmusic
    Music
    Random Music

    RSS Feed

Powered by Create your own unique website with customizable templates.