|
From: Tapio V. <aa...@us...> - 2011-01-19 09:07:09
|
Module: editor
Branch: master
Commit: 4d129f596854bc7b170f57fd024af893eae75f25
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 19 11:03:53 2011 +0200
Importing a music file now starts the analyzer on it.
PitchVis is now stored as a pointer. Pixel access was changed from
operator() to pixel() to make it prettier with pointer type.
---
editorapp.cc | 7 +++--
notegraphwidget.cc | 65 ++++++++++++++++++++++++++++-----------------------
notegraphwidget.hh | 8 ++++--
pitchvis.cc | 10 ++++----
pitchvis.hh | 4 +-
5 files changed, 52 insertions(+), 42 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 614ff9c..6c1bae9 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -82,7 +82,7 @@ void EditorApp::operationDone(const Operation &op)
void EditorApp::doOpStack()
{
- noteGraph->clear();
+ noteGraph->clearNotes();
// Re-apply all operations in the stack
// FIXME: This technique cannot work quickly enough, since analyzing would also be started from scratch
for (OperationStack::const_iterator opit = opStack.begin(); opit != opStack.end(); ++opit) {
@@ -143,7 +143,7 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
void EditorApp::on_actionNew_triggered()
{
if (promptSaving()) {
- noteGraph->clear();
+ noteGraph->clearNotes();
projectFileName = "";
}
updateMenuStates();
@@ -357,7 +357,8 @@ void EditorApp::on_actionMusicFile_triggered()
// FIXME: Temporary test
audioOutput->setVolume(50);
player->play();
- // TODO: Extract the raw data and fire up an analyzer
+ // Fire up analyzer
+ noteGraph->analyzeMusic(fileName);
}
}
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index c2e2760..e755f1e 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -16,27 +16,11 @@ namespace {
}
NoteGraphWidget::NoteGraphWidget(QWidget *parent)
- : QLabel(parent), m_pitch("music.ogg"), m_panHotSpot(), m_selectedNote(), m_selectedAction(NONE), m_actionHappened()
+ : QLabel(parent), m_panHotSpot(), m_selectedNote(), m_selectedAction(NONE), m_actionHappened(), m_pitch()
{
- unsigned width = m_pitch.width(), height = m_pitch.height;
- QProgressDialog progress(tr("Rendering pitch data..."), tr("&Abort"), 0, width, this);
- progress.setWindowModality(Qt::WindowModal);
-
- QImage image(width, height, QImage::Format_ARGB32_Premultiplied);
- unsigned* rgba = reinterpret_cast<unsigned*>(image.bits());
- for (unsigned x = 0; x < width; ++x) {
- progress.setValue(x);
- if (progress.wasCanceled()) break;
+ // FIXME: Temporary hack to make testing quicker
+ analyzeMusic("music.ogg");
- for (unsigned y = 0; y < height; ++y) {
- rgba[y * width + x] = m_pitch(x, y).rgba();
- }
- }
- setPixmap(QPixmap::fromImage(image));
- progress.setValue(width);
-
- // FIXME: Width should come from song length * pixPerSec
- setFixedSize(std::max(width, (unsigned)1024), h());
setFocusPolicy(Qt::StrongFocus);
setWhatsThis(tr("Note graph that displays the song notes and allows you to manipulate them."));
@@ -58,7 +42,7 @@ void NoteGraphWidget::selectNote(NoteLabel* note)
emit updateNoteInfo(m_selectedNote);
}
-void NoteGraphWidget::clear()
+void NoteGraphWidget::clearNotes()
{
selectNote(NULL);
// Clear NoteLabels
@@ -74,13 +58,13 @@ void NoteGraphWidget::setLyrics(QString lyrics)
{
QTextStream ts(&lyrics, QIODevice::ReadOnly);
- clear();
+ clearNotes();
bool first = true;
while (!ts.atEnd()) {
QString word;
ts >> word;
if (!word.isEmpty()) {
- m_notes.push_back(new NoteLabel(Note(word.toStdString()), this, QPoint(0, m_pitch.note2px(24)), QSize(), !first));
+ m_notes.push_back(new NoteLabel(Note(word.toStdString()), this, QPoint(0, m_pitch->note2px(24)), QSize(), !first));
doOperation(opFromNote(*m_notes.back(), m_notes.size()-1), Operation::NO_EXEC);
first = false;
}
@@ -91,7 +75,7 @@ void NoteGraphWidget::setLyrics(QString lyrics)
void NoteGraphWidget::setLyrics(const VocalTrack &track)
{
- clear();
+ clearNotes();
setFixedSize(s2px(track.endTime), h());
@@ -125,6 +109,29 @@ void NoteGraphWidget::finalizeNewLyrics()
updateNotes();
}
+void NoteGraphWidget::analyzeMusic(QString filepath)
+{
+ m_pitch.reset(new PitchVis(filepath.toStdString(), this));
+ unsigned width = m_pitch->width(), height = m_pitch->height;
+ QProgressDialog progress(tr("Rendering pitch data..."), tr("&Abort"), 0, width, this);
+ progress.setWindowModality(Qt::WindowModal);
+
+ QImage image(width, height, QImage::Format_ARGB32_Premultiplied);
+ unsigned* rgba = reinterpret_cast<unsigned*>(image.bits());
+ for (unsigned x = 0; x < width; ++x) {
+ progress.setValue(x);
+ if (progress.wasCanceled()) break;
+
+ for (unsigned y = 0; y < height; ++y) {
+ rgba[y * width + x] = m_pitch->pixel(x, y).rgba();
+ }
+ }
+ setPixmap(QPixmap::fromImage(image));
+ progress.setValue(width);
+
+ setFixedSize(width, height);
+}
+
int NoteGraphWidget::getNoteLabelId(NoteLabel* note) const
{
for (int i = 0; i < m_notes.size(); ++i)
@@ -337,12 +344,12 @@ void NoteGraphWidget::keyPressEvent(QKeyEvent *event)
break;
case Qt::Key_Up: // Move note up
if (m_selectedNote) {
- m_selectedNote->move(m_selectedNote->x(), m_pitch.note2px(m_pitch.px2note(m_selectedNote->y()) + 1));
+ m_selectedNote->move(m_selectedNote->x(), m_pitch->note2px(m_pitch->px2note(m_selectedNote->y()) + 1));
}
break;
case Qt::Key_Down: // Move note down
if (m_selectedNote) {
- m_selectedNote->move(m_selectedNote->x(), m_pitch.note2px(m_pitch.px2note(m_selectedNote->y()) - 1));
+ m_selectedNote->move(m_selectedNote->x(), m_pitch->note2px(m_pitch->px2note(m_selectedNote->y()) - 1));
}
break;
case Qt::Key_Delete: // Delete selected note
@@ -405,10 +412,10 @@ void NoteGraphWidget::doOperation(const Operation& op, Operation::OperationFlags
}
-int NoteGraphWidget::s2px(double sec) const { return m_pitch.time2px(sec); }
-double NoteGraphWidget::px2s(int px) const { return m_pitch.px2time(px); }
-int NoteGraphWidget::n2px(int note) const { return m_pitch.note2px(note); }
-int NoteGraphWidget::px2n(int px) const { return m_pitch.px2note(px); }
+int NoteGraphWidget::s2px(double sec) const { return m_pitch->time2px(sec); }
+double NoteGraphWidget::px2s(int px) const { return m_pitch->px2time(px); }
+int NoteGraphWidget::n2px(int note) const { return m_pitch->note2px(note); }
+int NoteGraphWidget::px2n(int px) const { return m_pitch->px2note(px); }
void FloatingGap::addNote(NoteLabel* n)
{
diff --git a/notegraphwidget.hh b/notegraphwidget.hh
index 15bfc7a..ffc2f92 100644
--- a/notegraphwidget.hh
+++ b/notegraphwidget.hh
@@ -5,6 +5,7 @@
#include "operation.hh"
#include <QLabel>
#include <QList>
+#include <QScopedPointer>
class NoteLabel;
typedef QList<NoteLabel*> NoteLabels;
@@ -17,9 +18,10 @@ public:
NoteGraphWidget(QWidget *parent = 0);
- void clear();
+ void clearNotes();
void setLyrics(QString lyrics);
void setLyrics(const VocalTrack &track);
+ void analyzeMusic(QString filepath);
void updateNotes();
void selectNote(NoteLabel* note);
@@ -33,7 +35,7 @@ public:
double px2s(int px) const;
int n2px(int note) const;
int px2n(int px) const;
- int h() const { return m_pitch.height; }
+ int h() const { return m_pitch->height; }
signals:
@@ -57,7 +59,7 @@ private:
enum NoteAction { NONE, RESIZE, MOVE } m_selectedAction;
bool m_actionHappened;
NoteLabels m_notes;
- PitchVis m_pitch;
+ QScopedPointer<PitchVis> m_pitch;
};
diff --git a/pitchvis.cc b/pitchvis.cc
index 698a8e1..230ee0d 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -21,7 +21,7 @@ template <typename T> void readVec(std::string const& filename, std::vector<T>&
if (!f) throw std::runtime_error("Error reading " + filename);
}
-PitchVis::PitchVis(std::string const& filename): step(512), height(768) {
+PitchVis::PitchVis(std::string const& filename, QWidget *parent): QWidget(parent), step(512), height(768) {
#if 0 // Change this to 1 to use old raw loading
std::vector<float> data;
try { readVec("music.raw", data); } catch(std::exception& e) { std::cerr << e.what() << std::endl; return; }
@@ -66,12 +66,12 @@ PitchVis::PitchVis(std::string const& filename): step(512), height(768) {
float value = 0.003 * (level2dB(peaks[i].level) + 80.0);
if (value <= 0.0) continue;
Pixel p(0.0f, 0.0f, value);
- (*this)(x, y) += p;
+ pixel(x, y) += p;
p.r *= 0.5;
p.g *= 0.5;
p.b *= 0.5;
- (*this)(x, y + 1) += p;
- (*this)(x, y - 1) += p;
+ pixel(x, y + 1) += p;
+ pixel(x, y - 1) += p;
}
Analyzer::Tones tones = analyzer.getTones();
unsigned int i = 0;
@@ -82,7 +82,7 @@ PitchVis::PitchVis(std::string const& filename): step(512), height(768) {
float value = 0.003 * (level2dB(it->levelSlow) + 80.0);
if (value <= 0.0) continue;
Pixel p(0.0f, value, 0.0f);
- for (int j = int(y) - 2; j <= int(y) + 2; ++j) (*this)(x, j) += p;
+ for (int j = int(y) - 2; j <= int(y) + 2; ++j) pixel(x, j) += p;
}
}
progress.setValue(width);
diff --git a/pitchvis.hh b/pitchvis.hh
index 1275a1a..62f7f03 100644
--- a/pitchvis.hh
+++ b/pitchvis.hh
@@ -37,9 +37,9 @@ class PitchVis: public QWidget {
MusicalScale scale;
public:
const std::size_t height;
- Pixel& operator()(std::size_t x, std::size_t y) { return img[x * height + y]; }
+ Pixel& pixel(std::size_t x, std::size_t y) { return img[x * height + y]; }
std::size_t width() const { return img.size() / height; }
- PitchVis(std::string const& filename);
+ PitchVis(std::string const& filename, QWidget *parent = NULL);
unsigned freq2px(double freq) const;
unsigned note2px(double note) const;
double px2note(unsigned px) const;
|