You can subscribe to this list here.
| 2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(25) |
Jul
(288) |
Aug
(119) |
Sep
(31) |
Oct
(59) |
Nov
(458) |
Dec
(359) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010 |
Jan
(268) |
Feb
(26) |
Mar
(36) |
Apr
(48) |
May
(119) |
Jun
(37) |
Jul
(173) |
Aug
(429) |
Sep
(137) |
Oct
(156) |
Nov
(59) |
Dec
(45) |
| 2011 |
Jan
(398) |
Feb
(257) |
Mar
(49) |
Apr
(5) |
May
(34) |
Jun
(11) |
Jul
(38) |
Aug
(12) |
Sep
(1) |
Oct
(49) |
Nov
(5) |
Dec
(10) |
| 2012 |
Jan
(21) |
Feb
(32) |
Mar
(20) |
Apr
(1) |
May
(2) |
Jun
|
Jul
(173) |
Aug
|
Sep
(25) |
Oct
(6) |
Nov
(44) |
Dec
|
|
From: Tapio V. <aa...@us...> - 2011-02-09 09:44:27
|
Module: editor
Branch: master
Commit: 25f8d6c6fce6a698b44d55a8692c3dea24438d9e
Author: Tapio Vierros <tap...@gm...>
Date: Wed Feb 9 10:32:29 2011 +0200
Very experimental synth mode.
Needs a lot of work, don't bother trying.
---
CMakeLists.txt | 2 +-
editor.ui | 7 +++
editorapp.cc | 8 +++-
editorapp.hh | 2 +
synth.hh | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 146 insertions(+), 2 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 819aab8..dac809b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,7 +41,7 @@ else(Phonon_FOUND)
endif(Phonon_FOUND)
# Headers that need MOC need to be defined separately
-file(GLOB MOC_HEADER_FILES editorapp.hh notelabel.hh notegraphwidget.hh textcodecselector.hh gettingstarted.hh pitchvis.hh)
+file(GLOB MOC_HEADER_FILES editorapp.hh notelabel.hh notegraphwidget.hh textcodecselector.hh gettingstarted.hh pitchvis.hh synth.hh)
file(GLOB SOURCE_FILES "*.cc")
file(GLOB HEADER_FILES "*.hh")
diff --git a/editor.ui b/editor.ui
index e5bbb0d..805c609 100644
--- a/editor.ui
+++ b/editor.ui
@@ -427,6 +427,13 @@
</property>
</widget>
</item>
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="chkSynth">
+ <property name="text">
+ <string>Play synthesized notes</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="tabLyrics">
diff --git a/editorapp.cc b/editorapp.cc
index d771260..8a5f6cd 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -26,7 +26,7 @@ namespace {
}
EditorApp::EditorApp(QWidget *parent)
- : QMainWindow(parent), gettingStarted(), noteGraph(), player(), audioOutput(), statusbarProgress(),
+ : QMainWindow(parent), gettingStarted(), noteGraph(), player(), audioOutput(), synth(), statusbarProgress(),
projectFileName(), hasUnsavedChanges(), latestPath(QDir::homePath())
{
ui.setupUi(this);
@@ -599,9 +599,15 @@ void EditorApp::playButton()
if (player && player->state() == Phonon::PlayingState) {
ui.cmdPlay->setText(tr("Pause"));
ui.cmdPlay->setIcon(QIcon::fromTheme("media-playback-pause", QIcon(":/icons/media-playback-pause.png")));
+ if (ui.chkSynth->isChecked()) {
+ synth.reset(new Synth(noteGraph->noteLabels()));
+ synth->start(player->currentTime());
+ }
} else {
ui.cmdPlay->setText(tr("Play"));
ui.cmdPlay->setIcon(QIcon::fromTheme("media-playback-start", QIcon(":/icons/media-playback-start.png")));
+ if (synth) synth->stop();
+ synth.reset();
}
}
diff --git a/editorapp.hh b/editorapp.hh
index 3c2910e..6013463 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -5,6 +5,7 @@
#include "ui_aboutdialog.h"
#include "operation.hh"
#include "song.hh"
+#include "synth.hh"
class QProgressBar;
class QCloseEvent;
@@ -110,6 +111,7 @@ private:
QScopedPointer<Song> song;
Phonon::MediaObject *player;
Phonon::AudioOutput *audioOutput;
+ QScopedPointer<Synth> synth;
QProgressBar *statusbarProgress;
QString projectFileName;
bool hasUnsavedChanges;
diff --git a/synth.hh b/synth.hh
new file mode 100644
index 0000000..30def9e
--- /dev/null
+++ b/synth.hh
@@ -0,0 +1,129 @@
+#pragma once
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+#include <cmath>
+#include <QBuffer>
+#include <QFile>
+#include <phonon/MediaObject>
+#include "notes.hh"
+#include "notegraphwidget.hh"
+#include "notelabel.hh"
+
+
+#ifndef M_PI
+ #define M_PI 3.141592653589793
+#endif
+
+
+inline std::string writeWavHeader(unsigned bits, unsigned ch, unsigned sr, unsigned samples) {
+ std::ostringstream out;
+ unsigned bps = ch * bits / 8; // Bytes per sample
+ unsigned datasize = bps * samples;
+ unsigned size = datasize + 0x2C;
+ out.write("RIFF" ,4); // RIFF chunk
+ { unsigned int tmp=size-0x8 ; out.write((char*)(&tmp),4); } // RIFF chunk size
+ out.write("WAVEfmt ",8); // WAVEfmt header
+ { int tmp=0x00000010 ; out.write((char*)(&tmp),4); } // Always 0x10
+ { short tmp=0x0001 ; out.write((char*)(&tmp),2); } // Always 1
+ { short tmp = ch; out.write((char*)(&tmp),2); } // Number of channels
+ { int tmp = sr; out.write((char*)(&tmp),4); } // Sample rate
+ { int tmp = bps * sr; out.write((char*)(&tmp),4); } // Bytes per second
+ { short tmp = bps; out.write((char*)(&tmp),2); } // Bytes per frame
+ { short tmp = bits; out.write((char*)(&tmp),2); } // Bits per sample
+ out.write("data",4); // data chunk
+ { int tmp = datasize; out.write((char*)(&tmp),4); }
+ return out.str();
+}
+
+class Synth: public QObject
+{
+ Q_OBJECT
+public:
+ Synth(NoteLabels& notes) : m_notes(notes), m_phase(0), m_player(Phonon::createPlayer(Phonon::MusicCategory)), m_curBuffer()
+ {
+ m_player->setParent(this);
+ }
+
+ //~Synth() { stop(); }
+
+ /// Starts/updates the synth
+ void start(qint64 pos) {
+ calcNext(pos / 1000.0);
+ }
+
+ /// Stops the synth
+ void stop(bool killPlayback = true) {
+ killTimer(m_timerId);
+ if (killPlayback) {
+ m_player->clear();
+ m_soundData[0].close();
+ m_soundData[1].close();
+ }
+ m_phase = 0;
+ }
+
+protected:
+ /// Plays next sound
+ void timerEvent(QTimerEvent*) {
+ killTimer(m_timerId);
+ m_player->clear();
+ m_soundData[m_curBuffer].close();
+ m_soundData[m_curBuffer].setData(createBuffer());
+ m_player->setCurrentSource(&(m_soundData[m_curBuffer]));
+ m_player->play();
+ m_curBuffer = (m_curBuffer+1) % 2;
+ calcNext(m_pos);
+ }
+
+private:
+ /// Calculates the next values
+ void calcNext(double pos) {
+ NoteLabels::const_iterator it = m_notes.begin();
+ while (it != m_notes.end() && (*it)->note().begin < pos) ++it;
+ Note n = (*it)->note();
+ if (it == m_notes.end() || n.type == Note::SLEEP) { stop(false); return; }
+ m_note = n.note; // % 12;
+ qint64 nextTime = (n.begin - pos + m_length) * 1000;
+ m_length = n.length(); //((n.begin > pos) ? n.length() : (n.end - pos));
+ m_pos = n.end; // Where to start the search for next note
+ m_timerId = startTimer(nextTime > 0 ? nextTime : 1);
+ std::cout << "lyr: " << n.syllable.toStdString() << " len: " << m_length << " dela: " << (int)nextTime << std::endl;
+ }
+
+ /// Creates the sound
+ QByteArray createBuffer() {
+ // This is simple beep, so we use mono, low sample rate and only 8 bits resolution
+ // --> quick to create and small memory foot print
+ std::string header = writeWavHeader(8, 1, srate, m_length * srate);
+ QByteArray buf(header.c_str(), header.size());
+ double d = (m_note + 1) / 13.0;
+ double freq = MusicalScale().getNoteFreq(m_note + 12);
+ // Synthesize tones
+ for (size_t i = 0; i < m_length * srate; ++i) {
+ float fvalue = d * 0.2 * std::sin(m_phase) + 0.2 * std::sin(2 * m_phase) + (1.0 - d) * 0.2 * std::sin(4 * m_phase);
+ m_phase += 2.0 * M_PI * freq / srate;
+
+ // 8-bit
+ quint8 value = (fvalue + 1) * 0.5 * 255;
+ buf.push_back(value);
+ }
+
+ //std::ofstream of("/tmp/wavdump.wav");
+ //of.write(buf.data(), buf.size());
+
+ return buf;
+ }
+
+ static const int srate = 8000; ///< Sample rate
+ NoteLabels& m_notes; ///< Notes
+ double m_phase; ///< Phase
+ int m_note; ///< Next note to synthesize
+ double m_length; ///< Next note length
+ double m_pos; ///< Position from where to start looking the next note
+ Phonon::MediaObject *m_player;
+ QBuffer m_soundData[2];
+ int m_curBuffer;
+ int m_timerId; ///< Timer ID
+};
|
|
From: Tapio V. <aa...@us...> - 2011-02-09 09:44:24
|
Module: editor Branch: master Commit: 0078f75761025ef971691662c95d27324b4c0334 Author: Tapio Vierros <tap...@gm...> Date: Wed Feb 9 09:22:58 2011 +0200 Ãber Renderer 3000 Pro (tm). --- CMakeLists.txt | 2 +- notegraphwidget.cc | 35 +++++++++++++---- notegraphwidget.hh | 4 ++ pitchvis.cc | 110 +++++++++++++++++++++++++++++++++++++-------------- pitchvis.hh | 23 ++++++++-- 5 files changed, 130 insertions(+), 44 deletions(-) |
|
From: Yoda-JM <yo...@us...> - 2011-02-08 23:18:29
|
Module: performous Branch: opengl2 Commit: f178feef440d8eabad18f53d0885784a0eed36e6 Author: Vincent Le Ligeour <yo...@us...> Date: Wed Feb 9 00:17:30 2011 +0100 Merge remote-tracking branch 'origin/opengl2' into opengl2 --- |
|
From: Yoda-JM <yo...@us...> - 2011-02-08 23:18:26
|
Module: performous Branch: opengl2 Commit: ea94bf85404e1fcd1ac14a9a81838bd933d632d9 Author: Vincent Le Ligeour <yo...@us...> Date: Wed Feb 9 00:16:41 2011 +0100 Merge remote-tracking branch 'origin/master' into opengl2 --- |
|
From: Yoda-JM <yo...@us...> - 2011-02-08 23:18:24
|
Module: performous
Branch: opengl2
Commit: d4ae07c79dbebc60b70dd077f3a6c202e706a178
Author: Vincent Le Ligeour <yo...@us...>
Date: Wed Feb 9 00:14:50 2011 +0100
Fixed score computation on multi-vocal tracks
---
game/notes.cc | 19 ++++++++++++++++++-
game/songparser-ini.cc | 2 --
game/songparser-txt.cc | 1 -
game/songparser.cc | 8 ++++++--
game/songparser.hh | 1 -
5 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/game/notes.cc b/game/notes.cc
index ed7c6c0..ed9f4ea 100644
--- a/game/notes.cc
+++ b/game/notes.cc
@@ -63,7 +63,24 @@ double Note::score(double n, double b, double e) const {
return scoreMultiplier() * powerFactor(n) * len;
}
-double Note::scoreMultiplier() const { return type == GOLDEN ? 2.0 : 1.0; }
+double Note::scoreMultiplier() const {
+ switch(type) {
+ case GOLDEN:
+ return 2.0;
+ case SLEEP:
+ return 0.0;
+ case FREESTYLE:
+ case NORMAL:
+ case SLIDE:
+ case TAP:
+ case HOLDBEGIN:
+ case HOLDEND:
+ case ROLL:
+ case MINE:
+ case LIFT:
+ return 1.0;
+ }
+}
double Note::powerFactor(double note) const {
if (type == FREESTYLE) return 1.0;
diff --git a/game/songparser-ini.cc b/game/songparser-ini.cc
index 8548f15..36e724b 100644
--- a/game/songparser-ini.cc
+++ b/game/songparser-ini.cc
@@ -245,7 +245,6 @@ void SongParser::iniParse() {
inter.note = n.note;
inter.type = Note::SLIDE;
inter.syllable = std::string("~");
- m_maxScore += inter.maxScore();
vocal.noteMin = std::min(vocal.noteMin, inter.note);
vocal.noteMax = std::max(vocal.noteMax,inter.note);
vocal.notes.push_back(inter);
@@ -255,7 +254,6 @@ void SongParser::iniParse() {
n.type = Note::NORMAL;
}
}
- m_maxScore += n.maxScore();
vocal.noteMin = std::min(vocal.noteMin, n.note);
vocal.noteMax = std::max(vocal.noteMax, n.note);
vocal.notes.push_back(n);
diff --git a/game/songparser-txt.cc b/game/songparser-txt.cc
index fd9d451..856ff9f 100644
--- a/game/songparser-txt.cc
+++ b/game/songparser-txt.cc
@@ -142,7 +142,6 @@ bool SongParser::txtParseNote(std::string line, VocalTrack &vocal) {
if (n.type != Note::SLEEP && n.end > n.begin) {
vocal.noteMin = std::min(vocal.noteMin, n.note);
vocal.noteMax = std::max(vocal.noteMax, n.note);
- m_maxScore += n.maxScore();
}
if (n.type == Note::SLEEP) {
if (notes.empty()) return true; // Ignore sleeps at song beginning
diff --git a/game/songparser.cc b/game/songparser.cc
index 8a20d98..2b7b9b4 100644
--- a/game/songparser.cc
+++ b/game/songparser.cc
@@ -43,7 +43,6 @@ SongParser::SongParser(Song& s):
m_prevtime(),
m_prevts(),
m_relativeShift(),
- m_maxScore(),
m_tsPerBeat(),
m_tsEnd()
{
@@ -131,7 +130,12 @@ void SongParser::finalize() {
}
// Set begin/end times
if (!vocal.notes.empty()) vocal.beginTime = vocal.notes.front().begin, vocal.endTime = vocal.notes.back().end;
- vocal.m_scoreFactor = 1.0 / m_maxScore;
+ // Compute maximum score
+ double max_score = 0.0;
+ for (Notes::iterator it = vocal.notes.begin(); it != vocal.notes.end(); ++it) {
+ max_score += it->maxScore();
+ }
+ vocal.m_scoreFactor = 1.0 / max_score;
}
if (m_tsPerBeat) {
// Add song beat markers
diff --git a/game/songparser.hh b/game/songparser.hh
index a0bb6e5..601fbce 100644
--- a/game/songparser.hh
+++ b/game/songparser.hh
@@ -48,7 +48,6 @@ class SongParser {
double m_prevtime;
unsigned int m_prevts;
unsigned int m_relativeShift;
- double m_maxScore;
struct BPM {
BPM(double _begin, double _ts, double bpm): begin(_begin), step(0.25 * 60.0 / bpm), ts(_ts) {}
double begin; // Time in seconds
|
|
From: Yoda-JM <yo...@us...> - 2011-02-08 23:16:04
|
Module: performous
Branch: master
Commit: d4ae07c79dbebc60b70dd077f3a6c202e706a178
Author: Vincent Le Ligeour <yo...@us...>
Date: Wed Feb 9 00:14:50 2011 +0100
Fixed score computation on multi-vocal tracks
---
game/notes.cc | 19 ++++++++++++++++++-
game/songparser-ini.cc | 2 --
game/songparser-txt.cc | 1 -
game/songparser.cc | 8 ++++++--
game/songparser.hh | 1 -
5 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/game/notes.cc b/game/notes.cc
index ed7c6c0..ed9f4ea 100644
--- a/game/notes.cc
+++ b/game/notes.cc
@@ -63,7 +63,24 @@ double Note::score(double n, double b, double e) const {
return scoreMultiplier() * powerFactor(n) * len;
}
-double Note::scoreMultiplier() const { return type == GOLDEN ? 2.0 : 1.0; }
+double Note::scoreMultiplier() const {
+ switch(type) {
+ case GOLDEN:
+ return 2.0;
+ case SLEEP:
+ return 0.0;
+ case FREESTYLE:
+ case NORMAL:
+ case SLIDE:
+ case TAP:
+ case HOLDBEGIN:
+ case HOLDEND:
+ case ROLL:
+ case MINE:
+ case LIFT:
+ return 1.0;
+ }
+}
double Note::powerFactor(double note) const {
if (type == FREESTYLE) return 1.0;
diff --git a/game/songparser-ini.cc b/game/songparser-ini.cc
index 8548f15..36e724b 100644
--- a/game/songparser-ini.cc
+++ b/game/songparser-ini.cc
@@ -245,7 +245,6 @@ void SongParser::iniParse() {
inter.note = n.note;
inter.type = Note::SLIDE;
inter.syllable = std::string("~");
- m_maxScore += inter.maxScore();
vocal.noteMin = std::min(vocal.noteMin, inter.note);
vocal.noteMax = std::max(vocal.noteMax,inter.note);
vocal.notes.push_back(inter);
@@ -255,7 +254,6 @@ void SongParser::iniParse() {
n.type = Note::NORMAL;
}
}
- m_maxScore += n.maxScore();
vocal.noteMin = std::min(vocal.noteMin, n.note);
vocal.noteMax = std::max(vocal.noteMax, n.note);
vocal.notes.push_back(n);
diff --git a/game/songparser-txt.cc b/game/songparser-txt.cc
index fd9d451..856ff9f 100644
--- a/game/songparser-txt.cc
+++ b/game/songparser-txt.cc
@@ -142,7 +142,6 @@ bool SongParser::txtParseNote(std::string line, VocalTrack &vocal) {
if (n.type != Note::SLEEP && n.end > n.begin) {
vocal.noteMin = std::min(vocal.noteMin, n.note);
vocal.noteMax = std::max(vocal.noteMax, n.note);
- m_maxScore += n.maxScore();
}
if (n.type == Note::SLEEP) {
if (notes.empty()) return true; // Ignore sleeps at song beginning
diff --git a/game/songparser.cc b/game/songparser.cc
index 8a20d98..2b7b9b4 100644
--- a/game/songparser.cc
+++ b/game/songparser.cc
@@ -43,7 +43,6 @@ SongParser::SongParser(Song& s):
m_prevtime(),
m_prevts(),
m_relativeShift(),
- m_maxScore(),
m_tsPerBeat(),
m_tsEnd()
{
@@ -131,7 +130,12 @@ void SongParser::finalize() {
}
// Set begin/end times
if (!vocal.notes.empty()) vocal.beginTime = vocal.notes.front().begin, vocal.endTime = vocal.notes.back().end;
- vocal.m_scoreFactor = 1.0 / m_maxScore;
+ // Compute maximum score
+ double max_score = 0.0;
+ for (Notes::iterator it = vocal.notes.begin(); it != vocal.notes.end(); ++it) {
+ max_score += it->maxScore();
+ }
+ vocal.m_scoreFactor = 1.0 / max_score;
}
if (m_tsPerBeat) {
// Add song beat markers
diff --git a/game/songparser.hh b/game/songparser.hh
index a0bb6e5..601fbce 100644
--- a/game/songparser.hh
+++ b/game/songparser.hh
@@ -48,7 +48,6 @@ class SongParser {
double m_prevtime;
unsigned int m_prevts;
unsigned int m_relativeShift;
- double m_maxScore;
struct BPM {
BPM(double _begin, double _ts, double bpm): begin(_begin), step(0.25 * 60.0 / bpm), ts(_ts) {}
double begin; // Time in seconds
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 20:42:23
|
Module: performous
Branch: opengl2
Commit: abe0b19de4ba43162c0f0d416328ac4280479f7f
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 21:40:51 2011 +0100
Move shaders to data dir (instead of theme) and make theme file lookup try from there too.
* TODO: Remove getThemePath and only use getPath (that will prefer theme dir if possible)?
---
data/CMakeLists.txt | 3 +++
{themes/default => data}/shaders/3dobject.frag | 0
{themes/default => data}/shaders/3dobject.vert | 0
{themes/default => data}/shaders/core.frag | 0
{themes/default => data}/shaders/core.vert | 0
{themes/default => data}/shaders/dancenote.frag | 0
{themes/default => data}/shaders/dancenote.vert | 0
{themes/default => data}/shaders/stereo3d.geom | 0
game/fs.cc | 11 ++++-------
themes/CMakeLists.txt | 3 ---
10 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
index 6574385..e43e2a5 100644
--- a/data/CMakeLists.txt
+++ b/data/CMakeLists.txt
@@ -22,3 +22,6 @@ install(FILES ${SOUND_FILES} DESTINATION "${SHARE_INSTALL}/sounds/")
file(GLOB BG_FILES "backgrounds/*.svg")
install(FILES ${BG_FILES} DESTINATION "${SHARE_INSTALL}/backgrounds/")
+file(GLOB SHADER_FILES "shaders/*")
+install(FILES ${SHADER_FILES} DESTINATION "${SHARE_INSTALL}/shaders/")
+
diff --git a/themes/default/shaders/3dobject.frag b/data/shaders/3dobject.frag
similarity index 100%
rename from themes/default/shaders/3dobject.frag
rename to data/shaders/3dobject.frag
diff --git a/themes/default/shaders/3dobject.vert b/data/shaders/3dobject.vert
similarity index 100%
rename from themes/default/shaders/3dobject.vert
rename to data/shaders/3dobject.vert
diff --git a/themes/default/shaders/core.frag b/data/shaders/core.frag
similarity index 100%
rename from themes/default/shaders/core.frag
rename to data/shaders/core.frag
diff --git a/themes/default/shaders/core.vert b/data/shaders/core.vert
similarity index 100%
rename from themes/default/shaders/core.vert
rename to data/shaders/core.vert
diff --git a/themes/default/shaders/dancenote.frag b/data/shaders/dancenote.frag
similarity index 100%
rename from themes/default/shaders/dancenote.frag
rename to data/shaders/dancenote.frag
diff --git a/themes/default/shaders/dancenote.vert b/data/shaders/dancenote.vert
similarity index 100%
rename from themes/default/shaders/dancenote.vert
rename to data/shaders/dancenote.vert
diff --git a/themes/default/shaders/stereo3d.geom b/data/shaders/stereo3d.geom
similarity index 100%
rename from themes/default/shaders/stereo3d.geom
rename to data/shaders/stereo3d.geom
diff --git a/game/fs.cc b/game/fs.cc
index 83f48d5..e34a784 100644
--- a/game/fs.cc
+++ b/game/fs.cc
@@ -120,13 +120,10 @@ std::string getThemePath(std::string const& filename) {
std::string theme = config["game/theme"].s();
static const std::string defaultTheme = "default";
if (theme.empty()) theme = defaultTheme;
- // Try current theme and if that fails, try default theme.
- try {
- return getPath(fs::path("themes") / theme / filename);
- } catch (std::runtime_error&) {
- if (theme == defaultTheme) throw;
- return getPath(fs::path("themes") / defaultTheme / filename);
- }
+ // Try current theme and if that fails, try default theme and finally data dir
+ try { return getPath(fs::path("themes") / theme / filename); } catch (std::runtime_error&) {}
+ if (theme == defaultTheme) try { return getPath(fs::path("themes") / defaultTheme / filename); } catch (std::runtime_error&) {}
+ return getPath(filename);
}
bool isThemeResource(fs::path filename){
diff --git a/themes/CMakeLists.txt b/themes/CMakeLists.txt
index d22be10..5a94855 100644
--- a/themes/CMakeLists.txt
+++ b/themes/CMakeLists.txt
@@ -1,6 +1,3 @@
FILE(GLOB THEME_FILES "default/*.ogg" "default/*.svg" "default/*.png" "default/*.bmp" "default/*.obj")
install(FILES ${THEME_FILES} DESTINATION ${SHARE_INSTALL}/themes/default/)
-FILE(GLOB SHADER_FILES "default/shaders/*")
-install(FILES ${SHADER_FILES} DESTINATION ${SHARE_INSTALL}/themes/default/shaders)
-
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 20:42:17
|
Module: performous
Branch: opengl2
Commit: d00731cc957af82393ad682ba2d8d788132ccb8f
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 21:31:51 2011 +0100
Shader cleanup
---
themes/default/shaders/core.frag | 21 ++++++++++-----------
themes/default/shaders/core.vert | 1 +
themes/default/shaders/stereo3d.geom | 8 ++------
3 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/themes/default/shaders/core.frag b/themes/default/shaders/core.frag
index 8b61013..02e7080 100644
--- a/themes/default/shaders/core.frag
+++ b/themes/default/shaders/core.frag
@@ -1,28 +1,27 @@
-#version 330
+#version 120
#extension GL_ARB_texture_rectangle : require
//DEFINES
#ifdef SURFACE
uniform sampler2DRect tex;
-#define TFUNC texture2DRect
+in vec2 texcoord;
+#define TEXFUNC texture2DRect(tex, texcoord)
#endif
#ifdef TEXTURE
uniform sampler2D tex;
-#define TFUNC texture2D
+in vec2 texcoord;
+#define TEXFUNC texture2D(tex, texcoord)
#endif
-uniform mat4 colorMatrix;
+#ifndef TEXFUNC
+#define TEXFUNC vec4(1,1,1,1)
+#endif
-in vec4 color;
-in vec2 texcoord;
+uniform mat4 colorMatrix;
void main() {
- gl_FragColor = colorMatrix * (color
-#ifdef TFUNC
- * TFUNC(tex, texcoord).rgba
-#endif
- );
+ gl_FragColor = colorMatrix * TEXFUNC;
}
diff --git a/themes/default/shaders/core.vert b/themes/default/shaders/core.vert
index d448a12..02a36a0 100644
--- a/themes/default/shaders/core.vert
+++ b/themes/default/shaders/core.vert
@@ -7,3 +7,4 @@ void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * vertex;
}
+
diff --git a/themes/default/shaders/stereo3d.geom b/themes/default/shaders/stereo3d.geom
index a17d8a4..b143d43 100644
--- a/themes/default/shaders/stereo3d.geom
+++ b/themes/default/shaders/stereo3d.geom
@@ -1,4 +1,4 @@
-#version 330 compatibility
+#version 330
#extension GL_ARB_viewport_array : require
layout(triangles) in;
@@ -7,18 +7,15 @@ layout(triangle_strip, max_vertices = 6) out;
uniform mat4 leftTransform;
uniform mat4 rightTransform;
-out vec4 color;
out vec2 texcoord;
void main() {
- // Fix Nvidia compile warnings ("may be used uninitialized")
- color = vec4(0);
+ // Fix Nvidia compile warnings ("might be used uninitialized")
texcoord = vec2(0);
gl_Position = vec4(0);
// Render the left eye
gl_ViewportIndex = 0;
for(int i=0; i < gl_in.length(); ++i) {
- color = gl_in[i].gl_FrontColor;
texcoord = gl_in[i].gl_TexCoord[0].st;
gl_Position = leftTransform * gl_in[i].gl_Position;
EmitVertex();
@@ -27,7 +24,6 @@ void main() {
// Render the right eye
gl_ViewportIndex = 1;
for(int i=0; i < gl_in.length(); ++i) {
- color = gl_in[i].gl_FrontColor;
texcoord = gl_in[i].gl_TexCoord[0].st;
gl_Position = rightTransform * gl_in[i].gl_Position;
EmitVertex();
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 17:34:58
|
Module: editor
Branch: master
Commit: d84cce3f86a2f45d229e0d0eedd2770cdd942aa1
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 18:34:16 2011 +0100
Avoid unnecessary copying of data that slows down the analysis towards the end.
---
pitch.hh | 1 +
pitchvis.cc | 9 +++------
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/pitch.hh b/pitch.hh
index d8c78a5..b10ee57 100644
--- a/pitch.hh
+++ b/pitch.hh
@@ -88,6 +88,7 @@ public:
}
unsigned processSize() const; ///< The number of samples required by process()
unsigned processStep() const; ///< The number of samples to increment the input position after each call to process()
+ double getTime() const { return m_moments.empty() ? 0.0 : m_moments.back().time(); }
private:
double m_rate;
std::string m_id;
diff --git a/pitchvis.cc b/pitchvis.cc
index 92bcaea..5decce9 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -48,12 +48,9 @@ void PitchVis::run()
// Update progress and check for quit flag
QMutexLocker locker(&mutex);
if (cancelled) return;
- Analyzer::Moments const& moments = analyzers[0].getMoments();
- if (!moments.empty()) {
- double t = moments.back().time();
- position = t;
- duration = std::max(duration, t + 0.01);
- }
+ double t = analyzers[0].getTime();
+ position = t;
+ duration = std::max(duration, t + 0.01);
}
}
// DEBUG: std::ofstream("audio.raw", std::ios::binary).write(reinterpret_cast<char*>(&data[0]), data.size() * sizeof(float));
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 17:09:48
|
Module: editor
Branch: master
Commit: 05ae875b9b2fb8e3d71468a8b1f0a704ca5098da
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 18:09:37 2011 +0100
Fixed a regression since missing fundamental processing was implemented.
---
pitch.cc | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/pitch.cc b/pitch.cc
index 34b9210..c06d1af 100644
--- a/pitch.cc
+++ b/pitch.cc
@@ -100,8 +100,8 @@ void Analyzer::calcTones() {
// Try to combine combos into tones (collections of harmonics)
Tones tones;
for (Combos::const_iterator it = combos.begin(), itend = combos.end(); it != itend; ++it) {
- Tone tone;
for (int div = 1; div <= 3; ++div) { // Missing fundamental processing
+ Tone tone;
int plausibleHarmonics = 0;
double basefreq = it->freq / div;
if (basefreq < FFT_MINFREQ) break; // Do not try any lower frequencies
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 16:25:28
|
Module: editor
Branch: master
Commit: 673ffca1eaee4e4986bd21edeb629163b252be12
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 17:25:15 2011 +0100
Slight parameter tuning.
---
pitch.cc | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/pitch.cc b/pitch.cc
index 176e6e1..34b9210 100644
--- a/pitch.cc
+++ b/pitch.cc
@@ -82,7 +82,7 @@ void Analyzer::calcTones() {
Combos combos;
for (size_t k = kMin; k < kMax; ++k) {
Peak const& p = m_peaks[k];
- bool ok = p.level > 1e-4 && p.freq >= FFT_MINFREQ && p.freq <= FFT_MAXFREQ && std::abs(p.freqFFT - p.freq) < freqPerBin;
+ bool ok = p.level > 1e-3 && p.freq >= FFT_MINFREQ && p.freq <= FFT_MAXFREQ && std::abs(p.freqFFT - p.freq) < freqPerBin;
if (!ok) continue;
// Do we need to add a new Combo (rather than using the last one)?
if (combos.empty() || !combos.back().match(p.freq)) combos.push_back(Combo());
@@ -94,7 +94,7 @@ void Analyzer::calcTones() {
}
// Only keep a reasonable amount of strongest combos
std::sort(combos.begin(), combos.end(), Combo::cmpByLevel);
- if (combos.size() > 20) combos.resize(20);
+ if (combos.size() > 30) combos.resize(30);
// The order may not be strictly correct, fix it...
std::sort(combos.begin(), combos.end(), Combo::cmpByFreq);
// Try to combine combos into tones (collections of harmonics)
|
|
From: Tapio V. <aa...@us...> - 2011-02-08 16:03:10
|
Module: editor
Branch: master
Commit: 56d58af45f9b6091c4c1873635b158e9ca024177
Author: Tapio Vierros <tap...@gm...>
Date: Tue Feb 8 17:47:19 2011 +0200
Small things.
---
editorapp.cc | 4 +++-
main.cc | 2 ++
notegraphwidget.cc | 8 +++++---
notegraphwidget.hh | 1 -
4 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index a9da936..d771260 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -25,7 +25,9 @@ namespace {
static const QDataStream::Version PROJECT_SAVE_FILE_STREAM_VERSION = QDataStream::Qt_4_7;
}
-EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), gettingStarted(), projectFileName(), hasUnsavedChanges(), latestPath(QDir::homePath())
+EditorApp::EditorApp(QWidget *parent)
+ : QMainWindow(parent), gettingStarted(), noteGraph(), player(), audioOutput(), statusbarProgress(),
+ projectFileName(), hasUnsavedChanges(), latestPath(QDir::homePath())
{
ui.setupUi(this);
readSettings();
diff --git a/main.cc b/main.cc
index 360938d..79e7d9c 100644
--- a/main.cc
+++ b/main.cc
@@ -8,11 +8,13 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(editor);
QApplication app(argc, argv);
+ // These values are used by e.g. Phonon and QSettings
app.setApplicationName(PACKAGE);
app.setApplicationVersion(VERSION);
app.setOrganizationName("Performous Team");
app.setOrganizationDomain("performous.org");
+ // Localization
QString locale = QLocale::system().name();
QTranslator translator;
translator.load(locale);
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 91a4225..b43607d 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -116,10 +116,12 @@ void NoteGraphWidget::analyzeMusic(QString filepath)
void NoteGraphWidget::timerEvent(QTimerEvent* event)
{
if (event->timerId() == m_playbackTimer) {
+ // Playback position update
m_playbackPos += m_playbackInterval.restart();
updateMusicPos(m_playbackPos);
} else if (event->timerId() == m_analyzeTimer && m_pitch) {
+ // PitchVis stuff
double progress, duration;
bool needUpdate, done;
{
@@ -129,7 +131,7 @@ void NoteGraphWidget::timerEvent(QTimerEvent* event)
needUpdate = m_pitch->newDataAvailable() || duration != m_duration;
done = m_pitch->isFinished();
}
- emit analyzeProgress(1000 * progress, 1000);
+ emit analyzeProgress(1000 * progress, 1000); // Update progress bar
if (needUpdate) {
m_duration = std::max(m_duration, duration);
update();
@@ -488,7 +490,7 @@ QString NoteGraphWidget::getCurrentSentence() const
if (m_notes[i]->isSelected()) lyrics += "</span>";
lyrics += " ";
}
- lyrics = lyrics.left(lyrics.size() - 1);
+ lyrics = lyrics.left(lyrics.size() - 1); // Remove trailing space
}
return lyrics;
}
@@ -507,7 +509,7 @@ QString NoteGraphWidget::getPrevSentence() const
if (i != id && m_notes[i]->note().lineBreak) break;
lyrics += m_notes[i]->lyric() + " ";
}
- lyrics = lyrics.left(lyrics.size() - 1);
+ lyrics = lyrics.left(lyrics.size() - 1); // Remove trailing space
}
return lyrics;
}
diff --git a/notegraphwidget.hh b/notegraphwidget.hh
index 3b37378..c27802e 100644
--- a/notegraphwidget.hh
+++ b/notegraphwidget.hh
@@ -133,7 +133,6 @@ private:
void finalizeNewLyrics();
void timeCurrent();
- int m_requiredWidth;
QPoint m_panHotSpot;
bool m_seeking;
bool m_actionHappened;
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 16:01:24
|
Module: editor
Branch: master
Commit: 7eceb8e175d0b50e8503a9d95c119b3fdfe4e976
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 17:00:48 2011 +0100
Fix a bug with missing fundamental processing
---
pitch.cc | 8 +++++---
pitch.hh | 3 ++-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/pitch.cc b/pitch.cc
index 903eeb2..176e6e1 100644
--- a/pitch.cc
+++ b/pitch.cc
@@ -82,7 +82,7 @@ void Analyzer::calcTones() {
Combos combos;
for (size_t k = kMin; k < kMax; ++k) {
Peak const& p = m_peaks[k];
- bool ok = p.level > 1e-6 && p.freq >= FFT_MINFREQ && p.freq <= FFT_MAXFREQ;
+ bool ok = p.level > 1e-4 && p.freq >= FFT_MINFREQ && p.freq <= FFT_MAXFREQ && std::abs(p.freqFFT - p.freq) < freqPerBin;
if (!ok) continue;
// Do we need to add a new Combo (rather than using the last one)?
if (combos.empty() || !combos.back().match(p.freq)) combos.push_back(Combo());
@@ -93,7 +93,7 @@ void Analyzer::calcTones() {
it->freq /= it->level;
}
// Only keep a reasonable amount of strongest combos
- std::sort(combos.rbegin(), combos.rend(), Combo::cmpByLevel);
+ std::sort(combos.begin(), combos.end(), Combo::cmpByLevel);
if (combos.size() > 20) combos.resize(20);
// The order may not be strictly correct, fix it...
std::sort(combos.begin(), combos.end(), Combo::cmpByFreq);
@@ -102,6 +102,7 @@ void Analyzer::calcTones() {
for (Combos::const_iterator it = combos.begin(), itend = combos.end(); it != itend; ++it) {
Tone tone;
for (int div = 1; div <= 3; ++div) { // Missing fundamental processing
+ int plausibleHarmonics = 0;
double basefreq = it->freq / div;
if (basefreq < FFT_MINFREQ) break; // Do not try any lower frequencies
for (Combos::const_iterator harm = it; harm != itend; ++harm) {
@@ -110,11 +111,13 @@ void Analyzer::calcTones() {
if (n > Tone::MAXHARM) break; // No more harmonics can be found
if (std::abs(ratio - n) > 0.03) continue; // Frequency doesn't match
if (n == 0) throw std::logic_error("combos not correctly sorted");
+ if (n % div != 0) ++plausibleHarmonics;
double l = harm->level;
tone.harmonics[n - 1] += l;
tone.level += l;
tone.freq += l * harm->freq / n; // The sum of all harmonics' fundies (weighted by l)
}
+ if (div > 1 && plausibleHarmonics < 3) continue; // Not a proper missing fundamental
tone.freq /= tone.level; // Average instead of sum
tones.push_back(tone);
}
@@ -129,7 +132,6 @@ void Analyzer::calcTones() {
double diff = std::abs(ratio - round(ratio));
bool erase = false;
if (diff < 0.02 && it2->level < 2.0 * it->level) erase = true; // Precisely harmonic and not much stronger than fundamental
- else if (diff < 0.06 && it2->harmonics[0] == 0.0) erase = true; // Missing fundamental
// Perform the action
if (erase) it2 = tones.erase(it2); else ++it2;
}
diff --git a/pitch.hh b/pitch.hh
index bffa523..d8c78a5 100644
--- a/pitch.hh
+++ b/pitch.hh
@@ -21,6 +21,7 @@ struct Tone {
// Linked list of a continuous tone
Tone* prev;
Tone* next;
+ static bool cmpByLevel(Tone const& a, Tone const& b) { return a.level > b.level; }
};
static inline bool operator==(Tone const& lhs, Tone const& rhs) { return lhs == rhs.freq; }
@@ -55,7 +56,7 @@ struct Combo {
void combine(Peak const& p);
bool match(double freqOther) const;
static bool cmpByFreq(Combo const& a, Combo const& b) { return a.freq < b.freq; }
- static bool cmpByLevel(Combo const& a, Combo const& b) { return a.level < b.level; }
+ static bool cmpByLevel(Combo const& a, Combo const& b) { return a.level > b.level; }
};
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 14:57:10
|
Module: editor
Branch: master
Commit: 0d98609cc5bcd73cc143fb16381376e1d558f304
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 15:57:00 2011 +0100
Simple post-filtering to remove some noise.
---
pitch.cc | 2 +-
pitchvis.cc | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/pitch.cc b/pitch.cc
index 85d159d..903eeb2 100644
--- a/pitch.cc
+++ b/pitch.cc
@@ -82,7 +82,7 @@ void Analyzer::calcTones() {
Combos combos;
for (size_t k = kMin; k < kMax; ++k) {
Peak const& p = m_peaks[k];
- bool ok = p.level > 1e-4 && p.freq >= FFT_MINFREQ && p.freq <= FFT_MAXFREQ;
+ bool ok = p.level > 1e-6 && p.freq >= FFT_MINFREQ && p.freq <= FFT_MAXFREQ;
if (!ok) continue;
// Do we need to add a new Combo (rather than using the last one)?
if (combos.empty() || !combos.back().match(p.freq)) combos.push_back(Combo());
diff --git a/pitchvis.cc b/pitchvis.cc
index 2151e6f..92bcaea 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -74,16 +74,18 @@ void PitchVis::run()
for (Tone const* n = &*it2; n; n = n->next) { tones.push_back(n); }
if (tones.size() < 3) continue; // Too short tone, ignored
PitchPath path(ch);
+ double score = 0.0;
Analyzer::Moments::const_iterator momit = mit[ch];
// Store path used for rendering
for (unsigned i = 0; i < tones.size(); ++i, ++momit) {
float t = momit->m_time;
float n = scale.getNote(tones[i]->freq);
float level = level2dB(tones[i]->level);
+ score += tones[i]->level;
path.fragments.push_back(PitchFragment(t, n, level));
}
QMutexLocker locker(&mutex);
- paths.push_back(path);
+ if (score > 1.0) paths.push_back(path);
moreAvailable = true;
}
}
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 14:31:21
|
Module: editor
Branch: master
Commit: f6e5363fa39914fcce35f802580f7e7c8a109e12
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 15:30:41 2011 +0100
Fix a bug in AudioQueue ring buffer.
---
ffmpeg.hh | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/ffmpeg.hh b/ffmpeg.hh
index 8814503..003ff29 100644
--- a/ffmpeg.hh
+++ b/ffmpeg.hh
@@ -45,14 +45,14 @@ public:
da::sample_t* outptr = &out[outsz];
Ring::iterator b = m_ring.begin() + m_position,
e = m_ring.begin() + (m_position + m_size) % m_ring.size();
- if (e < b) {
- // Two parts copied separately
+ if (e <= b) {
+ // Copy the first part
std::copy(b, m_ring.end(), outptr);
- std::copy(m_ring.begin(), e, outptr);
- } else {
- // All in one part
- std::copy(b, e, outptr);
+ outptr += m_ring.end() - b;
+ b = m_ring.begin();
}
+ // Copy the only/last part
+ std::copy(b, e, outptr);
m_size = 0;
m_needSpace.wakeOne();
return true;
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 14:31:18
|
Module: editor
Branch: master
Commit: 21197de51a15e93838f68bb98101c8a378d11a25
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 14:57:11 2011 +0100
Further FFMPEG cleanup, no functional changes.
---
ffmpeg.cc | 17 ++++++-----------
pitchvis.cc | 1 +
2 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/ffmpeg.cc b/ffmpeg.cc
index 45f8386..7ae263a 100644
--- a/ffmpeg.cc
+++ b/ffmpeg.cc
@@ -145,30 +145,25 @@ void FFmpeg::decodeNextFrame() {
} videoFrame;
int frameFinished=0;
+ std::vector<char, AvMalloc<char> > decodedBuffer(AVCODEC_MAX_AUDIO_FRAME_SIZE);
while (!frameFinished) {
ReadFramePacket packet(pFormatCtx);
- int packetSize = packet.size;
- quint8 *packetData = packet.data;
+ unsigned packetPos = 0;
if (packet.stream_index==audioStream) {
- while (packetSize) {
- if (packetSize < 0) throw std::logic_error("negative audio packet size?!");
+ while (packetPos < packet.size) {
if (m_quit || m_seekTarget == m_seekTarget) return;
- std::vector<char, AvMalloc<char> > decodedBuffer(AVCODEC_MAX_AUDIO_FRAME_SIZE);
- int outsize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ int outsize = decodedBuffer.size(); // In bytes
int bytesUsed;
{
short* decodedPtr = reinterpret_cast<short*>(&decodedBuffer[0]);
#if LIBAVCODEC_VERSION_INT > ((52<<16)+(25<<8)+0)
bytesUsed = avcodec_decode_audio3(pAudioCodecCtx, decodedPtr, &outsize, &packet);
#else
- bytesUsed = avcodec_decode_audio2(pAudioCodecCtx, decodedPtr, &outsize, packetData, packetSize);
+ bytesUsed = avcodec_decode_audio2(pAudioCodecCtx, decodedPtr, &outsize, packet.data + packetPos, packet.size - packetPos);
#endif
}
- // Negative means an error
if (bytesUsed < 0) throw std::runtime_error("cannot decode audio frame");
- // Move forward within the packet
- packetSize -= bytesUsed;
- packetData += bytesUsed;
+ packetPos += bytesUsed;
// Update position if timecode is available
if (packet.time() == packet.time()) m_position = packet.time();
// Output samples
diff --git a/pitchvis.cc b/pitchvis.cc
index 1d9c40a..2151e6f 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -56,6 +56,7 @@ void PitchVis::run()
}
}
}
+ // DEBUG: std::ofstream("audio.raw", std::ios::binary).write(reinterpret_cast<char*>(&data[0]), data.size() * sizeof(float));
// Filter the analyzer output data into QPainterPaths.
std::vector<Analyzer::Moments::const_iterator> mit(channels), mend(channels);
for (unsigned ch = 0; ch < channels; ++ch) {
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 14:31:16
|
Module: editor
Branch: master
Commit: dc6f4845743114ec328b0273ad6f607e1aa3ee0c
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 13:26:30 2011 +0100
NaN safe handling peaks in Analyzer.
---
pitch.cc | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/pitch.cc b/pitch.cc
index 0ac5924..85d159d 100644
--- a/pitch.cc
+++ b/pitch.cc
@@ -82,8 +82,8 @@ void Analyzer::calcTones() {
Combos combos;
for (size_t k = kMin; k < kMax; ++k) {
Peak const& p = m_peaks[k];
- if (p.level < 1e-4) continue;
- if (p.freq < FFT_MINFREQ || p.freq > FFT_MAXFREQ) continue;
+ bool ok = p.level > 1e-4 && p.freq >= FFT_MINFREQ && p.freq <= FFT_MAXFREQ;
+ if (!ok) continue;
// Do we need to add a new Combo (rather than using the last one)?
if (combos.empty() || !combos.back().match(p.freq)) combos.push_back(Combo());
combos.back().combine(p);
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 14:31:13
|
Module: editor
Branch: master
Commit: 7789d0fe67969d3b2bbd160cc7b9841fe14228f3
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 13:25:19 2011 +0100
Add more supported sample formats to FFMPEG and do other minor cleanup/fixes.
---
ffmpeg.cc | 45 +++++++++++++++++++++++++++++----------------
ffmpeg.hh | 4 ++--
2 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/ffmpeg.cc b/ffmpeg.cc
index e533b88..45f8386 100644
--- a/ffmpeg.cc
+++ b/ffmpeg.cc
@@ -153,27 +153,40 @@ void FFmpeg::decodeNextFrame() {
while (packetSize) {
if (packetSize < 0) throw std::logic_error("negative audio packet size?!");
if (m_quit || m_seekTarget == m_seekTarget) return;
- std::vector<qint16, AvMalloc<qint16> > decodedBuffer(AVCODEC_MAX_AUDIO_FRAME_SIZE);
- int outsize = AVCODEC_MAX_AUDIO_FRAME_SIZE*sizeof(qint16);
+ std::vector<char, AvMalloc<char> > decodedBuffer(AVCODEC_MAX_AUDIO_FRAME_SIZE);
+ int outsize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ int bytesUsed;
+ {
+ short* decodedPtr = reinterpret_cast<short*>(&decodedBuffer[0]);
#if LIBAVCODEC_VERSION_INT > ((52<<16)+(25<<8)+0)
- int decodeSize = avcodec_decode_audio3(pAudioCodecCtx, &decodedBuffer[0], &outsize, &packet);
+ bytesUsed = avcodec_decode_audio3(pAudioCodecCtx, decodedPtr, &outsize, &packet);
#else
- int decodeSize = avcodec_decode_audio2(pAudioCodecCtx, &decodedBuffer[0], &outsize, packetData, packetSize);
+ bytesUsed = avcodec_decode_audio2(pAudioCodecCtx, decodedPtr, &outsize, packetData, packetSize);
#endif
- // Handle special cases
- if (decodeSize == 0) break;
- if (outsize == 0) continue;
- if (decodeSize < 0) throw std::runtime_error("cannot decode audio frame");
+ }
+ // Negative means an error
+ if (bytesUsed < 0) throw std::runtime_error("cannot decode audio frame");
// Move forward within the packet
- packetSize -= decodeSize;
- packetData += decodeSize;
- // Convert outsize from bytes into number of samples
- outsize /= sizeof(qint16);
- // Calculate new positions
+ packetSize -= bytesUsed;
+ packetData += bytesUsed;
+ // Update position if timecode is available
if (packet.time() == packet.time()) m_position = packet.time();
- else m_position += outsize / audioQueue.samplesPerSecond();
- // Push to output queue (may block)
- audioQueue.input(decodedBuffer.begin(), decodedBuffer.begin() + outsize);
+ // Output samples
+#define OUTPUT_SAMPLES(TYPE, MAX_VALUE) \
+ {\
+ outsize /= sizeof(TYPE); /* Convert bytes into samples */ \
+ TYPE* samples = reinterpret_cast<TYPE*>(&decodedBuffer[0]);\
+ audioQueue.input(samples, samples + outsize, 1.0 / MAX_VALUE);\
+ }
+ switch (pAudioCodecCtx->sample_fmt) {
+ case SAMPLE_FMT_S16: OUTPUT_SAMPLES(short, 32767.0); break;
+ case SAMPLE_FMT_S32: OUTPUT_SAMPLES(int, 8388607.0); break; // 24 bit samples padded to 32 bits
+ case SAMPLE_FMT_FLT: OUTPUT_SAMPLES(float, 1.0); break;
+ case SAMPLE_FMT_DBL: OUTPUT_SAMPLES(double, 1.0); break;
+ default: throw std::runtime_error("Unsupported sample format");
+ }
+#undef OUTPUT_SAMPLES
+ m_position += outsize / audioQueue.samplesPerSecond(); // New position in case the next packet doesn't have packet.time()
}
// Audio frames are always finished
frameFinished = 1;
diff --git a/ffmpeg.hh b/ffmpeg.hh
index 7763b42..8814503 100644
--- a/ffmpeg.hh
+++ b/ffmpeg.hh
@@ -18,14 +18,14 @@ public:
m_needData.wakeOne();
m_needSpace.wakeOne();
}
- template <typename Iterator> void input(Iterator begin, Iterator end) {
+ template <typename Iterator> void input(Iterator begin, Iterator end, double scale) {
QMutexLocker lock(&m_mutex);
unsigned count = end - begin;
unsigned capacity = m_ring.size();
if (capacity < count) throw std::logic_error("AudioQueue input chunk is bigger than capacity");
while (capacity - m_size < count) m_needSpace.wait(&m_mutex);
for (unsigned i = 0; i < count; ++i) {
- m_ring[m_position + m_size++] = da::conv_from_s16(*begin++);
+ m_ring[m_position + m_size++] = *begin++ * scale;
}
m_needData.wakeOne();
}
|
|
From: Tapio V. <aa...@us...> - 2011-02-08 14:24:40
|
Module: editor
Branch: master
Commit: 45f04ea0f3db1919feda69bbdfee49eb79c786e1
Author: Tapio Vierros <tap...@gm...>
Date: Tue Feb 8 16:24:00 2011 +0200
Display also previous sentence and also highlight the selected word.
---
editor.ui | 7 +++++++
editorapp.cc | 6 ++++--
notegraphwidget.cc | 23 +++++++++++++++++++++++
notegraphwidget.hh | 1 +
4 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/editor.ui b/editor.ui
index ebeeda1..e5bbb0d 100644
--- a/editor.ui
+++ b/editor.ui
@@ -420,6 +420,13 @@
</property>
</widget>
</item>
+ <item row="3" column="1" colspan="2">
+ <widget class="QLabel" name="lblPrevSentence">
+ <property name="text">
+ <string>Previous sentence:</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="tabLyrics">
diff --git a/editorapp.cc b/editorapp.cc
index 6a45232..a9da936 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -188,7 +188,8 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
ui.chkFloating->setChecked(note->isFloating());
ui.chkLineBreak->setEnabled(true);
ui.chkLineBreak->setChecked(note->note().lineBreak);
- ui.lblCurrentSentence->setText(tr("Current sentence:") + " <b>" + noteGraph->getCurrentSentence() + "</b>");
+ ui.lblCurrentSentence->setText(tr("Current phrase:") + " <b>" + noteGraph->getCurrentSentence() + "</b>");
+ ui.lblPrevSentence->setText(tr("Previous phrase:") + " " + noteGraph->getPrevSentence());
} else {
ui.valNoteBegin->setText("-");
ui.valNoteEnd->setText("-");
@@ -197,7 +198,8 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
ui.cmbNoteType->setEnabled(false);
ui.chkFloating->setEnabled(false);
ui.chkLineBreak->setEnabled(false);
- ui.lblCurrentSentence->setText(tr("Current sentence:") + " -");
+ ui.lblCurrentSentence->setText(tr("Current phrase:") + " -");
+ ui.lblPrevSentence->setText(tr("Previous phrase:") + " -");
}
updateTitle();
}
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 1169b6b..91a4225 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -482,6 +482,29 @@ QString NoteGraphWidget::getCurrentSentence() const
int id = getNoteLabelId(selectedNote());
for (int i = id; i < m_notes.size(); ++i) {
if (i != id && m_notes[i]->note().lineBreak) break;
+ // Selected notes are highlighted with different color
+ if (m_notes[i]->isSelected()) lyrics += "<span style=\"color: #a00;\">";
+ lyrics += m_notes[i]->lyric();
+ if (m_notes[i]->isSelected()) lyrics += "</span>";
+ lyrics += " ";
+ }
+ lyrics = lyrics.left(lyrics.size() - 1);
+ }
+ return lyrics;
+}
+
+QString NoteGraphWidget::getPrevSentence() const
+{
+ QString lyrics;
+ if (!m_notes.isEmpty() && selectedNote()) {
+ // First find the previous start
+ int id = getNoteLabelId(selectedNote()), i = id-1;
+ for (; i >= 0 && !m_notes[i]->note().lineBreak; --i) ;
+ if (i < 0) return "";
+
+ // Now get the sentence
+ for (id = i; i < m_notes.size(); ++i) {
+ if (i != id && m_notes[i]->note().lineBreak) break;
lyrics += m_notes[i]->lyric() + " ";
}
lyrics = lyrics.left(lyrics.size() - 1);
diff --git a/notegraphwidget.hh b/notegraphwidget.hh
index bc4726d..3b37378 100644
--- a/notegraphwidget.hh
+++ b/notegraphwidget.hh
@@ -106,6 +106,7 @@ public:
VocalTrack getVocalTrack() const;
QString getCurrentSentence() const;
+ QString getPrevSentence() const;
QString dumpLyrics() const;
public slots:
|
|
From: Tapio V. <aa...@us...> - 2011-02-08 14:01:01
|
Module: editor
Branch: master
Commit: ed8ec9c8964ba103e89636dcbbf2178b22295a04
Author: Tapio Vierros <tap...@gm...>
Date: Tue Feb 8 16:00:22 2011 +0200
Draw a horizontal line for each octave's C note.
---
notegraphwidget.cc | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index e73d497..1169b6b 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -140,6 +140,8 @@ void NoteGraphWidget::timerEvent(QTimerEvent* event)
void NoteGraphWidget::paintEvent(QPaintEvent*) {
setFixedSize(s2px(m_duration), height());
+
+ // Find out the horizontal viewport
QScrollArea *scrollArea = NULL;
int x1 = 0, x2 = 0;
if (parentWidget())
@@ -148,7 +150,18 @@ void NoteGraphWidget::paintEvent(QPaintEvent*) {
x1 = scrollArea->horizontalScrollBar()->value();
x2 = x1 + scrollArea->width();
}
+
+ // Pitch
if (m_pitch) m_pitch->paint(this, x1, x2);
+
+ // Octave lines
+ QPainter painter;
+ painter.begin(this);
+ QPen pen; pen.setWidth(1); pen.setColor(QColor("#666"));
+ painter.setPen(pen);
+ for (int i = 1; i < 4; ++i)
+ painter.drawLine(x1, n2px(i*12), x2, n2px(i*12));
+ painter.end();
}
void NoteGraphWidget::updateNotes(bool leftToRight)
|
|
From: Yoda-JM <yo...@us...> - 2011-02-08 12:56:01
|
Module: editor
Branch: master
Commit: c18933c76efbe25693ec1d94728af9faeddc6561
Author: Vincent Le Ligeour <yo...@us...>
Date: Tue Feb 8 13:55:45 2011 +0100
Added Ctrl+0 zoom option (reset zoom)
---
notegraphwidget.cc | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 342355d..e73d497 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -415,6 +415,8 @@ void NoteGraphWidget::keyPressEvent(QKeyEvent *event)
zoom(1.0);
} else if (k == Qt::Key_Minus && (m & Qt::ControlModifier)) {
zoom(-1.0);
+ } else if (k == Qt::Key_0 && (m & Qt::ControlModifier)) {
+ zoom(getNaN());
} else {
QWidget::keyPressEvent(event);
}
|
|
From: Tapio V. <aa...@us...> - 2011-02-08 10:04:51
|
Module: editor
Branch: master
Commit: f3f0d5ba459a40947a0e9ccb21aa1c0e1282f2c5
Author: Tapio Vierros <tap...@gm...>
Date: Tue Feb 8 12:04:13 2011 +0200
Refactor NoteLabel::showContextMenu shorter.
---
notelabel.cc | 75 ++++++++++++++++++++++++----------------------------------
1 files changed, 31 insertions(+), 44 deletions(-)
diff --git a/notelabel.cc b/notelabel.cc
index 6f1b840..9f701ed 100644
--- a/notelabel.cc
+++ b/notelabel.cc
@@ -183,62 +183,49 @@ void NoteLabel::updateNote()
void NoteLabel::showContextMenu(const QPoint &pos)
{
- QAction actionFloating(NULL);
- actionFloating.setCheckable(true);
- actionFloating.setChecked(isFloating());
+ QMenu menuContext(NULL);
+ QMenu menuType(tr("Type"), NULL);
- QAction actionLineBreak(NULL);
- actionLineBreak.setCheckable(true);
- actionLineBreak.setChecked(isLineBreak());
+ QAction *actionFloating = menuContext.addAction(tr("Floating"));
+ actionFloating->setCheckable(true);
+ actionFloating->setChecked(isFloating());
- QAction actionNormal(NULL);
- actionNormal.setCheckable(true);
- actionNormal.setChecked(m_note.type == Note::NORMAL);
+ QAction *actionLineBreak = menuContext.addAction(tr("Line break"));
+ actionLineBreak->setCheckable(true);
+ actionLineBreak->setChecked(isLineBreak());
- QAction actionGolden(NULL);
- actionGolden.setCheckable(true);
- actionGolden.setChecked(m_note.type == Note::GOLDEN);
+ menuContext.addSeparator();
+ menuContext.addAction(menuType.menuAction());
- QAction actionFreestyle(NULL);
- actionFreestyle.setCheckable(true);
- actionFreestyle.setChecked(m_note.type == Note::FREESTYLE);
+ QAction *actionNormal = menuType.addAction(tr("Normal"));
+ actionNormal->setCheckable(true);
+ actionNormal->setChecked(m_note.type == Note::NORMAL);
- QAction actionSplit(NULL);
- QAction actionDelete(NULL);
+ QAction *actionGolden = menuType.addAction(tr("Golden"));
+ actionGolden->setCheckable(true);
+ actionGolden->setChecked(m_note.type == Note::GOLDEN);
- QMenu menuContext(NULL);
- QMenu menuType(NULL);
+ QAction *actionFreestyle = menuType.addAction(tr("Freestyle"));
+ actionFreestyle->setCheckable(true);
+ actionFreestyle->setChecked(m_note.type == Note::FREESTYLE);
- menuContext.addAction(&actionFloating);
- menuContext.addSeparator();
- menuContext.addAction(&actionLineBreak);
menuContext.addSeparator();
- menuContext.addAction(menuType.menuAction());
- menuContext.addAction(&actionSplit);
- menuContext.addAction(&actionDelete);
- menuType.addAction(&actionNormal);
- menuType.addAction(&actionGolden);
- menuType.addAction(&actionFreestyle);
-
- actionFloating.setText(tr("Floating"));
- actionLineBreak.setText(tr("Line break"));
- actionNormal.setText(tr("Normal"));
- actionGolden.setText(tr("Golden"));
- actionFreestyle.setText(tr("Freestyle"));
- actionSplit.setText(tr("Split"));
- actionDelete.setText(tr("Delete"));
- menuType.setTitle(tr("Type"));
+ QAction *actionSplit = menuContext.addAction(tr("Split"));
+ QAction *actionDelete = menuContext.addAction(tr("Delete"));
+ // Show maenu and wait for action
QPoint globalPos = mapToGlobal(pos);
QAction *sel = menuContext.exec(globalPos);
NoteGraphWidget* ngw = qobject_cast<NoteGraphWidget*>(parent());
if (sel && ngw) {
- if (sel == &actionSplit) ngw->split(this);
- else if (sel == &actionFloating) ngw->setFloating(this, !isFloating());
- else if (sel == &actionLineBreak) ngw->setLineBreak(this, !isLineBreak());
- else if (sel == &actionNormal) ngw->setType(this, 0);
- else if (sel == &actionGolden) ngw->setType(this, 1);
- else if (sel == &actionFreestyle) ngw->setType(this, 2);
- else if (sel == &actionDelete) ngw->del(this);
+ if (sel == actionSplit) ngw->split(this);
+ else if (sel == actionFloating) ngw->setFloating(this, !isFloating());
+ else if (sel == actionLineBreak) ngw->setLineBreak(this, !isLineBreak());
+ else if (sel == actionNormal) ngw->setType(this, 0);
+ else if (sel == actionGolden) ngw->setType(this, 1);
+ else if (sel == actionFreestyle) ngw->setType(this, 2);
+ else if (sel == actionDelete) ngw->del(this);
}
+ menuType.clear();
+ menuContext.clear();
}
|
|
From: Tapio V. <aa...@us...> - 2011-02-08 09:56:25
|
Module: editor
Branch: master
Commit: c18f7782fb8bd65f60df9b8b730bda3b26512030
Author: Tapio Vierros <tap...@gm...>
Date: Tue Feb 8 11:55:43 2011 +0200
Add "Reset zoom" functionality and context menu action.
---
notegraphwidget.cc | 23 ++++++++++-------------
notelabelmanager.cc | 6 ++++--
2 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 1c106d2..342355d 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -423,27 +423,24 @@ void NoteGraphWidget::keyPressEvent(QKeyEvent *event)
void NoteGraphWidget::showContextMenu(const QPoint &pos)
{
- QAction actionNew(NULL);
- QAction actionSelectAll(NULL);
- QAction actionDeselect(NULL);
QMenu menuContext(NULL);
- menuContext.addAction(&actionNew);
+ QAction *actionNew = menuContext.addAction(tr("New note"));
menuContext.addSeparator();
- menuContext.addAction(&actionSelectAll);
- menuContext.addAction(&actionDeselect);
-
- actionNew.setText(tr("New note"));
- actionSelectAll.setText(tr("Select all"));
- actionDeselect.setText(tr("Deselect"));
+ QAction *actionResetZoom = menuContext.addAction(tr("Reset zoom"));
+ menuContext.addSeparator();
+ QAction *actionSelectAll = menuContext.addAction(tr("Select all"));
+ QAction *actionDeselect = menuContext.addAction(tr("Deselect"));
QPoint globalPos = mapToGlobal(pos);
QAction *sel = menuContext.exec(globalPos);
if (sel) {
- if (sel == &actionNew) /*TODO*/;
- else if (sel == &actionSelectAll) selectAll();
- else if (sel == &actionDeselect) selectNote(NULL);
+ if (sel == actionNew) /*TODO*/;
+ else if (sel == actionResetZoom) zoom(getNaN());
+ else if (sel == actionSelectAll) selectAll();
+ else if (sel == actionDeselect) selectNote(NULL);
}
+ menuContext.clear();
}
diff --git a/notelabelmanager.cc b/notelabelmanager.cc
index 8b3b223..fce9119 100644
--- a/notelabelmanager.cc
+++ b/notelabelmanager.cc
@@ -258,8 +258,10 @@ void NoteLabelManager::zoom(float steps) {
if (scrollArea) scrollSecs = px2s(scrollArea->horizontalScrollBar()->value() + scrollArea->width()/2);
}
- // Update zoom factor
- m_pixelsPerSecond += steps * ppsStep;
+ // Update zoom factor, NaN means reset
+ if (steps != steps) m_pixelsPerSecond = ppsNormal;
+ else m_pixelsPerSecond += steps * ppsStep;
+ // Limits
if (m_pixelsPerSecond < ppsMin) m_pixelsPerSecond = ppsMin;
else if (m_pixelsPerSecond > ppsMax) m_pixelsPerSecond = ppsMax;
|
|
From: Tapio V. <aa...@us...> - 2011-02-08 09:56:23
|
Module: editor
Branch: master
Commit: 98b620035f06fcf5c91d5ed3c95fcef108cf6771
Author: Tapio Vierros <tap...@gm...>
Date: Tue Feb 8 11:44:59 2011 +0200
Show zoom level on title bar and as tooltip.
---
editorapp.cc | 14 +++++++++++++-
editorapp.hh | 1 +
notegraphwidget.cc | 2 ++
notegraphwidget.hh | 10 +++++++++-
notelabelmanager.cc | 24 ++++++++++++------------
5 files changed, 37 insertions(+), 14 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 92aaedd..6a45232 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -155,10 +155,21 @@ void EditorApp::updateMenuStates()
ui.actionRedo->setEnabled(false);
else ui.actionRedo->setEnabled(true);
// Window title
+ updateTitle();
+}
+
+void EditorApp::updateTitle()
+{
+ // Project name
QFileInfo finfo(projectFileName);
QString proName = finfo.fileName().isEmpty() ? tr("Untitled") : finfo.fileName();
if (hasUnsavedChanges) proName += "*";
- setWindowTitle(QString(PACKAGE) + " - " + proName);
+ // Zoom level
+ QString zoom = "";
+ if (noteGraph && noteGraph->getZoomLevel() != "100 %")
+ zoom = " - " + noteGraph->getZoomLevel();
+ // Set the title
+ setWindowTitle(QString(PACKAGE) + " - " + proName + zoom);
}
void EditorApp::updateNoteInfo(NoteLabel *note)
@@ -188,6 +199,7 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
ui.chkLineBreak->setEnabled(false);
ui.lblCurrentSentence->setText(tr("Current sentence:") + " -");
}
+ updateTitle();
}
void EditorApp::analyzeProgress(int value, int maximum)
diff --git a/editorapp.hh b/editorapp.hh
index ee1820f..3c2910e 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -34,6 +34,7 @@ public:
void updateSongMeta(bool readFromSongToUI = false);
void updateMenuStates();
+ void updateTitle();
void showTab(int tab) { ui.tabWidget->setCurrentIndex(tab); }
void showExportMenu() { ui.menuExport->exec(pos() + QPoint(0, ui.menubar->height())); }
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index b3b0e90..1c106d2 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -4,6 +4,7 @@
#include <QScrollBar>
#include <QPainter>
#include <QMenu>
+#include <QToolTip>
#include <iostream>
#include <algorithm>
#include <cmath>
@@ -337,6 +338,7 @@ void NoteGraphWidget::wheelEvent(QWheelEvent *event)
float numDegrees = event->delta() / 8; // Qt resolution is 8th of a degree
float numSteps = numDegrees / 15; // Usually mice have 15 degree steps
zoom(numSteps);
+ QToolTip::showText(event->globalPos(), "Zoom: " + getZoomLevel(), this);
event->accept();
return;
}
diff --git a/notegraphwidget.hh b/notegraphwidget.hh
index eeedde7..bc4726d 100644
--- a/notegraphwidget.hh
+++ b/notegraphwidget.hh
@@ -55,6 +55,7 @@ public:
void doOperation(const Operation& op, Operation::OperationFlags flags = Operation::NORMAL);
void zoom(float steps);
+ QString getZoomLevel();
int s2px(double sec) const;
double px2s(int px) const;
@@ -70,11 +71,18 @@ public slots:
void selectNextSentenceStart();
protected:
+
+ // Pixels Per Second values
+ static const double ppsStep = 20.0f;
+ static const double ppsMin = 100;
+ static const double ppsMax = 300;
+ static const double ppsNormal = 200;
+ double m_pixelsPerSecond;
+
NoteLabels m_notes;
NoteLabels m_selectedNotes;
enum NoteAction { NONE, RESIZE, MOVE } m_selectedAction;
int m_noteHalfHeight;
- double m_pixelsPerSecond;
};
diff --git a/notelabelmanager.cc b/notelabelmanager.cc
index d23ee67..8b3b223 100644
--- a/notelabelmanager.cc
+++ b/notelabelmanager.cc
@@ -9,7 +9,7 @@
#include "operation.hh"
NoteLabelManager::NoteLabelManager(QWidget *parent)
- : QLabel(parent), m_selectedAction(NONE), m_pixelsPerSecond(200.0)
+ : QLabel(parent), m_selectedAction(NONE), m_pixelsPerSecond(ppsNormal)
{
// Determine NoteLabel height
NoteLabel templabel(Note(" "), NULL);
@@ -246,12 +246,9 @@ void NoteLabelManager::doOperation(const Operation& op, Operation::OperationFlag
}
void NoteLabelManager::zoom(float steps) {
- // Limits
- const float ppsstep = 20.0f;
- const float minpps = 100;
- const float maxpps = 300;
- if (m_pixelsPerSecond <= minpps && steps < 0) return;
- else if (m_pixelsPerSecond >= maxpps && steps > 0) return;
+ // Check if we can do anything
+ if (m_pixelsPerSecond <= ppsMin && steps < 0) return;
+ else if (m_pixelsPerSecond >= ppsMax && steps > 0) return;
// Get scrollArea position
QScrollArea *scrollArea = NULL;
@@ -262,9 +259,9 @@ void NoteLabelManager::zoom(float steps) {
}
// Update zoom factor
- m_pixelsPerSecond += steps * ppsstep;
- if (m_pixelsPerSecond < minpps) m_pixelsPerSecond = minpps;
- else if (m_pixelsPerSecond > maxpps) m_pixelsPerSecond = maxpps;
+ m_pixelsPerSecond += steps * ppsStep;
+ if (m_pixelsPerSecond < ppsMin) m_pixelsPerSecond = ppsMin;
+ else if (m_pixelsPerSecond > ppsMax) m_pixelsPerSecond = ppsMax;
// Update scroll bar position
if (scrollArea && scrollSecs >= 0) {
@@ -272,7 +269,6 @@ void NoteLabelManager::zoom(float steps) {
int y = 0;
if (scrollVer) y = scrollVer->value();
scrollArea->ensureVisible(s2px(scrollSecs), y, scrollArea->width()/2, 0);
- std::cout << "YEAH" << std::endl;
}
// Update notes
@@ -283,9 +279,13 @@ void NoteLabelManager::zoom(float steps) {
// Update pitch visualization
update();
- std::cout << "pixPerSec: " << m_pixelsPerSecond << std::endl;
+
+ // Update window title
+ emit updateNoteInfo(selectedNote());
}
+QString NoteLabelManager::getZoomLevel() { return QString::number(int(m_pixelsPerSecond / ppsNormal * 100)) + " %"; }
+
int NoteLabelManager::s2px(double sec) const { return sec * m_pixelsPerSecond; }
double NoteLabelManager::px2s(int px) const { return px / m_pixelsPerSecond; }
int NoteLabelManager::n2px(double note) const { return height() - 16.0 * note; }
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-08 09:22:21
|
Module: performous
Branch: opengl2
Commit: 44e634659198a7dd8834eaac9881c01554d9de01
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Feb 8 10:22:09 2011 +0100
Geometry shader stereo rendering, still has issues.
---
game/glmath.hh | 5 ++++
game/video_driver.cc | 43 ++++++++++++++++++++++++---------
game/video_driver.hh | 2 +
themes/default/shaders/core.frag | 13 ++++++----
themes/default/shaders/stereo3d.geom | 37 +++++++++++++++++++++++++++++
5 files changed, 83 insertions(+), 17 deletions(-)
diff --git a/game/glmath.hh b/game/glmath.hh
index 675a3cf..9177f01 100644
--- a/game/glmath.hh
+++ b/game/glmath.hh
@@ -32,6 +32,11 @@ namespace glmath {
static inline Vec3 normalize(Vec3 const& v) { return (1 / len(v)) * v; }
struct Matrix {
+ static Matrix zero() {
+ Matrix ret;
+ ret(0,0) = ret(1,1) = ret(2,2) = ret(3,3) = 0.0;
+ return ret;
+ }
Vec4 cols[4];
/// Identity matrix
Matrix() { for (unsigned k = 0; k < 4; ++k) cols[k][k] = 1.0; }
diff --git a/game/video_driver.cc b/game/video_driver.cc
index e7e0a71..5598ee5 100644
--- a/game/video_driver.cc
+++ b/game/video_driver.cc
@@ -73,25 +73,28 @@ Window::Window(unsigned int width, unsigned int height, bool fs): m_windowW(widt
input::SDL::init(); // Joysticks etc.
shader("surface")
.compileFile(getThemePath("shaders/core.vert"))
+ .compileFile(getThemePath("shaders/stereo3d.geom"))
.compileFile(getThemePath("shaders/core.frag"), "#define SURFACE\n")
.link()
.bind()
.setUniformMatrix("colorMatrix", glmath::Matrix());
shader("texture")
.compileFile(getThemePath("shaders/core.vert"))
+ .compileFile(getThemePath("shaders/stereo3d.geom"))
.compileFile(getThemePath("shaders/core.frag"), "#define TEXTURE\n")
.link()
.bind()
.setUniformMatrix("colorMatrix", glmath::Matrix());
shader("3dobject")
.compileFile(getThemePath("shaders/3dobject.vert"))
+ .compileFile(getThemePath("shaders/stereo3d.geom"))
.compileFile(getThemePath("shaders/3dobject.frag"))
.link();
shader("dancenote")
.compileFile(getThemePath("shaders/dancenote.vert"))
+ .compileFile(getThemePath("shaders/stereo3d.geom"))
.compileFile(getThemePath("shaders/dancenote.frag"))
.link();
-
double vx = 0.5f * (screen->w - s_width);
double vy = 0.5f * (screen->h - s_height);
double vw = s_width, vh = s_height;
@@ -105,6 +108,15 @@ void Window::blank() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
+void Window::updateStereo(glmath::Matrix const& left, glmath::Matrix const& right) {
+ for (ShaderMap::iterator it = m_shaders.begin(); it != m_shaders.end(); ++it) {
+ Shader& sh = *it->second;
+ sh.bind();
+ sh.setUniformMatrix("leftTransform", left);
+ sh.setUniformMatrix("rightTransform", right);
+ }
+}
+
void Window::render(boost::function<void (void)> drawFunc) {
if (s_width < screen->w || s_height < screen->h) glClear(GL_COLOR_BUFFER_BIT); // Black bars
bool stereo = config["graphic/stereo3d"].b();
@@ -116,21 +128,28 @@ void Window::render(boost::function<void (void)> drawFunc) {
double vy = 0.5f * (screen->h - s_height);
double vw = s_width, vh = s_height;
glViewport(vx, vy, vw, vh); // Drawable area of the window (excluding black bars)
+ updateStereo();
view(0);
drawFunc();
return;
}
- // Render each eye to FBO
+ // Render both eyes to FBO
unsigned w = s_width;
unsigned h = s_height;
- if (type == 2) h /= 2; // Half-height mode
- FBO fboleft(w, h), fboright(w, h);
- FBO* fbo[] = { &fboleft, &fboright };
- for (unsigned i = 0; i < 2; ++i) {
- UseFBO user(*fbo[i]);
- glViewport(0, 0, w, h); // Full FBO
- view(i + 1);
+ if (type < 2) h *= 2; // Full resolution stereo
+ FBO fbo(w, h);
+ {
+ UseFBO user(fbo);
+ glViewportIndexedf(0, 0, 0, w, h / 2);
+ glViewportIndexedf(1, 0, h / 2, w, h / 2);
+ double separation = getSeparation();
+ glmath::Matrix l, r;
+ l(0,3) = -separation; l(0,2) = 0.5 * separation;
+ r(0,3) = separation; r(0,2) = -0.5 * separation;
+ updateStereo(l, r);
+ view(0);
drawFunc();
+ updateStereo();
}
// Render to actual framebuffer from FBOs
glViewport(0, 0, screen->w, screen->h); // Entire window
@@ -173,11 +192,11 @@ void Window::render(boost::function<void (void)> drawFunc) {
}
{
// Render FBO with 1:1 pixels, properly filtered/positioned for 3d
- UseTexture use(fbo[num]->getTexture());
+ UseTexture use(fbo.getTexture());
sh.setUniformMatrix("colorMatrix", colorMatrix);
Dimensions dim = Dimensions().stretch(2.0 * w / screen->w, 2.0 * h / screen->h);
- if (type == 2) dim.center(num == 0 ? 0.5 : -0.5);
- fbo[num]->getTexture().draw(dim, TexCoords(0.0, 0.0, w, h));
+ if (type != 2) dim.center((num == 0 ? -0.25 : 0.25) * dim.h());
+ fbo.getTexture().draw(dim, TexCoords(0.0, 0.0, w, h));
sh.setUniformMatrix("colorMatrix", glmath::Matrix());
}
}
diff --git a/game/video_driver.hh b/game/video_driver.hh
index 3546219..0c5040d 100644
--- a/game/video_driver.hh
+++ b/game/video_driver.hh
@@ -1,5 +1,6 @@
#pragma once
+#include "glmath.hh"
#include "glshader.hh"
#include "glutil.hh"
#include <boost/function.hpp>
@@ -56,6 +57,7 @@ private:
/// Setup everything for drawing a view.
/// @param num 0 = no stereo, 1 = left eye, 2 = right eye
void view(unsigned num);
+ void updateStereo(glmath::Matrix const& left = glmath::Matrix(), glmath::Matrix const& right = glmath::Matrix::zero());
SDL_Surface* screen;
unsigned int m_windowW, m_windowH;
unsigned int m_fsW, m_fsH;
diff --git a/themes/default/shaders/core.frag b/themes/default/shaders/core.frag
index 872ac36..8b61013 100644
--- a/themes/default/shaders/core.frag
+++ b/themes/default/shaders/core.frag
@@ -1,10 +1,8 @@
-#version 120
+#version 330
#extension GL_ARB_texture_rectangle : require
//DEFINES
-uniform mat4 colorMatrix;
-
#ifdef SURFACE
uniform sampler2DRect tex;
#define TFUNC texture2DRect
@@ -15,10 +13,15 @@ uniform sampler2D tex;
#define TFUNC texture2D
#endif
+uniform mat4 colorMatrix;
+
+in vec4 color;
+in vec2 texcoord;
+
void main() {
- gl_FragColor = colorMatrix * (gl_Color
+ gl_FragColor = colorMatrix * (color
#ifdef TFUNC
- * TFUNC(tex, gl_TexCoord[0].st).rgba
+ * TFUNC(tex, texcoord).rgba
#endif
);
}
diff --git a/themes/default/shaders/stereo3d.geom b/themes/default/shaders/stereo3d.geom
new file mode 100644
index 0000000..a17d8a4
--- /dev/null
+++ b/themes/default/shaders/stereo3d.geom
@@ -0,0 +1,37 @@
+#version 330 compatibility
+#extension GL_ARB_viewport_array : require
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices = 6) out;
+
+uniform mat4 leftTransform;
+uniform mat4 rightTransform;
+
+out vec4 color;
+out vec2 texcoord;
+
+void main() {
+ // Fix Nvidia compile warnings ("may be used uninitialized")
+ color = vec4(0);
+ texcoord = vec2(0);
+ gl_Position = vec4(0);
+ // Render the left eye
+ gl_ViewportIndex = 0;
+ for(int i=0; i < gl_in.length(); ++i) {
+ color = gl_in[i].gl_FrontColor;
+ texcoord = gl_in[i].gl_TexCoord[0].st;
+ gl_Position = leftTransform * gl_in[i].gl_Position;
+ EmitVertex();
+ }
+ EndPrimitive();
+ // Render the right eye
+ gl_ViewportIndex = 1;
+ for(int i=0; i < gl_in.length(); ++i) {
+ color = gl_in[i].gl_FrontColor;
+ texcoord = gl_in[i].gl_TexCoord[0].st;
+ gl_Position = rightTransform * gl_in[i].gl_Position;
+ EmitVertex();
+ }
+ EndPrimitive();
+}
+
|