Beads - Getting different results each time I run FFT

edited February 2018 in Library Questions

I am trying to use the Beads ShortFrameSegmenter and FFT in order to determine the pitch and harmonics of a sample but each time I run my sketch I get different results. Here's my code

import beads.*;
import org.jaudiolibs.beads.*;
import java.util.Timer;
import java.util.TimerTask;

AudioContext ac;
GranularSamplePlayer sample;
Gain gain;

ShortFrameSegmenter sfs;
FFT fft;
PowerSpectrum ps;
Frequency f;
SpectralPeaks sp;
float[][] meanHarmonics;

int numPeaks = 6;

int loops = 0;
double meanFrequency = 0.0;
Timer t = new Timer();
boolean finished = false;

void setup() {
  size(1600, 900);
  ac = new AudioContext();
  ac.start();
  sample = new GranularSamplePlayer(ac, SampleManager.sample(dataPath("") + "\\C2.mp3"));

  gain = new Gain(ac, 1, 1);

  // input chaining
  gain.addInput(sample);
  ac.out.addInput(gain);

  // setup analysis
  // break audio into more manageable chunks
  sfs = new ShortFrameSegmenter(ac);
  sfs.addInput(sample);

  // fast fourier transform to analyse the harmonic spectrum
  fft = new FFT();
  sfs.addListener(fft);

  // PowerSpectrum turns the raw FFT output into proper audio data.
  ps = new PowerSpectrum();
  fft.addListener(ps);

  // Frequency tries to determine the strongest frequency in the wave
  // which is the fundamental that determines the pitch of the sound
  f = new Frequency(44100.0f);
  ps.addListener(f);

  // Listens for harmonics
  sp = new SpectralPeaks(ac, numPeaks);
  ps.addListener(sp);

  meanHarmonics = new float[numPeaks][2];

  // initialise meanHarmonics
  for (int i = 0; i < numPeaks; i++) {
    for (int j = 0; j < 2; j++) {
      meanHarmonics[i][j] = 0;
    }
  }

  ac.out.addDependent(sfs);

  t.scheduleAtFixedRate(new TimerTask() {
    public void run() {
      loops++;
      if (loops == 1) {
        sample.start(0);
      } else if (loops >= 1500) {
        finished = true;
        t.cancel();
      }
      Float inputFrequency = f.getFeatures();
      if (inputFrequency != null && inputFrequency != Float.NaN) {
        println(inputFrequency);
        meanFrequency += inputFrequency;
      }
      float[][] harmonics = sp.getFeatures();
      if (harmonics != null) {
        for (int feature = 0; feature < numPeaks; feature++) {
          // harmonic must be in human audible range
          // and its amplitude must be large enough to be audible
          if (harmonics[feature][0] < 20000.0 && harmonics[feature][1] > 0.01) {
            // average out the frequencies
            meanHarmonics[feature][0] += harmonics[feature][0];
            // average out the amplitudes
            meanHarmonics[feature][1] += harmonics[feature][1];
          }
        }
      }
    }
  }
  , 0, 1);
  while (!finished) { 
    print("");
  }
  float maxAmp = 0.0;
  float freq = 0.0;
  sample.pause(true);
  meanFrequency /= loops;
  println(meanFrequency);
  for (int feature = 0; feature < numPeaks; feature++) {
    meanHarmonics[feature][0] /= loops;
    meanHarmonics[feature][1] /= loops;
    if (meanHarmonics[feature][1] > maxAmp) {
      freq = meanHarmonics[feature][0];
      maxAmp = meanHarmonics[feature][1];
    }
    println(meanHarmonics[feature][0] + " " + meanHarmonics[feature][1]);
  }
  println(freq + " " + meanFrequency);
  println();
}

For every run I do I get different values for the harmonics' frequencies and amplitudes as well as the meanFrequency value, which is often NaN. I've also noticed that when printing the inputFrequency on each iteration its values are not entirely accurate especially in the lower end of the frequency spectrum. I've tested this both with complex samples and simple sine waves.

StackOverflow question: https://stackoverflow.com/questions/48769181/getting-different-results-each-time-i-run-fft-with-processing-and-beads

Tagged:
Sign In or Register to comment.