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

8).  ARTY GOES INTERACTIVE

8/24/2015

1 Comment

 
Picture
One of the nice things about using an Arduino (or clone) is that, not only can you reprogram at will, you can add circuitry, as well. In this episode, I'd like to discuss making the “random gaze final” code into an interactive aleatory generator.

But first, the hardware. This can be bread-boarded or put into a fine walnut and bronze case – your choice is unlimited. I, being the Junkbox Junkie, decided to put my interactive control panel into what I call “The Seedy CD Case”. I know, I know. Sounds like a detective novel...

At any rate, I used an old cylindrical (empty) CD case and added:
  • 6 potentiometers (variable resistors)
  • 1 SPDT (run / stop) slide switch
  • 1 bi-color LED run / stop indicator (one could use two LEDs, if need be)
  • a handful of wire, solder, etc.

It uses the Arduino's analog inputs A0 – A5 and three digital GPIO lines; one input for the run/stop switch and 2 outputs for the LED indicator.

~~~Safety!~~~
As I've said before, if you know your way around a soldering iron and electronics, great. If not, please consult with someone who does. This isn't fun if you get damaged in the process!
~~~Safety!~~~

The schematic is on the Arty Schematics page. It is pretty straightforward. I managed to wire the potentiometers 'backwards' so that increasing values are obtained by moving the knob counter clockwise. I caught the goof, but then decided to keep it that way just to be different. You may do whatever you choose.

Some changes to the code need to happen to accommodate the use of six knobs and a switch. The interactive code is facilitated by using constants instead of #defines. I don't want to spawn any age-old C programming disagreements. You can find arguments on either side. Either way gets the job done, especially in the Arduino. These define our GPIO and analog port numbers for the 6 knobs and the red and green sides of the LED. It also provides constants for the three ways we can coerce the 0 to 1023 value range of the analog inputs down to our usable range of 0 to 127. More on that in just a bit.

The 'mapping' of the physical knobs can be a sticky point. In my case, I organized the six knobs in clock-wise order around the Seedy Case. Keeping with the analog port numbers, the lower left knob is knob0 and is connected to A0. Next, going clock-wise, knob1 is attached to A1. Finally, the sixth knob is knob5, attached to A5. This helps keep it all straight in my configuration. This is also flexible, because you can re-map which analog port goes to which knob, if you need to. As it stands, now, iKnobs[X] is filled by reading the analog port using the knobX constant, which in my system is connected to physical analog port AX (where X is 0 through 5).  


Picture
Whatever the values of the knobs are, when we capture them, we will store them in the iKnobs[] array. So, my lower left knob is iKnobs[0] and the lower right is iKnobs[5] and I can now pick and choose which knob I want to use for whatever.

One of the possibilities is using the knobs to set the range of our random functions. I've modified the getARand function by adding an optional 'switch' to the arguments list. interAct will be false by default, so using x=getARand(rType); will operate as it has in the past. A slight code change will be needed for cases where we used something like x=getARand(rType, value) or x=getARand(rType,loValue, hiValue); in that the interAct parameter must now be supplied as 'false'. So, they will have to be changed to x=getARand(rType, false, value) or x=getARand(rType, false, loValue, hiValue); respectively.

Interaction can be 'hard-coded', as I show in the RND_GAUSS, RND_GAUSS2, RND_SIN and RND_VOSSPREV cases in getARand(). Use this method if you are locked in to always using that knob for that function when interAct is true.

Another way to do is, with interAct being false, is to pass the knob values into the getARand() function as the loVal and hiVal arguments: x=getARand(RND_VOSSF,false,iKnobs[2],iKnobs[3]); for instance. I was shooting for maximum flexibility here, since there are so many ways to approach this whole aleatoric business.

In support of the run/stop switch and the LEDs used as running status indicators, a new function called setILED() is available. It has a default argument which is overridden at startup ('reboot') of the Arduino. Since I most deviously selected two PWM lines (digital GPIO 5 & 6) for the LED signals, this startup code will turn my bi-color LED orange if the run/stop switch is in run mode at startup. It does this using the analogWrite() function built-in to the Arduino language. Otherwise, if the Seedy Case is in run mode, the LED is green (and can be made to flicker, if you'd like). When I put it in stop mode, the LED is red.

The updateKnobs() function is what we use to grab the analog values of the knobs, and scale them to a value we can use. The first step, of course, is to read the knob values and store them in the iKnobs[] array. Then we can do one of three scaling operations.

updateKnobs() takes an argument which defaults to the upSHIFT mode of scaling. upSHIFT moves the bits of the binary number representing the knob value to the right three places, dropping off the three least significant bits of the number. A right shift operation is essentially like doing an integer divide by 2. We do it three times so it is like integer dividing 1023 by 8. It has an advantage that it cuts down on the 'jitter' that can happen as the analog signal is converted into a digital number. For example, the decimal number 955 is binary 1110111011. Pushing the three rightmost bits off into the right bit bucket makes the binary number = 1110111, or 119 decimal. 955 / 8 = 119.375, but as I said, this is an integer division, so the fractional value is simply chopped off, giving 119.

upTRUNC simply chops off the top, or three most significant bits of the number. The odd effect of this is that the number will go from 0 to 127 eight times during the turning of the knob from minimum to maximum, since we will only keep the lower 7 bits of the 10 bit number.

upSQUISH uses another built-in function called map(). This is almost, but not quite exactly like the upSHIFT function. Whereas the upSHIFT method simply drops bits, the map function does some math you can find at the reference page. The map() function, on the plus side, can let you spread the values however you want, as opposed to the upSHIFT method being pretty fixed. The downside is this post on the Arduino forum, the gist being it doesn't work 100% correctly, hence I have wrapped it with yet another built-in function, constrain().

Another new function is the checkRunStop() function, which reads the SPDT switch to determine if we are running or stopping. Actually, it just checks if we asked it to stop, but you could add an else if you have some other code you might want to run each time the switch is found to be in run mode. To stop, we call setILED() to change the color of the status LED and then turn off any notes that may be lingering. I also run the audioBootTest() function for audio confirmation of the stop. This was useful to me while recording samples, because I could hear that I had hit stop, rather than having just recorded a really long pause. It's not a necessary call in most cases.

setup() gets a few changes, too, as we define the pinMode for the two LED lines and the run/stop switch sense GPIOs. We call setILED(), and since this is at the start of everything, we set the argument of startup to true. This will make sure the LED is orange if we left the run/stop switch it in run mode before booting. Again, this was just a feature I added because I was recording samples and didn't want it to fire off in run mode before I was ready for it.

Last, but not least, we get to the main loop() function. For the basic example we run the three new functions at the head of the loop, for housekeeping and pulling in the knob values. Next, we pick a random note value, using the secondary method of passing the knob values into the getARand() function. When we send the MIDI information, the velocity value is determined from the iKnobs[2] value, making that knob function as a volume knob. Next, we manually turn off the green run LED to make it flicker as sort of a visual tempo indicator. Lastly, we use iKnobs[3] as a “tempo” control to change the speed of the delay. After turning off the MIDI note just sent, the loop repeats.
/*
+-------------------------------------------------+
| Arty The Aleatoric Arduino: random interactive  |
|                     based on random gaze final  |
| 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_GAUSS 0
#define RND_GAUSS2 1
#define RND_LIN 2
#define RND_SIN 3
#define RND_TAN 4
#define RND_VOSSF 5
#define RND_VOSSPREV 6
#define RND_VOSSGAUSS 7

//interactive constants and variables
const byte runStop = 4; //1=run; 0=stop
const byte gLED = 5;
const byte rLED = 6;
const byte knob0 = 0;
const byte knob1 = 1;
const byte knob2 = 2;
const byte knob3 = 3;
const byte knob4 = 4;
const byte knob5 = 5;
const byte upSHIFT = 0;
const byte upTRUNC = 1;
const byte upSQUISH = 2;
//array for knob values
unsigned int iKnobs[6];
//interactive

//global variables
SoftwareSerial MIDI(MIDI_IN, MIDI_OUT); // RX, TX
float pi_eye = -3.14159;
byte prevVal[] = {2, 3, 4, 3, 1, 1, 2, 7, 2}; // for use in getARand() function
byte noteVal;

//-----random functions
byte Voss_f(int last) {
  float probit, u;
  int Nu, J, K, L;
  Nu = 0;
  K = random(23);
  L = last;
  probit = 0.029384;
  while (K > 0) {
    J = L / K;
    if (J == 1) L -= K;
    u = random(-10, 21);
    if (u < probit) J = 1 - J;
    Nu += (J * K);
    K /= 2;
    probit *= random(1.25, 2.5);
  }
  return Nu;
}

byte Gauss_R(int range) {
  int count;
  float summ, std, mean;
  summ = 0.0;
  std = 0.2;
  mean = 0.5;
  for (count = 1; count < 25; count++) {
    summ += random(2);
  }
  return (byte((std * 0.707106781 * (summ - 12) + mean) * range + 1));
}

byte getARand(byte rType, boolean interAct = false, byte loVal = 0, byte hiVal = 127) {
  //get random stuffs
  // added interactive 08/08/2015
  byte retVal = 0;
  byte tmpVal;

  pi_eye += 0.05;
  switch (rType) {
    case RND_GAUSS:
      if (interAct) {
        retVal = Gauss_R(iKnobs[0]);
      } else {
        retVal = Gauss_R(random(loVal, hiVal + 1)); //must be hiVal+1 to include 127 (random is loVal to hiVal-1)
      }
      break;
    case RND_GAUSS2:
      if (interAct) {
        retVal = Gauss_R(iKnobs[1]) + Gauss_R(iKnobs[2]);
      } else {
        retVal = Gauss_R(loVal) + Gauss_R(hiVal);
      }
      break;
    case RND_LIN:
      retVal = random(loVal, hiVal + 1) - prevVal[rType];
      break;
    case RND_SIN:
      if (interAct) {
        retVal = sin(pi_eye / (iKnobs[5] + 1)) * iKnobs[4];
      } else {
        retVal = sin(pi_eye / (loVal + 1)) * hiVal;
      }
      break;
    case RND_TAN:
      retVal = tan(pi_eye / (loVal + 1)) * hiVal;
      break;
    case RND_VOSSF:
      retVal = Voss_f(hiVal * prevVal[rType]) + loVal;
      break;
    case RND_VOSSPREV:
      if (interAct) {
        retVal = Voss_f(prevVal[rType]) * iKnobs[4];
      } else {
        retVal = Voss_f(prevVal[rType]) * hiVal;
      }
      break;
    case RND_VOSSGAUSS:
      retVal = Voss_f(int(Gauss_R((hiVal - loVal) / 2)));
      break;
  }
  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 chanNotesOff(int channel = 0) {
  sendMIDI(0xB0 + channel, 0x7B, 0x00);
}

void allNotesOff(void) {
  for (int anoff = 0; anoff < 16; anoff++) {
    chanNotesOff(anoff);
  }
}

void setILED(boolean startup = false) {
  digitalWrite(rLED, LOW);
  digitalWrite(gLED, LOW);
  if (startup) {
    if (digitalRead(runStop) == 1) {
      analogWrite(rLED, 127);
      analogWrite(gLED, 200);
    } else {
      analogWrite(rLED, 0);
      analogWrite(gLED, 0);
    }
    while (digitalRead(runStop) == 1);
  } else {
    if (digitalRead(runStop) == 1) {
      digitalWrite(rLED, LOW);
      digitalWrite(gLED, HIGH);
    } else {
      digitalWrite(rLED, HIGH);
      digitalWrite(gLED, LOW);
    }
  }
}

void updateKnobs(byte style = upSHIFT) {
  iKnobs[0] = analogRead(knob0);
  iKnobs[1] = analogRead(knob1);
  iKnobs[2] = analogRead(knob2);
  iKnobs[3] = analogRead(knob3);
  iKnobs[4] = analogRead(knob4);
  iKnobs[5] = analogRead(knob5);
  switch (style) {
    case upSHIFT:
      //drop off the 3 LSB's by shifting right - cuts down on 'jitter' and keeps the value from 0-127
      iKnobs[0] = iKnobs[0] >> 3;
      iKnobs[1] = iKnobs[1] >> 3;
      iKnobs[2] = iKnobs[2] >> 3;
      iKnobs[3] = iKnobs[3] >> 3;
      iKnobs[4] = iKnobs[4] >> 3;
      iKnobs[5] = iKnobs[5] >> 3;
      break;
    case upTRUNC:
      // mask the value - will cause 'roll over' to start at 0 
      //as the value goes over 128, 256 and 512
      iKnobs[0] &= 127;
      iKnobs[1] &= 127;
      iKnobs[2] &= 127;
      iKnobs[3] &= 127;
      iKnobs[4] &= 127;
      iKnobs[5] &= 127;
      break;
    case upSQUISH:
      //use the map function (may be slow) to condense 0-1023 to 0-127
      iKnobs[0] = constrain(map(iKnobs[0], 0, 1024, 0, 128),0,127);
      iKnobs[1] = constrain(map(iKnobs[1], 0, 1024, 0, 128),0,127);
      iKnobs[2] = constrain(map(iKnobs[2], 0, 1024, 0, 128),0,127);
      iKnobs[3] = constrain(map(iKnobs[3], 0, 1024, 0, 128),0,127);
      iKnobs[4] = constrain(map(iKnobs[4], 0, 1024, 0, 128),0,127);
      iKnobs[5] = constrain(map(iKnobs[5], 0, 1024, 0, 128),0,127);
      break;
  }
}

void checkRunStop(void) {
  if (digitalRead(runStop) == LOW)
  {
    setILED();
    chanNotesOff();
    audioBootTest();
    while (digitalRead(runStop) == LOW);
    setILED();
  }
}

void setup() {
  Serial.begin(115200); // for looking at debug things
  MIDI.begin(31250); // our software serial MIDI connection
  //interactive setup
  pinMode(runStop, INPUT);
  pinMode(rLED, OUTPUT);
  pinMode(gLED, OUTPUT);
  setILED(true);
  //end interactive setup
  //turn all notes off, all channels
  allNotesOff();
  //get a random seed from an unattached analog pin
  randomSeed(analogRead(0));
}

void loop() {
  //random types are:
  // RND_GAUSS, RND_GAUSS2, RND_LIN, RND_SIN, RND_TAN, RND_VOSSF, RND_VOSSPREV and RND_VOSSGAUSS
setILED();
  updateKnobs(upSQUISH);
  checkRunStop();
  noteVal = getARand(RND_GAUSS,false,iKnobs[0],iKnobs[1]);
  sendMIDI(CMD_NOTE_ON, noteVal, iKnobs[2]);
  digitalWrite(gLED, LOW);
  delay(100+(2*iKnobs[3]));  //a tempo of sorts
  sendMIDI(CMD_NOTE_OFF, noteVal, 64);
}
Arty is now interactive!

Some things to explore are using upTRUNC and upSHIFT as the parameter to the updateKnobs() function; changing the random function selecting noteVal, including using the interAct = true feature. To randomize the loudness in the notes, try something like:

sendMIDI(CMD_NOTE_ON, noteVal, constrain((getARand(RND_SIN)/4)+(iKnobs[2]),0,127)) 

which will allow random variation in the notes hit, and still allow the knob to be used as a 'volume' control.

Have fun with it!
Copyright © 2015 by Bill L. Behrendt
1 Comment

5): RANDOM THOUGHTS II

8/7/2015

0 Comments

 
Now that you have been introduced to the basis of Arty's aleatoric nature, it's time to get seriously random. While the Arduino's random() function works well, it essentially provides a statistically similar pseudo-pattern without much change. Listen to it for a while and your ear will start picking up a bland sameness as time goes on. In order to get a bigger, spicier palette for generating music by way of non-restricted, semi-restricted and restricted methods, I decided on a handful of different 'tasting' random functions to start with. The getARand() code is open ended enough to have up to 255 types, but we will start off with four basic types, with variations, for eight total functions.

These functions come to us from a PC program I wrote many years ago. I do not remember exactly how they came about, but I had done some heavy research, and they are part of the result. We will be working with a watered-down, mutilated Gaussian-like function and a simplistic approximation of something similar to an almost recognizable Voss Fractal function. In addition, we'll be using two non-random functions, just to mix things up. And for good measure, we will throw in one which relies on the random() function.

To support these new random number types, we now have a Voss_f() and a Gauss_R() function, new #defines for the random types and another global variable. The float pi_eye is for the tan() and sin() functions. Also, the array holding the previous random value, prevVal[], now has 8 initial values.

I'm not a math wizard. I do remember, vaguely, in 1991, getting some books from the local college library and coming up with the Gauss_R() and Voss_f() functions for a program called “Jazzy”. Jazzy was an MS-DOS program, written in Turbo Pascal, and was a menu driven aleatoric MIDI output program. So, this code is known to work in this context, but frankly, I would have to research it all again to explain how it works. If any math types reading this would care to comment on the inner workings of these functions, please feel free.

In this version of the code, we simply pick out an endless melody by continually throwing random MIDI note numbers out, at a constant loudness and tempo. I've included charts of the first 100 numbers which came out of my Arduino for each RND_* function using the default loVal=0 and hiVal=127. This code, random_gazeFinal.ino, allows you to get an 'audio' feel for the functions. Change the line noteVal=getARand(RND_GAUSS); to experiment with different parameters, as we did last time. Although it is easier to get acquainted with the randomness by listening to only the changing MIDI note values, you can also throw in a randomness to the velocity parameter of the sendMIDI() function and vary the tempo by adding a random value to the delay() parameter, as we did last time.

You can, at your discretion, add functions to getARand(). Just remember to add a #define and another element to the 'previous value' array. Also keep in mind the memory limitations of the Arduino. Finally, as silly as it sounds, even though 'random music' seems to rely heavily on good, solid randomness: well... it doesn't. It's all about how the random numbers are used.

There are several techniques for non-restricted composition, one of which we are using here: just throwing out a random sequence of notes. This generates a melody, of course, which, aside from being random, has no other sort of 'key feeling' attributes necessary for well-formed Western style music. We could add a second sendMIDI() and use a noteVal2 to generate a random counterpoint line. You could keep stacking more notes for a triad chord (three notes sounding at once) and so on. That method quickly blows up the number of lines of code and variable space, though, and becomes a monster to control when you want to start semi- or totally restricting the music output by adding musical composition rules.

So, now that we have a good, basic method for getting the aleatory out of our Arduino, we can begin exploring the methods of converting that into musical output in an easier way. Next time, we'll start heading to the future of our music generation by first going back in time to the late 1890's, when I will present the piano roll method of Arty's Aleatoric Abilities.

/*
+-------------------------------------------------+
| Arty The Aleatoric Arduino: random gaze final   |
| 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_GAUSS 0
#define RND_GAUSS2 1
#define RND_LIN 2
#define RND_SIN 3
#define RND_TAN 4
#define RND_VOSSF 5
#define RND_VOSSPREV 6
#define RND_VOSSGAUSS 7

//global variables
SoftwareSerial MIDI(MIDI_IN, MIDI_OUT); // RX, TX
float pi_eye = -3.14159;
byte prevVal[] = {2, 3, 4, 3, 1, 1, 2, 7, 2}; // for use in getARand() function
byte noteVal;

//-----random functions
byte Voss_f(int last) {
  float probit, u;
  int Nu, J, K, L;
  Nu = 0;
  K = random(23);
  L = last;
  probit = 0.029384;
  while (K > 0) {
    J = L / K;
    if (J == 1) L -= K;
    u = random(-10, 21);
    if (u < probit) J = 1 - J;
    Nu += (J * K);
    K /= 2;
    probit *= random(1.25,2.5);
  }
  return Nu;
}

byte Gauss_R(int range) {
  int count;
  float summ, std, mean;
  summ = 0.0;
  std = 0.2;
  mean = 0.5;
  for (count = 1; count < 25; count++) {
    summ += random(2);
  }
  return (byte((std * 0.707106781 * (summ - 12) + mean) * range + 1));
}

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

  pi_eye += 0.05;
  switch (rType) {
    case RND_GAUSS:
      retVal = Gauss_R(random(loVal,hiVal+1)); //must be hiVal+1 to include 127 (random is loVal to hiVal-1)
      break;
    case RND_GAUSS2:
      retVal = Gauss_R(loVal) + Gauss_R(hiVal);
      break;
    case RND_LIN:
      retVal = random(loVal, hiVal+1) - prevVal[rType];
      break;
    case RND_SIN:
      retVal = sin(pi_eye / (loVal+1)) * hiVal;
      break;
    case RND_TAN:
      retVal = tan(pi_eye / (loVal+1)) * hiVal;
      break;
    case RND_VOSSF:
      retVal = Voss_f(hiVal*prevVal[rType])+loVal;
      break;      
    case RND_VOSSPREV:
      retVal = Voss_f(prevVal[rType]) * hiVal;
      break;
    case RND_VOSSGAUSS:
      retVal = Voss_f(int(Gauss_R((hiVal-loVal) / 2)));
      break;
  }
  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(9600); // 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() {
  //random types are:
  // RND_GAUSS, RND_GAUSS2, RND_LIN, RND_SIN, RND_TAN, RND_VOSSF, RND_VOSSPREV and RND_VOSSGAUSS
  noteVal=getARand(RND_GAUSS);
  sendMIDI(CMD_NOTE_ON,noteVal,64);
  delay(200);  //a tempo of sorts
  sendMIDI(CMD_NOTE_OFF,noteVal,64);
}
Copyright © 2015 by Bill L. Behrendt
0 Comments

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
0 Comments

      3):  MEET ARTY, THE ALEATORIC ARDUINO

7/31/2015

0 Comments

 
Picture
Keyboard / MIDI jack
The Arduino can make music in many different ways. You can search the internet and find a lot of MIDI schematics and code, as well as a few ways to have the Arduino act as a sound source, emitting its own musical notes.

I went ultra-simple on the hardware. I'm using an Arduino Uno R3 clone that set me back a whopping $7.00. In line with the Junkbox Junkie philosophy, the parts for the circuit cost me around... well, nothing. Zero. Zilch. Nada.

Arduino prototype shields are relatively inexpensive, but since I had a total of 3 components and a wire, I really didn't want to use an entire shield. So I made what I'll call an 'Arduino Bridge'. It's a piece of perfboard I had – yes – in my junkbox. It is wide enough to bridge between the power socket side and the digital out socket side. Two 220Ω resistors, five pins and a female MIDI jack which isn't a MIDI jack, but is a MIDI jack, and the hardware was complete.

So, about this MIDI jack thing. Little known fact: the older IBM clone XT and AT systems used a keyboard with a huge coiled wire thing that plugged into a jack on the main computer. This jack, which isn't a MIDI jack, is a MIDI jack. It's a 5-pin DIN style, exactly the same thing as a real female MIDI jack. So, again with the Junkbox Junkie thing, I desoldered the keyboard jack from a defunct motherboard and used it as my MIDI jack.

The schematic is simple. Here, I feel compelled to mention SAFETY. If you know how to solder and all the relevant safe practices, great. If you don't please consult with someone who does. Just be safe. This project isn't worth pursuing if you damage yourself. Safety glasses and care wielding a 350° soldering iron are in order.

The largest problem is probably making sure to look at the REAR of the MIDI (formerly keyboard) jack while connecting the resistors. I also used a total of five pins to connect to the Arduino. On the power (+5, GND) side, I added a pin to sort of align the bridge when connecting it. On the digital port side, I used pins for digital 11 and 12, again to help guide the plugging in of the board. Pin 11 is the MIDI send signal. Pin 12 would be the receive side of things, if we were sending MIDI back into the Arduino. Which we aren't.

So, that leaves the software. This first code attempt will be pretty lean. Don't expect major symphonic works of art just yet. There are a few 'must haves' in order to even get a MIDI command message sent out of the Arduino. SoftwareSerial is part of the standard libraries included when you download the IDE. We will be using that for the MIDI communication at 31,250 baud. To talk back to the PC, mostly to capture debug messages on the serial monitor, we'll be using the standard Serial object, connected by default to digital pins 0 and 1. We can use 9600 baud for now, but I reserve the right to chuck that up to 115,200 in future applications.


Next time: Some "random" thoughts on how to start generating music.

Test Program for the Arty Bridge:
/*
+-------------------------------------------------+
| Arty The Aleatoric Arduino: test_MIDI           |
| 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 command messages
#define CMD_NOTE_ON 0x90 //channel 1
#define CMD_NOTE_OFF 0x80 //channel 1

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

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) {

  //turns off all notes on all MIDI channels
  for (int anoff = 0; anoff < 16; anoff++) {
    sendMIDI(0xB0 + anoff, 0x7B, 0x00);
  }
}

void setup() {
  Serial.begin(9600); // for looking at debug things
  MIDI.begin(31250); // our software serial MIDI connection
  //turn all notes off, all channels then emit a chord
  allNotesOff();

  flashWorkLED(1);
  audioBootTest();
}

  void loop() {

    // send each MIDI note, one at a time
    for (int x = 0; x < 128; x++)
    {
      sendMIDI(CMD_NOTE_ON, x, 64);
      Serial.println(x);
      delay(150);
      sendMIDI(CMD_NOTE_OFF, x, 64);
    }

    flashWorkLED(0);
  }
Copyright © 2015 by Bill L. Behrendt
0 Comments

      2): If, By Chance, There Be MUSIC

7/29/2015

0 Comments

 
Picture
According to the Oxford Dictionaries website, “aleatoric” is a relatively recent adjective, coming into popular usage in the 1960's. However, the related adjective, aleatory, comes from the late 17th century. It probably got the final “-ic” in the 60's because it made it sound cooler. Plus there was a mistranslation from the lectures of German acoustician Werner Meyer-Eppler.

Aleatory has its genesis in Latin as aleator – a dice player which, in turn, comes from alea, the singular of dice, i.e. die. Aleatory art (or, to be 60's hip, aleatoric art), therefore, is based on randomness, like the throw of a die.

While there are sixty-three and two-thirds (an aleatoric number I just made up) variations on the theme, aleatoric music has some component of randomness. Similar to the idea of improvisation, but with a major difference: improvisation generally is done in a restricted manner. Improvisation is accomplished by being in the same key or mode of the song being played. It has a rhythmic relationship to the song, as well. This makes it 'fit in' to the song and yet allows for a more performer-varied expression and latitude than playing just the melody 'as written'. The genre of Jazz exhibits the most frequent use of improvisational technique. Frequent as in always.

Three broad, basic concepts exist for aleatoric music: unrestricted composition, semi-restricted composition and restricted composition. Improvisation essentially falls into the last category, restricted composition, because the song's key, tempo and rhythm limit the choices to something considerably less than randomly distributed notes, tempos and rhythmic structure. Even if the song goes through tempo changes, key changes, or whatever the composer throws out, the improvisational aspect follows along, changing its key, tempo and rhythm in sync.

Semi-restricted composition can be thought of as an extremely loose improvisation. For instance, the song's composer might indicate a chord outline for the piece and leave the details of individual notes, tempo and rhythm up to the performers. While this could end up sounding like two cats fighting in a metal garbage can rolling downhill, most experienced musicians actually have some sort of unspoken connection, very similar to the practitioners of stage improv, where actors play a scene only knowing a limited amount of information (Abe Lincoln and Mel Torme meet on a subway in New York City. Go!). It can lead to a very surreal experience for both the performers and the audience.

Unrestricted composition is the easiest to implement with a computer. Unrestricted means just that: no rules. Any note can be played at any time with or without any rhythm and tempo, or all those attributes can change from note to note. Needless to say, it can be “interesting” (in quotes, italicized), as we will see, and resembles the music I wrote when I first touched a piano at age 5. Meaning I hit random keys and made a lot of noise.

Even if you don't play piano, you probably can quickly see there are two groups totaling five black keys that repeat. So, take one die and roll it, then hit one of those five black keys. If you roll a six, that's a rest, or pause, and no note is played.

Even though it is called 'unrestricted', in fact there are still some restricted parameters in this composition type. Our tiny example limits the player to 5 notes, rather than the full 88 notes available on most pianos. Adding dice would lift that restriction, at the cost of sounding less like music and more like me at the piano, at the age of 5. The restriction imposed by our black-key die example limits the notes available to what is known as the pentatonic scale. Generally, you can't make displeasing music if you stay on just those five notes. You can even hit 2 or 3 of them at the same time and have a halfway decent sound.

I bring that up because it is the main theoretical postulate of what we will be doing here. To state it in simple terms, by judiciously choosing what rules to follow, we can have a computer make some pretty interesting music.

But, like me as a five year-old, we have to start somewhere and work our way up. So, next blog, we'll see the simple hardware we will start with to create what I call “Arty, The Aleatoric Arduino”.


Copyright © 2015 by Bill L. Behrendt
0 Comments

       1):  Welcome to the craziness...

7/28/2015

0 Comments

 
I've been itching to do something like this for the past 6 months. So, I decided to scratch. I'm just an average guy who plays (SAFELY) with electronics and music in whatever capacity the twain shall meet.

A little bit about my interests, since they are relevant and, perhaps, unique. Sort of my way to let you know this wasn't a sudden onset of craziness. You can check out the 'About' page for more.

Essentially, I fell in love with the idea of synthesis and synthesizers a way long time ago. It ended up being an on and off romance, competing with 'life' for my attention. Since I have no life, I guess I can devote more to this endeavor, now. ;)

In 1984, I wrote a book called Music and Sound for the Commodore 64. In chapter 10, I discuss several methods and present several programs for generating music with a C-64 computer.  At the end of the chapter, I noted that, at that time, the hardware was pretty much a limiting factor. Although the $595.00 (list price) C-64 was one of the most advanced sounding units on the market, having a full-fledged 3- voice synthesizer chip (The Sound Interface Device, or SID chip), it still suffered from having only 64K of RAM and a really slow processor (2 Mhz if I'm not mistaken) and slow, low density floppy drive system.

I picked up an Arduino Uno clone the other day for about $7.00. Considering it runs at 16Mhz, has 1K EEPROM, 2K RAM and 32K Flash, not to mention the RISC architecture... I think maybe it can handle what we throw at it, musically speaking.

Won't you join me in perambulating the miasma of the field of artificial music generation?
Copyright © 2015 by Bill L. Behrendt
0 Comments
    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.