Assignment 9.3

In the interest of creating larger, more complex projects as opposed to more frequent but simpler ones, I more or less combined 9.2 and 9.3 into a techno synth lead / drum machine / loop machine. The top 2 rows of keys act as a piano-type keyboard to control the synth, the bottom keys are a drum machine, and keys o and p control the loop ('o' starts and stops the loop because it is a circle, the standard symbol for record, and 'p' plays / pauses the loop). it can stack up to 3 tracks on top of each other (2 recorded and the one you are playing) although due to limitations in the minim library, the drum machine cannot be looped back. I wanted this to be able to play chords so I created a seperate sineWave instance for each key (although the audio does start clipping with the bigger chords, so if you want to rock out some jazz on this thing for whatever reason, just set the volume lower). At any rate, enjoy the product of about a day's worth of poking around in the minim documentation and subsequent frustrated debugging. I included an swf video of me hacking through the synth lead and drum part of "kids" by MGMT (great song).

Code:

import ddf.minim.*;

import ddf.minim.signals.*;

Minim minim; //sound library base class

AudioOutput out; //output channel for sinewaves

SineWave[] sine; //array of SineWave oscillator subclasses

AudioRecorder loopRecorder; //recorder objects for 2 loop tracks

AudioRecorder loopRecorder2;

AudioPlayer loopPlayer; //player objects for loop tracks

AudioPlayer loopPlayer2;

byte timesRecorded; //simple counter that goes up every time a track is recorded

AudioSample kick; //various audio samples for the drum machine

AudioSample snare;

AudioSample cowbell;

AudioSample hihat;

AudioSample crash;

AudioSample ride;

void setup()

{

size(512, 200, P2D);

minim = new Minim(this);

// get a line out from Minim, default bufferSize is 1024, default sample rate is 44100, bit depth is 16

out = minim.getLineOut(Minim.MONO);

//set loopRecorders to record "out" to file "recording(2).wav", with buffering true

loopRecorder = minim.createRecorder(out, "recording.wav", true);

loopRecorder2 = minim.createRecorder(out, "recording2.wav", true);

//allocate sinewaves

sine = new SineWave[26];

for(int i = 0; i < 26; i++) {

// create a sine wave Oscillator, set to respective, at 0.5 amplitude, sample rate from line out

sine[i] = new SineWave(0, 0.5, out.sampleRate());

// set the portamento speed on the oscillator to 200 milliseconds

sine[i].portamento(30);

// add the oscillator to the line out

out.addSignal(sine[i]);

}

//load samples from files into 256 byte buffers

kick = minim.loadSample("bassdrum.wav", 256);

snare = minim.loadSample("snare.wav", 256);

hihat = minim.loadSample("hihat.wav", 256);

crash = minim.loadSample("crash.wav", 256);

ride = minim.loadSample("ride.wav", 256);

cowbell = minim.loadSample("cowbell.wav", 256);

}

void draw()

{

make background green if playing, red if recording, black otherwise

if (timesRecorded > 0) {

if (loopRecorder.isRecording() || loopRecorder2.isRecording())

background(255, 0, 0);

else if (loopPlayer.isPlaying())

background(0, 255, 0);

else

background(0);

} else {

if (loopRecorder.isRecording())

background(255, 0, 0);

else

background(0);

}

stroke(255);

// draw the waveforms

for(int i = 0; i < out.bufferSize() - 1; i++)

{

float x1 = map(i, 0, out.bufferSize(), 0, width);

float x2 = map(i+1, 0, out.bufferSize(), 0, width);

line(x1, 50 + out.left.get(i)*50, x2, 50 + out.left.get(i+1)*50);

line(x1, 150 + out.right.get(i)*50, x2, 150 + out.right.get(i+1)*50);

}

// if loop starts getting out of sync while recording, end and save recording for playback

if (timesRecorded > 0) {

if (!loopPlayer.isPlaying() && loopRecorder2.isRecording()) {

loopRecorder2.endRecord();

loopRecorder2.save();

timesRecorded++;

}

}

}

void keyPressed() {

if (!(key-97 > 26) && !(key-97 < 0)) { //if 'key' == ASCII code of any of the letters of the alphabet (lowercase)

if (keysToNotes[int(key)-97] != 0) { //and the key corresponds to a note

sine[int(key)-97].setFreq(keysToNotes[int(key)-97]); //set the frequency to that note, based on the key's respective frequency in the keysToNotes array

}

}

if ( key == 'z' ) kick.trigger(); //if the key corresponds to a drum piece, play the clip