Skip to content

Make FFT.analyzeSample() correctly analyze samples which aren't a power of 2 #104

@tristanbay

Description

@tristanbay

I dug into the Processing source code to figure out why this is happening, and it apparently thinks that powers of 2 aren't powers of 2 when passing into the assert line in the numBits function of the FourierMath class in jsyn's softsynth code, even though it gets past the check in this function.

Here's the code I'm trying to run (just copy and paste it into the IDE, version 4.3). Even adapting and printing out the PowerOf2 & (PowerOf2 - 1) expression in my own code gives a 0 on the console:

import processing.sound.*;
SoundFile drums;
int bandcount = 512, vrate = 60, voverlap = 2, ch = 2;
int vframelen, videoframes;
float[] drums_sample, drums_l, drums_r, vtemp_l, vtemp_r;
float[][] drums_bands_l, drums_bands_r;

void setup()
{
  size(1920, 1080, P2D);
  drums = new SoundFile(this, "drums.wav");
  drums_sample = new float[drums.frames() * ch];
  vframelen = 44100 / vrate; // number of audio frames in video frame per channel
  drums_l = new float[(ceil((float)drums.frames() / vrate) * vrate) + (vframelen * voverlap)];
  drums_r = new float[(ceil((float)drums.frames() / vrate) * vrate) + (vframelen * voverlap)];
  vtemp_l = new float[vframelen * (voverlap + 1)];
  vtemp_r = new float[vframelen * (voverlap + 1)];
  videoframes = floor((float)drums.frames() / vframelen); // number of frames of video in sample
  drums_bands_l = new float[videoframes][bandcount];
  drums_bands_r = new float[videoframes][bandcount];
  drums.read(drums_sample);
  for (int i = 0; i < drums.frames(); i++) {
    drums_l[i] = drums_sample[i * 2];
    drums_r[i] = drums_sample[(i * 2) + 1];
  }
  for (int i = 0; i < videoframes; i++) {
    for (int j = 0; j < vtemp_l.length; j++) {
      vtemp_l[j] = drums_l[j + (vframelen * i)];
      vtemp_r[j] = drums_r[j + (vframelen * i)];
    }
    println(drums_bands_l[i].length & (drums_bands_l[i].length - 1));
    FFT.analyzeSample(vtemp_l, drums_bands_l[i]);
    FFT.analyzeSample(vtemp_r, drums_bands_r[i]);
  }
  background(255);
  loadPixels();
  for (int x = 0; x < width; x++) {
    for (int y = 0; y < height; y++) {
      pixels[(width * y) + x] = color(map(drums_bands_l[floor(map(x, 0, width, 0, videoframes))][floor(map(y, 0, height, 0, bandcount))], 0, 1, 255, 0));
    }
  }
  updatePixels();
}

Something seems to be altering the perceived length of those target arrays between checks. Could it have to do with using 2D arrays?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions