/***************************************************************************
* Copyright (C) 2008 - Giuseppe Cigala *
* g_cigala@virgilio.it *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "qfreq.h"
QFreq::QFreq(QWidget *parent) : QWidget(parent)
{
initValue();
initColor();
}
void QFreq::initValue()
{
start_point = 0;
zoom_point = ((1024/2)+1)*20000/22050;
freq1 = 0;
freq2 = 5;
freq3 = 10;
freq4 = 15;
freq5 = 20;
range_freq = 20;
typeFFT = 0;
lockFFT = false;
}
void QFreq::initColor()
{
colLin = Qt::black;
colLog = Qt::black;
col512 = Qt::black;
col1024 = Qt::black;
col2048 = Qt::black;
col4096 = Qt::black;
colLock = Qt::red;
}
void QFreq::setZoomPoint(int N)
{
zoom_point = ((N/2)+1)*20000/22050;
}
void QFreq::calculateFFT(int N)
{
/*
QFile file ("test.wav");
if (!file.open(QIODevice::ReadOnly))
return;
char *data;
file.read(data, N);
for (i =0; i <=N; i++)
{
in[i] = (double)data[i];
i++;
}
*/
double *in;
double *out;
fftw_plan plan;
double A[N];
magnitudeLin = 0;
magnitudeLog = 0;
min_val_lin = 5000000;
max_val_lin = -1000;
min_val_log = 5000000;
max_val_log = -1000;
int is16bitfile = 1;
int val, val2;
char inc[N];
FILE *infile;
const char * fileName = wavFile.toLatin1().data();
infile = fopen(fileName, "r");
// skip wav file header
fgets(inc,37,infile);
fgets(inc,9,infile);
// read data and fill "A"-array
for (int v=0; v<N; v++)
{
val = fgetc(infile);
if (is16bitfile)
{
val2 = fgetc(infile);
if (val2 > 127)
{
val2 = val2 - 255;
}
A[v] = 256*val2 + val;
}
else
{
A[v] = val;
}
}
// prepare fft with fftw
out = (double *)fftw_malloc(N * sizeof(double));
in = (double *)fftw_malloc(N * sizeof(double));
magnitudeLin = (double *)fftw_malloc(N * sizeof(double));
magnitudeLog = (double *)fftw_malloc(N * sizeof(double));
// create the fftw plan
plan = fftw_plan_r2r_1d(N, in, out, FFTW_R2HC, FFTW_ESTIMATE);
// we have no imaginary data, so clear idata
memset((void *)out, 0, N * sizeof(double));
// fill rdata with actual data
for (int i = 0; i < N; i++)
{
in[i] = A[i];
}
// make fft
fftw_execute(plan);
// post-process FFT data: make absolute values, and calculate
// real frequency of each power line in the spectrum (20 KHz : 22.05 KHz = num_p : (N/2)+1)
// typeFFT = 0 -> linear, 1 -> log
int num_p = ((N/2)+1)*20000/22050;
for (int i = 1; i < num_p; i++)
{
magnitudeLin[i] = abs(2.0*sqrt(out[i]*out[i])/N);
magnitudeLog[i] = abs(10*log10(2.0*sqrt(out[i]*out[i])/N));
// find min and max lin value
if (magnitudeLin[i] > max_val_lin)
max_val_lin = magnitudeLin[i];
if (magnitudeLin[i] < min_val_lin)
min_val_lin = magnitudeLin[i];
// find min and max log value
if (magnitudeLog[i] > max_val_log)
max_val_log = magnitudeLog[i];
if (magnitudeLog[i] < min_val_log)
min_val_log = magnitudeLog[i];
}
// housekeeping
fclose(infile);
fftw_destroy_plan(plan);
fftw_free(in);
fftw_free(out);
}
void QFreq::paintEvent(QPaintEvent *)
{
paintBorder();
paintFreq();
paintScale();
paintControl();
}
void QFreq::paintBorder()
{
QPainter painter(this);
painter.setWindow(0, 0, 800, 360);
painter.setRenderHint(QPainter::Antialiasing);
QLinearGradient linGrad(20, 50, 180, 250);
linGrad.setColorAt(0, Qt::gray);
linGrad.setColorAt(1, Qt::white);
linGrad.setSpread(QGradient::ReflectSpread);
painter.setBrush(linGrad);
QRectF border(10, 10, 780, 340);
painter.drawRoundRect(border, 5, 5);
// draw rack point
painter.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter.setBrush(Qt::white);
painter.drawRoundRect(20, 80, 20, 13, 30, 30);
painter.drawRoundRect(20, 260, 20, 13, 30, 30);
painter.drawRoundRect(760, 80, 20, 13, 30, 30);
painter.drawRoundRect(760, 260, 20, 13, 30, 30);
QLinearGradient linGrad1(50, 180, 57, 180);
linGrad1.setColorAt(0, Qt::white);
linGrad1.setColorAt(1, QColor(80,80,80));
linGrad1.setSpread(QGradient::PadSpread);
painter.setBrush(linGrad1);
painter.setPen(QPen(Qt::black, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
QRectF border1(50, 40, 700, 280);
painter.drawRect(border1);
painter.setPen(QPen(Qt::black, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter.drawLine(750, 318, 750, 42);
painter.setBrush(Qt::black);
QRectF panel(102, 63, 595, 197);
painter.drawRect(panel);
}
void QFreq::paintFreq()
{
if (wavFile.isEmpty())
return;
else
{
QPainter painter(this);
painter.setWindow(0, 0, 800, 360);
painter.setRenderHint(QPainter::Antialiasing);
QLinearGradient linGrad(400, 320, 400, 40);
linGrad.setColorAt(0, Qt::green);
linGrad.setColorAt(1, Qt::red);
linGrad.setSpread(QGradient::PadSpread);
painter.setBrush(linGrad);
painter.setPen(QPen(linGrad, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
// draw the frequency value
// X axis is 700 pt. - Y axis is 360 pt.
// 1024/2 pt : 22050 Hz = x : 20000 Hz -> x = 464 ?????
// DC freq (0 kz) not draw
// typeFFT = 0 linear 1 logaritmic
if (typeFFT == 0)
{
for (int i = 1; i <= zoom_point-1; i++)
{
painter.drawLine(100+(i*600/zoom_point), 260, 100+(i*600/zoom_point), (260-195*(magnitudeLin[i+start_point]/max_val_lin)));
}
}
if (typeFFT == 1)
{
for (int i = 1; i <= zoom_point-1; i++)
{
painter.drawLine(100+(i*600/zoom_point), 260, 100+(i*600/zoom_point), (260-195*(magnitudeLog[i+start_point]/max_val_log)));
}
}
}
}
void QFreq::paintScale()
{
QPainter painter(this);
painter.setWindow(0, 0, 800, 360);
painter.setRenderHint(QPainter::Antialiasing);
//draw scale
painter.setPen(QPen(Qt::yellow, 1, Qt::SolidLine));
painter.drawLine(100, 265, 700, 265);
for (int i = 0; i <= 4; i++)
{
painter.drawLine(100+(150*i), 265, 100+(150*i), 275);
}
painter.save();
for (int i = 1; i <= 4; i++)
{
for (int i = 1; i <=
- 1
- 2
- 3
前往页