如何将音频频谱扩展到网格中

时间:2018-11-24 13:39:51

标签: processing

我正在尝试使用处理来获取音频输入,并创建一个音频频谱,该音频频谱分成多行,并与草图的宽度一致。 我希望椭圆形像时尚一样散布在网格中,并代表光谱的不同部分。

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

Minim minim;
FFT fft;
AudioInput mic;

void setup()
{
  size(512, 512, P3D); 
  minim = new Minim(this);  
  mic = minim.getLineIn();
  fft = new FFT(mic.bufferSize(), mic.sampleRate());
}

void draw()
{
  background(0);
  stroke(255);
  fft.forward(mic.mix);
  for(int i = 0; i < fft.specSize(); i++)
  {
    float size = fft.getBand(i);
    float x = map(i, 0, fft.specSize(), 0, height);
    float y = i;
    ellipse(x, y, size, size );

  }
}

1 个答案:

答案 0 :(得分:0)

fft数据是一维信号,您希望将数据可视化为2D网格。

如果知道网格要拥有多少行和列,则可以使用算术运算法则来基于索引计算x和y网格位置。

假设您有100个元素,并且想要以10x10的网格显示它们:

使用1D数组计数器,对列数取模(%)来计算2D x索引,然后将(/)除以列数以计算2D y索引:

for(int i = 0 ; i < 100; i++){
   println(i,i % 10, i / 10);
}

这是一个更长的评论示例:

// fft data placeholder
float[] values = new float[100];
// fill with 100 random values
for(int i = 0 ; i < values.length; i++){
  values[i] = random(0.0,1.0);
}
// how many rows/cols
int rows = 10;
int cols = 10;
// how large will a grid element be (including spacing)
float widthPerSquare = (width / cols);

// grid elements offset from top left
float offsetX = widthPerSquare * 0.5;
float offsetY = widthPerSquare * 0.5;

noStroke();
smooth();

println("i,gridX,gridY,value");
// traverse data
for(int i = 0; i < 100; i++){
  // calculate x,y indices
  int gridX = i % rows;
  int gridY = i / rows;

  println(i+","+gridX+","+gridY+","+values[i]);
  // calculate on screen x,y position based on grid element size 
  float x = offsetX + (gridX * widthPerSquare);
  float y = offsetY + (gridY * widthPerSquare);

  // set the size to only be 75% of the grid element (to leave some spacing)
  float size = values[i] * widthPerSquare * 0.75;

  //fill(values[i] * 255);
  ellipse(x,y,size,size);
}

在您的情况下,假设fft.specSize()约为512,并且您想绘制一个正方形网格,则可以执行以下操作:

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

Minim minim;
FFT fft;
AudioInput mic;

int rows;
int cols;

float xSpacing;
float ySpacing;

void setup()
{
  size(512, 512, P3D);
  noStroke();

  minim = new Minim(this);  
  mic = minim.getLineIn();
  fft = new FFT(mic.bufferSize(), mic.sampleRate());

  // define your own grid size or use an estimation based on square root of your FFT data
  rows = cols = (int)sqrt(fft.specSize());
  println(rows,rows * rows);
  xSpacing = width / cols;
  ySpacing = height / rows;
}

void draw()
{
  background(0);

  fft.forward(mic.mix);

  for(int i = 0; i < fft.specSize(); i++)
  {
    float size = fft.getBand(i) * 90;

    float x = (i % rows) * xSpacing;
    float y = (i / rows) * ySpacing;

    ellipse(x, y, size, size );

  }
}

请注意,该示例未应用偏移量,并且网格为22 x 22(484!= 512), 但希望它将给您一些想法。

要记住的另一件事是该FFT数组的内容。 您可能需要对数缩放以解决how we perceive声音。 查看处理>示例>分布式库>最小>分析> SoundSpectrum ,并查看logAverages()。玩minBandwidthbandsPerOctave可能会帮助您获得更好的可视化效果。

如果您想更深入地了解可视化,请检查这个wakjah的出色答案here,如果有时间,请参加Dan Ellis的精彩Music Signal Computing课程