javaaudioprocessingminim

how to make two FFT objects for the left and right channel with the minim library for processing


I have the following code that creates an FFT object from an audio file see the code below:

import ddf.minim.*;
import ddf.minim.analysis.*;

Minim       minim;
AudioPlayer player;
FFT         fft;


void setup(){
  minim = new Minim(this);
  player = minim.loadFile("audio.mp3");
  fft = new FFT( player.bufferSize(), player.sampleRate() ); 
  fft.logAverages(86, 1); 
  fft.window(FFT.HAMMING);
  numZones = fft.avgSize();
}

But now i want to create two FFT objects for the left and the right channel. So in the end i want to have a fftLeft = new FFT(audio.left) and a fftRight = new FFT(audio.right)

i have tried the method .getChannel(player.LEFT) but this didnt work. does anyone have a tip or suggestion on how to do this?


Solution

  • When you run the FFT's forward() method you can pass the channel you want.

    Something like this:

    //in setup()
    fftLeft  = new FFT( player.bufferSize(), player.sampleRate() );
    fftRight = new FFT( player.bufferSize(), player.sampleRate() );
    //in draw()
    fftLeft.forward(player.left);
    fftRight.forward(player.right);
    

    Here's a tweaked version of the SoundSpectrum sample that comes with minim:

    /**
      * An FFT object is used to convert an audio signal into its frequency domain representation. This representation
      * lets you see how much of each frequency is contained in an audio signal. Sometimes you might not want to 
      * work with the entire spectrum, so it's possible to have the FFT object calculate average frequency bands by 
      * simply averaging the values of adjacent frequency bands in the full spectrum. There are two different ways 
      * these can be calculated: <b>Linearly</b>, by grouping equal numbers of adjacent frequency bands, or 
      * <b>Logarithmically</b>, by grouping frequency bands by <i>octave</i>, which is more akin to how humans hear sound.
      * <br/>
      * This sketch illustrates the difference between viewing the full spectrum, 
      * linearly spaced averaged bands, and logarithmically spaced averaged bands.
      * <p>
      * From top to bottom:
      * <ul>
      *  <li>The full spectrum.</li>
      *  <li>The spectrum grouped into 30 linearly spaced averages.</li>
      *  <li>The spectrum grouped logarithmically into 10 octaves, each split into 3 bands.</li>
      * </ul>
      *
      * Moving the mouse across the sketch will highlight a band in each spectrum and display what the center 
      * frequency of that band is. The averaged bands are drawn so that they line up with full spectrum bands they 
      * are averages of. In this way, you can clearly see how logarithmic averages differ from linear averages.
      * <p>
      * For more information about Minim and additional features, visit http://code.compartmental.net/minim/
      */
    
    import ddf.minim.analysis.*;
    import ddf.minim.*;
    
    Minim minim;  
    AudioPlayer jingle;
    
    FFT fftLogLeft,fftLogRight;
    
    float height3;
    float height23;
    float spectrumScale = 4;
    
    float centerFrequency;
    
    PFont font;
    
    void setup()
    {
      size(512, 480);
      height3 = height/3;
      height23 = 2*height/3;
    
      minim = new Minim(this);
      jingle = minim.loadFile("jingle.mp3", 1024);
    
      // loop the file
      jingle.loop();
    
      // create an FFT object for calculating logarithmically spaced averages
      // left channel
      fftLogLeft = new FFT( jingle.bufferSize(), jingle.sampleRate() );
      fftLogLeft.logAverages( 22, 3 );
    
      fftLogRight = new FFT( jingle.bufferSize(), jingle.sampleRate() );
      fftLogRight.logAverages( 22, 3 );
    
      rectMode(CORNERS);
    }
    
    void draw()
    {
      background(0);
      //run FFT on left channel
      fftLogLeft.forward( jingle.left );
      //run FFT on left channel
      fftLogRight.forward( jingle.right );
    
      plotFFT(fftLogLeft,height-50,"Left Channel");
      plotFFT(fftLogRight,height,"Right Channel");
    }
    
    void plotFFT(FFT fft,float y,String prefix){
      // draw the logarithmic averages
      {
        // since logarithmically spaced averages are not equally spaced
        // we can't precompute the width for all averages
        for(int i = 0; i < fft.avgSize(); i++)
        {
          centerFrequency    = fft.getAverageCenterFrequency(i);
          // how wide is this average in Hz?
          float averageWidth = fft.getAverageBandWidth(i);   
    
          // we calculate the lowest and highest frequencies
          // contained in this average using the center frequency
          // and bandwidth of this average.
          float lowFreq  = centerFrequency - averageWidth/2;
          float highFreq = centerFrequency + averageWidth/2;
    
          // freqToIndex converts a frequency in Hz to a spectrum band index
          // that can be passed to getBand. in this case, we simply use the 
          // index as coordinates for the rectangle we draw to represent
          // the average.
          int xl = (int)fft.freqToIndex(lowFreq);
          int xr = (int)fft.freqToIndex(highFreq);
    
          // if the mouse is inside of this average's rectangle
          // print the center frequency and set the fill color to red
          if ( mouseX >= xl && mouseX < xr )
          {
            fill(255, 128);
            text(prefix + "Logarithmic Average Center Frequency: " + centerFrequency, 5, y - 25);
            fill(255, 0, 0);
          }
          else
          {
              fill(255);
          }
          // draw a rectangle for each average, multiply the value by spectrumScale so we can see it better
          rect( xl, y, xr, y - fft.getAvg(i)*spectrumScale );
        }
      }
    }
    

    Notes: