X-Git-Url: http://git.johnwright.org/?p=fmit.git;a=blobdiff_plain;f=src%2Fmodules%2FGLFT.cpp;fp=src%2Fmodules%2FGLFT.cpp;h=42071f74c95b5e192bd5da5adf3947607f9016aa;hp=bbde0d6324f93d851518e28b5e3f1848b895039d;hb=49947d1cd4506f5574b3be62ee90e9f00227d9fd;hpb=82c9faab9421b3d87a0faa84a73f55aaccbbb689 diff --git a/src/modules/GLFT.cpp b/src/modules/GLFT.cpp index bbde0d6..42071f7 100644 --- a/src/modules/GLFT.cpp +++ b/src/modules/GLFT.cpp @@ -16,6 +16,8 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// TODO zoom with a rectangle + #include "GLFT.h" static const unsigned char g_icon_FT[] = { @@ -168,6 +170,9 @@ static const unsigned char g_icon_FT[] = { using namespace std; #include #include +#include +#include +#include #include #include #include @@ -176,80 +181,122 @@ using namespace Music; using namespace Math; GLFT::GLFT(QWidget* parent) -: QGLWidget(parent, "GLFT") -, View("Fourier Transform", this) +: QGLWidget(parent) +, View(tr("Fourier Transform"), this) , m_components_max(1.0) { m_start_move_mouse = true; - m_x = 0; - m_y = 0; - m_z = 0.0; - m_zp_factor = 4; // actually, actuellement, not zero-padding but win-size-factor + m_os = 2; // over sampling factor // settings - QImage img; + QPixmap img; img.loadFromData(g_icon_FT, sizeof(g_icon_FT), "PNG"); - setting_show->setIconSet(QIconSet(QImage(img))); - setting_show->setOn(false); + setting_show->setIcon(QIcon(img)); + setting_show->setChecked(false); hide(); - setting_autoScale = new QAction(this); - setting_autoScale->setMenuText(tr("Auto scale")); - setting_autoScale->setToggleAction(true); - connect(setting_autoScale, SIGNAL(toggled(bool)), this, SLOT(update())); - setting_autoScale->setOn(true); - setting_autoScale->addTo(&m_popup_menu); - - setting_db_scale = new QAction(this); - setting_db_scale->setMenuText(tr("dB scale")); - setting_db_scale->setToggleAction(true); - connect(setting_db_scale, SIGNAL(toggled(bool)), this, SLOT(update())); - setting_db_scale->setOn(true); - setting_db_scale->addTo(&m_popup_menu); - - m_popup_menu.insertItem(new Title(tr("Size"), &m_popup_menu)); - setting_spinNumComponents = new QSpinBox(1, 65536, 1, &m_popup_menu); - setting_spinNumComponents->setValue(8192); - m_components.resize(setting_spinNumComponents->value()); - QToolTip::add(setting_spinNumComponents, tr("Size")); - connect(setting_spinNumComponents, SIGNAL(valueChanged(int)), this, SLOT(spinNumComponentsChanged(int))); - m_popup_menu.insertItem(setting_spinNumComponents); - m_popup_menu.insertItem(new Title(tr("- Press left mouse button and move mouse to zoom"), &m_popup_menu)); - m_popup_menu.insertItem(new Title(tr("- Press SHIFT key, left mouse button and move mouse to move view"), &m_popup_menu)); - m_popup_menu.insertItem(new Title(tr("- Double-click to reset view"), &m_popup_menu)); - - m_plan.resize(setting_spinNumComponents->value()); - m_components.resize(m_plan.size()/2, 0.0); - win = hann(m_plan.size()); + setting_db_scale = new QAction(tr("dB scale"), this); + setting_db_scale->setCheckable(true); + connect(setting_db_scale, SIGNAL(toggled(bool)), this, SLOT(dBScaleChanged(bool))); + setting_db_scale->setChecked(true); + m_popup_menu.addAction(setting_db_scale); + resetaxis(); + + QHBoxLayout* sizeActionLayout = new QHBoxLayout(&m_popup_menu); + + QLabel* sizeActionTitle = new QLabel(tr("Size"), &m_popup_menu); + sizeActionLayout->addWidget(sizeActionTitle); + + setting_winlen = new QSpinBox(&m_popup_menu); + setting_winlen->setObjectName("setting_winlen"); + setting_winlen->setMinimum(1); + setting_winlen->setMaximum(1000); + setting_winlen->setSingleStep(1); + setting_winlen->setValue(20); + setting_winlen->setSuffix(" ms"); + setting_winlen->setToolTip(tr("window length")); + connect(setting_winlen, SIGNAL(valueChanged(int)), this, SLOT(spinWinLengthChanged(int))); + sizeActionLayout->addWidget(setting_winlen); + + QWidget* sizeActionWidget = new QWidget(&m_popup_menu); + sizeActionWidget->setLayout(sizeActionLayout); + + QWidgetAction* sizeAction = new QWidgetAction(&m_popup_menu); + sizeAction->setDefaultWidget(sizeActionWidget); + m_popup_menu.addAction(sizeAction); + + QWidgetAction* helpCaption01 = new QWidgetAction(&m_popup_menu); + helpCaption01->setDefaultWidget(new Title(tr("- Press left mouse button to move the view"), &m_popup_menu)); + m_popup_menu.addAction(helpCaption01); + QWidgetAction* helpCaption02 = new QWidgetAction(&m_popup_menu); + helpCaption02->setDefaultWidget(new Title(tr("- Press SHIFT key and left mouse button to zoom in and out"), &m_popup_menu)); + m_popup_menu.addAction(helpCaption02); + QWidgetAction* helpCaption03 = new QWidgetAction(&m_popup_menu); + helpCaption03->setDefaultWidget(new Title(tr("- Double-click to reset the view"), &m_popup_menu)); + m_popup_menu.addAction(helpCaption03); + + s_settings->add(setting_winlen); + + spinWinLengthChanged(setting_winlen->value()); } -void GLFT::save() +void GLFT::refreshGraph() { - s_settings->writeEntry("spinNumComponents", setting_spinNumComponents->value()); + while(int(buff.size())>m_plan.size()) + buff.pop_back(); } -void GLFT::load() + +void GLFT::setSamplingRate(int sr) { - setting_spinNumComponents->setValue(s_settings->readNumEntry("spinNumComponents", setting_spinNumComponents->value())); + m_maxf=sr/2; } -void GLFT::clearSettings() + +void GLFT::resetaxis() { - s_settings->removeEntry("spinNumComponents"); -} + m_minf=0; + m_maxf=Music::GetSamplingRate()/2; // sr is surely -1 because not yet defined -void GLFT::refreshGraph() + if(setting_db_scale->isChecked()) + { + m_minA = -50; // [dB] + m_maxA = 100; // [dB] + } + else + { + m_maxA = 1; // [amplitude] + } +} +void GLFT::dBScaleChanged(bool db) { - while(int(buff.size())>m_plan.size()) - buff.pop_back(); + resetaxis(); + update(); } -void GLFT::spinNumComponentsChanged(int num) +void GLFT::spinWinLengthChanged(int num) { - m_plan.resize(int(m_zp_factor*num)); - m_components.resize(m_plan.size()/2); - win = hann(num); - - cerr << "GLFT: INFO: window size=" << win.size() << " FFT size=" << m_plan.size() << endl; + if(Music::GetSamplingRate()>0) + { + // Create window + int winlen = int(num/1000.0*Music::GetSamplingRate()); + win = hann(winlen); + double win_sum = 0.0; + // normalize the window in energy + for(size_t i=0; ix() - old_x; int dy = e->y() - old_y; - if(Qt::LeftButton & e->state()) + if(Qt::LeftButton & e->buttons()) { - if(Qt::ShiftButton & e->state()) + if(Qt::ShiftModifier & e->modifiers()) { - m_x += dx; - m_y -= dy; + double f = (m_maxf-m_minf)*double(m_press_x)/width()+m_minf; + double zx = double(m_press_x-e->x())/width(); + zx = pow(8, zx); + m_minf = f - zx*(f-m_press_minf); + m_maxf = f + zx*(m_press_maxf-f); } else { - m_z += dx/100.0; - if(m_z<0.0) m_z = 0.0; + m_minf -= (m_maxf-m_minf)*dx/width(); + m_maxf -= (m_maxf-m_minf)*dx/width(); + + if(setting_db_scale->isChecked()) + { + m_minA += (m_maxA-m_minA)*dy/height(); + m_maxA += (m_maxA-m_minA)*dy/height(); + } + else + m_maxA -= m_maxA*double(dy)/height(); } updateGL(); @@ -316,19 +378,22 @@ void GLFT::paintGL() { glClear(GL_COLOR_BUFFER_BIT); - if(int(buff.size())>=m_plan.size()) + if(win.size()>0 && int(buff.size())>=m_plan.size()) { + // Use last samples while(int(buff.size())>m_plan.size()) buff.pop_back(); + int sr = Music::GetSamplingRate(); + +// cout << m_plan.size() << endl; + // name - string str = tr("Fourier Transform"); + string str = tr("Fourier Transform").toStdString(); glColor3f(0.75,0.75,0.75); glRasterPos2i(2, height()-20); for(size_t i = 0; i < str.size(); i++) - glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, str[i]); - - int scale_height = 0; + glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, (unsigned char)str[i]); for(int i=0; iisOn()) - m_components[i] = 100+20*log10(m_components[i]); - m_components_max = max(m_components_max, m_components[i]); - } - -// cerr << m_components_max << endl; - - double scale_factor = 1.0; - if(setting_autoScale->isOn() && m_components_max>0.0) - scale_factor = 1.0/m_components_max; -// cerr << scale_factor << endl; - - // bars - glBegin(GL_QUADS); - float step = float(width())/m_components.size() + m_z; - int space = (step>2)?1:0; - for(size_t i=0; i