changeset 589:7ebd5a21d74f sonification

Branch to handle audio feedback and metadata sonification interactively with the UI. Piano keyboard audio feedback: The midi pitch of a piano keyboard note is retrieved in SpectrogramLayer::processMouseEvent when a left click is made on the note in the Select tool mode (SpectrogramLayer with a log frequency scale). The same process should be applied to the Spectrum layer (log frequency scale) as well.
author mathieub <mathieu.barthet@eecs.qmul.ac.uk>
date Wed, 22 Jun 2011 00:04:21 +0100
parents 4806715f7a19
children 241929c5d57c
files layer/Layer.h layer/SpectrogramLayer.cpp layer/SpectrogramLayer.h view/Pane.cpp
diffstat 4 files changed, 62 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/layer/Layer.h	Tue Jun 14 15:27:05 2011 +0100
+++ b/layer/Layer.h	Wed Jun 22 00:04:21 2011 +0100
@@ -511,6 +511,11 @@
      */
     virtual RangeMapper *getNewVerticalZoomRangeMapper() const { return 0; }
 
+    //function to override in Layer subclasses in order to handle mouse events
+    //within the layer (e.g. audio feedback when clicking on the piano keyboard notes
+    //in SpectrogramLayer and SpectrumLayer)
+    virtual void processMouseEvent(const View *, QMouseEvent *, int) {}
+
 public slots:
     void showLayer(View *, bool show);
 
--- a/layer/SpectrogramLayer.cpp	Tue Jun 14 15:27:05 2011 +0100
+++ b/layer/SpectrogramLayer.cpp	Wed Jun 22 00:04:21 2011 +0100
@@ -3781,3 +3781,36 @@
     setNormalizeVisibleArea(normalizeVisibleArea);
 }
     
+void
+SpectrogramLayer::processMouseEvent(const View *v, QMouseEvent *e, int w)
+{
+
+    std::cerr<< "Mouse click detected in the layer: (" << e->x() << "," << e->y() << ")" << std::endl;
+
+    //is there a way to declare pkw and w may as class private variables?
+
+    int pkw = (m_frequencyScale == LogFrequencyScale ? 10 : 0);
+
+    int pianoKeyboardXLeft = w - pkw - 1;
+    int pianoKeyboardXRight = w;    
+
+    float freq;
+    QString unit;
+    float *centsOffsetReturn = 0;
+    float concertA = 0.0;
+    int midipitch;
+
+    if ((e->x() >= pianoKeyboardXLeft)&&(e->x() <= pianoKeyboardXRight))
+    {
+        std::cerr << "Piano keyboard left border: " << pianoKeyboardXLeft<<std::endl;
+        std::cerr << "Piano keyboard right border: " << pianoKeyboardXRight<<std::endl;
+        std::cerr<< "Mouse click detected within the piano keyboard: (" << e->x() << "," << e->y() << ")" << std::endl;
+
+        if (getYScaleValue(v, e->y(),freq, unit)) {
+
+            midipitch = Pitch::getPitchForFrequency(freq,centsOffsetReturn,concertA);
+
+            std::cerr<< "Frequency: " << freq << " " << unit.toStdString() << " (midi pitch = " << midipitch << ")" << std::endl;
+        }
+    }
+}
--- a/layer/SpectrogramLayer.h	Tue Jun 14 15:27:05 2011 +0100
+++ b/layer/SpectrogramLayer.h	Wed Jun 22 00:04:21 2011 +0100
@@ -227,6 +227,8 @@
 
     virtual const Model *getSliceableModel() const;
 
+    virtual void processMouseEvent(const View *, QMouseEvent *, int);
+
 protected slots:
     void cacheInvalid();
     void cacheInvalid(size_t startFrame, size_t endFrame);
--- a/view/Pane.cpp	Tue Jun 14 15:27:05 2011 +0100
+++ b/view/Pane.cpp	Wed Jun 22 00:04:21 2011 +0100
@@ -25,6 +25,10 @@
 #include "base/Preferences.h"
 #include "layer/WaveformLayer.h"
 
+#include "layer/LayerFactory.h"
+#include "layer/Layer.h"
+#include "layer/SpectrogramLayer.h"
+
 //!!! ugh
 #include "data/model/WaveFileModel.h"
 
@@ -1305,6 +1309,24 @@
             m_dragStartMinValue = dmin;
         }
 
+    //to process the mouse event when a left click is made in the layer and the tool mode is Select
+    //(to handle e.g. the audio feedback of the piano keyboard notes)
+    //does not work with the Navigate tool mode: (mode == ViewManager::NavigateMode) ||
+    //which could be also interesting
+    } else if ((mode == ViewManager::SelectMode) &&
+                   (e->buttons() & Qt::LeftButton)) {
+
+            Layer *layer = getTopLayer();
+            LayerFactory::LayerType type = LayerFactory::getInstance()->getLayerType(layer);
+
+            //if (type==(LayerFactory::LayerType) MelodicRangeSpectrogram) layer->checkMouseClick(this, e);
+
+            //std::cerr << "Vertical scale width: " << getVerticalScaleWidth() << std::endl;
+
+            //should call processMouseEvent only when a LogFrequencyScale is used but this is handled by
+            //overidding the function only in the relevant layer types
+            layer->processMouseEvent(this, e, getVerticalScaleWidth());
+
     } else if (mode == ViewManager::SelectMode) {
 
         if (!hasTopLayerTimeXAxis()) return;