Electronic music interface

From Wikiversity
Jump to navigation Jump to search
Synthesizer interface with knob for every possibility

Problem/Finish Description[edit | edit source]

There is no standard user interface to a synthesizer, yet there is a great synthesizer in the cheapest kids toy. Goal is to develop an open source, standardized user interface to a synthesizer.

Conceive[edit | edit source]

Synthesizer interfaces typically have limited selection or a knob for every possibility. Neither engage kids. Parents end up throwing away any kids toy that generates sounds.

Drums seem to be the starting point of making synthesizer. And the most attractive drum interface seems to be the beat bearing [video]. Electronic music and DIY festivals exist at which this synthesizer could be demonstrated.

Current System Diagram

Design[edit | edit source]

Block Diagram and Subsystems

Block diagrams were created using Google Drawing.

The original block diagram had the FPGA attached to the flatscreen monitor through a VGA output. However, it was decided that having a computer connect to the monitor would be easier. The current diagram has arrows depicting the flow of information through the system.


Electronics
Fritzing

We used an open-source software that allows people to design prototypes on the computer called fritzing in order to create a more detailed and accurate block diagram.

The way the program works is by dragging and dropping parts from the parts bin onto the screen and connect them.

The final diagram

Our first attempt at using fritzing did not depict an accurate diagram of the system. The reason is because fritzing does not have the Papilio Platform Papilio One (an FPGA platform) or the Papilio Platform LogicStart Metawing V1.2 in their database.

FPGA stands for Field Programmable Gate Array. FPGA is a circuit designed to be programmed by a customer or designer after it has been manufactured. A papilio uses FPGA in order to become a digital circuit.

We learned it is possible to create your own fritzing parts and add them to the program. According to fritzing, a file is made up of a metadata file, and up to four SVG files. There are also multiple image files since there are multiple ways to view an image in fritzing (breadboard, schematic, and pcb). Fritzing uses specific font and templates for their parts which are available for download here. In addition, since there are so many files associated with making one part, many of the websites gave instructions on how to name/organize files to make it easier to find them.

Once all of the files are ready, they are uploaded into fritzing and there it can be determined where the pins and connections should be placed.

As the project moved forward, we decided to put the Fritzing aspect of the project on hold. However, the research we have done is a good starting point which can be used in the future.


User Interface
First Design


The MIDI shield has three buttons and two analog knobs, and the Papilio Platform has a joystick and eight switches. Each will have a different function. The required functions are listed below:

  • Buttons
    • Select/Reset: push briefly to start sequence, hold to clear
    • Memorize: save current setup to layer new sounds
    • Instrument Select: cycles through available instruments
  • Knobs
    • Volume control
    • Tempo control
    • Pitch control
    • Papilio switch to toggle functions
  • Switches
    • Individual rows - edit on/off
    • Toggle Knob functions
    • Toggle instrument type for Instrument Select
  • Joystick
    • Measure select
    • Loop select

Creating a music sequence:

  • Press Select
  • Press Instrument Select to choose instruments for each row
  • Place marbles
  • Press Select to run/test sequence
  • Press Memorize to save sequence
  • Rearrange marbles and choose new instruments
  • Press Select to run/test new layer
  • Press Memorize to add loop to sequence

Save Options:

  • Separate program on PC to save/load songs
  • Songs play independent of Processing
Microphone Input & Looping

Looping is becoming a part of performance. This video shows a looping machine being used with two petal latch/moment function and other devices. All music originated through a microphone. No synthesizer was used. No midi codes as found in the example midi arduino software below are being used. Everything is done by recording the microphone. Do the steal balls substitute for the pedals and buttons? Can an arduino interface be better than the different looping interfaces of various vendors?

Market Survey

These features and functions of electronic music need to be surveyed in order to expand the features:


Implement[edit | edit source]

Materials

An arduino is a single-board multi-controller that makes using electronics easier. It can be plugged into a computer via a USB port. It also has a DC power jack.

MIDI stands for Musical Instrument Digital Interface. In other words, MIDI is data that tells an instrument what to play. The MIDI Breakout allows the arduino (or other micro-controller) to communicate with electronic instruments. A MIDI shield is similar to the MIDI Breakout except that it has additional buttons and knobs.

For this project, a MIDI Shield must be used, not a MIDI Breakout board.

Soldering Midi Shields
Assembled MIDI Shield

However, the MIDI shield did't work. And after trying many times, discovered that the board was soldered incorrectly. Instead on one strip of solder running across the analog pins, each pin needed to be soldered individually.

Make sure that each pin is soldered individually!

The MIDI Shield is made up of the following parts:

SparkFun states that potentiometers are used to control volume, tone, and pitch.

MIDI
Introduction to Arduino Midi programming

Binary numbers play a major role in programming MIDI. In the Mary Had A Little Lamb Code (see here) most of the code is comprised of a set of numbers. Below is an example of a portion of the code. These numbers are referring hex (0x) numbers.

  noteOn(0x90, 0x40, 0x28)
  
  noteOn(0x90, 0x3E, 0x28)
  
  noteOn(0x90, 0x3C, 0x28)
Binary 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Hex 0 1 2 3 4 5 6 7 8 9 A B C D E F


Binary, decimal, and hex (short for hexadecimal) are all ways to write the same thing. This site says "0x" indicates that the number is a hexadecimal number. The 90 which follows the 0x refers to the decimal; thus, 0x90 equals 10010000, or 8 bits of information.

Arudino Code A table of common commands and their meanings

Command Meaning
// Whatever is following is just a comment
0x90 Turn note on
0x80 Turn note off
0X1E; note < 0x5A; note ++ Start on note 30 (0x1E) and if the following notes are less than note 90 (0x5A), add one note (note ++). In other words, play a scale
delay (100) Delay the next note by 100 milliseconds
0x00 (in the velocity column) Play the note at a silent velocity. Mutes/turns off the key
int Integer
int note = [command] Command is only followed in that particular section
void Whatever is in that command is super important (they are followed throughout the entire code)
void setup Command is only done once
void loop Command is done over and over
Serial begin (31250) Setting of the MIDI baud rate (baud rate = symbols per second). 31250 bits sent per second.
void noteOn(int cmd, int pitch, int velocity) Says what the three values in the noteOn mean.

MIDI Code

From MIDI tutorial learned that there are 16 MIDI channels, meaning up to 16 instruments can be played at once.

The velocity value determines how loud the note is played.

Volume Velocity Value
pp 31
p 42
mp 53
mf 64
f 80
ff 96

In order to play two notes at once, simply have two "noteOn" lines in a row (see below).

noteOn(0x90, 0x4B, 0x60); // E flat
noteOn(0x90, 0x50, 0x60); //A flat

The middle column of numbers in the code (0x4B, 0x50) correlate with a note on the keyboard. Their binary numbers are 01001011 and 01010000 respectively. Using different combinations of numbers are used to play different notes. Note values range from 0-127 (middle C = 60, C# = 61, D = 62, etc.).

According to the MIDI tutorial, the sounds use a "program change" message to indicate that a different instrument is being played. A program change contains one status byte and one data byte. A status byte is 1100 CCCC and one data byte is 0XXX XXXX. The MIDI channel (0-15) is XXXXXXX. It is important to note that once you determine the note you want to be played, you must convert it to a hex number. This site can convert to hex as well as the windows calculator.

The general MIDI Level 1 Patch Map was used to determine what tone is used (piano, violin, space pad, etc.). For example, suppose a xylophone tone was wanted. Look at the chart, determine the number (in this case, 14), and then convert it to hex (0E). Then insert it into the code.

Helpful Links

'How to upload code to the arduino/MIDI shield

  1. Place MIDI shield on top of arduino
  2. Plug arduino into computer via USB cable
  3. Enter code into arduino software
  4. Upload code onto arduino
  5. Turn on keyboard
  6. Switch to tone-map G (press "Transpose/Tune/MIDI" button until the tone map screen appears in the viewing window, press the "+" key so the window says "Tone map G)
  7. Plug in "out" side of MIDI cable into "out" port on MIDI shield
  8. Plug in the "in" side of the MIDI cable into the "in" port of the keyboard

Coding Tips

  • Make sure the right hex number is selected. It's very easy to get the hex and decimal numbers confused.
  • Double check EVERYTHING. This will save so much time in the long run.
  • Labeling helps (but only if the labels are correct)
  • Understanding how the code works helps greatly
Test Arduino/Midi Shield Code

A sample MIDI code

Goal: To play a simple series of notes

>
/*
 MIDI note player
 
 This sketch shows how to use the serial transmit pin (pin 1) to send MIDI note data.
 If this circuit is connected to a MIDI synth, it will play 
 the notes F#-0 (0x1E) to F#-5 (0x5A) in sequence.

 
 The circuit:
 * digital in 1 connected to MIDI jack pin 5
 * MIDI jack pin 2 connected to ground
 * MIDI jack pin 4 connected to +5V through 220-ohm resistor
 Attach a MIDI cable to the jack, then to a MIDI synth, and play music.

 created 13 Jun 2006
 modified 13 Aug 2012
 by Tom Igoe 

 This example code is in the public domain.
 
 http://www.arduino.cc/en/Tutorial/Midi
 
 */

void setup() {
  //  Set MIDI baud rate:
  Serial.begin(31250);
}

void loop() {
  // play notes from F#-0 (0x1E) to F#-5 (0x5A):
  for (int note = 0x1E; note < 0x5A; note ++) {
    //Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
    noteOn(0x90, note, 0x45);
    delay(100);
    //Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
    noteOn(0x90, note, 0x00);   
    delay(100);
  }
}

//  plays a MIDI note.  Doesn't check to see that
//  cmd is greater than 127, or that data values are  less than 127:
void noteOn(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}
Keyboard Synthesizer Manual

The Casio CTK 519 Keyboard user manual gives information about MIDI. It said that MIDI messages are received by attaching the "out" port to the device and the "in" port to the keyboard. The manual also said that there are 16 MIDI channels on the keyboard and that both the sending machine and the receiving machine have to be set to the same channel. Another thing the manual mentioned is that the keyboard has two tone maps. Tone map N allows tones from 0 to 99 whereas tone map G allows for tones from 0 to 127. The manual also said to use MIDI channels 1, 2, 3, 4, or 10.

In order to change the channels as well as the tone map, press the transpose/tune/MIDI button three or four times and use the + and - buttons to change the setting. The keyboard is not General MIDI compatible but it can still connect to a computer or other MIDI equipment.

Sample MIDI Songs
Mary had a Little Lamb

Video

void setup() {
  Serial.begin(31250);
  //MIDI protocol baud rate is 31250 bits per second
}

void loop() {
  //Plays Mary Had a Little Lamb on a loop at 145 BPM
 
  //Bar 1
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  noteOn(0x90, 0x3E, 0x28); //Quarter note: D
  delay(414);
  
  noteOn(0x90, 0x3C, 0x28); //Quarter note: C
  delay(414);
  
  noteOn(0x90, 0x3E, 0x28); //Quarter note: D
  delay(414);
  
  //Bar 2
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  noteOn(0x90, 0x40, 0x28); //Half note: E
  delay(828);
  
  //Bar 3
  noteOn(0x90, 0x3E, 0x28); //Quarter note: D
  delay(414);
  
  noteOn(0x90, 0x3E, 0x28); //Quarter note: D
  delay(414);
  
  noteOn(0x90, 0x3E, 0x28); //Half note: D
  delay(828);
  
  //Bar 4
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  noteOn(0x90, 0x43, 0x28); //Quarter note: G
  delay(414);
  
  noteOn(0x90, 0x43, 0x28); //Half note: G
  delay(828);
  
  //Bar5
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  noteOn(0x90, 0x3E, 0x28); //Quarter note: D
  delay(414);
  
  noteOn(0x90, 0x3C, 0x28); //Quarter note: C
  delay(414);
  
  noteOn(0x90, 0x3E, 0x28); //Quarter note: D
  delay(414);
  
  //Bar 6
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  //Bar 7
  noteOn(0x90, 0x3E, 0x28); //Quarter note: D
  delay(414);
  
  noteOn(0x90, 0x3E, 0x28); //Quarter note: D
  delay(414);
  
  noteOn(0x90, 0x40, 0x28); //Quarter note: E
  delay(414);
  
  noteOn(0x90, 0x3E, 0x28); //Quarter note: D
  delay(414);
  
  //Bar 8
  noteOn(0x90, 0x3C, 0x28); //Whole note: C
  delay(1656);
  noteOn(0x90, 0x3C, 0x00); //"Silent" note that makes sure the note stops playing.
  delay(2000);
  
  //End song
  //Wait 2 seconds after the last note is struck to repeat
}

void noteOn(int cmd, int pitch, int velocity) { //Sets what each of the 3 values in the "noteOn" function does
  Serial.write(cmd); //All MIDI protocol messages start with 0x90 to signify the start of a MIDI message
  Serial.write(pitch); //The note. Middle C (0x3C), for example
  Serial.write(velocity); //Length of time the note is played. Values range from 0 to 127 (0x64), for example
}
Chords, Multiple Instruments & Drums
void setup() {
  Serial.begin(31250);
  //MIDI protocol baud rate is 31250 bits per second
}
 
void loop() {
   // Channel 0 (hex = 0xC0) is alto sax (65 on the Gen MIDI Patch Map) hex = 0x41
   Serial.write(0xC0);
   Serial.write(0x41);
   // Channel 1 (hex = 0xC1) is piano 0 (0 on patch map) hex = 0x00
   Serial.write(0xC1);
   Serial.write(0x00);
   // Channel 9 (hex = 0xC9) is drums 0 (the drum line is always channel 9) 
   Serial.write(0xC9);
   Serial.write(0x00);

  //t=0 ... from www.music-software-development.com/midi-tutorial.html
  noteOn(0x90, 0x48, 0x40); // start sax 
  noteOn(0x91, 0x3C, 0x40); //start piano
  noteOn(0x91, 0x43, 0x40); //start piano
  noteOn(0x91, 0x4C, 0x40); //start piano
  noteOn(0x99, 0x23, 0x7F); //start bass drum
  //0x90 refers to channel 0 (sax), 0x91 refers to channel 1 (piano), and 0x99 refers to channel 9 (drums) 
  delay(414);  // delay song by 414 miliseconds
 
 //t=1
  noteOn(0x90, 0x48, 0x00); //stop sax
  noteOn(0x99, 0x23, 0x00); //stop bass drum
  noteOn(0x90, 0x4A, 0x40); //start sax
  delay(414);
 
 //t=2
  noteOn(0x90, 0x4A, 0x00); //stop sax
  noteOn(0x90, 0x4C, 0x40); //start sax
  noteOn(0x99, 0x23, 0x7F); //start bass drum
  delay(414);
 
  //t=3
  noteOn(0x90, 0x4C, 0x00); //stop sax
  noteOn(0x99, 0x23, 0x00); //stop bass drum
  noteOn(0x90, 0x4F, 0x40); //start sax
  delay(414);

 //t=4
  noteOn(0x90, 0x4F, 0x00); //start sax
  noteOn(0x91, 0x3C, 0x40); //play cord again
  noteOn(0x91, 0x43, 0x40); //play cord again
  noteOn(0x91, 0x4C, 0x40); //play cord again
  delay(2000);
 
  //End song
  //Wait 2 seconds after the last note is struck to repeat
}
 
void noteOn(int cmd, int pitch, int velocity) { //Sets what each of the 3 values in the "noteOn" function does
  Serial.write(cmd); //All MIDI protocol messages start with 0x90 to signify the start of a MIDI message
  Serial.write(pitch); //The note. Middle C (0x3C), for example
  Serial.write(velocity); //Volume of note
}
Sail by AWOLNATION

We wanted to program part of a song that was relatively simple but had a variety of instruments so we chose Sail by AWOLNATION. We decided to use tone "synth strings" which is number 51 on the patch map. The song is in E flat minor which means for the beginning notes we want an E flat and A flat. We also raised it up an octave. E flat was number 75 on the keyboard and its hex number is 4B. A flat was number 80, hex number is 50.

Version 1
>
void setup() {
  Serial.begin(31250);
  //MIDI protocol baud rate is 31250 bits per second
}
 
void loop() {
    // channel 0 synth strings 1 (51) 0xC0,0x33
   Serial.write(0xC0);
   Serial.write(0x33);

  //t=0 
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x50, 0x60); //start strings, A flat	
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x50, 0x00); //stop strings, A flat
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x50, 0x60); //start strings, A flat	
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x50, 0x00); //stop strings, A flat

delay(414);

//t=1 
 noteOn(0x90, 0x4B, 0x60); // start strings, E flat
 noteOn(0x90, 0x50, 0x60); //start strings, A flat
 noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
 noteOn(0x90, 0x50, 0x00); //stop strings, A flat
 noteOn(0x90, 0x4B, 0x60); // start strings, E flat
 noteOn(0x90, 0x50, 0x60); //start strings, A flat	
 noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
 noteOn(0x90, 0x50, 0x00); //stop strings, A flat

delay(414);

 //End song
  //Wait 2 seconds after the last note is struck to repeat
}
 
void noteOn(int cmd, int pitch, int velocity) { 
  Serial.write(cmd); 
  Serial.write(pitch); 
  Serial.write(velocity); 
}

When we uploaded it to the arduino and then plugged in the MIDI cable, the piano started playing, but it was really soft and scratchy. The tempo was also faster than what we wanted. See video here. We split each second into two (each "t =" only had 4 noteOn's instead of 8) and re-uploaded. It still sounded very faint. We tried switching to tone map G (I was previously on tone map N) and it started playing normally. See here.

Version 2

We then raised the note velocity to 60 so it would be louder. We tried going higher than 60 but the notes would just go silent. We also added the bass note (E flat). The E bass flat is number 39 with a hex number of 27. We also added more of the song into the code. This code represents 8 measures of the song.

void setup() {
  Serial.begin(31250);
  //MIDI protocol baud rate is 31250 bits per second
}
 
void loop() {
    // channel 0 synth strings 1 (51) 0xC0,0x33
   Serial.write(0xC0);
   Serial.write(0x33);
  // channel 1 Pad 3 poly synth (91)  0xC1,0x5B
   Serial.write(0xC1);
   Serial.write(0x5B);
  // channel 9 drums 0
   Serial.write(0xC9);
   Serial.write(0x00);

//0x4B = E flat 8va
//0x50 = A flat 8va
//0x49 = G flat 8va
//0x27 = E flat (bass)

  //t=0 
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x50, 0x60); //start strings, A flat	
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x50, 0x00); //stop strings, A flat

delay(550);

//t=1 
 noteOn(0x90, 0x4B, 0x60); // start strings, E flat
 noteOn(0x90, 0x50, 0x60); //start strings, A flat
 noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
 noteOn(0x90, 0x50, 0x00); //stop strings, A flat

delay(550);

//t=2
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

  delay(550);
 
 //t=3
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

  delay(550);
 
 //t=4
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

delay (550);

//t=5 
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

  delay(550);
 
  //t=6
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

  delay(550);

//t=7
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

delay (550);

 //t=8 
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x50, 0x60); //start strings, A flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)	
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x50, 0x00); //stop strings, A flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

delay(550);

//t=9
 noteOn(0x90, 0x4B, 0x60); // start strings, E flat
 noteOn(0x90, 0x50, 0x60); //start strings, A flat
 noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
 noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
 noteOn(0x90, 0x50, 0x00); //stop strings, A flat
 noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

delay(550);

//t=10
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

 delay(550);
 
 //t= 11
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

  delay(550);
 
 //t=12
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

delay (550);

//t=13 

  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

 delay(550);
 
  //t=14
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

  delay(550);

//t= 15
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

delay (550);

 //t= 16
  noteOn(0x90, 0x4B, 0x60); // start strings, E flat
  noteOn(0x90, 0x50, 0x60); //start strings, A flat
  noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)	
  noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
  noteOn(0x90, 0x50, 0x00); //stop strings, A flat
  noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

delay(550);

//t= 17
 noteOn(0x90, 0x4B, 0x60); // start strings, E flat
 noteOn(0x90, 0x50, 0x60); //start strings, A flat
 noteOn(0x90, 0x27, 0x60); //start strings, E flat (bass)
 noteOn(0x90, 0x4B, 0x00); //stop strings, E flat
 noteOn(0x90, 0x50, 0x00); //stop strings, A flat
 noteOn(0x90, 0x27, 0x00); //stop strings, E flat (bass)

delay(550);

//t= 18
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x4D, 0x60); //start strings,  F
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); //stop strings, D flat
 noteOn(0x90, 0x4D, 0x00); //stop strings, F flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550);

//t= 19
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x4D, 0x60); //start strings,  F
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); //stop strings, D flat
 noteOn(0x90, 0x4D, 0x00); //stop strings, F flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550);

//t= 20
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x4D, 0x60); //start strings,  F
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); //stop strings, D flat
 noteOn(0x90, 0x4D, 0x00); //stop strings, F flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550);

//t= 21
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x4D, 0x60); //start strings,  F
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); //stop strings, D flat
 noteOn(0x90, 0x4D, 0x00); //stop strings, F flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550);

//t= 22
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x4D, 0x60); //start strings,  F
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); //stop strings, D flat
 noteOn(0x90, 0x4D, 0x00); //stop strings, F flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550);

//t= 23
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x4D, 0x60); //start strings,  F
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); //stop strings, D flat
 noteOn(0x90, 0x4D, 0x00); //stop strings, F flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550);


//t= 24
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x4D, 0x60); //start strings,  F
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); //stop strings, D flat
 noteOn(0x90, 0x4D, 0x00); //stop strings, F flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550);

//t= 25
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x4D, 0x60); //start strings,  F
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); //stop strings, D flat
 noteOn(0x90, 0x4D, 0x00); //stop strings, F flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550);

 //t=26
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x55, 0x60);//start strings, D flat 
  noteOn(0x90, 0x2A, 0x60); //start strings, G flat (bass)
  noteOn(0x90, 0x4E, 0x00); //stop strings, G flat
  noteOn(0x90, 0x55, 0x00); //stop strings, D flat 
  noteOn(0x90, 0x2A, 0x00); //start stop, G flat (bass)

  delay(550);

 //t=27
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x55, 0x60);//start strings, D flat 
  noteOn(0x90, 0x2A, 0x60); //start strings, G flat (bass)
  noteOn(0x90, 0x4E, 0x00); //start strings, G flat
  noteOn(0x90, 0x55, 0x00);//start strings, D flat 
  noteOn(0x90, 0x2A, 0x00); //start strings, G flat (bass)

  delay(550);

 //t=28
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x55, 0x60);//start strings, D flat 
  noteOn(0x90, 0x2A, 0x60); //start strings, G flat (bass)
  noteOn(0x90, 0x4E, 0x00); //start strings, G flat
  noteOn(0x90, 0x55, 0x00);//start strings, D flat 
  noteOn(0x90, 0x2A, 0x00); //start strings, G flat (bass)

  delay(550);

 //t=29
  noteOn(0x90, 0x4E, 0x60); //start strings, G flat
  noteOn(0x90, 0x55, 0x60);//start strings, D flat 
  noteOn(0x90, 0x2A, 0x60); //start strings, G flat (bass)
  noteOn(0x90, 0x4E, 0x00); //start strings, G flat
  noteOn(0x90, 0x55, 0x00);//start strings, D flat 
  noteOn(0x90, 0x2A, 0x00); //start strings, G flat (bass)

  delay(550);

//t=30
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x50, 0x60); //start strings, A flat
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); // stop strings, D flat
 noteOn(0x90, 0x50, 0x00); //stop strings, A flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550); 

//t=31
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x50, 0x60); //start strings, A flat
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); // stop strings, D flat
 noteOn(0x90, 0x50, 0x00); //stop strings, A flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550); 

//t=32
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x50, 0x60); //start strings, A flat
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); // stop strings, D flat
 noteOn(0x90, 0x50, 0x00); //stop strings, A flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550); 

//t=33
 noteOn(0x90, 0x49, 0x60); // start strings, D flat
 noteOn(0x90, 0x50, 0x60); //start strings, A flat
 noteOn(0x90, 0x25, 0x60); //start strings, D flat (bass)
 noteOn(0x90, 0x49, 0x00); // stop strings, D flat
 noteOn(0x90, 0x50, 0x00); //stop strings, A flat
 noteOn(0x90, 0x25, 0x00); //stop strings, D flat (bass)

delay(550); 

  //End song
  //Wait 2 seconds after the last note is struck to repeat
}
 
void noteOn(int cmd, int pitch, int velocity) { 
  Serial.write(cmd); 
  Serial.write(pitch); 
  Serial.write(velocity); 
}


Video is here.

We also played the song in the normal piano tone. This created a much louder noise, even when the volume was down. See video here.


Drums
Table of drum sounds
Drum Sound Key Number Hex Number
Acoustic Bass Drum 35 23
Bass Drum 1 36 24
Side Stick 37 25
Acoustic Snare 38 26
Hand Clap 39 27
Electric Snare 40 28
Low Floor Tom 41 29
Closed Hi Hat 42 2A
High Floor Tom 43 2B
Pedal Hi-Hat 44 2C
Low Tom 45 2D
Open Hi-Hat 46 2E
Low-Mid Tom 47 2F
Hi-Mid Tom 48 30
Crash Cymbal 1 49 31
High Tom 50 32
Ride Cymbal 1 51 33
Chinese Cymbal 52 34
Ride Bell 53 35
Tambourine 54 36
Splash Cymbal 55 37
Cowbell 56 38
Crash Cymbal 2 57 39
Vibraslap 58 3A
Ride Cymbal 2 59 3B
Hi Bongo 60 3C
Low Bongo 61 3D
Mute Hi Conga 62 3E
Open Hi Conga 63 3F
Low Conga 64 40
High Timbale 65 41
Low Timbale 66 42
High Agogo 67 43
Low Agogo 68 44
Cabasa 69 45
Maracas 70 46
Short Whistle 71 47
Long Whistle 72 48
Short Guiro 73 49
Long Guiro 74 4A
Claves 75 4B
Hi Wood Block 76 4C
Low Wood Block 77 4D
Mute Cuica 78 4E
Open Cuica 79 4F
Mute Triangle 80 50
Open Triangle 81 51
Exploring drum sounds

video

>

void setup() {
  Serial.begin(31250);
  //MIDI protocol baud rate is 31250 bits per second
}
 
void loop() {
  // channel 9 drums 0
   Serial.write(0xC9);
   Serial.write(0x00);

  //t=
  noteOn(0x99, 0x23, 0x60); // short whistle 
  noteOn(0x99, 0x48, 0x60); //start bass drum
  noteOn(0x99, 0x57, 0x60); //hand clap?
 
  delay(414);

//t=
  noteOn(0x99, 0x34, 0x60); // start chinese cymbal 

delay(414); 

 //t=
  noteOn(0x99, 0x34, 0x00); //stop chinese cymbal 

  delay(414);
 
 //t=
 noteOn(0x99, 0x48, 0x60); //start bass drum
 noteOn(0x99, 0x48, 0x00); //stop bass drum

delay(414);

//t=
 noteOn(0x99, 0x48, 0x60); //start bass drum
 noteOn(0x99, 0x48, 0x00); //stop bass drum


//t
 noteOn(0x99, 0x48, 0x60); //start bass drum
 noteOn(0x99, 0x48, 0x00); //stop bass drum

delay(414);

//t=
 noteOn(0x99, 0x48, 0x60); //start bass drum
 noteOn(0x99, 0x48, 0x00); //stop bass drum

delay(414);

 //t=
 noteOn(0x99, 0x3A, 0x60); //start vibraslap
 noteOn(0x99, 0x3A, 0x00); //stop vibraslap drum

delay(414);

//t=
 noteOn(0x99, 0x48, 0x60); //start bass drum
 noteOn(0x99, 0x48, 0x00); //stop bass drum

delay(200);

//t=
 noteOn(0x99, 0x48, 0x60); //start bass drum
 noteOn(0x99, 0x48, 0x00); //stop bass drum

delay(414);

//t=
 noteOn(0x99, 0x48, 0x60); //start bass drum
 noteOn(0x99, 0x48, 0x00); //stop bass drum

delay(200);

//t=
 noteOn(0x99, 0x44, 0x60); //start low agogo
 noteOn(0x99, 0x44, 0x00); //stop lowagogo

 delay(414);

//t=
  noteOn(0x99, 0x37, 0x60); // start splash cymbal
  noteOn(0x99, 0x37, 0x00);// stop splash cymbal 

delay(414); 

//t=
 noteOn(0x99, 0x32, 0x60); //start high tom
 noteOn(0x99, 0x32, 0x00); //stop high tom

delay(200);

//t=
 noteOn(0x99, 0x48, 0x60); //start bass drum
 noteOn(0x99, 0x48, 0x00); //stop bass drum

delay(500);

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(500); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(50); 

//t=
 noteOn(0x99, 0x44, 0x60); //start low agogo
 noteOn(0x99, 0x44, 0x00); //stop lowagogo

delay(200);

//t=
  noteOn(0x99, 0x28, 0x60); // start electric snare
  noteOn(0x99, 0x28, 0x00);// stop electric snare

delay(414); 

//t=
  noteOn(0x99, 0x28, 0x60); // start electric snare
  noteOn(0x99, 0x28, 0x00);// stop electric snare

delay(100); 

//t=
  noteOn(0x99, 0x28, 0x60); // start electric snare
  noteOn(0x99, 0x28, 0x00);// stop electric snare

delay(150); 

//t=
  noteOn(0x99, 0x28, 0x60); // start electric snare
  noteOn(0x99, 0x28, 0x00);// stop electric snare

delay(160); 

//t=
  noteOn(0x99, 0x39, 0x60); // start crash cymbal 2
  noteOn(0x99, 0x39, 0x00);// stop crash cymbal 2 

delay(414); 

//t=
  noteOn(0x99, 0x39, 0x60); // start crash cymbal 2
  noteOn(0x99, 0x39, 0x00);// stop crash cymbal 2 

delay(414); 

//t=
  noteOn(0x99, 0x38, 0x60); // start cowbell
  noteOn(0x99, 0x38, 0x00);// stop cowbell 

delay(414); 

   //End song
  //Wait 2 seconds after the last note is struck to repeat
}
 
void noteOn(int cmd, int pitch, int velocity) { 
  Serial.write(cmd); 
  Serial.write(pitch); 
  Serial.write(velocity); 
}
All drum sounds from from the General MIDI Level 1 Percussion Key Map

video

void setup() {
 Serial.begin(31250);
 //MIDI protocol baud rate is 31250 bits per second
}

void loop() {
 // channel 9 drums 0
  Serial.write(0xC9);
  Serial.write(0x00);

 //t=
  noteOn(0x99, 0x23, 0x60); // start acoustic bass drum
  
 delay(414);
 
//t=
 noteOn(0x99, 0x23, 0x00); // stop acoustic bass drum
 noteOn(0x99, 0x24, 0x60); // start bass drum 1

delay(414);

//t=
 noteOn(0x99, 0x24, 0x00); // stop  bass drum 1
 noteOn(0x99, 0x25, 0x60); // start  side stick
 
 delay(414);

//t=
noteOn(0x99, 0x25, 0x00); // stop side stick
noteOn(0x99, 0x26, 0x60); // start acoustic snare
 
delay(414);
 
//t=
 noteOn(0x99, 0x26, 0x00); // stop acoustic  snare
 noteOn(0x99, 0x27, 0x60); // start hand clap

delay(414);

//t=
 noteOn(0x99, 0x27, 0x00); // stop hand clap
 noteOn(0x99, 0x28, 0x60); // start electric snare

 delay(414);

//t=
noteOn(0x99, 0x28, 0x00); // stop electric snare
noteOn(0x99, 0x29, 0x60); // start low floor tom

delay(414);

//t=
 noteOn(0x99, 0x29, 0x00); // stop low floor tom
 noteOn(0x99, 0x2A, 0x60); // start closed hi-hat
 
delay(414);

//t=
 noteOn(0x99, 0x2A, 0x00); // stop closed hi-hat
 noteOn(0x99, 0x2B, 0x60); // start high floor tom
 
 delay(414);

//t=
noteOn(0x99, 0x2B, 0x00); // stop high floor tom
noteOn(0x99, 0x2C, 0x60); // start pedal hi-hat
 
delay(414);
 
//t=
 noteOn(0x99, 0x2C, 0x00); // stop pedal hi-hat
 noteOn(0x99, 0x2D, 0x60); // start low tom

delay(414);

//t=
 noteOn(0x99, 0x2D, 0x00); // stop low tom
 noteOn(0x99, 0x2E, 0x60); // start open hi-hat

delay(414);

//t=
 noteOn(0x99, 0x2E, 0x00); // stop open hi-hat
 noteOn(0x99, 0x2F, 0x60); // start low-mid tom
 
 delay(414);

//t=
noteOn(0x99, 0x2F, 0x00); // stop low-mid tom
noteOn(0x99, 0x30, 0x60); // start high mid-tom
 
delay(414);
 
//t=
 noteOn(0x99, 0x30, 0x00); // stop high mid-tom
 noteOn(0x99, 0x31, 0x60); // start crash cymbals 1

delay(414);

//t=
 noteOn(0x99, 0x31, 0x00); // stop crash cymbals 1
 noteOn(0x99, 0x32, 0x60); // start high tom

 delay(414);

//t=
noteOn(0x99, 0x32, 0x00); // stop high tom
noteOn(0x99, 0x33, 0x60); // start ride cymbal 1

delay(414);

//t=
 noteOn(0x99, 0x33, 0x00); // stop ride cymbal 1
 noteOn(0x99, 0x34, 0x60); // start Chinese cymbal
 
delay(414);

//t=
 noteOn(0x99, 0x34, 0x00); // stop Chinese cymbal
 noteOn(0x99, 0x35, 0x60); // start ride bell
 
 delay(414);

//t=
noteOn(0x99, 0x35, 0x00); // stop ride bell
noteOn(0x99, 0x36, 0x60); // start tambourine
 
delay(414);
 
//t=
 noteOn(0x99, 0x36, 0x00); // stop tambourine
 noteOn(0x99, 0x37, 0x60); // start splash cymbal
 
delay(414);
 
//t=
 noteOn(0x99, 0x37, 0x00); // stop splash cymbal
 noteOn(0x99, 0x38, 0x60); // start cowbell
 
delay(414);
//t=
 noteOn(0x99, 0x38, 0x00); // stop cowbell
 noteOn(0x99, 0x39, 0x60); // start crash cymbal 2
 
delay(414);
 
//t=
  noteOn(0x99, 0x39, 0x00); // stop crash cymbal 2
  noteOn(0x99, 0x3A, 0x60); // start vibraslap

delay(414);
 
//t=
 noteOn(0x99, 0x3A, 0x00); // stop vibraslap
 noteOn(0x99, 0x3B, 0x60); // start ride cymbal 2
 
 delay(414);

//t=
noteOn(0x99, 0x3B, 0x00); // stop ride cymbal 2
noteOn(0x99, 0x3C, 0x60); // start hi-bongo
 
delay(414);
 
//t=
 noteOn(0x99, 0x3C, 0x00); // stop hi-bongo
 noteOn(0x99, 0x3D, 0x60); // start low bongo

delay(414);
 
//t=
 noteOn(0x99, 0x3D, 0x00); // stop low bongo
 noteOn(0x99, 0x3E, 0x60); // start mute hi-conga

delay(414);
 
//t=
 noteOn(0x99, 0x3E, 0x00); // stop mute hi-conga
 noteOn(0x99, 0x3F, 0x60); // start open hi-conga

delay(414);
 
//t=
noteOn(0x99, 0x3F, 0x00); // stop open hi-conga
noteOn(0x99, 0x40, 0x60); // start low conga
 
delay(414);
 
//t=
 noteOn(0x99, 0x40, 0x00); // stop high conga
 noteOn(0x99, 0x41, 0x60); // start high timbale

delay(414);

//t=
 noteOn(0x99, 0x41, 0x00); // stop high timbale
 noteOn(0x99, 0x42, 0x60); // start low timbale

 delay(414);

//t=
noteOn(0x99, 0x42, 0x00); // stop low timbale
noteOn(0x99, 0x43, 0x60); // start high agogo

delay(414);

//t=
 noteOn(0x99, 0x43, 0x00); // stop high agogo
 noteOn(0x99, 0x44, 0x60); // start low agogo
 
delay(414);

//t=
 noteOn(0x99, 0x44, 0x00); // stop low agogo
 noteOn(0x99, 0x45, 0x60); // start cabasa
 
 delay(414);

//t=
noteOn(0x99, 0x45, 0x00); // stop cabasa
noteOn(0x99, 0x46, 0x60); // start maracas
 
delay(414);
 
//t=
 noteOn(0x99, 0x46, 0x00); // stop maracas
 noteOn(0x99, 0x47, 0x60); // start short whistle
 
delay(414);
 
//t=
 noteOn(0x99, 0x47, 0x00); // stop short whistle
 noteOn(0x99, 0x48, 0x60); // start long whistle
 
delay(414);
 
//t=
 noteOn(0x99, 0x48, 0x00); // stop whistle
 noteOn(0x99, 0x49, 0x60); // start short guiro
 
delay(414);
 
//t=
  noteOn(0x99, 0x49, 0x00); // stop short guiro
  noteOn(0x99, 0x4A, 0x60); // start long guiro

delay(414);
 
//t=
 noteOn(0x99, 0x4A, 0x00); // stop long guiro
 noteOn(0x99, 0x4B, 0x60); // start claves
 
 delay(414);

//t=
noteOn(0x99, 0x4B, 0x00); // stop claves
noteOn(0x99, 0x4C, 0x60); // start hi-wood block
 
delay(414);
 
//t=
 noteOn(0x99, 0x4C, 0x00); // stop hi-wood block
 noteOn(0x99, 0x4D, 0x60); // start low wood block

delay(414);
 
//t=
 noteOn(0x99, 0x4D, 0x00); // stop low wood block
 noteOn(0x99, 0x4E, 0x60); // start mute cuica

delay(414);
 
//t=
 noteOn(0x99, 0x4E, 0x00); // stop mute cuica
 noteOn(0x99, 0x4F, 0x60); // start open cuica

delay(414);
 
//t=
 noteOn(0x99, 0x4F, 0x00); // stop open cuica
 noteOn(0x99, 0x50, 0x60); // start mute triangle

delay(414);
 
//t=
 noteOn(0x99, 0x50, 0x00); // stop mute triangle
 noteOn(0x99, 0x51, 0x60); // start open triangle

delay(414);
 
//t=
 noteOn(0x99, 0x51, 0x00); // stop triangle
 
delay(414);

  //End song
 //Wait 2 seconds after the last note is struck to repeat
}
void noteOn(int cmd, int pitch, int velocity) {
 Serial.write(cmd);
 Serial.write(pitch);
 Serial.write(velocity);
}
Exploring MIDI Level 2 Drum Sounds

All of the current drum sounds are from General MIDI Level 1. There is General MIDI Level 2 which is based off of General MIDI. According to midi.org, General MIDI 2 is a group of extensions made to General MIDI 1 which allows more sounds to be played.

There are other possible drum kits besides the one previously used. The Void, for example, lists other possible kits such as a room kit, power kit, orchestra kit, and more. These kits all have different patch numbers. According to Wikipedia, "the drum bank is accessed by setting cc#0 (Bank Select MSB) to 120 and cc#32 (Bank Select LSB) to 0 and PC (Program Change) to select drum kit". PG Music also has a list of possible drum kits. GMStandardDrumMap.gif


Speed and Volume

Used the midisheild potentiometer connected on Analog0 (A0) to control the speed of a beat. Started with analogIn arduino example.

Controlling speed of song
 /*
 MIDI note player
 */
 int potPin = 0;    // select the input pin for the potentiometer
 int Speed = 13;   // select the pin for the Speed
 int val = 0;       // variable to store the value coming from the sensor
 void setup() {
  //  Set MIDI baud rate:
  Serial.begin(31250);
  //
  pinMode(Speed, OUTPUT);  // declare the Speed as an OUTPUT
 }
 void loop(){
   
    //Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
    noteOn(0x90, 0x43, 0x45);
    delay(100);
    //Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
    noteOn(0x90, 0x23, 0x00);   
    delay(100);
    val = analogRead(potPin);    // read the value from the sensor
  digitalWrite(Speed, HIGH);  // Makes song fast
  delay(val);                  // stop the program for some time
  digitalWrite(Speed, LOW);   // Makes song slow
  delay(val);                  // stop the program for some time
 }
 //  plays a MIDI note.  Doesn't check to see that
 //  cmd is greater than 127, or that data values are  less than 127:
 void noteOn(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
 }

This VIDEO shows the speed change.

The second analog port was tested controling the volume by editing the velocity part of midi codes.

Controlling volume
  /*
 MIDI note player
 */
 int potPin = 0;    // select the input pin for the potentiometer
 int Speed = 13;   // select the pin for the Speed
 int val = 0;       // variable to store the value coming from the sensor
 const int sensorMin = 23;      // sensor minimum, discovered through experiment
 const int sensorMax = 1000;    // sensor maximum, discovered through experiment
 int volume=50;
 int val2;       // second potentiometer


 void setup() {
 //  Set MIDI baud rate:
 Serial.begin(31250);
 //
 pinMode(Speed, OUTPUT);  // declare the Speed as an OUTPUT
}
void loop(){
  
   //Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
   noteOn(0x90, 0x43, volume);
   delay(100);
   val2=analogRead(1);
   volume=map(val2,0,1000,0,100); // takes range on val2 and converts to pot range.
   val = analogRead(potPin);    // read the value from the sensor
 digitalWrite(Speed, HIGH);  // makes song faster
 delay(val);                  // stop the program for some time
 digitalWrite(Speed, LOW);   // Slows down Speed
 delay(val);                  // stop the program for some time

}


//  plays a MIDI note. 
//  cmd is greater than 127, or that data values are  less than 127:
void noteOn(int cmd, int pitch, int velocity) {
 Serial.write(cmd);
 Serial.write(pitch);
 Serial.write(velocity);
}

This video shows the volume change.


Beat Bearing Board

The goal is to place a steel ball on top of two washers. This should electrically connect them.

Attachment of washer halves to the plexiglass board

The first design was based off of the instructions for building a beat bearing board found on the Jameco BeatBearing webpage, which called for screwing the washer halves to the board. However, instead of soldering the wires to soldering tabs, our modified design based on these instructiuons was to use wiring crimps to connect the wires to the washer system.

The next design we created was based off of ideas gathered from our classmates, modified to our own specifications. It called for the washer halves to be glued down to the plexiglass, where the wires could come through the bottom of the board and attach to the washers. This was the design we used moving forward with the project.

The glued down design was chosen by our group to be used as the design for connecting the washer halves to the plexiglass. The problem with the ball bearing touching the plexiglass was tackled in the wire connection part of our design.

Designing Wire Connection to washers

The first wire connection designs had the wires coming up through separate holes drilled into the plexiglass board from the bottom, then attached to the washer halves by either being coiled around the washer or sandwiched between the washer when glued down.

The coiled design was chosen to be used as the design, because it offered a better connection. New ideas for advancements to the coil design were given to our group by the class, and are shown below. These ideas were offered to solve the problem of the ball bearing touching the plexiglass when placed on the washer system. We chose the design we thought to have the most potential, and tested it.

The fourth idea was then built, and tested. The design process for building the prototype are shown below.

This prototype was then tested using a multimeter. The multimeter measured resistance of the system, and produces a noise if the sensors are connected to a system which is conductive.

Adjustments to this prototype were then made, and in the next section the final working manufacturing design can be seen.

Testing Washer Attachment System

The final working design was discovered after the prototype seen above was tested. It included aspects from the prototype built, as well as aspects from other design ideas not yet tested. But when built, tested, duplicated, then tested again, this design was consistently working. Also, the plexiglass board configuration is including along with the working washer system design.

  • The important part of our working design was the measurements of the washer halves. The spacing between each half is crucial for the ball bearing to sit in the system without touching the plexiglass. Here are the drawings with labels and measurements of the working design:

When this design was built and the ball bearing was placed atop, then tested with the multimeter, the multimeter produced a sound, signifying that the system was conductive. Thus we had a working design.

VIDEO --- Washer Design Tested With Multimeter

The design was then duplicated, using small wooden spacers (one of which was wrapped in electrical tape), to guarantee the exact measurements of the spacing of washer halves was maintained. The duplicate washer system was tested and proved to be successful, giving more credibility to the working final design.

So we have developed a final working design of the washer system, that will be used along with the designed plexiglass board, to create the beat bearing board for the Music project.

Planning Beat Bearing Board Construction

The design of the board was broken up into calculating the accurate measurements so that it sat well on top of the flat screen monitor and was spaced correctly. The calculations and design of the board then came together and we achieved a blueprint of the board which is seen below.

Creating Construction Spacing Template
Learning SketchUp

Google SketchUp was used to draw a 3D model of the washer template that would be printed using the MakerBot and used to glue down the 32 washer systems to the board correctly and efficiently. We successfully drew and printed the washer template, however the dimensions of the spaces for the washers have to be amended. Below is a SketchUp file that can be accessed and amended.

These videos were helpful when learning about converting SketchUp files to STL files that could then be transported to Makerware software and then printed. Also just for learning how to use SketchUp and the functions of all the tools.

Important tools to utilize while drawing in SketchUp:

Dimensions

This table has all of the conversions from inches to millimeters to obtain a more accurate drawing in SketchUp. The calculations were all done in inches, so it was important to get values in millimeters that we could input into SketchUp during the drawing process of the template. Using millimeters while working in SketchUp will yield the most accurate desired dimensions.

Measured Part Measurement in Inches Conversion to Millimeters
Width of Prism 1 3/8 in 34.925 mm
Length of Prism 13 3/8 in 339.72 mm
Height of Prism 3/16 in 4.7625 mm
Gap Between Washer System (top and bottom) 1/8 in 3.1750 mm
Space Between Washer Halves 3/16 in 4.7625 mm
Vertical Distance of Washer System 9/8 in 28.575 mm
Horizontal Distance (diameter of washer) 7/8 in 22.225 mm
Space Between Washer Systems 17/24 in 17.992 mm
Length of Cut Washer Ends 1/4 in 6.3500 mm
Vertical Distance of Cut Washer 0.4375 in 11.112 mm

Washer Template Drawing File In SketchUp

IMPORTANT --- You will need to install Google SketchUp in order to open the file. Click the file link, and then hit "Download." Then, if SketchUp is installed on your computer, it should automatically be opened with SketchUp. When the SketchUp window comes up, hit "Choose Template." Next, select "Architectural Design - Millimeters" and then hit "Start Using SketchUp." You should have then successfully opened the file in SketchUp, with the ability to make changes to the drawing.

3D printing Template

3D Printing

The first step to print a SketchUp drawing on the MakerBot is to convert the SketchUp file to an STL file. The SketchUp STL extension can be found on the SketchUp Extension Warehouse, and then by following the steps your SketchUp file can be converted to an STL file quite easily. You will need to Sign In with a Google account to download the extension.

Next the file will need to be uploaded into MakerWare software, and adjusted properly to obtain optimal 3D printing. A tutorial on how how to operate and use MakerWare can be found by clicking the link below.

Finally, once the file is exported from MakerWare onto an SD card, it is ready to be printed using the MakerBot. A tutorial on how to save the file properly on the SD card, and use the MakerBot appropriately and Safely can be found by clicking the link below.

Below are some screen shots of our work using MakerWare software to print the washer template after converting the SketchUp file to an STL file and then uploaded into MakerWare software.

Washer Template'

The washer template drawn in SketchUp was created to make the construction of the board easier and more efficient. Specifically, the template will be used to glue the washer halves with the coiled wire down to the board, with eh correct spacing, for all 32 washer systems in each row.

Because the MakerBot only has an 11 inch building plate, and the total length of our board is 13 3/8 inches, we cut the original design of the template in half, and then printed two of the same template. The images below show the successfully printed template which was drawn in SketchUp.

After examining the printed washer templates, and placing cut washer-halves into the cut holes, it appears that the measurements for the spaces designed to fit the washer halves into place are too big. This means the next step is to redesign the washer template in SketchUp, using the dimensions that will be found by re-measuring the washer halves, and the printed template. This is why we left the SketchUp file, which can be found above in the "SketchUp" section of this page. Instead of starting form scratch, our drawing can just be amended to fit the modifications of the washer size and new measurements taken. Then a new template will be printed again using the same process.

Rebuilding template with room for washer halves

The original washer template was the correct length and width but the holes for the washers were too big.

1) Change the cut out to be 8mm wide in a sample template

When we tested to see if it would still work with the ball bearing we found that the spacing was too far apart.

2) Change the distance between the two halves to 2.3mm

When we tested this we found it to work perfectly with the ball bearing.

3) Create a full size washer template

When we did this everything worked fine but have of the first section would not extrude through in Google Sketch Up. To solve this we still printed the template and used the sample template.


First Construction Attempt
Setting Up Plexiglass Board

Next the calculations were done to figure what numbers to use when drawing in SketchUp to use throughout the template design. This included knowing the dimensions for the plexiglass runners, rectangular prism of template, and the washer system spacing.

The board will be constructed using plexiglass. The plexiglass pieces needed to be attached will be glued together using acrylic glue. Information about using acrylic glue, and safety concerns can be found below.

  • How to use Acrylic Glue
  • MSDS For Arcrylic Glue by Tapplastics
  • The channels underneath the board were made from 1/4" plexiglass runners which were glued using PVC pipe to the base 1/8" plexiglass board. The channels are 1" wide, and as long as the base board, which will depend on the size of the monitor screen we decide to use. The channels should be spread out enough so there 1/4" of space above and below the top of washer. This will allow for the wiring to run fluidly through the channel on the underside of the board, without having excess space.

Cutting Plexiglass

  • We used scoring and a table saw to cut the plexiglass. Scoring worked well for the 1/8" pieces, and the table saw was used for the 1/4" pieces because they were too thick to score and break apart, especially because we needed them to be only about an inch wide.

Next clamps were used to position the pieces

Gluing Runners Onto Board

Steps

  1. Use syringe to apply epoxy to glue the two pieces of plexiglass together.
  2. apply pressure to the plexiglass runners. Applying too much pressure or no pressure will not make a good seal. Make sure to practice to find the right amount of pressure needed.
  3. Use camps so that the plexiglass runners will not move.
  4. Put syringe next to plexiglass seem and the epoxy will seep under the space. Watch video below for example.

**WARNING**

Use gloves, because it is extremely sticky and can damage skin.

Below is a video of the epoxy being applied to the runners.

epoxy and runners

Alternative design

While the epoxy will work to glue the runners to the board we decided to try hot glue to see if it would work. Hot glue did work and was safer and easier to work with.

  1. To glue the runner to the board using hot glue simple apply glue to the runner till its completely covered
  2. Put on top of board and apply pressure till the glue has dried
  3. Scrape off any excess glue that seeped out onto the board


Gluing washers on board
  1. Use hot glue guns
  2. Apply small amount of glue on washer
  3. Turn washer over into appropriate placement

**Warning** When the washer touches the board after it has hot glue on it, you have about 2 seconds before it is stuck there forever.

Drilling Holes
  1. Used a 1/8 inch drill bit to drill each hole.
  2. Used the washer template so that we knew where each hole would go.
  3. When drilling the holes go about half way into the washer

Below is a video of how we drilled the holes drilling holes


Arduino reading beat bearing board switch

Modified Arduino Example: StateChangeDetection. Turned LED to turn on as we placed the ball on washer halves and turn off when removed.

Drawing showing components and wiring

video of working


Wiring Harness
Connecting Grounds
  1. Cut 28 pieces of wire at 2.5"
  2. Cut 4 pieces of wire at 6"
  3. Twist 7 pieces of the shorter wire together and one piece of longer wire at the end (do this 4 times)
  4. Feed the wire where the pieces meet through the holes
  5. With the wire sticking out of the holed wrap it around the washer halves on apply super glue to hole them together

Apply solder in the hole to connect the wire with the washer

Attaching the switched side
  1. Each positive washer has to have a different wire unlike the negative side where they are wired in a continuous path.
  2. Use a ribbon cable to wire the positive just like the negative side except keep the wire on the ribbon cable.
  3. Each positive washer needs a different wire.

Video of the positive side being tested for continuity

Soldering each wire in the ribbon cable to the washer

video of soldering the wire and washer



Serial Monitor and Arrays

The arduino is going to have to communicate with the papilio or the computer running processing in order to coordinate the LCD display under the beat bearing board and perhaps save/load songs, communicate timber, pitch, volume, speed, drum rudiment, etc. The arduino serial library allows the arduino to send and receive information.

The arduino can send information back to the computer through the serial monitor. However, when we selected the serial monitor, the information came back in symbols. What we want is for it to come back the the name of the drum sound that is being play at that moment.

Arrays are going to be important in the development of this code. An array is a list in which each item in the list has a number. The video's example of an array was a stack of papers and each paper has a number. If you want to select one paper, you would select the number it is assigned in the array. More information on arrays can be found here Below is a sample code taken from an tutorial which explains how an array works.

Example Array Code
/*
  Arrays
 
 Demonstrates the use of  an array to hold pin numbers
 in order to iterate over the pins in a sequence. 
 Lights multiple LEDs in sequence, then in reverse.
 
 Unlike the For Loop tutorial, where the pins have to be
 contiguous, here the pins can be in any random order.
 
 The circuit:
 * LEDs from pins 2 through 7 to ground
 
 created 2006
 by David A. Mellis
 modified 30 Aug 2011
 by Tom Igoe 

This example code is in the public domain.
 
 http://www.arduino.cc/en/Tutorial/Array
 */

int timer = 100;           // The higher the number, the slower the timing.
int ledPins[] = { 
  2, 7, 4, 6, 5, 3 };       // an array of pin numbers to which LEDs are attached
int pinCount = 6;           // the number of pins (i.e. the length of the array)

void setup() {
  // the array elements are numbered from 0 to (pinCount - 1).
  // use a for loop to initialize each pin as an output:
  for (int thisPin = 0; thisPin < pinCount; thisPin++)  {
    pinMode(ledPins[thisPin], OUTPUT);      
  }
}

void loop() {
  // loop from the lowest pin to the highest:
  for (int thisPin = 0; thisPin < pinCount; thisPin++) { 
    // turn the pin on:
    digitalWrite(ledPins[thisPin], HIGH);   
    delay(timer);                  
    // turn the pin off:
    digitalWrite(ledPins[thisPin], LOW);    

  }

  // loop from the highest pin to the lowest:
  for (int thisPin = pinCount - 1; thisPin >= 0; thisPin--) { 
    // turn the pin on:
    digitalWrite(ledPins[thisPin], HIGH);
    delay(timer);
    // turn the pin off:
    digitalWrite(ledPins[thisPin], LOW);
  }
}



LCD monitor programming with processing

At first, eight successive versions of the monitor code were made video.

8th version
void setup(){
   setupSD();
   setupCG();
   
  }
  
  void draw(){
    drawSD();
    drawCG();
    
  }
float y = 100;

void setupSD() {
  size(360, 640);  // inverted
  stroke(255);     // moving line color
  frameRate(200);
}

void drawSD() { 
                       // background();    blank reveals fading circles
  y = y - 1; 
  if (y < 0) { 
    y = height; 
  } 
  line(0, y, width, y);  
} 

PGraphics pg;
int barWidth = 90;                //adjust bar width to fit 4
int lastBar = -1;

void setupCG(){
  size(360, 640);    //inverted
  pg = createGraphics(1, 1);  //minimized grey box, now virtually invisible
}

void drawCG(){
  fill(0, 10);                  //duration of circle fade
  rect(0, 0, width, height);
  colorMode(HSB, height, height, height);      //attempts to give circle hue behavior
  stroke(HSB, height, height, height);    //attempts to give stroke hue behavior
  ellipse(mouseX, mouseY, 90, 90);    //dimensions of circle 60 -> 90
  
  pg.beginDraw();
                   //pg.background();    hope to make background transparent
  int ellipse = mouseX / barWidth;      //insert drawH() here, replacing the fill() function of drawCG(). 
    if (ellipse != lastBar) {            //replaced whichBar with ellipse, no change.
    int barX = ellipse * barWidth;
    fill(mouseY, height, height);
    rect(barX, 0, barWidth, height);
    lastBar = ellipse;
  }
  pg.stroke(HSB, height, height, height);        //attempts to give stroke hue behavior
  pg.ellipse(mouseX-120, mouseY-60, 60, 60);
  pg.endDraw();
  
  // Draw the offscreen buffer to the screen with image() 
  
}

Current version is the 11th: Video.

11th Version
void setup(){
   setupSD();
   setupCG();
   setupH();
                       
  }
  
  void draw(){
    drawSD();
    drawCG();
    drawH();
  }


float y = 100;

void setupSD() {
  size(640, 360);  // back to original dimensions
  stroke(255);     // moving line color
  frameRate(200);
}

void drawSD() {         //tried changing y to x (no change)
                       // background();    blank reveals fading circles
  y = y + 1;           //swap sign; goes left to right but now it doesn't repeat
  if (y < 0) {         //if + and >, the line doesn't appear
    y = height;        //height and width are no difference
  } 
  line(y, height, y, 0);      //put 0 at end
} 


PGraphics pg;

void setupCG(){
  size(640, 360);    //back to original
                              //minimized grey box, now virtually invisible
                              //trying to delete this function caused a string of NullPointerException errors under pg.beginDraw();
                              //deleted pg = createGraphics(1, 1); no longer needed
}

void drawCG(){
  fill(0, 12);
  rect(0, 0, width, height);
  fill(255);     //white
  stroke(255);    //white
  ellipse(mouseX, mouseY, 90, 90);    //dimensions of circle 60 -> 90
  
   /* 
  *pg.beginDraw();
  *                   //pg.background();    hope to make background transparent
  *pg.noFill();
  *pg.stroke(255);
  *pg.ellipse(mouseX-120, mouseY-60, 60, 60);
  *pg.endDraw();
  *
  *  // Draw the offscreen buffer to the screen with image() 
  *image(pg, 120, 60); 
  *Erasing this chunk of code got rid of the grey box
  */
}
 
 
int barWidth = 90;                //adjust bar width to fit 4
int lastBar = -1;

void setupH() 
{
  size(640,360);                              //inverted
  colorMode(HSB, height, height, height);  
  noStroke();                                //altered from noStroke();
                                 //background();
}

void drawH()                             //need to change bar to horizontal
{
  int whichBar = mouseX / barWidth;
  if (whichBar != lastBar) {
    int barX = whichBar * barWidth;
    fill(mouseY, height, height);
    rect(barX, 0, barWidth, height);
    lastBar = whichBar;
  }
}


Operate[edit | edit source]

Demo[edit | edit source]

Next Steps[edit | edit source]

  • Build plexiglass beat bearing board (intro class)
  • Fit into the Roland Boss Loop Station world video
  • Expand drum repertoire of midi synthesizers (intro class)
shrink this drum rudiment history into a small paragraph
add the 40 rudiments
go through different drum patterns that drummers practice and bundle them into arduino code
  • go through free software file formats/mechanisms for recording and mixing sounds that can capture (store in a file on hard drive) what this beat bearing synthesizer creates ... figure out what data captured by the program running in the arduino that controls the interface can be stored ... see if it can be translated into an open source format (intro class)
  • Write sample code to use the midi buttons to stop and start a song (intro class)
  • Processing use of the LCD monitor (intro class)
  • Papilio FPGA use LCD monitor (enes-245)
  • Papilio interface to beat bearing board (enes-245)
  • Papilio serial interface to arduino (enes-245)
  1. Write arduino code to cycle through all drum possibilities using the midi shield buttons to stop and start moving through the possibilities
  2. Write arduino code to using the midi shield pots to change tempo
  3. Write arduino code to send signals to processing through usb cable