Now this here works purty good. I try to post a video tonight.
/**
* MusicalBlinkyLights
* by Scott Kovaleski
*
* Make an mp3 player and analyzer to blink some strings of lights.
*/
import processing.serial.*;
import ddf.minim.analysis.*;
import ddf.minim.*;
Serial myPort; // Create a Serial port object
AudioPlayer player; // Create an audio player object
Minim minim; // This one has the FFT stuff in it
FFT fft; // FFT object
BeatDetect beat;
BeatListener bl;
String windowName;
int nChannel = 1; // number of lighting channels for magnitude info
String outString; // string of 1s and 0s to send to the Arduino
void setup()
{
size(512, 200, P2D); // sets up a window
minim = new Minim(this); // set up a Minim object
// load a file, give the AudioPlayer buffers that are 1024 samples
long
// player = minim.loadFile("groove.mp3");
// load a file, give the AudioPlayer buffers that are 2048 samples
long
player = minim.loadFile("FunkyKingston.mp3", 2048);
player.loop(); // play the file on a loop
//
player.play(); // play the file one time through
// create an FFT object that has a time-domain buffer the same size
as player's sample buffer
// note that this needs to be a power of two and that it means the
size of the spectrum
// will be 512. see the online tutorial for more info.
fft = new FFT(player.bufferSize(), player.sampleRate());
fft.linAverages(nChannel); // do nchannel averages over the
spectrum
textFont(createFont("SanSerif", 12));
windowName = "None";
// a beat detection object that is FREQ_ENERGY mode that
// expects buffers the length of song's buffer size
// and samples captured at songs's sample rate
beat = new BeatDetect(player.bufferSize(), player.sampleRate());
// set the sensitivity to 300 milliseconds
// After a beat has been detected, the algorithm will wait for 300
milliseconds
// before allowing another beat to be reported. You can use this to
dampen the
// algorithm if it is giving too many false-positives. The default
value is 10,
// which is essentially no damping. If you try to set the
sensitivity to a negative value,
// an error will be reported and it will be set to 10 instead.
beat.setSensitivity(100);
// make a new beat listener, so that we won't miss any buffers for
the analysis
bl = new BeatListener(beat, player);
// I know that the first port in the serial list on my mac
// is usually my Arduino, so I open Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
println(portName);
myPort = new Serial(this, portName, 9600);
}
void draw()
{
background(0); // black window background
stroke(255); // white lines on the window
// draw the waveforms
// the values returned by left.get() and right.get() will be between
-1 and 1,
// so we need to scale them up to see the waveform
// note that if the file is MONO, left.get() and right.get() will
return the same value
for(int i = 0; i < player.left.size()-1; i++)
{
line(i, 50 + player.left.get(i)*50, i+1, 50 + player.left.get(i
+1)*50);
line(i, 150 + player.right.get(i)*50, i+1, 150 + player.right.get(i
+1)*50);
}
// perform a forward FFT on the samples in player's left buffer
// note that if player were a MONO file, this would be the same as
using player.right or player.left
fft.forward(player.mix);
for(int i = 0; i < fft.specSize(); i++)
{
// draw the line for frequency band i, scaling it by 4 so we can
see it a bit better
line(i, height, i, height - fft.getBand(i)*4);
}
fill(255);
// keep us informed about the window being used
text("The window being used is: " + windowName, 5, 20);
/* Here is one way to do this
// average fft info into bands and send it to the microcontroller to
switch on the lights
for (int i=0; i < fft.avgSize(); i++) {
// stores the on or off info in binary form in outstring. A string
// of 8-1s and 0s for ons and offs
if (fft.getAvg(i) > 1) outString += 1;
else outString += 0;
}
*/
/* Here is another way to do this
// Using the lowest band average, turn on the lights
int num = int(fft.getAvg(0));
if (num > nChannel) num = nChannel;
for (int i=0; i<num; i++) outString += 1;
if (num < nChannel) for (int i=num; i<nChannel; i++) outString += 0;
*/
// Using the lowest band average, turn on the lights
int num = int(fft.getAvg(0));
if (num > 2) num = 2;
for (int i=0; i<num; i++) outString += 1;
if (num < 2) for (int i=num; i<2; i++) outString += 0;
if (beat.isKick()) {
outString += 1;
outString += 1;
} else {
outString += 0;
outString += 0;
}
if (beat.isSnare()) {
outString += 1;
outString += 1;
} else {
outString += 0;
outString += 0;
}
if (beat.isHat()) {
outString += 1;
outString += 1;
} else {
outString += 0;
outString += 0;
}
// Write it out to the Arduino
myPort.write(outString);
print(outString+", ");
println(fft.getAvg(0));
// Clear outstring and wait a little to improve serial coms. This
part sucks, makes sync less good.
outString="";
delay(200);
}
void keyReleased()
{
if ( key == 'w' )
{
// a Hamming window can be used to shape the sample buffer that is
passed to the FFT
// this can reduce the amount of noise in the spectrum
fft.window(FFT.HAMMING);
windowName = "Hamming";
}
if ( key == 'e' )
{
fft.window(FFT.NONE);
windowName = "None";
}
}
void stop()
{
// always close Minim audio classes when you are done with them
player.close();
minim.stop();
super.stop();
}
class BeatListener implements AudioListener
{
private BeatDetect beat;
private AudioPlayer source;
BeatListener(BeatDetect beat, AudioPlayer source)
{
this.source = source;
this.source.addListener(this);
this.beat = beat;
}
void samples(float[] samps)
{
beat.detect(source.mix);
}
void samples(float[] sampsL, float[] sampsR)
{
beat.detect(source.mix);
}
On Dec 18, 5:17 pm,
Scott.Kovale...@gmail.com wrote:
> FYI, programming light blinking in an automated and intelligent way !=
> trivial.
>