nov 19
Today I worked on splicing in a third input channel to my previous code.
I also worked on also mapping the input to an equal tempered scale.
(see new functions, midi_to_hertz, map_to_midi_note, input_to_midi_hertz and rounded_input_to_midi_hertz)
Arduino code:
//multiple_analog_output_11_04_11
int pin_0 = 0;
int pin_1 = 1;
int pin_2 = 2;
void setup() {
// initialize the serial communication:
Serial.begin(9600);
}
void loop() {
// send the value of analog input 0:
Serial.print("<");
Serial.print(analogRead(pin_0));
Serial.print(",");
Serial.print(analogRead(pin_1));
Serial.print(",");
Serial.print(analogRead(pin_2));
Serial.print(">\n");
// wait a bit for the analog-to-digital converter
// to stabilize after the last reading:
delay(20);
}
Processing code:
// [Dual] Graphing sketch (modified to graph two inputs and output two sine waves (using Minim)
// This program takes ASCII-encoded strings
// from the serial port at 9600 baud and graphs them. It expects values in the
// range 0 to 1023 [in a comma separated list (example: "10, 20, 30")], followed by a newline, or newline and carriage return
// Created 20 Apr 2005
// Updated 18 Jan 2008
// by Tom Igoe
// This example code is in the public domain.
//MODIFIED BY: Aaron Evan-Browning 11-04-11
import ddf.minim.*;
import ddf.minim.signals.*;
//import controlP5.*;
import processing.serial.*;
Minim minim;
AudioOutput out;
SineWave sine1;
SineWave sine2;
SineWave sine3;
int num_inputs = 3;
//sin1
float sin1Amp = 0.33; //these floats were public. I'm not sure why that was necessary. It was probably for the controlP5 GUI.
float sin1Pan = 0;
float sin1Freq = 440;
int sin1Glide = 100;
int sin1_multiplier = 1;
//sin2
float sin2Amp = 0.33;
float sin2Pan = 1;
float sin2Freq = 330;
int sin2Glide = 50; //changed temporarily to be shorter so there is more of a glissando effect.
int sin2_multiplier = 1;
//sin3
float sin3Amp = 0.33;
float sin3Pan = 1;
float sin3Freq = 220;
int sin3Glide = 50; //changed temporarily
int sin3_multiplier = 1;
Serial myPort; // The serial port
public int xPos = 1; // horizontal position of the graph
int x_size = 800; // x and y canvas sizes
int y_size = 500;
void setup () {
// set the window size:
size (x_size, y_size); // this line also had ", P3D" as a parameter of size. We're just using 2 dimensions right now.
minim = new Minim(this);
// get a stereo line out from Minim with a 2048 sample buffer, default sample rate is 44100, bit depth is 16
out = minim.getLineOut(Minim.STEREO, 2048);
// create a sine wave Oscillator, set to 440 Hz, at 0.5 amplitude, sample rate 44100 to match the line out
sine1 = new SineWave(440, 0.5, out.sampleRate());
sine2 = new SineWave(330, 0.5, out.sampleRate());
sine3 = new SineWave(220, 0.5, out.sampleRate());
// set the portamento speed on the oscillator to 200 milliseconds
sine1.portamento(sin1Glide);
sine2.portamento(sin2Glide);
sine3.portamento(sin3Glide);
// add the oscillator to the line out
out.addSignal(sine1);
out.addSignal(sine2);
out.addSignal(sine3);
// List all the available serial ports
println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
// don't generate a serialEvent() unless you get a newline character:
myPort.bufferUntil('\n');
// set inital background:
background(0); //sets the background color
}
void debug_print (int incomingValues[]) {
print(incomingValues[0]);
print(",");
println(incomingValues[1]);
print(",");
println(incomingValues[2]);
}
int draw_graph (int xPos, float graphline1, float graphline2, float graphline3) {
stroke(0,0,255);
line(xPos, height, xPos, (height - graphline1));
stroke(0, 255, 0, 75);
line(xPos, height, xPos, (height - graphline2));
stroke(255, 0, 0, 75);
line(xPos, height, xPos, (height - graphline3));
if (xPos >= width) {
xPos = 0;
background(0);
}
else {
// increment the horizontal position:
xPos++;
}
return xPos;
}
float midi_to_hertz (float number) {
//returns the hertz value of the equivalent midi note
//midi_to_hertz(69) returns 440 (A above middle C)
float hertz = 440 * pow(2, ((number - 69)/12));
return hertz;
}
float map_to_midi_note (float analog_input) {
float outfreq = 0.0;
outfreq = map(analog_input, 0, 1023, 57, 81); //******changed temporarily to a smaller range.
return outfreq;
}
float input_to_midi_hertz (float analog_input){
float outfreq = midi_to_hertz(map_to_midi_note(analog_input));
return outfreq;
}
float rounded_input_to_midi_hertz (float analog_input){
//this just rounds down the value of map_to_midi() so that the notes fall on the nearest pitch.
float outfreq = midi_to_hertz(int(map_to_midi_note(analog_input)));
return outfreq;
}
void draw () {
// everything happens in the serialEvent()
}
void serialEvent (Serial myPort) {
// get the ASCII string:
String inString = myPort.readStringUntil('\n');
inString = trim(inString); //surprisingly important.
if (inString != null) {
if (inString.length() > 0) {
println("\n" + inString);
//test whether the string begins with '<' and ends with '>' :
if((inString.charAt(0) == '<') && (inString.charAt(inString.length()-1) == '>')){
// convert to an array of ints, trimming off the '<' and '>' :
int incomingValues[] = int(split((inString.substring(1, inString.length()-1)), ","));
if(incomingValues.length != num_inputs){
print("incomingValues.length does not equal num_inputs!");
}
else{
debug_print(incomingValues);
float graphline1 = map(incomingValues[0], 0, 1023, 0, height); //possibly separate out the outputs into three horizontal bars?
float graphline2 = map(incomingValues[1], 0, 1023, 0, height);
float graphline3 = map(incomingValues[2], 0, 1023, 0, height);
float outfreqsin1 = rounded_input_to_midi_hertz(incomingValues[0]); //using rounded_input_to_midi rather than input_to_midi.
float outfreqsin2 = rounded_input_to_midi_hertz(incomingValues[1]);
float outfreqsin3 = rounded_input_to_midi_hertz(incomingValues[2]);
sine1.setFreq(outfreqsin1);
sine2.setFreq(outfreqsin2);
sine3.setFreq(outfreqsin3);
// draw the line:
xPos = draw_graph(xPos, graphline1, graphline2, graphline3);
}
}
}
delay(10);
}
}
void stop()
{
out.close();
minim.stop();
super.stop();
}