我正在研究音频可视化,基本上应该是圆形频谱图。我有一个图表,它已经显示了频率和一个弧线,该弧线根据经过的时间而变化。现在,我想根据每个频率的幅度用白点填充弧形,就像在这里: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
作为纹理,但是纹理映射不清楚如果同时使用
PGraphics
和PShape
会使您感到困惑,则仅使用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
相同):有一个注释版本,其中考虑了轨道持续时间附言我还想知道如何基于FFT数据获得良好的视觉效果,并通过一些过滤技巧获得不错的结果。我建议还检查wakjah's answer here。