1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4     Rosegarden
5     A MIDI and audio sequencer and musical notation editor.
6     Copyright 2000-2009 the Rosegarden development team.
7 
8     Other copyrights also apply to some parts of this work.  Please
9     see the AUTHORS file and individual file headers for details.
10 
11     This program is free software; you can redistribute it and/or
12     modify it under the terms of the GNU General Public License as
13     published by the Free Software Foundation; either version 2 of the
14     License, or (at your option) any later version.  See the file
15     COPYING included with this distribution for more information.
16 */
17 
18 
19 #include "PitchTrackerConfigurationPage.h"
20 #include "sound/Tuning.h"
21 #include "sound/PitchDetector.h"
22 #include "misc/ConfigGroups.h"
23 #include "misc/Debug.h"
24 // Might need default analysis sizes
25 #include "gui/configuration/PitchTrackerConfigurationPage.h"
26 #include "sound/PitchDetector.h"
27 // Tunings are returned a stl vector. See sound/Tuning.h
28 #include <vector>
29 #include <QLabel>
30 #include <QComboBox>
31 #include <QSpinBox>
32 #include <QCheckBox>
33 #include <QSettings>
34 #include <QWidget>
35 #include <QHBoxLayout>
36 #include <QToolTip>
37 #include <QLayout>
38 
39 namespace Rosegarden
40 {
41 
42 const int PitchTrackerConfigurationPage::defaultGraphWidth = 4000;
43 const int PitchTrackerConfigurationPage::defaultGraphHeight = 100;
44 const bool PitchTrackerConfigurationPage::defaultIgnore8ve = true;
45 
PitchTrackerConfigurationPage(QWidget * parent)46 PitchTrackerConfigurationPage::PitchTrackerConfigurationPage(QWidget *parent) :
47         TabbedConfigurationPage(parent),
48         m_noTuningsAlert(parent)
49 {
50     QSettings settings;
51     settings.beginGroup(PitchTrackerConfigGroup);
52 
53     QFrame *frame;
54     QGridLayout *layout;
55 
56     frame = new QFrame(m_tabWidget);
57     frame->setContentsMargins(10, 10, 10, 10);
58     layout = new QGridLayout(frame);
59     layout->setSpacing(5);
60 
61     int row = 0;
62 
63     layout->setRowMinimumHeight(row, 15);
64     ++row;
65 
66     layout->addWidget(new QLabel(tr("Tuning"), frame), row, 0);
67 
68     m_tuningMode = new QComboBox(frame);
69     connect(m_tuningMode, SIGNAL(activated(int)),
70             this, SLOT(slotModified()));
71     m_tuningMode->setEditable(false);
72 
73     slotPopulateTuningCombo(true);
74 
75     int defaultTuningMode = settings.value("tuning", 0).toInt() ;
76     m_tuningMode->setCurrentIndex(defaultTuningMode);
77     layout->addWidget(m_tuningMode, row, 1, 1, 2);
78     ++row;
79 
80     // TODO: write Edit Tuning dialogue to allow these to be edited
81     // Currently, the settings make A440 in MIDI 12ET be the same note
82     // in all tunings (a regression since rosegarden v1.2.4gpt1)
83     m_rootPitch = 69;
84     m_refPitch  = 69;
85     m_refFreq   = 440.0;
86     layout->addWidget(new QLabel(tr("Root Pitch"), frame), row, 0);
87     m_rootPitchLabel = new QLabel("A3");
88     layout->addWidget(m_rootPitchLabel, row, 1, 1, 2);
89     row++;
90     layout->addWidget(new QLabel(tr("Reference Pitch"), frame), row, 0);
91     m_refPitchLabel = new QLabel("A3");
92     layout->addWidget(m_refPitchLabel, row, 1, 1, 2);
93     row++;
94     layout->addWidget(new QLabel(tr("Reference Frequency"), frame), row, 0);
95     m_refFreqLabel = new QLabel("440.0");
96     layout->addWidget(m_refFreqLabel, row, 1, 1, 2);
97     row++;
98 
99     layout->setRowStretch(row, 2);
100     frame->setLayout(layout);
101     addTab(frame, tr("General"));
102 
103     frame = new QFrame(m_tabWidget);
104     frame->setContentsMargins(10, 10, 10, 10);
105     layout = new QGridLayout(frame);
106     layout->setSpacing(5);
107     row = 0;
108 
109     // TODO: Add input source combo
110     layout->addWidget(new QLabel(tr("Method"), frame), row, 0);
111     m_method = new QComboBox(frame);
112     connect(m_method, SIGNAL(activated(int)),
113             this, SLOT(slotModified()));
114     m_method->setEditable(false);
115     const QVector<PitchDetector::Method> *pt_methods =
116         PitchDetector::getMethods();
117     if (pt_methods) {
118         QVector<PitchDetector::Method>::const_iterator i;
119         for (i = pt_methods->begin(); i != pt_methods->end(); ++i) {
120             m_method->addItem(*i);
121         }
122         int defaultMethod = settings.value("method", 0).toInt() ;
123         if (defaultMethod >= 0 && defaultMethod < pt_methods->size()) {
124             m_method->setCurrentIndex(defaultMethod);
125         }
126     }
127     layout->addWidget(m_method, row, 1, 1, 2);
128     ++row;
129 
130     layout->addWidget(new QLabel(tr("Frame Size"), frame), row, 0);
131     m_frameSize = new QSpinBox(frame);
132     connect(m_frameSize, SIGNAL(valueChanged(int)),
133             this, SLOT(slotModified()));
134     m_frameSize->setMinimum(64);
135     m_frameSize->setMaximum(32768);
136     int frameSize = settings.value("framesize",
137                                    PitchDetector::defaultFrameSize).toInt();
138     if (frameSize >= 64 && frameSize <= 32768) {
139         m_frameSize->setValue(frameSize);
140     }
141     layout->addWidget(m_frameSize, row, 1, 1, 2);
142     ++row;
143 
144     layout->addWidget(new QLabel(tr("Step Size"), frame), row, 0);
145     m_stepSize = new QSpinBox(frame);
146     connect(m_stepSize, SIGNAL(valueChanged(int)),
147             this, SLOT(slotModified()));
148     m_stepSize->setMinimum(64);
149     m_stepSize->setMaximum(8192);
150     int stepSize = settings.value("stepsize",
151                                   PitchDetector::defaultStepSize).toInt();
152     if (stepSize >= 64 && stepSize <= 8192) {
153         m_stepSize->setValue(stepSize);
154     }
155     layout->addWidget(m_stepSize, row, 1, 1, 2);
156     ++row;
157 
158     layout->addWidget(new QLabel(tr("Ignore Octave Errors"), frame), row, 0);
159     m_ignore8ve = new QCheckBox(frame);
160     connect(m_ignore8ve, &QCheckBox::stateChanged,
161             this, &PitchTrackerConfigurationPage::slotModified);
162     bool defaultIgnore8ve =
163            settings.value("ignoreoctave",
164                           PitchTrackerConfigurationPage::defaultIgnore8ve
165                          ).toBool();
166     m_ignore8ve->setChecked(defaultIgnore8ve);
167     layout->addWidget(m_ignore8ve, row, 1, 1, 2);
168     ++row;
169 
170     layout->setRowStretch(row, 2);
171     frame->setLayout(layout);
172     addTab(frame, tr("Algorithm"));
173 
174     frame = new QFrame(m_tabWidget);
175     frame->setContentsMargins(10, 10, 10, 10);
176     layout = new QGridLayout(frame);
177     layout->setSpacing(5);
178     row = 0;
179     layout->addWidget(new QLabel(tr("Graph Width (ms)"), frame), row, 0);
180     m_graphWidth = new QSpinBox(frame);
181     connect(m_graphWidth, SIGNAL(valueChanged(int)),
182             this, SLOT(slotModified()));
183     m_graphWidth->setMinimum(200);
184     m_graphWidth->setMaximum(20000);
185     const int graphWidth =
186         settings.value("graphwidth", defaultGraphWidth).toInt();
187     if (graphWidth >= 200 && graphWidth <= 20000) {
188         m_graphWidth->setValue(graphWidth);
189     }
190     layout->addWidget(m_graphWidth, row, 1, 1, 2);
191     ++row;
192 
193     layout->addWidget(new QLabel(tr("Graph Height (cents)"), frame), row, 0);
194     m_graphHeight = new QSpinBox(frame);
195     connect(m_graphHeight, SIGNAL(valueChanged(int)),
196             this, SLOT(slotModified()));
197     m_graphHeight->setMinimum(20);
198     m_graphHeight->setMaximum(600);
199     const int graphHeight =
200         settings.value("graphheight", defaultGraphHeight).toInt();
201     if (graphHeight >= 20 && graphHeight <= 600) {
202         m_graphHeight->setValue(graphHeight);
203     }
204     layout->addWidget(m_graphHeight, row, 1, 1, 2);
205     ++row;
206 
207     layout->setRowStretch(row, 2);
208     frame->setLayout(layout);
209     addTab(frame, tr("Appearance"));
210     settings.endGroup();
211 }
212 
213 void
slotPopulateTuningCombo(bool rescan)214 PitchTrackerConfigurationPage::slotPopulateTuningCombo(bool rescan)
215 {
216     // Read the tunings file to determine those available, and populate the
217     // combo box.
218     if (rescan || !m_tunings) m_tunings = Accidentals::Tuning::getTunings();
219 
220     if (m_tunings) {
221         // Empty the tuning mode combo box and repopulate.
222         while (m_tuningMode->count()) {
223             m_tuningMode->removeItem(0);
224         }
225 
226         std::vector<Accidentals::Tuning *>::iterator t;
227         for (t = m_tunings->begin(); t != m_tunings->end(); ++t) {
228             m_tuningMode->addItem(QString((*t)->getName().c_str()));
229         }
230     } else { // the tunings file couldn't be found, so display a message
231         RG_WARNING << "Pitch Tracker: Error: No tunings!!\n"
232                      "Probably a missing tuning.xml file.\n"
233                      "The user will have been warned.";
234 
235         m_noTuningsAlert.showMessage(tr(
236             "The tunings file could not be found! "
237             "The file named \"tunings.xml\" containing tuning definitions "
238             "has not been found in any of the standard "
239             "directories. On Linux platforms, these include "
240             "/usr/share/rosegarden/pitches, "
241             "/usr/local/share/rosegarden/pitches and "
242             "$HOME/.local/share/rosegarden/pitches. "
243             "This file should be part of the standard installation."));
244     }
245 }
246 
247 void
apply()248 PitchTrackerConfigurationPage::apply()
249 {
250     QSettings settings;
251     settings.beginGroup(PitchTrackerConfigGroup);
252 
253     settings.setValue("tuning", m_tuningMode->currentIndex());
254     settings.setValue("rootpitch", "A3");
255     settings.setValue("refpitch", "A3");
256     settings.setValue("reffrequency", 440.0);
257     settings.setValue("method", m_method->currentIndex());
258     settings.setValue("framesize", m_frameSize->value());
259     settings.setValue("stepsize", m_stepSize->value());
260     settings.setValue("ignoreoctave", m_ignore8ve->isChecked());
261     settings.setValue("graphwidth", m_graphWidth->value());
262     settings.setValue("graphheight", m_graphHeight->value());
263 
264     settings.endGroup();
265 }
266 
267 }
268