【问题标题】:How to spread the audio spectrum into a grid如何将音频频谱展开成网格
【发布时间】:2018-11-24 13:39:51
【问题描述】:

我正在尝试使用处理来获取音频输入并创建一个音频频谱,该频谱被分成多行并均匀地适合草图的宽度。 我希望椭圆以网格状的方式展开,并代表光谱的不同部分。

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 );

  }
}

【问题讨论】:

    标签: processing


    【解决方案1】:

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

    如果您知道您希望网格有多少行和列,您可以使用算术计算基于索引的 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 声音。 查看 Processing > Examples > Contributed Libraries > Minim > Analysis > SoundSpectrum 并查看 logAverages()。播放 minBandwidthbandsPerOctave 可能会帮助您获得更好的可视化效果。

    如果您想更深入地了解可视化,请查看此 wakjah 的出色答案 here,如果您有时间,请学习 Dan Ellis 的精彩 Music Signal Computing 课程

    【讨论】:

    • 非常感谢您的详尽回答。我非常感谢你,你帮了很多忙。这周我会试试这个。
    猜你喜欢
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 2019-05-20
    • 1970-01-01
    • 2011-06-08
    • 1970-01-01
    相关资源
    最近更新 更多