Assignment 9.3

posted Jul 30, 2010, 11:41 PM by Unknown user   [ updated Jul 31, 2010, 12:10 AM ]
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
  if ( key == 'c' ) snare.trigger();
  if ( key == 'b' ) hihat.trigger();
  if ( key == 'n' ) crash.trigger();
  if ( key == 'x' ) cowbell.trigger();    //needs more cowbell
  if ( key == 'm') cowbell.trigger();    //there it is
  if ( key == 'v' ) ride.trigger();
  if ( key == 'o' ) {
    if (loopRecorder.isRecording() == true || loopRecorder2.isRecording() == true) {
      if (timesRecorded > 0) {
        loopRecorder2.endRecord();        //if recording and have recorded previous loops, save as recording2
        loopRecorder2.save();
        loopPlayer.pause();
      } else {
        loopRecorder.endRecord();        //else save as recording
        loopRecorder.save();
      }
      timesRecorded++;                        //increment counter
      if (timesRecorded > 0) loopPlayer = minim.loadFile("../recording.wav", 2048);        //reload player files
      if (timesRecorded > 1) loopPlayer = minim.loadFile("../recording2.wav", 2048);
    } else {
      if (timesRecorded > 0) {                //if not currently recording, start recording
        loopRecorder2.beginRecord();
        loopPlayer = minim.loadFile("../recording.wav", 2048);
        loopPlayer.play();
      } else {
        loopRecorder.beginRecord();
      }
    }
  }
  if ( key == 'p' && timesRecorded > 0) {        //if pressed key p and have recorded a track
    if (loopPlayer.isPlaying()) {
      loopPlayer.pause();                                //pause it if it's playing
      if (timesRecorded > 1) loopPlayer2.pause();
    } else {
      loopPlayer = minim.loadFile("../recording.wav", 2048);
      loopPlayer.loop();                                                        //but load and play the track if it's not playing
    } 
    if (timesRecorded > 1) {
      loopPlayer2 = minim.loadFile("../recording2.wav", 2048);    //and play recording2 if it exists
      loopPlayer2.loop();
    } 
  }
}

void keyReleased() {                                //if key is released
  if (!(key-97 > 26) && !(key-97 < 0)) {        //set the frequency for the sinewave class corresponding to that key to 0
    if (keysToNotes[int(key)-97] != 0) {
      sine[int(key)-97].setFreq(0);
    }
  }
}

void stop()
{
  out.close();
  minim.stop();
  
  super.stop();
}

PITCHES FILE:
 
 
 /*************************************************
  * Public Constants
  *************************************************/

 public static int NOTE_B0  =31;        //these need to be public static ints
 public static int NOTE_C1  =33;        //because apparently lame Java doesn't
 public static int NOTE_CS1 =35;       //have a preprocessor!! Obj-C is so much better
 public static int NOTE_D1  =37;
 public static int NOTE_DS1 =39;
 public static int NOTE_E1  =41;
 public static int NOTE_F1  =44;
 public static int NOTE_FS1 =46;
 public static int NOTE_G1  =49;
 public static int NOTE_GS1 =52;
 public static int NOTE_A1  =55;
 public static int NOTE_AS1 =58;
 public static int NOTE_B1  =62;
 public static int NOTE_C2  =65;
 public static int NOTE_CS2 =69;
 public static int NOTE_D2  =73;
 public static int NOTE_DS2 =78;
 public static int NOTE_E2  =82;
 public static int NOTE_F2  =87;
 public static int NOTE_FS2 =93;
 public static int NOTE_G2  =98;
 public static int NOTE_GS2 =104;
 public static int NOTE_A2  =110;
 public static int NOTE_AS2 =117;
 public static int NOTE_B2  =123;
 public static int NOTE_C3  =131;
 public static int NOTE_CS3 =139;
 public static int NOTE_D3  =147;
 public static int NOTE_DS3 =156;
 public static int NOTE_E3  =165;
 public static int NOTE_F3  =175;
 public static int NOTE_FS3 =185;
 public static int NOTE_G3  =196;
 public static int NOTE_GS3 =208;
 public static int NOTE_A3  =220;
 public static int NOTE_AS3 =233;
 public static int NOTE_B3  =247;
 public static int NOTE_C4  =262;
 public static int NOTE_CS4 =277;
 public static int NOTE_D4  =294;
 public static int NOTE_DS4 =311;
 public static int NOTE_E4  =330;
 public static int NOTE_F4  =349;
 public static int NOTE_FS4 =370;
 public static int NOTE_G4  =392;
 public static int NOTE_GS4 =415;
 public static int NOTE_A4  =440;
 public static int NOTE_AS4 =466;
 public static int NOTE_B4  =494;
 public static int NOTE_C5  =523;
 public static int NOTE_CS5 =554;
 public static int NOTE_D5  =587;
 public static int NOTE_DS5 =622;
 public static int NOTE_E5  =659;
 public static int NOTE_F5  =698;
 public static int NOTE_FS5 =740;
 public static int NOTE_G5  =784;
 public static int NOTE_GS5 =831;
 public static int NOTE_A5  =880;
 public static int NOTE_AS5 =932;
 public static int NOTE_B5  =988;
 public static int NOTE_C6  =1047;
 public static int NOTE_CS6 =1109;
 public static int NOTE_D6  =1175;
 public static int NOTE_DS6 =1245;
 public static int NOTE_E6  =1319;
 public static int NOTE_F6  =1397;
 public static int NOTE_FS6 =1480;
 public static int NOTE_G6  =1568;
 public static int NOTE_GS6 =1661;
 public static int NOTE_A6  =1760;
 public static int NOTE_AS6 =1865;
 public static int NOTE_B6  =1976;
 public static int NOTE_C7  =2093;
 public static int NOTE_CS7 =2217;
 public static int NOTE_D7  =2349;
 public static int NOTE_DS7 =2489;
 public static int NOTE_E7  =2637;
 public static int NOTE_F7  =2794;
 public static int NOTE_FS7 =2960;
 public static int NOTE_G7  =3136;
 public static int NOTE_GS7 =3322;
 public static int NOTE_A7  =3520;
 public static int NOTE_AS7 =3729;
 public static int NOTE_B7  =3951;
 public static int NOTE_C8  =4186;
 public static int NOTE_CS8 =4435;
 public static int NOTE_D8  =4699;
 public static int NOTE_DS8 =4978;
 
 //table for key to note conversion
int[] keysToNotes = {NOTE_C5, 0, 0, NOTE_E5, NOTE_DS5, NOTE_F5, NOTE_G5, 
      NOTE_A5, 0, NOTE_B5, NOTE_C6, 0, 0, 0, 0, 0, NOTE_B4, 0, 
      NOTE_D5, NOTE_FS5, NOTE_AS5, 0, NOTE_CS5, 0, NOTE_GS5, 0};
 
ċ
Synth.swf
(1698k)
Unknown user,
Jul 31, 2010, 12:09 AM
Comments