I am experimenting with automated music generation. This is a loop sequencer that creates its own loops (given a set of samples) and gradually evolves them overtime. It doesn't make anything close to good music but sometimes the beats aren't that bad either. Quality is also dependent on having good samples (looperman dot com has some good free samples). I have hopes of using genetic algorithms to more "intelligently" alter the loops but that hasn't been implemented yet.
It uses minim but plenty of things could be improved (e.g., not having to stop the samples before the next one plays). I tried to load all the samples in memory but that seems to eat up a ton of memory depending on how many you have.
Samples should be placed in a folder names "samples" in the sketch location.
Code://Simple automated loop sequencer
import processing.core.*;
import ddf.minim.*;
String sample_dir = "C:\\Documents and Settings\\Administrator\\My Documents\\Processing\\EvoMusic\\samples\\";
int presses_left = 0;
int presses_right = 0;
float session_duration = 300000;
boolean start = false;
boolean finished = false;
boolean saved = false;
float start_time = -1;
int index;
int bpm = 300; //This is the programmrd beats-per-minute
int obtained_bpm=0;
int obtained_count = 0;
float measurement_time;
int last_slot;
int slot;
float time_between_beats = 0;
Minim minim;
AudioSample sample;
String[] samples;
PFont myFont;
float time;
Loop current_loop;
void setup() {
size(600, 200);
minim = new Minim(this);
println("Listing samples:: ");
samples = listFileNames(sample_dir);
for (int i=0;i<samples.length;i++) {
println("reading " + samples[i]);
}
current_loop = new Loop(null);
index = 1;
myFont = createFont("verdana", 12);
bpm = 300;
textFont(myFont);
frameRate(60);
}
public void draw() {
background(0);
fill(255);
time = millis() % current_loop.loop_time;
current_loop.loop_time = 60000/bpm * current_loop.loop_size; //2000
slot = int(current_loop.loop_size * time / current_loop.loop_time);
if (slot != last_slot) {
if (slot == 0) {
current_loop.plays_left--;
if (current_loop.plays_left <= 0) {
current_loop = new Loop(current_loop);
}
}
if (slot < current_loop.slots.length) {
if (current_loop.slots[slot] >= 0) {
if (sample != null) sample.close();
sample = minim.loadSample("samples\\" + samples[current_loop.slots[slot]],400);
sample.trigger();
}
}
last_slot = slot;
}
text(time,10,32);
time_between_beats = 60000 / bpm;
text("time between beats: " + time_between_beats,10,53);
text("slot: " + slot,10,73);
text("bpm: " + bpm,10,92);
text("plays left: " + current_loop.plays_left,10,112);
int obtained_bpm = int(60000/time_between_beats);
text("obtained bpm: " + obtained_bpm,10,132);
show_loop(current_loop,time);
}
void show_loop(Loop thisloop,float time) {
int slot_length = 30;
int total_length = int(slot_length * thisloop.loop_size);
int linex = int(total_length * time / thisloop.loop_time);
for (int i=0;i<thisloop.loop_size;i++) {
text(thisloop.slots[i],10+slot_length*i,12);
}
stroke(255,0,0);
line( 9+linex,2, 9+linex,12);
line(10+linex,2,10+linex,12);
line(11+linex,2,11+linex,12);
}
// This method responds to key presses when the
// program window is active: These methods test the
// Znet AT commands and such:
public void keyPressed() {
switch (key) {
case'q':
if (index >= samples.length) index = 0;
println("samples.length: " + samples.length + " index: " + index);
println("samples[" + index + "] = " + samples[index]);
index++;
break;
case 'p':
if (index >= samples.length) index = 0;
println("samples.length: " + samples.length + " index: " + index);
if (sample != null) sample.close();
sample = minim.loadSample("samples\\" + samples[index],400);
sample.trigger();
index++;
break;
case '1':
bpm--;
time_between_beats = 60000 / bpm;
break;
case '2':
bpm++;
time_between_beats = 60000 / bpm;
break;
case 'n':
if (sample != null) sample.close();
current_loop = new Loop(null);
break;
}
}
String[] listFileNames(String dir) {
File file = new File(dir);
if (file.isDirectory()) {
String names[] = file.list();
return names;
} else {
// If it's not a directory
return null;
}
}
public void stop() {
sample.close();
minim.stop();
super.stop();
}
There's one more class you need. I'll attach it in a reply.