📄 fftlab.java
字号:
else if (si>sv) sv = si;
}
return sv;
}
private void updateSampleValues(SamplesView realView, SamplesView imagView) {
float sv = computeSampleValue(realView.samples,imagView.samples);
realView.setSampleValue(sv);
imagView.setSampleValue(sv);
}
private void transform(int sign,
Samples sar, Samples sai,
Samples bar, Samples bai) {
float ar[] = sar.values;
float ai[] = sai.values;
float br[] = bar.values;
float bi[] = bai.values;
for (int i=0; i<length; ++i) {
br[i] = ar[i];
bi[i] = ai[i];
}
if (originCentered) {
for (int i=1; i<length; i+=2) {
br[i] = -br[i];
bi[i] = -bi[i];
}
}
Fft.complexToComplex(sign,length,br,bi);
if (originCentered) {
for (int i=1; i<length; i+=2) {
br[i] = -br[i];
bi[i] = -bi[i];
}
}
}
private void initSamples() {
fReal.values[fReal.origin+1] = 1.0f;
transform(1,fReal,fImag,gReal,gImag);
}
private void updateLengths() {
int length = this.length;
fReal.setLength(length);
fImag.setLength(length);
gReal.setLength(length);
gImag.setLength(length);
}
private void updateOrigins() {
int origin = (originCentered)?length/2:0;
int shift = origin-fReal.origin;
fReal.origin = origin;
fImag.origin = origin;
gReal.origin = origin;
gImag.origin = origin;
fReal.rotate(shift);
fImag.rotate(shift);
gReal.rotate(shift);
gImag.rotate(shift);
}
private void repaintViews() {
fRealView.repaint();
fImagView.repaint();
gRealView.repaint();
gImagView.repaint();
}
private void shiftSamples(Samples s, int shift) {
float temp[] = new float[length];
int j = shift%length;
for (int i=0; i<length; ++i,++j) {
if (j<0) j += length;
if (j>=length) j -= length;
temp[j] = s.values[i];
}
s.values = temp;
}
}
// Simple Fast Fourier Transform.
class Fft {
public static void complexToComplex(int sign, int n,
float ar[], float ai[]) {
float scale = (float)Math.sqrt(1.0f/n);
int i,j;
for (i=j=0; i<n; ++i) {
if (j>=i) {
float tempr = ar[j]*scale;
float tempi = ai[j]*scale;
ar[j] = ar[i]*scale;
ai[j] = ai[i]*scale;
ar[i] = tempr;
ai[i] = tempi;
}
int m = n/2;
while (m>=1 && j>=m) {
j -= m;
m /= 2;
}
j += m;
}
int mmax,istep;
for (mmax=1,istep=2*mmax; mmax<n; mmax=istep,istep=2*mmax) {
float delta = (float)sign*3.141592654f/(float)mmax;
for (int m=0; m<mmax; ++m) {
float w = (float)m*delta;
float wr = (float)Math.cos(w);
float wi = (float)Math.sin(w);
for (i=m; i<n; i+=istep) {
j = i+mmax;
float tr = wr*ar[j]-wi*ai[j];
float ti = wr*ai[j]+wi*ar[j];
ar[j] = ar[i]-tr;
ai[j] = ai[i]-ti;
ar[i] += tr;
ai[i] += ti;
}
}
mmax = istep;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// Digital lollipop view of samples.
class SamplesView extends Canvas {
public static int EDIT_NONE = 0;
public static int EDIT_DRAW = 1;
public static int EDIT_ZERO = 2;
public static int EDIT_NEGATE = 3;
public static int EDIT_SHIFT = 4;
public Samples samples;
public SamplesView(Samples s) {
samples = s;
setSampleValue(1.0f);
updateDrawingSizes();
setBackground(Color.yellow);
}
public void setSampleValue(float v) {
int height = size().height;
sampleValue = (v!=0.0f)?v:1.0f;
sampleScale = -0.25f*height/sampleValue;
}
public void setEditMode(int mode) {
editMode = mode;
}
public void paint(Graphics g) {
updateDrawingSizes();
drawSamples(g);
}
public Dimension minimumSize() {
return new Dimension(100,50);
}
public Dimension preferredSize() {
return minimumSize();
}
public boolean mouseDown(Event e, int x, int y) {
if (editMode==EDIT_NONE) return true;
lastDrag = -1;
return mouseDrag(e,x,y);
}
public boolean mouseDrag(Event e, int x, int y) {
if (editMode==EDIT_NONE) return true;
if (x<0 || x>size().width) return true;
if (y<sampleRadius || y>size().height-sampleRadius) return true;
int i = (int)((float)(x-sampleStart)/(float)sampleWidth+0.5);
if (i<0) i = 0;
if (i>=samples.values.length) i = samples.values.length-1;
if (editMode==EDIT_NEGATE && i==lastDrag) return true;
Graphics g = getGraphics();
if (editMode==EDIT_SHIFT) {
if (i!=lastDrag && lastDrag>=0) {
g.setColor(getBackground());
drawSamples(g);
samples.rotate(i-lastDrag);
g.setColor(getForeground());
drawSamples(g);
}
lastDrag = i;
return true;
}
g.setColor(getBackground());
drawOneSample(g,i);
if (editMode==EDIT_ZERO) {
samples.values[i] = 0.0f;
} else if (editMode==EDIT_NEGATE) {
samples.values[i] = -samples.values[i];
} else {
samples.values[i] = (float)(y-sampleBase)/sampleScale;
}
g.setColor(getForeground());
drawOneSample(g,i);
lastDrag = i;
return true;
}
public boolean mouseUp(Event e, int x, int y) {
if (editMode!=EDIT_NONE) samples.notifyObservers();
return true;
}
private int editMode = EDIT_DRAW;
private int sampleStart,sampleBase,sampleWidth,sampleRadius;
private float sampleScale,sampleValue;
private int lastDrag;
private void drawOneSample(Graphics g, int i) {
int x = sampleStart+i*sampleWidth;
int y = sampleBase;
int r = sampleRadius;
int w = sampleWidth;
int h = (int)(samples.values[i]*sampleScale);
g.drawLine(x-w/2,y,x+w/2,y);
g.drawLine(x,y,x,y+h);
if (i==samples.origin) {
g.drawOval(x-r,y+h-r,2*r,2*r);
} else {
g.fillOval(x-r,y+h-r,2*r+1,2*r+1);
}
}
private void drawSamples(Graphics g) {
for (int i=0; i<samples.values.length; ++i) {
drawOneSample(g,i);
}
}
private void updateDrawingSizes() {
int width = size().width;
int height = size().height;
int nSamples = samples.values.length;
sampleWidth = (int)((float)width/(float)(nSamples+1));
sampleStart = (width-(nSamples-1)*sampleWidth)/2;
sampleBase = (int)(0.5f*height);
sampleScale = -0.25f*height/sampleValue;
sampleRadius = (int)(0.4f*sampleWidth);
int maxRadius = (int)(0.5f*height);
if (sampleRadius>maxRadius) sampleRadius = maxRadius;
}
}
/////////////////////////////////////////////////////////////////////////////
// Collection of sample values.
class Samples extends Observable {
public float values[];
public int origin;
public Samples(int length, int origin) {
this.origin = origin;
values = new float[length];
zero();
}
public void setLength(int length) {
if (length==values.length) return;
values = new float[length];
zero();
}
public void zero() {
for (int i=0; i<values.length; ++i) values[i] = 0.0f;
}
public void rotate(int n) {
int length = values.length;
float temp[] = new float[length];
int j = n%length;
for (int i=0; i<length; ++i,++j) {
if (j<0) j += length;
if (j>=length) j -= length;
temp[j] = values[i];
}
values = temp;
}
public void notifyObservers() {
setChanged();
super.notifyObservers();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -