?? fft.cpp
字號:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <math.h>#include <qwidget.h>#include "sound.h"#include "fft.moc"#include <X11/Xlib.h>extern "C" { #include "soundfft.h"}#define FFT_MAX 8192#define FFT_LEFT 100#define FFT_RIGHT 10000#define DB_MAX 0.0#define DB_MIN -100.0/* ---------------------------------------------------------------------- */FFTWindow::FFTWindow(QWidget *parent, char *name) : QWidget(parent,name,0){ XColor color,dummy; Colormap map = DefaultColormapOfScreen (DefaultScreenOfDisplay(x11Display())); gc = XCreateGC(x11Display(),winId(),0,NULL); XAllocNamedColor(x11Display(),map,"white",&color,&dummy); back = color.pixel; XAllocNamedColor(x11Display(),map,"red",&color,&dummy); fore = color.pixel; /* flag: no init so far... */ channels = 0; logmap = NULL; ylog = false;}voidFFTWindow::make_logmap(){ int i,w,h; float freq,up; w = width(); h = height(); if (!w || !h || !channels) return; if (logmap) { free(logmap); free(segments); free(buffer); EndFFT(); } logmap = (int*) malloc((w+1)*sizeof(int)); segments = (XSegment*)malloc((w)*sizeof(XSegment)); buffer = (short*)malloc(fft_size*sizeof(short)*channels); InitializeFFT(fft_size); up = log(FFT_RIGHT/FFT_LEFT)/log(2); for (i = 0; i <= w; i++) { freq = pow(2,up*i/w)* FFT_LEFT; logmap[i] = (int)(fft_size*freq/rate); } for (i = 0; i < w; i++) { segments[i].x1 = i; segments[i].x2 = i; segments[i].y2 = h; }}voidFFTWindow::calculate(unsigned char *data){ int i,j; if (NULL == logmap) { fprintf(stderr,"Oops: fft no logmap (yet)\n"); return; } switch (afmt) { case FMT_8BIT: for (i = 0; i < audio_size; i++) buffer[i] = (data[i] ^ 0x80) << 8; break;#if 0 case AFMT_S8: for (i = 0; i < audio_size; i++) buffer[i] = data[i] << 8; break;#endif case FMT_16BIT: memcpy(buffer,data,audio_size);#if 0 /* byte swap */ for (i = 0; i < fft_size; i++) buffer[i] = ((buffer[i] & 0xff00) >> 8) | ((buffer[i] & 0x00ff) << 8); /* unsigned -> signed */ if (afmt == AFMT_U16_LE || afmt == AFMT_U16_BE) for (i = 0; i < fft_size; i++) buffer[i] ^= 0x8000;#endif break; default: fprintf(stderr,"oops(fft): unknown sound format\n"); exit(1); } for (i = 0, lmax = 0; i < fft_size; i++) if ((j = abs((signed short)buffer[i])) > lmax) lmax = j; if (channels == 2) { for (i = 0, j = 0; i < fft_size; i++, j+=2) buffer[i] = (buffer[j]+buffer[j+1])>>1; } RealFFT(buffer);}voidFFTWindow::drawhist(){ XGCValues gcval; int re,im,ab; int i,j,max,w,h; int len = fft_size>>1; w = width(); h = height(); for (i = 0; i < w; i++) { max = 0; j = logmap[i]; do { if (j >= len) break; re = buffer[BitReversed[j]]; im = buffer[BitReversed[j]+1]; ab = re*re+im*im; if (ab > max) max = ab; j++; } while (j < logmap[i+1]); if (ylog) { float dBVal = 20 * log10( sqrt(max)/FFT_MAX ); max = (int)( h * ( dBVal-DB_MIN )/( DB_MAX-DB_MIN )); } else { max = (int)(sqrt(max) * h / FFT_MAX); } segments[i].y1 = h-max; } gcval.foreground = back; XChangeGC(x11Display(),gc,GCForeground,&gcval); XFillRectangle(x11Display(),winId(),gc,0,0,width(),height()); gcval.foreground = fore; XChangeGC(x11Display(),gc,GCForeground,&gcval); XDrawSegments(x11Display(),winId(),gc,segments,w); if (ylog) { float dBVal = 20 * log10( (double)lmax/32768 ); max = h - (int)( h * ( dBVal-DB_MIN )/( DB_MAX-DB_MIN )); } else { max = height() - lmax*height()/32768; } XDrawLine(x11Display(),winId(),gc,0,max,width(),max);}/* ---------------------------------------------------------------------- */voidFFTWindow::resizeEvent(QResizeEvent *event){ make_logmap();}voidFFTWindow::new_params(struct SOUNDPARAMS *p){ afmt = p->format; channels = p->channels; rate = p->rate; audio_size = p->blocksize; fft_size = audio_size/channels/2; if (afmt != FMT_16BIT) fft_size *= 2; make_logmap();}voidFFTWindow::new_data(void *data){ if (!channels || !isVisible()) return; calculate((unsigned char*)data); drawhist();}voidFFTWindow::set_ylog(int linear){ ylog = (linear==0); drawhist();}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -