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

问题描述 投票:1回答:1

我正在研究音频可视化,基本上应该是圆形频谱图。我有一个图表,它已经显示了频率和一个弧线,该弧线根据经过的时间而变化。现在,我想根据每个频率的幅度用白点填充弧形,就像这里: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);
  }
}
audio processing visualization
1个回答
0
投票

根据您的代码,一些概念似乎不清楚:

  1. [如果您打算在pg PGraphics实例中使用.表示法渲染圆弧,并在beginDraw() / endDraw()调用之间调用绘图功能。目前,在pg中没有渲染任何内容,而使用image()则pg在任何地方都没有渲染。有关更多详细信息,请参见createGraphics()参考,运行示例代码/对其进行调整/将其破坏/修复/对其进行理解
  2. 同样创建PShape arc,但未使用
  3. 尝试使用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)的坐标转换公式来做同样的事情。

FFT line plot verticall drawn leaving grayscale trails rotating clockwise as a radial spectrogram

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

© www.soinside.com 2019 - 2024. All rights reserved.