Basic Electroacoustics II: Music-Making Systems |
Music G6602Y |
TueThu 3:10-5:00pm |
Spring 2008 |
hello. |
Professor: Douglas Repetto [douglas at music columbia edu] |
TA: Victor Adan [vga2102 at columbia edu] |
hello. |
Our Motto: "Why and how." |
hello. |
syllabus | lectures |
AudioSnippet is good for very simple playback of short sounds. They're loaded into memory, so there's some limit to how many you can load (I seem to have gotten stuck at 32). You just the sound, cue it up, and play it. Note that "1.wav" is a soundfile in a folder called "data" that I made in the sketch's folder. processing will automatically find sound files there. You can also pass a complete path name if you need to be more explicit.
import ddf.minim.*; AudioSnippet snippet; void setup() { //always do this! Minim.start(this); //load sample snippet = Minim.loadSnippet("1.wav"); //we'll play once per second frameRate(1); } void draw() { //this resets the sample back to the beginning //you can also use cue to start at some arbitrary point //in the sample snippet.cue(0); //play it! snippet.play(); } //always do this, including a .close() for each output object you create void stop() { snippet.close(); super.stop(); }
++++++++++++++++++++++++++++++++++++++++++++++++++
As always, it's more flexible if you use variables/arrays:
import ddf.minim.*; //let's use several snippets //we'll also add a looping option to help create a big mess! int numSnippets = 4; AudioSnippet snippets[] = new AudioSnippet[numSnippets]; int frameNum = 0; boolean looping = false; void setup() { //always do this! Minim.start(this); //load samples loadSnippets(numSnippets); //we'll play once per second frameRate(1); } void loadSnippets(int howMany) { for (int i = 0; i < howMany; i++) { //we'll construct the filenames on the fly... //using (i + 1) because our first filename is 1.wav, not 0.wav println("loading snippit: " + (i + 1) + ".wav"); snippets[i] = Minim.loadSnippet((i + 1) + ".wav"); } } void draw() { //this will cycle through our snippets as frameNum increases eternally int snippetToPlay = frameNum % numSnippets; println("doing snippet: " + snippetToPlay); if (looping) { //if we're already looping then we don't need to do anything! if (!snippets[snippetToPlay].isLooping()) { //set our sample back to beginning snippets[snippetToPlay].cue(0); //loop until the end of the world snippets[snippetToPlay].loop(); } } else { //set our sample back to beginning snippets[snippetToPlay].cue(0); //play once snippets[snippetToPlay].play(); } frameNum++; } void mousePressed() { //click to toggle looping on and off looping = !looping; } //always do this, including a .close() for each output object you create void stop() { for (int i = 0; i < numSnippets; i++) snippets[i].close(); super.stop(); }
+++++++++++++++++++++++++++++++++++++++++
If you're doing more complex playback of short samples then you might want to look at AudioSample instead. One important thing that AudioSample gives you is the ability to play multiple copies of the same sound at one time. AudioSnippet will restart the sample if you play it again before it's finished. AudioSample will simply play another copy along with the first.
import ddf.minim.*; //okay, let's use AudioSamples this time //we'll put a grid on the screen that lets you trigger //any of the four sounds repeatedly String filenames[] = {"counting.wav", "letters.wav", "woof.wav", "meow.wav"}; int numSnippets = filenames.length; AudioSample snippets[] = new AudioSample[numSnippets]; int frameNum = 0; void setup() { //we'll make a grid with squares 100x100 pixels for each sample size(numSnippets/2 * 100, 200); //always do this! Minim.start(this); //load samples loadSnippets(numSnippets); frameRate(10); //let's just draw the screen once since it doesn't change. firstDraw(); } void loadSnippets(int howMany) { for (int i = 0; i < numSnippets; i++) { snippets[i] = Minim.loadSample(filenames[i]); } } void firstDraw() { int c = 0; for (int i = 0; i < numSnippets/2; i++) { fill(c); rect(i * 100, 0, 100, 100); if (c == 0) c = 255; else c = 0; fill(c); rect(i * 100, 100, 100, 100); } } void draw() { //we only start a new sound if the mouse button is pressed if (mousePressed == false) return; int squareNum = whichSquare(); println("we're in square: " + squareNum); snippets[squareNum].trigger(); } //figure out which square the mouse is in! int whichSquare() { //we'll use -1 to indicate that we haven't found the square yet int squareNum = -1; //println("x: " + mouseX + " y: " + mouseY); for (int i = 0; i < numSnippets; i++) { int squareLeft = 0; int squareRight = 0; int squareTop = 0; int squareBottom = 0; if (i % 2 == 0) { squareLeft = i/2 * 100; squareRight = squareLeft + 100; squareTop = 0; squareBottom = 100; } if (i % 2 == 1) { squareLeft = i/2 * 100; squareRight = squareLeft + 100; squareTop = 100; squareBottom = 200; } //println("i: " + i + " L: " + squareLeft + " R: " + squareRight + " T: " + squareTop + " B: " + squareBottom); if (mouseX >= squareLeft && mouseX <= squareRight) { if (mouseY >= squareTop && mouseY <= squareBottom) squareNum = i; } } return squareNum; } //always do this, including a .close() for each output object you create void stop() { for (int i = 0; i < numSnippets; i++) snippets[i].close(); super.stop(); }
+++++++++++++++++++++++++++++
Longer samples should be played from disc rather than loaded into memory (although exactly what counts as a "long" sample really depends on how much RAM you have to play with...) Minim works well with different kinds of files, here we'll use an mp3, but we'll treat it the same way we would a .wav or .aiff. We'll run our sound through a filter too, YOWZA, NOW THAT'S MUSIC!!!
//notice we have an extra import! import ddf.minim.*; import ddf.minim.effects.*; //let's play back a longer file with AudioPlayer and run it through a filter, //the parameters of which are tweaked by mouse position AudioPlayer player; BandPass filter; byte c = 0; void setup() { size(500, 500); //always do this! Minim.start(this); //load the soundfile player = Minim.loadFile("mann.mp3"); //start it looping player.loop(); //create the bandpass filter with: //300Hz center freq //20Hz bandwidth filter = new BandPass(300, 20, player.sampleRate()); //add it to the player so that the audio from the player passes //through the filter player.addEffect(filter); //reasonable update rate so that our changes in freq/bw are smooth frameRate(10); //let's just draw the screen once since it doesn't change. firstDraw(); } void firstDraw() { background(0); } void draw() { //+1 is to avoid divide by zero errors! int divisor = int(random(width/5)) + 1; int xIncr = width/divisor; int yIncr = height/divisor; for (int i = 0; i < 10; i++) { stroke(c, c, c); c++; line(i * xIncr, 0, i * xIncr, height); line(0, i * yIncr, width, i * yIncr); } //we'll square mouseX to get better sensitivity in the low end int x = mouseX * mouseX; int y = mouseY; //map freq from 60 to 1000 Hz //and bandwidth from 50 to 250Hz int freq = int(map(x, 0, width * width, 60, 1000)); int bandwidth = int(map(y, 0, height, 50, 250)); filter.setFreq(freq); filter.setBandWidth(bandwidth); if (mousePressed) println("x: " + x + " freq: " + freq + " y: " + y + " bandwidth: " + bandwidth); } //always do this, including a .close() for each output object you create void stop() { player.close(); super.stop(); }
+++++++++++++++++++++++++++++++++++++
One last example: infinite beets!!!
+++++++++++++++++++++++++++++++++++++