我正在研究音频可视化,基本上应该是圆形频谱图。我有一个图表,它已经显示了频率和一个弧线,该弧线根据经过的时间而变化。现在,我想根据每个频率的幅度用白点填充弧形,就像在这里:https://vimeo.com/27135957。显然,我需要制作一个充满点的PGraphics,这些点会根据幅度从白色变为黑色。然后,我需要使用此图形对弧进行纹理处理。有谁知道如何做到这一点?

import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;

Minim minim;
AudioPlayer song;
FFT fft;
PGraphics pg;
PShape arc;

float deg = 90;
float rad = radians(deg);

void setup()
{
  size(1000, 1000);

  minim = new Minim(this);
  song = minim.loadFile("Anthology.mp3");
  song.play();

  fft = new FFT(song.bufferSize(), song.sampleRate());

  pg = createGraphics(width, height);
}

void draw()
{
  background(0);
  fft.forward(song.mix);

  for (int i = 0; i < fft.specSize(); i++)
  {
    pushMatrix();
    stroke(255);
    line(i, height, i, height - fft.getBand(i)*0.5);
    popMatrix();
    println(fft.getBand(i));

    //Map Amplitude to 0 → 255, fill with points and color them
    float brightness = map(fft.getBand(i), -1, 1, 0, 255);
    pg.beginDraw();
    pg.endDraw();

    fill(255, 255, 255,);
    noStroke();
    float evolution = radians(map(song.position(), 0, song.length(), 90, 450));
    //texture(pg);
    arc(height/2, height/2, height-100, height-100, rad, evolution, PIE);
  }
}

最佳答案

根据您的代码,有一些概念可能不清楚:

  • 如果您打算在pg PGraphics实例中渲染圆弧,请使用.表示法访问pg,并在beginDraw() / endDraw()调用之间调用绘图功能。目前,在pg中没有渲染任何东西,而使用image()却没有在pg渲染任何地方。有关更多详细信息,请参见createGraphics()引用,运行示例代码/对其进行调整/将其破坏/修复/对其进行理解
  • 类似地创建了PShape arc,但未使用
  • 有人尝试使用pg作为纹理,但是纹理映射不清楚

  • 如果同时使用PGraphicsPShape会使您感到困惑,则仅使用PGraphics即可达到类似的效果:只需渲染一些较大的灰点而不是圆弧即可。这不会是完全相同的效果,但是会花费更少的精力就具有非常相似的外观。

    这是基于您的代码的变体:
    import ddf.minim.*;
    import ddf.minim.analysis.*;
    import ddf.minim.effects.*;
    import ddf.minim.signals.*;
    import ddf.minim.spi.*;
    import ddf.minim.ugens.*;
    
    Minim minim;
    AudioPlayer song;
    FFT fft;
    
    PGraphics pg;
    
    void setup()
    {
      size(600, 600, P2D);
    
      minim = new Minim(this);
      song = minim.loadFile("jingle.mp3", 1024);
      song.loop();
    
      fft = new FFT(song.bufferSize(), song.sampleRate());
      // optional: use logarithmic averages: clover to how we perceive sound
      fft.logAverages( 30, 6 );
      // setup pg graphics layer disable fill, make points stroke thick
      pg = createGraphics(width, height);
      pg.beginDraw();
      pg.strokeWeight(3);
      pg.noFill();
      pg.endDraw();
    }
    
    void draw()
    {
      background(0);
      image(pg, 0, 0);
      // perform FFT on stereo mix
      fft.forward(song.mix);
      // center coordinates
      float cx = width * 0.5;
      float cy = height * 0.5;
      // count FFT bins
      int fftSpecSize = fft.specSize();
      // calculate the visual size for representing an FFT bin
      float sizePerSpec = (height * 0.5 ) / fftSpecSize;
    
      stroke(255);
      noFill();
    
      // start @editing@ the pg layer (once
      pg.beginDraw();
    
      // start the FFT graph shape
      beginShape();
    
      // for each FFT bin
      for (int i = 0; i < fftSpecSize; i++)
      {
        // get the vands in reverse order (low frequencies last)
        float fftBand = fft.getBand(fftSpecSize - i - 1);
        // scale FFT bin value to pixel/render size
        float xOffset = fftBand * 10;
        // map FFT bins to 0-255 brightness levels (note 35 may differ
        float brightness = map(fftBand, 0, 35, 0, 255);
    
        // draw the line graph vertex
        vertex(cx + xOffset, cy + sizePerSpec * i);
        // map song position (millis played) to 360 degrees in radians (2 * PI)
        // add HALF_PI (90 degrees) because  0 degrees points to the right and drawing should start pointing down (not right)
        //float angle = map(song.position(), 0, song.length(), 0, TWO_PI) + HALF_PI;
        // as a test map it to a lower value
        float angle = (frameCount * 0.0025) + HALF_PI;
        // map radius from FFT index
        float radius = map(i, 0, fftSpecSize - 1, 0, width * 0.5);
        // use mapped brightness as point stroke
        pg.stroke(brightness);
        // use polar coordinates mapped from the centre
        pg.pushMatrix();
        pg.translate(cx,cy);
        pg.rotate(angle);
        pg.point(radius,0);
        pg.popMatrix();
        // alternatively use polar to cartesian coordinate conversion
        // x = cos(angle) * radius
        // y = sin((angle) * radius
        // cx, cy are added to offset from center
        //pg.point(cx + (cos(angle) * radius),
        //         cy + (sin(angle) * radius));
      }
      // finish FFT graph line
      endShape();
      // fnish pg layer
      pg.endDraw();
    }
    

    注意
  • 您可能想将jingle.mp3更改为音频文件名
  • 为了进行短轨道测试,我使用了angle的任意映射(与代码中的evolution相同):有一个注释版本,其中考虑了轨道持续时间
  • 使用坐标变换渲染灰度点位置。请务必仔细阅读2D Transformations tutorial并牢记转换顺序很重要。替代地,有一个版本,它使用极坐标(角/半径)到笛卡尔坐标系(x,y)的转换公式来执行相同的操作。

  • audio - 如何制作充满点的PGraphics(白色等级取决于振幅)和不断变化的弧线的纹理?-LMLPHP

    附言我还想知道如何基于FFT数据获得良好的视觉效果,并通过一些过滤技巧获得不错的结果。我建议还检查wakjah's answer here

    09-27 06:34