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: Lasse Kärkkäi. <tr...@us...> - 2011-01-31 16:41:20
|
Module: editor
Branch: master
Commit: c267f418d5e22da681729be9e734a542bfb8f436
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Jan 31 17:40:30 2011 +0100
Improved normalization
---
songparser.cc | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/songparser.cc b/songparser.cc
index 605d141..97e633c 100644
--- a/songparser.cc
+++ b/songparser.cc
@@ -83,19 +83,26 @@ namespace {
return (1200 + 6 + target - note) / 12 * 12 - 1200; // 1200 for always positive, 6 for mathematical rounding
}
void normalize(Notes& notes, int limLow, int limHigh) {
- // Find the correction required for freestyle notes (over the entire song)
+ // Analyze the entire song first
+ int defaultShift = 0;
int shiftFS = 0;
{
std::vector<int> fsNotes, regNotes;
for (Notes::iterator it = notes.begin(); it != notes.end(); ++it) {
(it->type == Note::FREESTYLE ? fsNotes : regNotes).push_back(it->note);
}
- if (!regNotes.empty() && !fsNotes.empty()) {
+ if (!regNotes.empty()) {
std::sort(regNotes.begin(), regNotes.end());
- std::sort(fsNotes.begin(), fsNotes.end());
- shiftFS = nearestOctave(fsNotes[fsNotes.size() / 2], regNotes[regNotes.size() / 2]);
+ // Find a good starting value for default shift
+ defaultShift = nearestOctave(regNotes[regNotes.size() / 2], 0.5 * (limLow + limHigh));
+ // Find the additional correction required for freestyle notes
+ if (!fsNotes.empty()) {
+ std::sort(fsNotes.begin(), fsNotes.end());
+ shiftFS = nearestOctave(fsNotes[fsNotes.size() / 2], regNotes[regNotes.size() / 2]);
+ }
}
}
+ // Process sentence by sentence
for (Notes::iterator it = notes.begin(), itnext = it; it != notes.end();) {
int low, high;
low = high = it->note;
@@ -109,12 +116,13 @@ namespace {
}
// Per-sentence shift
int shift = nearestOctave(0.5 * (low + high), 0.5 * (limLow + limHigh));
+ if (std::abs(defaultShift - shift) <= 12) shift = defaultShift;
// Shift the notes into position
for (; it != itnext; ++it) {
if (it->type == Note::SLEEP) continue;
int s = shift;
if (it->type == Note::FREESTYLE) s += shiftFS;
- // The last resort if everything else fails
+ // The last resort if everything else fails (per-note shifting)
while (it->note + s < limLow) s += 12;
while (it->note + s > limHigh) s -= 12;
it->note += s;
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-31 15:49:09
|
Module: editor
Branch: master
Commit: 1ab477902b3163b997aa6cc51e5237135631d097
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Jan 31 16:48:48 2011 +0100
Fix various bugs in the normalizer
---
songparser.cc | 17 ++++++++++-------
1 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/songparser.cc b/songparser.cc
index f9eec78..605d141 100644
--- a/songparser.cc
+++ b/songparser.cc
@@ -80,7 +80,7 @@ bool SongParser::getline(QString &line)
namespace {
/// Return the amount of shift (in notes) required for note to make put it in the nearest octave of the target note
int nearestOctave(int note, int target) {
- return (1006 + target - note) / 12 * 12 - 1006; // 1006 for mathematical rounding (always positive, round up from 6)
+ return (1200 + 6 + target - note) / 12 * 12 - 1200; // 1200 for always positive, 6 for mathematical rounding
}
void normalize(Notes& notes, int limLow, int limHigh) {
// Find the correction required for freestyle notes (over the entire song)
@@ -90,24 +90,28 @@ namespace {
for (Notes::iterator it = notes.begin(); it != notes.end(); ++it) {
(it->type == Note::FREESTYLE ? fsNotes : regNotes).push_back(it->note);
}
- std::sort(regNotes.begin(), regNotes.end());
- std::sort(fsNotes.begin(), fsNotes.end());
- if (!regNotes.empty() && !fsNotes.empty()) shiftFS = nearestOctave(fsNotes[fsNotes.size() / 2], regNotes[regNotes.size() / 2]);
+ if (!regNotes.empty() && !fsNotes.empty()) {
+ std::sort(regNotes.begin(), regNotes.end());
+ std::sort(fsNotes.begin(), fsNotes.end());
+ shiftFS = nearestOctave(fsNotes[fsNotes.size() / 2], regNotes[regNotes.size() / 2]);
+ }
}
for (Notes::iterator it = notes.begin(), itnext = it; it != notes.end();) {
int low, high;
low = high = it->note;
// Analyze the sentence and find the end of it
while (++itnext != notes.end() && !itnext->lineBreak) {
+ if (itnext->type == Note::SLEEP) continue;
int n = itnext->note;
if (itnext->type == Note::FREESTYLE) n += shiftFS;
low = std::min(low, n);
high = std::max(high, n);
}
// Per-sentence shift
- int shift = nearestOctave(high - low, limHigh - limLow);
+ int shift = nearestOctave(0.5 * (low + high), 0.5 * (limLow + limHigh));
// Shift the notes into position
- while (it != itnext) {
+ for (; it != itnext; ++it) {
+ if (it->type == Note::SLEEP) continue;
int s = shift;
if (it->type == Note::FREESTYLE) s += shiftFS;
// The last resort if everything else fails
@@ -115,7 +119,6 @@ namespace {
while (it->note + s > limHigh) s -= 12;
it->note += s;
it->notePrev += s;
- ++it;
}
}
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 15:33:13
|
Module: editor
Branch: master
Commit: 33f3c9aee74485cd92398a8650fc7ba7044dca7c
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 17:24:59 2011 +0200
Remember previously used path in open/save dialogs.
---
editorapp.cc | 30 +++++++++++++++++++-----------
editorapp.hh | 1 +
2 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 9e6bf1b..37fec8f 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -24,7 +24,7 @@ namespace {
static const QDataStream::Version PROJECT_SAVE_FILE_STREAM_VERSION = QDataStream::Qt_4_7;
}
-EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName(), hasUnsavedChanges()
+EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName(), hasUnsavedChanges(), latestPath(QDir::homePath())
{
ui.setupUi(this);
readSettings();
@@ -198,7 +198,7 @@ void EditorApp::on_actionOpen_triggered()
if (!promptSaving()) return;
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
- QDir::homePath(),
+ latestPath,
tr("All supported formats") + "(*." + PROJECT_SAVE_FILE_EXTENSION + " *.xml *.mid *.ini *.txt);;" +
tr("Project files") +" (*." + PROJECT_SAVE_FILE_EXTENSION + ") ;;" +
tr("SingStar XML") + " (*.xml);;" +
@@ -208,6 +208,7 @@ void EditorApp::on_actionOpen_triggered()
if (!fileName.isNull()) {
QFileInfo finfo(fileName);
+ latestPath = finfo.path();
try {
if (finfo.suffix() == PROJECT_SAVE_FILE_EXTENSION) {
@@ -264,12 +265,13 @@ void EditorApp::on_actionSave_triggered()
void EditorApp::on_actionSaveAs_triggered()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Save Project"),
- QDir::homePath(),
+ latestPath,
tr("Project files ") + "(*." + PROJECT_SAVE_FILE_EXTENSION + ");;" +
tr("All files") + " (*)");
if (!fileName.isNull()) {
// Add the correct suffix if it is missing
QFileInfo finfo(fileName);
+ latestPath = finfo.path();
if (finfo.suffix() != PROJECT_SAVE_FILE_EXTENSION)
fileName += "." + PROJECT_SAVE_FILE_EXTENSION;
saveProject(fileName);
@@ -313,8 +315,9 @@ void EditorApp::saveProject(QString fileName)
void EditorApp::exportSong(QString format, QString dialogTitle)
{
- QString path = QFileDialog::getExistingDirectory(this, dialogTitle, QDir::homePath());
+ QString path = QFileDialog::getExistingDirectory(this, dialogTitle, latestPath);
if (!path.isNull()) {
+ latestPath = path;
// Sync notes
if (noteGraph) song->insertVocalTrack(TrackName::LEAD_VOCAL, noteGraph->getVocalTrack());
// Pick exporter
@@ -336,9 +339,10 @@ void EditorApp::on_actionFoFMIDI_triggered() { exportSong("INI", tr("Export Fret
void EditorApp::on_actionLyricsToFile_triggered()
{
- QString fileName = QFileDialog::getSaveFileName(this, tr("Export to plain text lyrics"), QDir::homePath());
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Export to plain text lyrics"), latestPath);
if (!fileName.isNull()) {
QFile f(fileName);
+ QFileInfo finfo(f); latestPath = finfo.path();
if (f.open(QFile::WriteOnly | QFile::Truncate)) {
QTextStream out(&f);
out << noteGraph->dumpLyrics();
@@ -416,10 +420,11 @@ void EditorApp::on_actionAntiAliasing_toggled(bool checked)
void EditorApp::on_actionMusicFile_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
- QDesktopServices::storageLocation(QDesktopServices::MusicLocation),
+ latestPath,
tr("Music files") + " (*.mp3 *.ogg *.wav *.wma *.flac)");
if (!fileName.isNull()) {
+ QFileInfo finfo(fileName); latestPath = finfo.path();
ui.valMusicFile->setText(fileName);
// Metadata is updated when it becomes available (signal)
player->setCurrentSource(Phonon::MediaSource(QUrl::fromLocalFile(fileName)));
@@ -432,16 +437,17 @@ void EditorApp::on_actionMusicFile_triggered()
void EditorApp::on_actionLyricsFromFile_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
- QDir::homePath(),
+ latestPath,
tr("Text files (*.txt)"));
if (!fileName.isNull()) {
QFile file(fileName);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
- return;
+ QFileInfo finfo(file); latestPath = finfo.path();
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return;
- QString text = TextCodecSelector::readAllAndHandleEncoding(file, this);
- if (text != "") noteGraph->setLyrics(text);
+ QString text = TextCodecSelector::readAllAndHandleEncoding(file, this);
+ if (text != "") noteGraph->setLyrics(text);
}
}
@@ -617,6 +623,7 @@ void EditorApp::readSettings()
QSize size = settings.value("size", QSize(800, 600)).toSize();
bool maximized = settings.value("maximized", false).toBool();
bool aa = settings.value("anti-aliasing", true).toBool();
+ latestPath = settings.value("latestpath", QDir::homePath()).toString();
// Apply them
if (!pos.isNull()) move(pos);
resize(size);
@@ -631,6 +638,7 @@ void EditorApp::writeSettings()
settings.setValue("size", size());
settings.setValue("maximized", isMaximized());
settings.setValue("anti-aliasing", ui.actionAntiAliasing->isChecked());
+ settings.setValue("latestpath", latestPath);
}
diff --git a/editorapp.hh b/editorapp.hh
index 3a8b561..9db3da7 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -106,4 +106,5 @@ private:
QProgressBar *statusbarProgress;
QString projectFileName;
bool hasUnsavedChanges;
+ QString latestPath;
};
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-31 15:08:04
|
Module: editor
Branch: master
Commit: 3d1cdb74d7cd1ad0fb2d7590447310e1b8e89fe1
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Jan 31 16:07:51 2011 +0100
The ultimate über normalization
---
songparser.cc | 56 +++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/songparser.cc b/songparser.cc
index ae4d9cc..f9eec78 100644
--- a/songparser.cc
+++ b/songparser.cc
@@ -82,6 +82,43 @@ namespace {
int nearestOctave(int note, int target) {
return (1006 + target - note) / 12 * 12 - 1006; // 1006 for mathematical rounding (always positive, round up from 6)
}
+ void normalize(Notes& notes, int limLow, int limHigh) {
+ // Find the correction required for freestyle notes (over the entire song)
+ int shiftFS = 0;
+ {
+ std::vector<int> fsNotes, regNotes;
+ for (Notes::iterator it = notes.begin(); it != notes.end(); ++it) {
+ (it->type == Note::FREESTYLE ? fsNotes : regNotes).push_back(it->note);
+ }
+ std::sort(regNotes.begin(), regNotes.end());
+ std::sort(fsNotes.begin(), fsNotes.end());
+ if (!regNotes.empty() && !fsNotes.empty()) shiftFS = nearestOctave(fsNotes[fsNotes.size() / 2], regNotes[regNotes.size() / 2]);
+ }
+ for (Notes::iterator it = notes.begin(), itnext = it; it != notes.end();) {
+ int low, high;
+ low = high = it->note;
+ // Analyze the sentence and find the end of it
+ while (++itnext != notes.end() && !itnext->lineBreak) {
+ int n = itnext->note;
+ if (itnext->type == Note::FREESTYLE) n += shiftFS;
+ low = std::min(low, n);
+ high = std::max(high, n);
+ }
+ // Per-sentence shift
+ int shift = nearestOctave(high - low, limHigh - limLow);
+ // Shift the notes into position
+ while (it != itnext) {
+ int s = shift;
+ if (it->type == Note::FREESTYLE) s += shiftFS;
+ // The last resort if everything else fails
+ while (it->note + s < limLow) s += 12;
+ while (it->note + s > limHigh) s -= 12;
+ it->note += s;
+ it->notePrev += s;
+ ++it;
+ }
+ }
+ }
}
void SongParser::finalize() {
@@ -100,23 +137,8 @@ void SongParser::finalize() {
else sentenceStart = false;
}
// Note normalization
- const int limLow = 0, limHigh = 48;
- if (vocal.noteMin <= limLow || vocal.noteMax >= limHigh) {
- std::vector<int> fsNotes, regNotes;
- for (Notes::iterator it = vocal.notes.begin(); it != vocal.notes.end(); ++it) {
- (it->type == Note::FREESTYLE ? fsNotes : regNotes).push_back(it->note);
- }
- std::sort(regNotes.begin(), regNotes.end());
- std::sort(fsNotes.begin(), fsNotes.end());
- // Center the entire song to the middle of the permitted range
- int shift = regNotes.empty() ? 0 : nearestOctave(regNotes[regNotes.size() / 2], 24);
- int shiftFS = fsNotes.empty() ? 0 : nearestOctave(fsNotes[fsNotes.size() / 2], 24);
- for (Notes::iterator it = vocal.notes.begin(); it != vocal.notes.end(); ++it) {
- int s = (it->type == Note::FREESTYLE ? shiftFS : shift);
- it->note += s;
- it->notePrev += s;
- }
- }
+ const int limLow = 1, limHigh = 47;
+ if (vocal.noteMin < limLow || vocal.noteMax > limHigh) normalize(vocal.notes, limLow, limHigh);
}
if (m_tsPerBeat) {
// Add song beat markers
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-31 15:08:02
|
Module: editor
Branch: master
Commit: 3453a023e5510c0b02000fa92b55dd443cd421a7
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Jan 31 16:07:13 2011 +0100
Fix function return type
---
notelabel.hh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/notelabel.hh b/notelabel.hh
index 62aed85..ff68456 100644
--- a/notelabel.hh
+++ b/notelabel.hh
@@ -31,7 +31,7 @@ public:
bool isFloating() const { return m_floating; }
void setFloating(bool state) { m_floating = state; createPixmap(size()); }
bool isLineBreak() const { return m_note.lineBreak; }
- bool setLineBreak(bool state) { m_note.lineBreak = state; createPixmap(size()); }
+ void setLineBreak(bool state) { m_note.lineBreak = state; createPixmap(size()); }
void setType(int newtype) { m_note.type = Note::types[newtype]; createPixmap(size()); }
void startResizing(int dir);
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 14:58:34
|
Module: editor
Branch: master
Commit: 97120403609aa93d88cc31aa16c94c76af85b330
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 16:50:18 2011 +0200
Limit displayed digits of notes' time codes.
---
editorapp.cc | 6 +++---
notelabel.cc | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 36a34ea..9e6bf1b 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -144,9 +144,9 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
{
if (note) {
MusicalScale ms;
- ui.valNoteBegin->setText(QString::number(note->note().begin) + tr(" s"));
- ui.valNoteEnd->setText(QString::number(note->note().end) + tr(" s"));
- ui.valNoteDuration->setText(QString::number(note->note().length()) + tr(" s"));
+ ui.valNoteBegin->setText(QString::number(note->note().begin, 'f', 2) + tr(" s"));
+ ui.valNoteEnd->setText(QString::number(note->note().end, 'f', 2) + tr(" s"));
+ ui.valNoteDuration->setText(QString::number(note->note().length(), 'f', 2) + tr(" s"));
ui.valNote->setText(ms.getNoteStr(ms.getNoteFreq(note->note().note))
+ " (" + QString::number(note->note().note) + ")");
ui.cmbNoteType->setEnabled(true);
diff --git a/notelabel.cc b/notelabel.cc
index bcfc307..160523b 100644
--- a/notelabel.cc
+++ b/notelabel.cc
@@ -161,8 +161,8 @@ void NoteLabel::updateNote()
.arg(lyric())
.arg(m_note.typeString())
.arg(ms.getNoteStr(ms.getNoteFreq(m_note.note)))
- .arg(QString::number(m_note.begin))
- .arg(QString::number(m_note.end))
+ .arg(QString::number(m_note.begin, 'f', 3))
+ .arg(QString::number(m_note.end, 'f', 3))
);
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 14:48:30
|
Module: editor
Branch: master
Commit: 9a2c7340c8bac13c29bfaf66049624bfdeaf941d
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 16:40:45 2011 +0200
Fix wrong time codes when exporting low bpm songs to XML.
---
songwriter-xml.cc | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/songwriter-xml.cc b/songwriter-xml.cc
index dd77a46..182bd20 100644
--- a/songwriter-xml.cc
+++ b/songwriter-xml.cc
@@ -110,9 +110,9 @@ void SingStarXMLWriter::writeXML() {
}
int SingStarXMLWriter::sec2dur(double sec) {
- return round(tempo / 60.0 * sec * 8); // 8 for Demisemiquaver
+ return round(tempo / 60.0 * sec * (res == "Demisemiquaver" ? 8 : 4));
}
double SingStarXMLWriter::dur2sec(int ts) {
- return ts * 60.0 / (tempo * 8); // 8 for Demisemiquaver
+ return ts * 60.0 / (tempo * (res == "Demisemiquaver" ? 8 : 4));
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 14:38:06
|
Module: editor
Branch: master
Commit: 7bd441d5bfb48ee4415ef14e4705f40de2de7039
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 16:29:37 2011 +0200
Refactor song exporting.
---
editorapp.cc | 41 ++++++++++++++---------------------------
editorapp.hh | 1 +
2 files changed, 15 insertions(+), 27 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 12d189d..36a34ea 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -311,41 +311,28 @@ void EditorApp::saveProject(QString fileName)
updateMenuStates();
}
-void EditorApp::on_actionSingStarXML_triggered()
+void EditorApp::exportSong(QString format, QString dialogTitle)
{
- QString path = QFileDialog::getExistingDirectory(this, tr("Export SingStar XML"), QDir::homePath());
+ QString path = QFileDialog::getExistingDirectory(this, dialogTitle, QDir::homePath());
if (!path.isNull()) {
- song->insertVocalTrack(TrackName::LEAD_VOCAL, noteGraph->getVocalTrack());
- try { SingStarXMLWriter(*song.data(), path); }
- catch (const std::exception& e) {
+ // Sync notes
+ if (noteGraph) song->insertVocalTrack(TrackName::LEAD_VOCAL, noteGraph->getVocalTrack());
+ // Pick exporter
+ try {
+ if (format == "XML") SingStarXMLWriter(*song.data(), path);
+ else if (format == "TXT") UltraStarTXTWriter(*song.data(), path);
+ else if (format == "INI") FoFMIDIWriter(*song.data(), path);
+ } catch (const std::exception& e) {
QMessageBox::critical(this, tr("Error exporting song!"), e.what());
}
}
}
-void EditorApp::on_actionUltraStarTXT_triggered()
-{
- QString path = QFileDialog::getExistingDirectory(this, tr("Export UltraStar TXT"), QDir::homePath());
- if (!path.isNull()) {
- song->insertVocalTrack(TrackName::LEAD_VOCAL, noteGraph->getVocalTrack());
- try { UltraStarTXTWriter(*song.data(), path); }
- catch (const std::exception& e) {
- QMessageBox::critical(this, tr("Error exporting song!"), e.what());
- }
- }
-}
+void EditorApp::on_actionSingStarXML_triggered() { exportSong("XML", tr("Export SingStar XML")); }
-void EditorApp::on_actionFoFMIDI_triggered()
-{
- QString path = QFileDialog::getExistingDirectory(this, tr("Export FoF MIDI"), QDir::homePath());
- if (!path.isNull()) {
- song->insertVocalTrack(TrackName::LEAD_VOCAL, noteGraph->getVocalTrack());
- try { FoFMIDIWriter(*song.data(), path); }
- catch (const std::exception& e) {
- QMessageBox::critical(this, tr("Error exporting song!"), e.what());
- }
- }
-}
+void EditorApp::on_actionUltraStarTXT_triggered() { exportSong("TXT", tr("Export UltraStar TXT")); }
+
+void EditorApp::on_actionFoFMIDI_triggered() { exportSong("INI", tr("Export Frets on Fire MIDI")); }
void EditorApp::on_actionLyricsToFile_triggered()
{
diff --git a/editorapp.hh b/editorapp.hh
index 81934b9..3a8b561 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -37,6 +37,7 @@ public:
private:
bool promptSaving();
void saveProject(QString fileName);
+ void exportSong(QString format, QString dialogTitle);
void doOpStack();
void playButton();
void readSettings();
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 14:38:03
|
Module: editor
Branch: master
Commit: 0b4e91eac4d910acca57b84dcf8785e49d7fb302
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 16:16:10 2011 +0200
Fix line break check box text.
---
editor.ui | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/editor.ui b/editor.ui
index 08f831e..da46a5a 100644
--- a/editor.ui
+++ b/editor.ui
@@ -179,7 +179,7 @@
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
- <string>Line break after this</string>
+ <string>Sentence beginning</string>
</property>
</widget>
</item>
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 14:38:00
|
Module: editor
Branch: master
Commit: bbb8af2a5233ad239624b8aa051ea48e64257338
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 16:14:50 2011 +0200
Now edited notes can be exported.
---
editorapp.cc | 3 +++
notegraphwidget.cc | 17 +++++++++++++++++
notegraphwidget.hh | 1 +
3 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 585c1a0..12d189d 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -315,6 +315,7 @@ void EditorApp::on_actionSingStarXML_triggered()
{
QString path = QFileDialog::getExistingDirectory(this, tr("Export SingStar XML"), QDir::homePath());
if (!path.isNull()) {
+ song->insertVocalTrack(TrackName::LEAD_VOCAL, noteGraph->getVocalTrack());
try { SingStarXMLWriter(*song.data(), path); }
catch (const std::exception& e) {
QMessageBox::critical(this, tr("Error exporting song!"), e.what());
@@ -326,6 +327,7 @@ void EditorApp::on_actionUltraStarTXT_triggered()
{
QString path = QFileDialog::getExistingDirectory(this, tr("Export UltraStar TXT"), QDir::homePath());
if (!path.isNull()) {
+ song->insertVocalTrack(TrackName::LEAD_VOCAL, noteGraph->getVocalTrack());
try { UltraStarTXTWriter(*song.data(), path); }
catch (const std::exception& e) {
QMessageBox::critical(this, tr("Error exporting song!"), e.what());
@@ -337,6 +339,7 @@ void EditorApp::on_actionFoFMIDI_triggered()
{
QString path = QFileDialog::getExistingDirectory(this, tr("Export FoF MIDI"), QDir::homePath());
if (!path.isNull()) {
+ song->insertVocalTrack(TrackName::LEAD_VOCAL, noteGraph->getVocalTrack());
try { FoFMIDIWriter(*song.data(), path); }
catch (const std::exception& e) {
QMessageBox::critical(this, tr("Error exporting song!"), e.what());
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 172274b..bd551e7 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -10,6 +10,7 @@
#include <cmath>
#include "notelabel.hh"
#include "notegraphwidget.hh"
+#include "song.hh"
#include "util.hh"
@@ -595,6 +596,22 @@ int NoteGraphWidget::n2px(int note) const { return PitchVis::note2px(note) - m_n
int NoteGraphWidget::px2n(int px) const { return PitchVis::px2note(px + m_noteHalfHeight); }
+VocalTrack NoteGraphWidget::getVocalTrack() const
+{
+ VocalTrack track(TrackName::LEAD_VOCAL);
+ Notes& notes = track.notes;
+ if (!m_notes.isEmpty()) {
+ for (int i = 0; i < m_notes.size(); ++i) {
+ notes.push_back(m_notes[i]->note());
+ track.noteMin = std::min(notes.back().note, track.noteMin);
+ track.noteMax = std::max(notes.back().note, track.noteMin);
+ }
+ track.beginTime = notes.front().begin;
+ track.endTime = notes.back().end;
+ }
+ return track;
+}
+
QString NoteGraphWidget::dumpLyrics() const
{
QString lyrics;
diff --git a/notegraphwidget.hh b/notegraphwidget.hh
index eedaf14..7ef5ba5 100644
--- a/notegraphwidget.hh
+++ b/notegraphwidget.hh
@@ -61,6 +61,7 @@ public:
int px2n(int px) const;
int h() const { return m_pitch->height; }
+ VocalTrack getVocalTrack() const;
QString dumpLyrics() const;
public slots:
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 14:03:38
|
Module: editor
Branch: master
Commit: c2bed5f4aa5b4f7ff331e7bb33fee4cf7826fa02
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 15:54:47 2011 +0200
Make XML export actually use lineBreak flags.
This doesn't actually improve anything for now, because as it turns
out, SongWriter doesn't use editor's notes, but imported unedited ones.
---
songwriter-xml.cc | 37 +++++++++++++++++++++----------------
1 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/songwriter-xml.cc b/songwriter-xml.cc
index 7a70cd3..dd77a46 100644
--- a/songwriter-xml.cc
+++ b/songwriter-xml.cc
@@ -51,39 +51,44 @@ void SingStarXMLWriter::writeXML() {
firstNoteElem.setAttribute("Duration", QString::number(ts));
firstNoteElem.setAttribute("Lyric", "");
sentenceElem.appendChild(firstNoteElem);
+ bool firstNote = true;
// Iterate all notes
for (unsigned int i = 0; i < notes.size(); ++i) {
Note const& n = notes[i];
+ if (n.type == Note::SLEEP) continue; // Skip SLEEPs
- // SLEEP notes indicate sentence end
- if (n.type == Note::SLEEP) {
+ // New sentence
+ if (n.lineBreak && !firstNote) {
root.appendChild(sentenceElem);
++sentencenum;
sentenceElem = doc.createElement("SENTENCE");
sentenceComment = doc.createComment(QString("Track %1, Sentence %2").arg(tracknum).arg(sentencenum));
sentenceElem.appendChild(sentenceComment);
-
- } else { // Regular note handling
-
- // Construct the note element
- int l = sec2dur(n.length()); ts += l;
- QDomElement noteElem = doc.createElement("NOTE");
- noteElem.setAttribute("MidiNote", QString::number(n.note));
- noteElem.setAttribute("Duration", QString::number(l));
- noteElem.setAttribute("Lyric", n.syllable);
- if (n.type == Note::GOLDEN) noteElem.setAttribute("Bonus", "Yes");
- if (n.type == Note::FREESTYLE) noteElem.setAttribute("FreeStyle", "Yes");
- sentenceElem.appendChild(noteElem);
}
+ firstNote = false;
+
+ // Construct a regular note element
+ int l = sec2dur(n.length()); ts += l;
+ QDomElement noteElem = doc.createElement("NOTE");
+ noteElem.setAttribute("MidiNote", QString::number(n.note));
+ noteElem.setAttribute("Duration", QString::number(l));
+ noteElem.setAttribute("Lyric", n.syllable);
+ if (n.type == Note::GOLDEN) noteElem.setAttribute("Bonus", "Yes");
+ if (n.type == Note::FREESTYLE) noteElem.setAttribute("FreeStyle", "Yes");
+ sentenceElem.appendChild(noteElem);
// Construct a note element, indicationg the pause before next note
// This is only done if the pause has duration
// We also take the overall position into consideration (counter rounding errors)
int pauseLen = 0;
double end = dur2sec(ts);
- if (i < notes.size() - 1)
- pauseLen = sec2dur(notes[i+1].begin - end); // Difference to next note
+ for (int j = i + 1; j < notes.size(); ++j) { // Find the next non-SLEEP note
+ if (notes[j].type != Note::SLEEP) {
+ pauseLen = sec2dur(notes[j].begin - end); // Difference to next note
+ break;
+ }
+ }
if (pauseLen > 0) {
QDomElement pauseElem = doc.createElement("NOTE");
pauseElem.setAttribute("MidiNote", "0");
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 13:31:24
|
Module: editor
Branch: master
Commit: 29d26b8c9a2a3466bb1a381fd6a92f645e6f73fd
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 15:24:22 2011 +0200
Plain text lyrics import now also has line breaks in the new style.
---
notegraphwidget.cc | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 0211b47..172274b 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -75,21 +75,23 @@ void NoteGraphWidget::setLyrics(QString lyrics)
QTextStream ts(&lyrics, QIODevice::ReadOnly);
clearNotes();
- bool first = true;
+ bool firstNote = true;
while (!ts.atEnd()) {
// We want to loop one line at the time to insert line breaks
+ bool sentenceStart = true;
QString sentence = ts.readLine();
QTextStream ts2(&sentence, QIODevice::ReadOnly);
while (!ts2.atEnd()) {
QString word;
ts2 >> word;
if (!word.isEmpty()) {
- m_notes.push_back(new NoteLabel(Note(word), this, QPoint(0, n2px(24)), QSize(), !first));
+ m_notes.push_back(new NoteLabel(Note(word), this, QPoint(0, n2px(24)), QSize(), !firstNote));
doOperation(opFromNote(*m_notes.back(), m_notes.size()-1), Operation::NO_EXEC);
- first = false;
+ if (sentenceStart) setLineBreak(m_notes.back(), true);
+ firstNote = false;
+ sentenceStart = false;
}
}
- if (!m_notes.isEmpty()) setLineBreak(m_notes.back(), true);
}
finalizeNewLyrics();
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 13:17:01
|
Module: editor
Branch: master
Commit: 9414295e5d21dc530690d9718019d9124891d1bf
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 15:09:31 2011 +0200
SongParser now puts line break flags to sentences' first notes.
Also visualization is now on the left side.
---
notelabel.cc | 2 +-
songparser-txt.cc | 1 -
songparser-xml.cc | 3 +--
songparser.cc | 7 +++++++
4 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/notelabel.cc b/notelabel.cc
index f8254da..bcfc307 100644
--- a/notelabel.cc
+++ b/notelabel.cc
@@ -77,7 +77,7 @@ void NoteLabel::createPixmap(QSize size)
// Render sentence end indicator
if (m_note.lineBreak) {
painter.setPen(QPen(QBrush(QColor(255, 0, 0)), 4));
- painter.drawLine(image.width()-2, 0, image.width()-2, image.height()-1);
+ painter.drawLine(2, 0, 2, image.height()-1);
}
painter.end();
diff --git a/songparser-txt.cc b/songparser-txt.cc
index 6f9a625..381724a 100644
--- a/songparser-txt.cc
+++ b/songparser-txt.cc
@@ -146,7 +146,6 @@ bool SongParser::txtParseNote(QString line, VocalTrack &vocal) {
if (n.type == Note::SLEEP) {
if (notes.empty()) return true; // Ignore sleeps at song beginning
n.begin = n.end = prevtime; // Normalize sleep notes
- notes.back().lineBreak = true; // lineBreak flag for notes preceding SLEEPs
}
notes.push_back(n);
return true;
diff --git a/songparser-xml.cc b/songparser-xml.cc
index 78a6016..2099271 100644
--- a/songparser-xml.cc
+++ b/songparser-xml.cc
@@ -95,8 +95,7 @@ void SongParser::xmlParse()
noteElem = noteElem.nextSiblingElement();
}
- // Now add sentence end indicators
- if (!notes.empty()) notes.back().lineBreak = true;
+ // Now add sentence end indicator
Note n;
n.type = Note::SLEEP;
n.note = 0;
diff --git a/songparser.cc b/songparser.cc
index 40a59dd..ae4d9cc 100644
--- a/songparser.cc
+++ b/songparser.cc
@@ -92,6 +92,13 @@ void SongParser::finalize() {
if (vocal.notes.empty()) continue;
// Set begin/end times
vocal.beginTime = vocal.notes.front().begin, vocal.endTime = vocal.notes.back().end;
+ // Setup sentence start indicators
+ bool sentenceStart = true;
+ for (Notes::iterator it = vocal.notes.begin(); it != vocal.notes.end(); ++it) {
+ it->lineBreak = sentenceStart;
+ if (it->type == Note::SLEEP) sentenceStart = true;
+ else sentenceStart = false;
+ }
// Note normalization
const int limLow = 0, limHigh = 48;
if (vocal.noteMin <= limLow || vocal.noteMax >= limHigh) {
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-31 12:50:25
|
Module: editor
Branch: master
Commit: 9a6da37c961fcc641bdc42f9f184483ce73dc6cb
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Jan 31 13:49:54 2011 +0100
Fix segfaults
---
songparser.cc | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/songparser.cc b/songparser.cc
index cd3ecae..40a59dd 100644
--- a/songparser.cc
+++ b/songparser.cc
@@ -102,7 +102,7 @@ void SongParser::finalize() {
std::sort(regNotes.begin(), regNotes.end());
std::sort(fsNotes.begin(), fsNotes.end());
// Center the entire song to the middle of the permitted range
- int shift = regNotes.empty() ? 0 : nearestOctave(fsNotes[fsNotes.size() / 2], 24);
+ int shift = regNotes.empty() ? 0 : nearestOctave(regNotes[regNotes.size() / 2], 24);
int shiftFS = fsNotes.empty() ? 0 : nearestOctave(fsNotes[fsNotes.size() / 2], 24);
for (Notes::iterator it = vocal.notes.begin(); it != vocal.notes.end(); ++it) {
int s = (it->type == Note::FREESTYLE ? shiftFS : shift);
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 12:42:40
|
Module: editor
Branch: master
Commit: 94deeb95e726590caa8451d02b7769dc202e6c54
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 14:35:23 2011 +0200
Fix import of SS XML files with floating point tempo.
---
songparser-xml.cc | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/songparser-xml.cc b/songparser-xml.cc
index e22d815..78a6016 100644
--- a/songparser-xml.cc
+++ b/songparser-xml.cc
@@ -29,7 +29,7 @@ void SongParser::xmlParse()
// Parse meta
QDomElement root = doc.documentElement();
- m_song.bpm = root.attribute("Tempo").toInt();
+ m_song.bpm = root.attribute("Tempo").toDouble();
if (m_song.bpm == 0)
throw std::runtime_error(QT_TR_NOOP("Invalid tempo"));
if (root.attribute("Resolution") == QString("Demisemiquaver"))
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-31 12:30:31
|
Module: editor
Branch: master
Commit: 38640ecdf1691ed132f35ee9e900935bd7ce99f0
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Jan 31 13:30:15 2011 +0100
Separate normalization for regular and freestyle notes, use medians instead of avg of Min/Max.
---
songparser.cc | 36 +++++++++++++++++++++++++-----------
1 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/songparser.cc b/songparser.cc
index ffe6182..cd3ecae 100644
--- a/songparser.cc
+++ b/songparser.cc
@@ -2,6 +2,7 @@
#include "textcodecselector.hh"
#include <QFile>
#include <QFileInfo>
+#include <algorithm>
namespace SongParserUtil {
@@ -76,26 +77,39 @@ bool SongParser::getline(QString &line)
return !m_stream.atEnd();
}
+namespace {
+ /// Return the amount of shift (in notes) required for note to make put it in the nearest octave of the target note
+ int nearestOctave(int note, int target) {
+ return (1006 + target - note) / 12 * 12 - 1006; // 1006 for mathematical rounding (always positive, round up from 6)
+ }
+}
+
void SongParser::finalize() {
std::vector<QString> tracks = m_song.getVocalTrackNames();
for(std::vector<QString>::const_iterator it = tracks.begin() ; it != tracks.end() ; ++it) {
- // Note normalization
VocalTrack& vocal = m_song.getVocalTrack(*it);
+ vocal.m_scoreFactor = 1.0 / m_maxScore;
+ if (vocal.notes.empty()) continue;
+ // Set begin/end times
+ vocal.beginTime = vocal.notes.front().begin, vocal.endTime = vocal.notes.back().end;
+ // Note normalization
const int limLow = 0, limHigh = 48;
if (vocal.noteMin <= limLow || vocal.noteMax >= limHigh) {
- // Phase 1: Center the entire song to the middle of the permitted range
- int midnote = (vocal.noteMin + vocal.noteMax) / 2;
- unsigned int shift = (1006 + 24 - midnote) / 12 * 12 - 1006; // 1006 for mathematical rounding (always positive, round up from 6)
- vocal.noteMin += shift;
- vocal.noteMax += shift;
+ std::vector<int> fsNotes, regNotes;
+ for (Notes::iterator it = vocal.notes.begin(); it != vocal.notes.end(); ++it) {
+ (it->type == Note::FREESTYLE ? fsNotes : regNotes).push_back(it->note);
+ }
+ std::sort(regNotes.begin(), regNotes.end());
+ std::sort(fsNotes.begin(), fsNotes.end());
+ // Center the entire song to the middle of the permitted range
+ int shift = regNotes.empty() ? 0 : nearestOctave(fsNotes[fsNotes.size() / 2], 24);
+ int shiftFS = fsNotes.empty() ? 0 : nearestOctave(fsNotes[fsNotes.size() / 2], 24);
for (Notes::iterator it = vocal.notes.begin(); it != vocal.notes.end(); ++it) {
- it->note += shift;
- it->notePrev += shift;
+ int s = (it->type == Note::FREESTYLE ? shiftFS : shift);
+ it->note += s;
+ it->notePrev += s;
}
}
- // 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;
}
if (m_tsPerBeat) {
// Add song beat markers
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-31 10:31:51
|
Module: editor
Branch: master
Commit: 079e604f770c1ccc257df8be8a148b94de196d2a
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Jan 31 11:30:19 2011 +0100
Show shorter fragments
---
pitchvis.cc | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/pitchvis.cc b/pitchvis.cc
index 7ef7d60..9a324f6 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -58,7 +58,7 @@ void PitchVis::run()
// Copy the linked list into vector for easier access and calculate max level
std::vector<Tone const*> tones;
for (Tone const* n = &*it2; n; n = n->next) { tones.push_back(n); }
- if (tones.size() < 5) continue; // Too short or weak tone, ignored
+ if (tones.size() < 3) continue; // Too short tone, ignored
PitchPath path;
Analyzer::Moments::const_iterator momit = it;
// Render
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 10:05:56
|
Module: editor
Branch: master
Commit: 9f6a3882acfe0cfd25ba7593447c4666722ec6f2
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 12:00:21 2011 +0200
SingStar XML import/export: Perfect timing sync round-trip.
---
songwriter-xml.cc | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/songwriter-xml.cc b/songwriter-xml.cc
index 3fd2d6d..7a70cd3 100644
--- a/songwriter-xml.cc
+++ b/songwriter-xml.cc
@@ -81,7 +81,7 @@ void SingStarXMLWriter::writeXML() {
// This is only done if the pause has duration
// We also take the overall position into consideration (counter rounding errors)
int pauseLen = 0;
- double end = dur2sec(ts) + n.length();
+ double end = dur2sec(ts);
if (i < notes.size() - 1)
pauseLen = sec2dur(notes[i+1].begin - end); // Difference to next note
if (pauseLen > 0) {
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 09:37:23
|
Module: editor
Branch: master
Commit: 01c3c445fe511d92d1be911e0cb7f87ff6a56074
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 11:32:11 2011 +0200
Make the use of anti-aliasing configurable.
---
editor.ui | 29 +++++++++++++++++++----------
editorapp.cc | 37 ++++++++++++++++++++++++++++++++++++-
editorapp.hh | 7 ++++---
pitchvis.cc | 5 ++++-
4 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/editor.ui b/editor.ui
index 540d3ad..08f831e 100644
--- a/editor.ui
+++ b/editor.ui
@@ -462,7 +462,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
- <height>21</height>
+ <height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@@ -494,10 +494,16 @@
<property name="title">
<string>&Edit</string>
</property>
+ <widget class="QMenu" name="menuPreferences">
+ <property name="title">
+ <string>&Preferences</string>
+ </property>
+ <addaction name="actionAntiAliasing"/>
+ </widget>
<addaction name="actionUndo"/>
<addaction name="actionRedo"/>
<addaction name="separator"/>
- <addaction name="actionPreferences"/>
+ <addaction name="menuPreferences"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
@@ -586,14 +592,6 @@
<string>Ctrl+Shift+Z</string>
</property>
</action>
- <action name="actionPreferences">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>&Preferences</string>
- </property>
- </action>
<action name="actionSingStarXML">
<property name="text">
<string>&SingStar XML...</string>
@@ -639,6 +637,17 @@
<string>&What's this?</string>
</property>
</action>
+ <action name="actionAntiAliasing">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&Anti-aliasing</string>
+ </property>
+ <property name="toolTip">
+ <string>Use anti-aliasing for the pitch visualization</string>
+ </property>
+ </action>
</widget>
<resources/>
<connections/>
diff --git a/editorapp.cc b/editorapp.cc
index 5e369ad..585c1a0 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -65,7 +65,7 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName(), h
ui.actionExit->setIcon(QIcon::fromTheme("application-exit", QIcon(":/icons/application-exit.png")));
ui.actionUndo->setIcon(QIcon::fromTheme("edit-undo", QIcon(":/icons/edit-undo.png")));
ui.actionRedo->setIcon(QIcon::fromTheme("edit-redo", QIcon(":/icons/edit-redo.png")));
- ui.actionPreferences->setIcon(QIcon::fromTheme("preferences-other", QIcon(":/icons/preferences-other.png")));
+ ui.menuPreferences->setIcon(QIcon::fromTheme("preferences-other", QIcon(":/icons/preferences-other.png")));
ui.actionMusicFile->setIcon(QIcon::fromTheme("insert-object", QIcon(":/icons/insert-object.png")));
ui.actionLyricsFromFile->setIcon(QIcon::fromTheme("insert-text", QIcon(":/icons/insert-text.png")));
ui.actionLyricsFromClipboard->setIcon(QIcon::fromTheme("insert-text", QIcon(":/icons/insert-text.png")));
@@ -179,6 +179,11 @@ void EditorApp::analyzeProgress(int value, int maximum)
}
}
+
+
+// File menu
+
+
void EditorApp::on_actionNew_triggered()
{
if (promptSaving()) {
@@ -362,6 +367,11 @@ void EditorApp::on_actionExit_triggered()
close();
}
+
+
+// Edit menu
+
+
void EditorApp::on_actionUndo_triggered()
{
if (opStack.isEmpty())
@@ -401,6 +411,18 @@ void EditorApp::on_actionRedo_triggered()
doOpStack();
}
+
+void EditorApp::on_actionAntiAliasing_toggled(bool checked)
+{
+ QSettings settings; // Default QSettings parameters given in main()
+ settings.setValue("anti-aliasing", checked);
+}
+
+
+
+// Insert menu
+
+
void EditorApp::on_actionMusicFile_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
@@ -451,6 +473,11 @@ void EditorApp::on_actionLyricsFromClipboard_triggered()
}
}
+
+
+// Help menu
+
+
void EditorApp::on_actionWhatsThis_triggered()
{
QWhatsThis::enterWhatsThisMode();
@@ -462,6 +489,11 @@ void EditorApp::on_actionAbout_triggered()
aboutDialog.exec();
}
+
+
+// Misc stuff
+
+
void EditorApp::updateSongMeta(bool readFromSongToUI)
{
if (!song) return;
@@ -594,10 +626,12 @@ void EditorApp::readSettings()
QPoint pos = settings.value("pos", QPoint()).toPoint();
QSize size = settings.value("size", QSize(800, 600)).toSize();
bool maximized = settings.value("maximized", false).toBool();
+ bool aa = settings.value("anti-aliasing", true).toBool();
// Apply them
if (!pos.isNull()) move(pos);
resize(size);
if (maximized) showMaximized();
+ ui.actionAntiAliasing->setChecked(aa);
}
void EditorApp::writeSettings()
@@ -606,6 +640,7 @@ void EditorApp::writeSettings()
settings.setValue("pos", pos());
settings.setValue("size", size());
settings.setValue("maximized", isMaximized());
+ settings.setValue("anti-aliasing", ui.actionAntiAliasing->isChecked());
}
diff --git a/editorapp.hh b/editorapp.hh
index 1f4bcd7..81934b9 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -71,6 +71,7 @@ public slots:
// Edit menu
void on_actionUndo_triggered();
void on_actionRedo_triggered();
+ void on_actionAntiAliasing_toggled(bool checked);
// Insert menu
void on_actionMusicFile_triggered();
@@ -86,9 +87,9 @@ public slots:
void on_txtArtist_editingFinished();
void on_txtGenre_editingFinished();
void on_txtYear_editingFinished();
- void on_cmbNoteType_currentIndexChanged(int);
- void on_chkFloating_stateChanged(int);
- void on_chkLineBreak_stateChanged(int);
+ void on_cmbNoteType_currentIndexChanged(int state);
+ void on_chkFloating_stateChanged(int state);
+ void on_chkLineBreak_stateChanged(int state);
protected:
void closeEvent(QCloseEvent *event);
diff --git a/pitchvis.cc b/pitchvis.cc
index 41c7c86..7ef7d60 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -8,6 +8,7 @@
#include <QPainter>
#include <QProgressDialog>
#include <QLabel>
+#include <QSettings>
PitchVis::PitchVis(QString const& filename, QWidget *parent)
: QWidget(parent), QThread(), mutex(), pixelsPerSecond(), fileName(filename), moreAvailable(), cancelled(), curX(), m_width()
@@ -82,10 +83,12 @@ void PitchVis::run()
}
void PitchVis::paint(QPaintDevice* widget, int x1, int x2) {
+ QSettings settings; // Default QSettings parameters given in main()
+ bool aa = settings.value("anti-aliasing", true).toBool();
QMutexLocker locker(&mutex);
QPainter painter;
painter.begin(widget);
- painter.setRenderHint(QPainter::Antialiasing);
+ if (aa) painter.setRenderHint(QPainter::Antialiasing);
QPen pen;
pen.setWidth(8);
pen.setCapStyle(Qt::RoundCap);
|
|
From: Tapio V. <aa...@us...> - 2011-01-31 08:54:10
|
Module: editor
Branch: master
Commit: 6c8acf1592ac6e8fa15e7b54154f7de0d8d6f172
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 31 10:48:38 2011 +0200
Draw only the visible portion of pitch visualization (initial version).
---
notegraphwidget.cc | 11 ++++++++++-
pitchvis.cc | 6 +++++-
pitchvis.hh | 2 +-
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index e897beb..0211b47 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -141,11 +141,20 @@ void NoteGraphWidget::timerEvent(QTimerEvent*)
QMutexLocker locker(&m_pitch->mutex);
emit analyzeProgress(m_pitch->getXValue(), width());
if (m_pitch->newDataAvailable()) update();
+ if (m_pitch->isFinished()) killTimer(m_analyzeTimer);
}
}
void NoteGraphWidget::paintEvent(QPaintEvent*) {
- if (m_pitch) m_pitch->paint(this);
+ QScrollArea *scrollArea = NULL;
+ int x1 = 0, x2 = 0;
+ if (parentWidget())
+ scrollArea = qobject_cast<QScrollArea*>(parentWidget()->parent());
+ if (scrollArea && scrollArea->horizontalScrollBar()) {
+ x1 = scrollArea->horizontalScrollBar()->value();
+ x2 = x1 + 2000; // FIXME: Need to figure out the real viewport width from somewhere
+ }
+ if (m_pitch) m_pitch->paint(this, x1, x2);
}
int NoteGraphWidget::getNoteLabelId(NoteLabel* note) const
diff --git a/pitchvis.cc b/pitchvis.cc
index 071daa5..41c7c86 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -81,7 +81,7 @@ void PitchVis::run()
curX = width();
}
-void PitchVis::paint(QPaintDevice* widget) {
+void PitchVis::paint(QPaintDevice* widget, int x1, int x2) {
QMutexLocker locker(&mutex);
QPainter painter;
painter.begin(widget);
@@ -92,6 +92,10 @@ void PitchVis::paint(QPaintDevice* widget) {
PitchVis::Paths const& paths = getPaths();
for (PitchVis::Paths::const_iterator it = paths.begin(), itend = paths.end(); it != itend; ++it) {
int oldx, oldy;
+ // Only render paths in view
+ if (time2px(it->back().time) < x1) continue;
+ else if (time2px(it->front().time) > x2) break;
+ // Iterate through the path points
for (PitchPath::const_iterator it2 = it->begin(), it2end = it->end(); it2 != it2end; ++it2) {
int x = time2px(it2->time);
int y = note2px(it2->note);
diff --git a/pitchvis.hh b/pitchvis.hh
index c317da6..ff24bfb 100644
--- a/pitchvis.hh
+++ b/pitchvis.hh
@@ -28,7 +28,7 @@ public:
void run(); // Thread runs here
void stop() { cancelled = true; }
- void paint(QPaintDevice* widget);
+ void paint(QPaintDevice* widget, int x1, int x2);
Paths const& getPaths() { moreAvailable = false; return paths; }
bool newDataAvailable() const { return moreAvailable; }
int getXValue() const { return curX; }
|
|
From: Yoda-JM <yo...@us...> - 2011-01-29 09:19:18
|
Module: editor
Branch: master
Commit: fe4a02ba05ce0305f004342f71257239638527d9
Author: Vincent Le Ligeour <yo...@us...>
Date: Sat Jan 29 10:15:23 2011 +0100
Added Lyrics tab
---
editor.ui | 32 +++++++++++++++++++++++++++++++-
editorapp.cc | 6 ++++++
editorapp.hh | 1 +
3 files changed, 38 insertions(+), 1 deletions(-)
diff --git a/editor.ui b/editor.ui
index 1dd2b95..540d3ad 100644
--- a/editor.ui
+++ b/editor.ui
@@ -418,6 +418,36 @@
</item>
</layout>
</widget>
+ <widget class="QWidget" name="tabLyrics">
+ <attribute name="title">
+ <string>Lyrics</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_7">
+ <item row="1" column="0">
+ <widget class="QPushButton" name="cmdRefreshLyrics">
+ <property name="text">
+ <string>Refresh</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QTextEdit" name="textEditLyrics">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
</layout>
@@ -432,7 +462,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
- <height>25</height>
+ <height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
diff --git a/editorapp.cc b/editorapp.cc
index b9b1b8b..5e369ad 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -513,6 +513,12 @@ void EditorApp::playButton()
}
}
+void EditorApp::on_cmdRefreshLyrics_clicked()
+{
+ QString text = noteGraph->dumpLyrics();
+ ui.textEditLyrics->setText(text);
+}
+
void EditorApp::on_cmdPlay_clicked()
{
if (player) {
diff --git a/editorapp.hh b/editorapp.hh
index a6baa25..1f4bcd7 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -54,6 +54,7 @@ public slots:
void on_cmdPlay_clicked();
void on_cmdStop_clicked();
+ void on_cmdRefreshLyrics_clicked();
// File menu
void on_actionNew_triggered();
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-28 13:39:41
|
Module: editor
Branch: master
Commit: 0cc803d4b0aa15cc58f53d76f3d4023e491844d2
Author: Lasse Karkkainen <tro...@tr...>
Date: Fri Jan 28 14:38:42 2011 +0100
Phase 1 of note normalization.
---
songparser.cc | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/songparser.cc b/songparser.cc
index 1fabe55..ffe6182 100644
--- a/songparser.cc
+++ b/songparser.cc
@@ -79,10 +79,13 @@ bool SongParser::getline(QString &line)
void SongParser::finalize() {
std::vector<QString> tracks = m_song.getVocalTrackNames();
for(std::vector<QString>::const_iterator it = tracks.begin() ; it != tracks.end() ; ++it) {
- // Adjust negative notes
+ // Note normalization
VocalTrack& vocal = m_song.getVocalTrack(*it);
- if (vocal.noteMin <= 0) {
- unsigned int shift = (1 - vocal.noteMin / 12) * 12;
+ const int limLow = 0, limHigh = 48;
+ if (vocal.noteMin <= limLow || vocal.noteMax >= limHigh) {
+ // Phase 1: Center the entire song to the middle of the permitted range
+ int midnote = (vocal.noteMin + vocal.noteMax) / 2;
+ unsigned int shift = (1006 + 24 - midnote) / 12 * 12 - 1006; // 1006 for mathematical rounding (always positive, round up from 6)
vocal.noteMin += shift;
vocal.noteMax += shift;
for (Notes::iterator it = vocal.notes.begin(); it != vocal.notes.end(); ++it) {
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-28 10:40:16
|
Module: performous Branch: opengl2 Commit: 8e0a5ea04ccebecb623d1cde7b95fbf4304ac12a Author: Lasse Karkkainen <tro...@tr...> Date: Fri Jan 28 11:40:04 2011 +0100 float4x4 to mat4 fixes GLSL compile error --- themes/default/shaders/core.frag | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/themes/default/shaders/core.frag b/themes/default/shaders/core.frag index bdf7016..f1bd943 100644 --- a/themes/default/shaders/core.frag +++ b/themes/default/shaders/core.frag @@ -1,6 +1,6 @@ #extension GL_ARB_texture_rectangle : enable -uniform float4x4 colorMatrix; +uniform mat4 colorMatrix; uniform int texMode; uniform sampler2D tex; uniform sampler2DRect texRect; |
|
From: Tapio V. <aa...@us...> - 2011-01-28 10:03:54
|
Module: editor
Branch: master
Commit: 913285a67b45ad0b76ea869fe452e9cd9502bd8d
Author: Tapio Vierros <tap...@gm...>
Date: Fri Jan 28 12:00:58 2011 +0200
Use "Rap" attribute if "Lyric" is empty in SingStar XML parser.
---
songparser-xml.cc | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/songparser-xml.cc b/songparser-xml.cc
index 14a3039..e22d815 100644
--- a/songparser-xml.cc
+++ b/songparser-xml.cc
@@ -63,9 +63,11 @@ void SongParser::xmlParse()
unsigned int ts = m_prevts;
// See if it is an actual note and not sleep
- if (noteElem.attribute("MidiNote") != "0" || !noteElem.attribute("Lyric").isEmpty()) {
+ QString lyric = noteElem.attribute("Lyric").isEmpty()
+ ? noteElem.attribute("Rap") : noteElem.attribute("Lyric");
+ if (noteElem.attribute("MidiNote") != "0" || !lyric.isEmpty()) {
// TODO: Prettify lyric? (as ss_extract)
- Note n(noteElem.attribute("Lyric"));
+ Note n(lyric);
if (noteElem.attribute("Bonus") == QString("Yes"))
n.type = Note::GOLDEN;
else if (noteElem.attribute("FreeStyle") == QString("Yes"))
|
|
From: Tapio V. <aa...@us...> - 2011-01-28 07:59:22
|
Module: editor
Branch: master
Commit: 7202bb05b4532808dd3ad2710d230b831f16965e
Author: Tapio Vierros <tap...@gm...>
Date: Fri Jan 28 09:58:26 2011 +0200
Remember bpm from importing and use it when exporting.
Something is still wrong. :(
---
song.cc | 1 +
song.hh | 1 +
songparser-txt.cc | 4 ++--
songparser-xml.cc | 8 ++++----
songparser.cc | 1 -
songparser.hh | 3 +--
songwriter-xml.cc | 6 +++++-
songwriter.hh | 3 ++-
8 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/song.cc b/song.cc
index 4850f79..4964e71 100644
--- a/song.cc
+++ b/song.cc
@@ -30,6 +30,7 @@ void Song::reload(bool errorIgnore) {
videoGap = 0.0;
start = 0.0;
preview_start = getNaN();
+ bpm = 0.0;
hasBRE = false;
b0rkedTracks = false;
if (!filename.isEmpty()) {
diff --git a/song.hh b/song.hh
index 941b580..fe5cbb7 100644
--- a/song.hh
+++ b/song.hh
@@ -125,6 +125,7 @@ class Song {
QString cover; ///< cd cover
QString background; ///< background image
QString video; ///< video
+ double bpm; ///< used for more accurate import --> export cycle
/// Variables used for comparisons (sorting)
QString collateByTitle;
QString collateByTitleOnly;
diff --git a/songparser-txt.cc b/songparser-txt.cc
index 1762b16..6f9a625 100644
--- a/songparser-txt.cc
+++ b/songparser-txt.cc
@@ -20,7 +20,7 @@ void SongParser::txtParse() {
while (getline(line) && txtParseField(line)) {}
if (m_song.title.isEmpty() || m_song.artist.isEmpty())
throw std::runtime_error("Required header fields missing");
- if (m_bpm != 0.0) addBPM(0, m_bpm);
+ if (m_song.bpm != 0.0) addBPM(0, m_song.bpm);
// Parse notes
VocalTrack vocal(TrackName::LEAD_VOCAL);
@@ -57,7 +57,7 @@ bool SongParser::txtParseField(QString const& line) {
else if (key == "PREVIEWSTART") m_song.preview_start = value.toDouble(&ok);
else if (key == "RELATIVE") assign(m_relative, value);
else if (key == "GAP") { m_gap = value.toDouble(&ok); m_gap *= 1e-3; }
- else if (key == "BPM") m_bpm = value.toDouble(&ok);
+ else if (key == "BPM") m_song.bpm = value.toDouble(&ok);
else if (key == "LANGUAGE") m_song.language= value;
else if (key == "YEAR") m_song.year = value;
diff --git a/songparser-xml.cc b/songparser-xml.cc
index ee266c4..14a3039 100644
--- a/songparser-xml.cc
+++ b/songparser-xml.cc
@@ -29,12 +29,12 @@ void SongParser::xmlParse()
// Parse meta
QDomElement root = doc.documentElement();
- m_bpm = root.attribute("Tempo").toInt();
- if (m_bpm == 0)
+ m_song.bpm = root.attribute("Tempo").toInt();
+ if (m_song.bpm == 0)
throw std::runtime_error(QT_TR_NOOP("Invalid tempo"));
if (root.attribute("Resolution") == QString("Demisemiquaver"))
- m_bpm *= 2;
- addBPM(0, m_bpm);
+ m_song.bpm *= 2;
+ addBPM(0, m_song.bpm);
m_song.genre = root.attribute("Genre");
m_song.year = root.attribute("Year");
diff --git a/songparser.cc b/songparser.cc
index 2a48c8e..1fabe55 100644
--- a/songparser.cc
+++ b/songparser.cc
@@ -20,7 +20,6 @@ SongParser::SongParser(Song& s):
m_linenum(),
m_relative(),
m_gap(),
- m_bpm(),
m_prevtime(),
m_prevts(),
m_relativeShift(),
diff --git a/songparser.hh b/songparser.hh
index 5ece020..46aa2e1 100644
--- a/songparser.hh
+++ b/songparser.hh
@@ -22,7 +22,6 @@ class SongParser {
bool getline(QString& line);
bool m_relative;
double m_gap;
- double m_bpm;
// UltraStar TXT
bool txtCheck(QString const& data);
@@ -48,7 +47,7 @@ class SongParser {
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) {}
+ BPM(double _begin, double _ts, double _bpm): begin(_begin), step(0.25 * 60.0 / _bpm), ts(_ts) {}
double begin; // Time in seconds
double step; // Seconds per quarter note
double ts;
diff --git a/songwriter-xml.cc b/songwriter-xml.cc
index 456963e..3fd2d6d 100644
--- a/songwriter-xml.cc
+++ b/songwriter-xml.cc
@@ -6,6 +6,10 @@
void SingStarXMLWriter::writeXML() {
+ if (tempo > 300) {
+ tempo /= 2;
+ res = "Demisemiquaver"; // Demisemiquaver = 2x tempo of Semiquaver
+ }
QDomDocument doc("");
QDomElement root = doc.createElement("MELODY");
root.setAttribute("xmlns", "http://www.singstargame.com");
@@ -13,7 +17,7 @@ void SingStarXMLWriter::writeXML() {
root.setAttribute("Version", "1");
root.setAttribute("Tempo", QString::number(tempo));
root.setAttribute("FixedTempo", "Yes");
- root.setAttribute("Resolution", "Demisemiquaver"); // Demisemiquaver = 2x tempo of Semiquaver
+ root.setAttribute("Resolution", res);
root.setAttribute("Genre", s.genre);
root.setAttribute("Year", s.year);
root.setAttribute("xsi:schemaLocation", "http://www.singstargame.com http://15GMS-SINGSQL/xml_schema/melody.xsd");
diff --git a/songwriter.hh b/songwriter.hh
index fe21997..62da8e2 100644
--- a/songwriter.hh
+++ b/songwriter.hh
@@ -13,12 +13,13 @@ struct SongWriter
struct SingStarXMLWriter: public SongWriter
{
SingStarXMLWriter(const Song& s_, const QString& path_)
- : SongWriter(s_, path_), tempo(160) { writeXML(); }
+ : SongWriter(s_, path_), tempo(s_.bpm > 0 ? s_.bpm : 180), res("Semiquaver") { writeXML(); }
private:
void writeXML();
int sec2dur(double sec);
double dur2sec(int ts);
int tempo;
+ QString res;
};
struct UltraStarTXTWriter: public SongWriter
|