Manual: Minim

[ javadoc | examples ]

Minim is the name of the audio library you are reading about. Minim is a class in the library that provided a bunch of methods that you can call to get audio resources from the system. To use it, you must declare a variable of type Minim before your setup() function and then instantiate a Minim object, , passing this as the argument. You must do this so that Minim can initialize some things and have access to the data folder of your sketch.

Code Sample

import ddf.minim.*;
 
Minim minim;
 
void setup()
{
  size(100, 100);
 
  minim = new Minim(this);
}
 
void draw()
{
}

Obtaining Audio Resources From Minim

There are four things you can do with Minim: play an audio file, play synthesized audio, monitor audio input, and record audio to disk. All of these things are handled by different classes in the library and instances of those classes are all obtained by calling the appropriate methods of Minim.

Loading An Audio File

There are three different classes for playing an audio file, each designed to address a particular kind of playback. I will devote a section to each class, so for now just know that they are: AudioSnippet, AudioSample, and AudioPlayer. Rather than creating new instances of these classes by using the new keyword, you create them by calling one of the methods of Minim. They are as follows:

loadSnippet(String filename)
loadSample(String filename)
loadSample(String filename, int bufferSize)
loadFile(String filename)
loadFile(String filename, int bufferSize)

loadSnippet returns an AudioSnippet, loadSample returns an AudioSample, and loadFile returns an AudioPlayer. In all cases filename is either the name of an audio file in your sketch’s data folder, an absolute path to an audio file, or a URL that returns an audio file (like an mp3 file on a server or even the URL of an internet radio station). bufferSize is how large you want the sample buffers of the returned object to be. The size of the actual audio buffer used by the system will be proportional to bufferSize, so you can achieve somewhat lower latency by requesting smaller buffers. A good value for bufferSize is 1024, which is how large the sample buffers will be if you do not specify a size.

Code Sample

import ddf.minim.*;
 
Minim minim;
AudioPlayer in;
 
void setup()
{
  size(512, 200);
  // instantiate a Minim object
  minim = new Minim(this);
  // load a file, default sample buffer size is 1024
  in = minim.loadFile("music.mp3");
  // play the file
  in.play();
}
 
void draw()
{
  // do whatever you do here
}
 
void stop()
{
  // always close audio I/O classes
  in.close();
  // always stop your Minim object
  minim.stop();
 
  super.stop();
}

Getting An AudioOutput

Minim provides the class AudioOutput for the playback of synthesized audio. This is audio that is created on the fly by your program and then fed to the speakers. AudioOutput can handle both mono and stereo audio and you can indicate which kind you will be synthesizing when you call one of the methods of Minim that is used to obtain an AudioOutput. Those methods are as follows:

getLineOut()
getLineOut(int type)
getLineOut(int type, int bufferSize)
getLineOut(int type, int bufferSize, float sampleRate)
getLineOut(int type, int bufferSize, float sampleRate, int bitDepth)

type indicates whether you want a stereo or mono AudioOuput. You should use either Minim.MONO or Minim.STEREO as the value for this argument. The default value for type (i.e. what will be used in the case of the method with no arguments) is Minim.STEREO. bufferSize, as above, is how large you want the sample buffers to be. The default value of bufferSize is 1024. sampleRate is what the sample rate of your synthesized audio will be. The default value for sampleRate is 44100. bitDepth is what the bit depth of your synthesized audio will be. Currently, the only acceptable values for bitDepth are 8 and 16. The default value for bitDepth is 16. It should also be noted that the parameters of this method are describing the attributes that you want your output to have and it may be the case that audio hardware of your machine doesn’t support the particular set of attributes you care about, in which case these method will return null. When this happens it doesn’t necessarily mean that you can’t get a output at all, just that you asked for an unavailable configuration.

Sample Code

import ddf.minim.*;
import ddf.minim.signals.*;
 
Minim minim;
AudioOutput out;
SineWave sine;
 
void setup()
{
  size(512, 200);
  // instantiate a Minim object
  minim = new Minim(this);
  // get a line out from Minim, 
  // default sample rate is 44100, bit depth is 16
  out = minim.getLineOut(Minim.STEREO, 512);
  // create a sine wave Oscillator, set to 440 Hz, at 0.5 amplitude, 
  // sample rate 44100 to match the line out
  sine = new SineWave(440, 0.5, 44100);
  // add the oscillator to the line out
  out.addSignal(sine);
}
 
void draw()
{
  // do whatever you are going to do
}
 
void stop()
{
  // always closes audio I/O classes
  out.close();
  // always stop your Minim object
  minim.stop();
 
  super.stop();
}

Getting An AudioInput

Minim provides the class AudioInput for monitoring the user’s current record source (this is often set in the sound card control panel). There is currently no way to request a specific input, such as the microphone or the line-in, and what you actually get a handle on is not entirely consistent across platforms. Nevertheless, the methods for obtaining an AudioIutput look almost exactly like the ones for obtaining an AudioOutput:

getLineIn()
getLineIn(int type)
getLineIn(int type, int bufferSize)
getLineIn(int type, int bufferSize, float sampleRate)
getLineIn(int type, int bufferSize, float sampleRate, int bitDepth)

type indicates whether you want a stereo or mono AudioInput. You should use either Minim.MONO or Minim.STEREO as the value for this argument. The default value for type (i.e. what will be used in the case of the method with no arguments) is Minim.STEREO. bufferSize is how large you want the sample buffers to be. The default value of bufferSize is 1024. sampleRate is what the sample rate of your synthesized audio will be. The default value for sampleRate is 44100. bitDepth is what the bit depth of your synthesized audio will be. Currently, the only acceptable values for bitDepth are 8 and 16. The default value for bitDepth is 16. It should also be noted that the parameters of this method are describing the attributes that you want your input to have and it may be the case that audio hardware of your machine doesn’t support the particular set of attributes you care about, in which case these methods will return null. When this happens it doesn’t necessarily mean that you can’t get a input at all, just that you asked for an unavailable configuration.

Sample Code

import ddf.minim.*;
 
Minim minim;
AudioInput in;
 
void setup()
{
  size(512, 200);
  // instatiate a Minim object
  minim = new Minim(this);
  // get a line out from Minim, 
  // default sample rate is 44100, bit depth is 16
  in = minim.getLineIn(Minim.STEREO, 512);
}
 
void draw()
{
  // do whatever you are going to do
}
 
void stop()
{
  // always close audio I/O classes
  in.close();
  // always stop your Minim object
  minim.stop();
 
  super.stop();
}

Creating An AudioRecorder

Minim provides the class AudioRecorder for recording audio data to disk. The details for how to use this class will be covered later, here is the method used to obtain an AudioRecorder:

createRecorder(Recordable source, String filename, boolean buffered)

source is the Recordable object that you want to use as the record source. filename is the name of the file, including the extension, to save to. buffered indicates whether you want to use buffered recording or not (see the AudioRecorder section).

Sample Code

import ddf.minim.*;
 
Minim minim;
AudioInput in;
AudioRecorder fout;
 
void setup()
{
  size(512, 400);
 
  minim = new Minim(this);
 
  // get a stereo line-in: sample buffer length of 512
  // default sample rate is 44100, default bit depth is 16
  in = minim.getLineIn(Minim.STEREO, 512);
  // get a recorder that will record from in to the 
  // filename specified using buffered recording
  fout = minim.createRecorder(in, "myrecording.wav", true);
}
 
void draw()
{
  // do whatever you're going to do
}
 
void keyReleased()
{
  // maybe set up keybindings to start and stop recording
  // and then save to disk
}
 
void stop()
{
  // always close audio I/O classes
  in.close();
  // always stop your Minim object
  minim.stop();
 
  super.stop();
}

Setting the System Mixers

Javasound provides access to specific input and outputs of a computer’s audio system through the use of an object called a Mixer. If you want the sound from your application to go to a particular output, or you want to monitor a particular input, you can set the input or output mixer that should be used before creating the resource. AudioPlayer, AudioSnippet, AudioSample, and AudioOuput will all use the output mixer to obtain an audio output. AudioInput will use the input mixer, when obtaining an input. For example, if you have a multi-channel soundcard, it is likely that each output, or perhaps pairs of outputs, will be represented by a Mixer. You can then play audio on a particular output of your soundcard by setting the appropriate mixer before loading the file you want to play.

Sample Code (online example)

/**
  * This sketch demonstrates how to use the <code>setOutputMixer</code> 
  * method of <code>Minim</code> in conjunction with the <code>getLineOut</code> 
  * method. By accessing the Mixer objects of Javasound, you can find one that 
  * corresponds to the output mixer of the sound device of your choice. You can 
  * then set this Mixer as the one that should use when creating an AudioOutput for you.
  * This Mixer will also be used when obtaining outputs for AudioPlayers, AudioSamples, 
  * and any other classes that result in sound being ouput to your speakers.
  * <p>
  * This sketch uses controlP5 for the GUI, a user-contributed Processing library.
  */
 
import ddf.minim.*;
// need signals package for SineWave
import ddf.minim.signals.*;
import controlP5.*;
// need to import this so we can use Mixer and Mixer.Info objects
import javax.sound.sampled.*;
 
Minim minim;
AudioOutput out;
// an array of info objects describing all of 
// the mixers the AudioSystem has. we'll use
// this to populate our gui scroll list and
// also to obtain an actual Mixer when the
// user clicks on an item in the list.
Mixer.Info[] mixerInfo;
 
// a signal for our output
SineWave sine;
 
ControlP5 gui;
 
void setup()
{
  size(512, 275);
 
  minim = new Minim(this);
  gui = new ControlP5(this);
 
  ScrollList mixers = gui.addScrollList("Mixers", 10, 10, 475, 280);
  mixers.setLabel("Choose A Mixer");
 
  mixerInfo = AudioSystem.getMixerInfo();
 
  for(int i = 0; i < mixerInfo.length; i++)
  {
    controlP5.Button b = mixers.addItem("item"+i, i);
    b.setLabel(mixerInfo[i].getName());
  } 
 
  sine = new SineWave(220, 0.3, 44100);
 
}
 
void draw()
{
  background(0);
 
  //gui.draw();
 
  if ( out != null )
  {
    stroke(255);
    // draw the waveforms
    for(int i = 0; i < out.bufferSize() - 1; i++)
    {
      line(i, 50 + out.left.get(i)*50, i+1, 50 + out.left.get(i+1)*50);
      line(i, 150 + out.right.get(i)*50, i+1, 150 + out.right.get(i+1)*50);
    }
  }
}
 
public void controlEvent(ControlEvent theEvent) 
{
  int mixerIndex = (int)theEvent.controller().value();
 
  println("User chose " + theEvent.controller().label());
  println("Using mixer info " + mixerInfo[mixerIndex].getName());
 
  Mixer mixer = AudioSystem.getMixer(mixerInfo[mixerIndex]);
 
  minim.setOutputMixer(mixer);
 
  if ( out != null )
  {
    out.close();
  }
 
  out = minim.getLineOut(Minim.STEREO);  
 
  if ( out != null )
  {
    out.addSignal(sine);
  }
}
 
 
void stop()
{
  // always close Minim audio classes when you are done with them
  if ( out != null )
  {
    out.close();
  }
  minim.stop();
 
  super.stop();
}

Similarly, you can set the input mixer when you want to monitor a particular input of your soundcard.

Sample Code (online examples)

/**
  * This sketch demonstrates how to use the <code>setInputMixer</code> 
  * method of <code>Minim</code> in conjunction with the <code>getLineIn</code> 
  * method. By accessing the <code>Mixer</code> objects of Javasound, 
  * you can find one that corresponds to the input mixer of the sound device 
  * of your choice. You can then set this <code>Mixer</code> as the one 
  * that <code>Minim</code> should use when creating an <code>AudioInput</code> 
  * for you
  * <p>
  * This sketch uses controlP5 for the GUI, a user-contributed Processing library.
  */
 
import ddf.minim.*;
import controlP5.*;
// need to import this so we can use Mixer and Mixer.Info objects
import javax.sound.sampled.*;
 
Minim minim;
AudioInput in;
// an array of info objects describing all of 
// the mixers the AudioSystem has. we'll use
// this to populate our gui scroll list and
// also to obtain an actual Mixer when the
// user clicks on an item in the list.
Mixer.Info[] mixerInfo;
 
ControlP5 gui;
 
void setup()
{
  size(512, 275);
 
  minim = new Minim(this);
  gui = new ControlP5(this);
 
  ScrollList mixers = gui.addScrollList("Mixers", 10, 10, 475, 280);
  mixers.setLabel("Choose A Mixer");
 
  mixerInfo = AudioSystem.getMixerInfo();
 
  for(int i = 0; i < mixerInfo.length; i++)
  {
    controlP5.Button b = mixers.addItem("item"+i, i);
    b.setLabel(mixerInfo[i].getName());
  } 
 
}
 
void draw()
{
  background(0);
 
  //gui.draw();
 
  if ( in != null )
  {
    stroke(255);
    // draw the waveforms
    for(int i = 0; i < in.bufferSize() - 1; i++)
    {
      line(i, 50 + in.left.get(i)*50, i+1, 50 + in.left.get(i+1)*50);
      line(i, 150 + in.right.get(i)*50, i+1, 150 + in.right.get(i+1)*50);
    }
  }
}
 
public void controlEvent(ControlEvent theEvent) 
{
  int mixerIndex = (int)theEvent.controller().value();
 
  println("User chose " + theEvent.controller().label());
  println("Using mixer info " + mixerInfo[mixerIndex].getName());
 
  Mixer mixer = AudioSystem.getMixer(mixerInfo[mixerIndex]);
 
  if ( in != null )
  {
    in.close();
  }
 
  minim.setInputMixer(mixer);
 
  in = minim.getLineIn(Minim.STEREO);
 
}
 
 
void stop()
{
  // always close Minim audio classes when you are done with them
  if ( in != null )
  {
    in.close();
  }
  minim.stop();
 
  super.stop();
}

2 thoughts on “Manual: Minim

  1. Pingback: MINIM | adrian segovia

  2. Pingback: Creativity & Computation » Archive » Personal Audio Visualizer

Comments are closed.