Entropy Piano Tuner  1.1.3 (documentation not yet complete)
An open-source experimental software for piano tuning by entropy minimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tuningindicatordrawer.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright 2015 Haye Hinrichsen, Christoph Wick
3  *
4  * This file is part of Entropy Piano Tuner.
5  *
6  * Entropy Piano Tuner is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * Entropy Piano Tuner is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * Entropy Piano Tuner. If not, see http://www.gnu.org/licenses/.
18  *****************************************************************************/
19 
20 //=============================================================================
21 // Tuning indicator
22 //=============================================================================
23 
24 #include "tuningindicatordrawer.h"
25 
26 #include "../messages/messagenewfftcalculated.h"
27 #include "../messages/messagekeyselectionchanged.h"
28 #include "../messages/messagepreliminarykey.h"
29 #include "../messages/messagemodechanged.h"
30 #include "../messages/messageprojectfile.h"
31 #include "../messages/messagetuningdeviation.h"
32 #include "../messages/messagestroboscope.h"
33 #include "../math/mathtools.h"
34 #include "../system/log.h"
35 #include "../settings.h"
36 
38  DrawerBase(graphics),
39  mPiano(nullptr),
40  mNumberOfKeys(0),
41  mSelectedKey(-1),
42  mRecognizedKey(-1),
43  mOperationMode(MODE_COUNT),
44  mDataVector()
45 {
46 }
47 
48 
49 //-----------------------------------------------------------------------------
50 // Message listener
51 //-----------------------------------------------------------------------------
52 
60 
62 {
63  switch (m->getType())
64  {
66  {
67  // Copy the operation mode and redraw when switched to tuning
68  auto mmc(std::static_pointer_cast<MessageModeChanged>(m));
69  mOperationMode = mmc->getMode();
70  if (mOperationMode == MODE_TUNING) redraw(true);
71  break;
72  }
74  {
75  // Store the recognized key and redraw in tuning mode
77  {
78  auto message(std::static_pointer_cast<MessagePreliminaryKey>(m));
79  mRecognizedKey = message->getKeyNumber();
80  redraw(true);
81  }
82  else mRecognizedKey=-1;
83  break;
84  }
86  {
87  // Store the selcted key and redraw in tuning mode
88  auto mksc(std::static_pointer_cast<MessageKeySelectionChanged>(m));
89  mSelectedKey = mksc->getKeyNumber();
91  break;
92  }
94  {
95  auto mpf(std::static_pointer_cast<MessageProjectFile>(m));
96  mPiano = &mpf->getPiano();
98  mSelectedKey = std::min<int>(mSelectedKey, mNumberOfKeys); // ??
99  if (mOperationMode == MODE_TUNING) redraw(true);
100  break;
101  }
103  {
104  auto mtd(std::static_pointer_cast<MessageTuningDeviation>(m));
105  mFrequencyDetectionResult = mtd->getResult();
106  redraw();
107  break;
108  }
110  {
111  if (mOperationMode == MODE_TUNING and Settings::getSingleton().isStroboscopeActive())
112  {
113  auto mmc(std::static_pointer_cast<MessageStroboscope>(m));
114  mDataVector = mmc->getData();
115  draw();
116  }
117  break;
118  }
120  {
121  redraw();
122  break;
123  }
124  default:
125  {
126  break;
127  }
128  }
129 }
130 
131 
132 //-----------------------------------------------------------------------------
133 // Toggle between spectral and stroboscopic operation mode
134 //-----------------------------------------------------------------------------
135 
139 
141 {
142  LogI("Toggle between spectral and stroboscopic tuning indicator by mouse click");
143  bool stroboscope = Settings::getSingleton().isStroboscopeActive();
144  Settings::getSingleton().setStroboscopeMode (not stroboscope);
145  redraw(true);
146 }
147 
148 
149 //-----------------------------------------------------------------------------
150 // Reset
151 //-----------------------------------------------------------------------------
152 
156 
158 {
159  mFFTData.reset();
161 }
162 
163 
164 //-----------------------------------------------------------------------------
165 // Drawing function
166 //-----------------------------------------------------------------------------
167 
178 
179 
181 {
182  //-- If stroboscopic mode forward the data to the GraphicsViewAdapter ----
183 
184  if (Settings::getSingleton().isStroboscopeActive())
185  {
187  return;
188  }
189 
190  //---------------------- Handle the spectral mode -------------------------
191 
192  //------- Draw a horizontal and a vertical line separating the field ------
193 
196 
197  int keynumber = (mSelectedKey >= 0 ? mSelectedKey : mRecognizedKey);
198  if (keynumber<0) return;
199 
200  if (not mFrequencyDetectionResult) {return;} // we need data
201  if (not mPiano) {return;} // and a piano
202 
203  // show only a quarter of the actual deviation curve
204  const int specWindowSize = mFrequencyDetectionResult->tuningDeviationCurve.size() / 4;
205 
206  for (int i=1; i<specWindowSize; i++)
207  {
208  double x = (1.0*i)/specWindowSize;
209  double y = ((i-specWindowSize/2)%10==0 ? 1 : 0.85);
211  }
212 
213  //---------------------- Draw tuning deviation curve -----------------
214 
215  if (specWindowSize > 0)
216  {
217  double max = *std::max_element(mFrequencyDetectionResult->tuningDeviationCurve.begin(),
218  mFrequencyDetectionResult->tuningDeviationCurve.end());
219 
220  std::vector<GraphicsViewAdapter::Point> points;
221  const int centerIndex = mFrequencyDetectionResult->tuningDeviationCurve.size() / 2;
222  const int startIndex = std::max<int>(0, centerIndex - specWindowSize / 2 +
223  MathTools::roundToInteger(mFrequencyDetectionResult->positionOfMaximum) -
224  mFrequencyDetectionResult->deviationInCents);
225  const int endIndex = std::min<int>(startIndex + specWindowSize,
226  mFrequencyDetectionResult->tuningDeviationCurve.size());
227  for (int i = startIndex; i < endIndex; ++i) {
228  double y = mFrequencyDetectionResult->tuningDeviationCurve[i] / max;
229  y *= y;
230  y = 0.8 - 0.77 * y;
231  double x = static_cast<double>(i - startIndex) / specWindowSize;
232  points.push_back({x, y});
233  }
235  }
236 
237  //---------------------- Draw overpull marker ------------------------
238 
239  double overpull = mFrequencyDetectionResult->overpullInCents;
240  if (std::abs(overpull)>0.2 and std::abs(overpull)<100)
241  {
242  auto overpullColor = GraphicsViewAdapter::PEN_MEDIUM_MAGENTA;
243  if (std::abs(overpull) > specWindowSize/2)
244  {
245  overpullColor = GraphicsViewAdapter::PEN_MEDIUM_RED;
246  overpull = specWindowSize/2 * (overpull>0 ? 1:-1);
247  }
248  double x = 0.5 + overpull / specWindowSize;
249  mGraphics->drawLine(x,0,x,0.8,overpullColor);
250  }
251 
252  //----------------------- Draw tuning marker -------------------------
253 
254  double markerWidth = 0.1;
255  double markerHeight = 0.1;
256  double deviation = mFrequencyDetectionResult->deviationInCents;
257  double mx = 0.5 - markerWidth / 2 + deviation / specWindowSize;
258  double my = 0.9 - markerHeight / 2;
259 
260  auto borderline = GraphicsViewAdapter::PEN_THIN_DARK_GRAY;
261  auto filling = GraphicsViewAdapter::FILL_RED;
262  if (std::abs(deviation) < 5) filling = GraphicsViewAdapter::FILL_GREEN;
263  else if (std::abs(deviation) < 10) filling = GraphicsViewAdapter::FILL_ORANGE;
264 
265  mGraphics->drawFilledRect(mx, my, markerWidth, markerHeight, borderline, filling);
266 }
267 
virtual void clear() overridefinal
Clear the shared pointer to the FFT.
virtual GraphicsItem * drawChart(const std::vector< Point > &points, PenType pen=PEN_THIN_BLACK)=0
Abstract function: Draw a chart (polygon).
std::shared_ptr< Message > MessagePtr
Global type of a shared message pointer.
Definition: message.h:98
virtual void setStroboscopeMode(bool enable)
Set flag indicating the stroboscopic mode of the tuning indicator.
Definition: settings.h:79
GraphicsViewAdapter * mGraphics
Pointer to the graphics view adapter.
Definition: drawerbase.h:53
tuning deviation curve has been updated
Definition: message.h:71
static Settings & getSingleton()
Get a pointer to the singleton instance.
Definition: settings.cpp:46
void toggleSpectralAndStroboscopeMode()
Toggle between spectral and stroboscopic operation mode.
virtual void draw() overridefinal
Main drawing function.
Message that a change was made with the current project file.
Definition: message.h:68
const Piano * mPiano
Pointer to the piano.
Message that the operation mode has changed.
Definition: message.h:65
int roundToInteger(T x)
Round a floating point number to an integer.
Definition: mathtools.h:43
virtual void drawStroboscope(const ComplexVector &data)=0
Message that a key has been selected.
Definition: message.h:63
The count of modes.
Definition: prerequisites.h:73
void redraw(bool force=false)
Function to completely redraw the scene.
Definition: drawerbase.cpp:57
const Keyboard & getKeyboard() const
Definition: piano.h:83
virtual GraphicsItem * drawFilledRect(double x, double y, double w, double h, PenType pen=PEN_THIN_BLACK, FillTypes fill=FILL_RED)=0
Abstract function: Draw a filled rectangle.
bool isStroboscopeActive() const
Get flag indicating the stroboscopic mode of the tuning indicator.
Definition: settings.h:77
virtual void clear()
Clear the whole view.
Definition: drawerbase.h:51
stroboscope message
Definition: message.h:70
#define LogI(...)
Definition: log.h:50
number of the key recognized during recording
Definition: message.h:67
int mRecognizedKey
Number of recognized key, -1 if none.
int mSelectedKey
Number of selected key, -1 if none.
Mode for manually tuning the piano.
Definition: prerequisites.h:71
FrequencyDetectionResult mFrequencyDetectionResult
Copy of frequency detection result.
ComplexVector mDataVector
Data vector holding complex phases for stroboscope.
Abstract base class for implementations rendering graphics.
TuningIndicatorDrawer(GraphicsViewAdapter *graphics)
virtual GraphicsItem * drawLine(double x1, double y1, double x2, double y2, PenType pen=PEN_THIN_BLACK)=0
Abstract function: Draw a line.
virtual void handleMessage(MessagePtr m) override
Message listener.
FFTDataPointer mFFTData
Pointer to the Fourier transform data.
settings in the system options changed
Definition: message.h:56
int getNumberOfKeys() const
Definition: keyboard.h:72
Abstract base class for drawing 2d graphics.
Definition: drawerbase.h:40
OperationMode mOperationMode
Current operation mode of the EPT.
int mNumberOfKeys
Total number of keys.