Quickstart Guide

Setup and Shutdown

There are two things you must always do when you use Minim for audio I/O. Before you call any of the other methods of Minim, you must first call Minim.start(this) so that the library can properly load files from the data folder of your sketch. Additionally, before your program exits, it must close any audio I/O classes you get from Minim. These include AudioPlayer, AudioSample, AudioSnippet, AudioInput, and AudioOutput. A good way to ensure this happens is to define a stop method in your sketch where you close all audio classes. Like this:

void stop()
{
  // an AudioPlayer you got from Minim.loadFile()
  player.close();
  // an AudioInput you got from Minim.getLineIn()
  input.close();
  super.stop();
}

Users of Ess and Sonia should be familiar with this convention. The reason for doing this is because all of the audio I/O is handled in separate threads and they must be allowed to finish in a normal fashion. You might also close an audio class during execution of your program in order to free the resources it has.

Playing A File

One of the main motivaters behind writing Minim was that neither of the available libraries for Processing allowed stereo playback of audio files. Minim to the rescue! It is incredibly easy to play a file using Minim. Just put the file into the data folder of your sketch and then use this code:

import ddf.minim.*;
 
AudioPlayer song;
 
void setup()
{
  size(100, 100);
 
  // always start Minim first!
  Minim.start(this);
 
  // this loads mysong.wav from the data folder
  song = Minim.loadFile("mysong.wav");
  song.play();
}
 
void draw()
{
  background(0);
}
 
void stop()
{
  song.close();
  super.stop();
}

Minim can play all of the typical uncompressed file formats such a WAV, AIFF, and AU. It can also play MP3 files thanks to the inclusion of Javazoom’s MP3SPI package with the distribution. MP3SPI has support for reading ID3 tags, as well, and I intend to make this functionality available in a future release of Minim.

Drawing A Waveform

Something else you might want to do is to use the sample values to draw the waveform of the sound you are playing. All of the classes in Minim that handle input and output of audio data (with the exception of AudioSnippet) derive from a class called AudioSource. This class defines three AudioBuffer members that are then inherited by classes that extend AudioSource. AudioPlayer is just such a class, so you can access these buffers with an AudioPlayer object. The buffers are named left, right, and mix. They contain the left channel, the right channel, and the mix of the left and right channels, respectively. Even if the audio you are playing is mono, all three buffers will be available and return values. When you are playing a mono file you will simply find that all three buffers contain the same information. So, let’s draw a waveform. We can redefine the draw function from up above like this:

void draw()
{
  background(0);
  stroke(255);
  // we draw the waveform by connecting neighbor values with a line
  // we multiply each of the values by 50 
  // because the values in the buffers are normalized
  // this means that they have values between -1 and 1. 
  // If we don't scale them up our waveform 
  // will look more or less like a straight line.
  for(int i = 0; i < song.bufferSize() - 1; i++)
  {
    line(i, 50 + song.left.get(i)*50, i+1, 50 + song.left.get(i+1)*50);
    line(i, 150 + song.right.get(i)*50, i+1, 150 + song.right.get(i+1)*50);
  }
}

This drawing code will work regardless of what kind of input or output class song is because they all extend AudioSource, which provides the buffers. There are two problems with the code we have so far, the window size is set to 100×100 up in setup and we have no idea how long the buffers are (i.e. what number song.bufferSize() returns). The first problem is easy enough to fix, we can set the window dimensions to 512×200. The second problem we can fix by including the buffer length we want in the call to loadFile. Now setup should look like this:

void setup()
{
  size(512, 200);
 
  // always start Minim first!
  Minim.start(this);
 
  // specify 512 for the length of the sample buffers
  // the default buffer size is 1024
  song = Minim.loadFile("mysong.wav", 512);
  song.play();
}

This ensures that we have the same number of values in the buffer as we have screen real-estate to display them. If you don’t provide a value for the buffer size, the buffers will be 1024 samples long.

Drawing a Frequency Spectrum

Something else you might be interested in doing is analyzing your song while it plays and drawing the frequency spectrum. You can do this by using an FFT object. If we include an FFT object in our program and draw the spectrum a little faded out behind the waveform, our program will look like this:

import ddf.minim.*;
import ddf.minim.analysis.*;
 
AudioPlayer song;
FFT fft;
 
void setup()
{
  size(512, 200);
 
  // always start Minim first!
  Minim.start(this);
 
  // specify 512 for the length of the sample buffers
  // the default buffer size is 1024
  song = Minim.loadFile("mysong.wav", 512);
  song.play();
 
  // an FFT needs to know how 
  // long the audio buffers it will be analyzing are
  // and also needs to know 
  // the sample rate of the audio it is analyzing is
  fft = new FFT(song.bufferSize(), song.sampleRate());
}
 
void draw()
{
  background(0);
  // first perform a forward fft on one of song's buffers
  // I'm using the mix buffer
  //  but you can use any one you like
  fft.forward(song.mix);
 
  stroke(255, 0, 0, 128);
  // draw the spectrum as a series of vertical lines
  // I multiple the value of getBand by 4 
  // so that we can see the lines better
  for(int i = 0; i < fft.specSize(); i++)
  {
    line(i, height, i, height - fft.getBand(i)*4);
  }
 
  stroke(255);
  // I draw the waveform by connecting 
  // neighbor values with a line. I multiply 
  // each of the values by 50 
  // because the values in the buffers are normalized
  // this means that they have values between -1 and 1. 
  // If we don't scale them up our waveform 
  // will look more or less like a straight line.
  for(int i = 0; i < song.left.size() - 1; i++)
  {
    line(i, 50 + song.left.get(i)*50, i+1, 50 + song.left.get(i+1)*50);
    line(i, 150 + song.right.get(i)*50, i+1, 150 + song.right.get(i+1)*50);
  }
}
 
void stop()
{
  song.close();
  super.stop();
}

Synthesizing Sound

Finally, just a quick introduction to the oscillator and filter classes available in Minim. The first thing you need to do to play synthesized sound is get an AudioOutput. You do this by asking Minim for one:

AudioOutput out = Minim.getLineOut();

Calling getLineOut with no arguments will return a stereo line out with a buffer size of 1024 samples that plays 16 bit audio at a 44100 Hz sample rate. It’s mostly those first two things you want to worry about. If you want a mono line out or a different buffer size, you can call getLineOut like this:

AudioOutput out = Minim.getLineOut(Minim.MONO);

OR

AudioOutput out = Minim.getLineOut(Minim.STEREO, 512);

where 512 is the length you want the buffers to be. Once you have an AudioOutput, you can attach AudioSignals and AudioEffects to it. Minim comes with quite a few of both. So let’s attach a SquareWave to our AudioOutput and also a LowPassSP filter:

import ddf.minim.*;
import ddf.minim.signals.*;
import ddf.minim.effects.*;
 
AudioOutput out;
SquareWave square;
LowPassSP   lowpass;
 
void setup()
{
  size(512, 200);
  // always start Minim first!
  Minim.start(this);
 
  // get a stereo line out with a sample buffer of 512 samples
  out = Minim.getLineOut(Minim.STEREO, 512);
 
  // create a SquareWave with a frequency of 440 Hz, 
  // an amplitude of 1 and the same sample rate as out
  square = new SquareWave(440, 1, 44100);
 
  // create a LowPassSP filter with a cutoff frequency of 200 Hz 
  // that expects audio with the same sample rate as out
  lowpass = new LowPassSP(200, 44100);
 
  // now we can attach the square wave and the filter to our output
  out.addSignal(square);
  out.addEffect(lowpass);
}
 
void draw()
{
  // you might decide to draw the waveform here or do something else
}
 
// here we provide a way to mute out
// because, let's face it, it's not a very pleasant sound
void keyPressed()
{
  if ( key == 'm' )
  {
    if ( out.isMuted() ) 
    {
      out.unmute();
    }
    else 
    {
      out.mute();
    }
  }
}
 
void stop()
{
  out.close();
  super.stop();
}

That’s it for the Quickstart Guide! I haven’t covered absolutely everything you can do with Minim, but I have touched on some of the main features. You can read the Javadoc to find out about the full API, or continue on to the manual, which provides a more thorough description of Minim than this guide. Additionally, you can browse the online examples, which demonstrate all of the features on Minim in one way or another. All of the online examples are included in the full distrubution of Minim and can be found in File > Sketchbook > Examples > minim of the PDE. If you have any questions, or find any bugs, you can contact me through my website, or through the Processing forum.