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-01-18 11:02:58
|
Module: editor
Branch: master
Commit: a7ec0d5c2dc6884714f15a9258b44e54a814e998
Author: Tapio Vierros <tap...@gm...>
Date: Tue Jan 18 13:01:54 2011 +0200
Consider initial state 'saved' and fix save prompt.
---
editorapp.cc | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index de36fac..e018353 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -37,9 +37,7 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName(), h
moveop << (int)noteGraph->noteLabels().size()-1 << 600 - noteGraph->noteLabels().back()->width() << noteGraph->noteLabels().back()->y();
noteGraph->doOperation(moveop);
noteGraph->doOperation(Operation("BLOCK")); // Lock the undo stack
-
noteGraph->updateNotes();
-
updateNoteInfo(NULL);
song.reset(new Song);
@@ -59,6 +57,9 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName(), h
ui.actionLyricsFromFile->setIcon(QIcon::fromTheme("insert-text"));
ui.actionLyricsFromClipboard->setIcon(QIcon::fromTheme("insert-text"));
ui.actionAbout->setIcon(QIcon::fromTheme("help-about"));
+
+ hasUnsavedChanges = false;
+ updateMenuStates();
}
void EditorApp::operationDone(const Operation &op)
@@ -233,10 +234,11 @@ bool EditorApp::promptSaving()
on_actionSave_triggered();
case QMessageBox::No:
return true;
- default: break;
+ default:
+ return false;
}
}
- return false;
+ return true;
}
void EditorApp::saveProject(QString fileName)
|
|
From: Tapio V. <aa...@us...> - 2011-01-18 10:34:21
|
Module: editor
Branch: master
Commit: f1f38ff678e1904ad59b95c9a39fa4931934a9c3
Author: Tapio Vierros <tap...@gm...>
Date: Tue Jan 18 12:32:19 2011 +0200
Trim whitespace when loading US TXT lyrics.
---
notegraphwidget.cc | 2 +-
songparser-txt.cc | 1 +
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 882c813..5f0c8f2 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -102,7 +102,7 @@ void NoteGraphWidget::setLyrics(const VocalTrack &track)
int diff = track.noteMax - track.noteMin;
m_octaves = std::ceil(diff / 12.0f) + 1;
m_lowestNote = clamp(track.noteMin - 6, 0, 1000);
- std::cout << "--: " << m_octaves << " " << m_lowestNote << std::endl;
+ //std::cout << "Octaves: " << m_octaves << " Lowest:" << m_lowestNote << std::endl;
setFixedSize(s2px(track.endTime), ndiff2px(m_octaves*12));
bool first = true;
diff --git a/songparser-txt.cc b/songparser-txt.cc
index 6854f2a..29b7ea4 100644
--- a/songparser-txt.cc
+++ b/songparser-txt.cc
@@ -95,6 +95,7 @@ bool SongParser::txtParseNote(std::string line, VocalTrack &vocal) {
n.notePrev = n.note; // No slide notes in TXT yet.
if (m_relative) ts += m_relativeShift;
if (iss.get() == ' ') std::getline(iss, n.syllable);
+ boost::trim(n.syllable);
n.end = tsTime(ts + length);
}
break;
|
|
From: Tapio V. <aa...@us...> - 2011-01-18 10:34:19
|
Module: editor
Branch: master
Commit: 4fab80ddc7e33ffb40aebf6999ff7b65a28c2c72
Author: Tapio Vierros <tap...@gm...>
Date: Tue Jan 18 12:21:47 2011 +0200
SingStarWriter: duration conversion multiplier 4.
---
songwriter-xml.cc | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/songwriter-xml.cc b/songwriter-xml.cc
index 96458da..0fddb1d 100644
--- a/songwriter-xml.cc
+++ b/songwriter-xml.cc
@@ -90,5 +90,5 @@ void SingStarXMLWriter::writeXML() {
}
int SingStarXMLWriter::sec2dur(double sec) {
- return round(tempo / 60.0 * sec);
+ return round(tempo / 60.0 * sec * 4);
}
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-18 10:29:37
|
Module: editor
Branch: master
Commit: 1e68bf0b23e8298aba3e2a6b3c993bc3a9b7bb48
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Jan 18 11:29:23 2011 +0100
Link PulseAudio on Linux (required for by QtMultiMediaKit)
---
CMakeLists.txt | 6 +++
cmake/FindLibPulse.cmake | 28 ++++++++++++++++
cmake/LibFindMacros.cmake | 76 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c4df760..0e173b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,6 +24,12 @@ find_package(Qt4 COMPONENTS QtCore QtGui QtXml QtNetwork QtMultimediaKit REQUIRE
include(${QT_USE_FILE})
list(APPEND LIBS ${QT_LIBRARIES})
+# Not used directly but is a dep of QtMultimediaKit
+if(${CMAKE_SYSTEM_NAME} MATCHES Linux)
+ find_package(LibPulse REQUIRED)
+ list(APPEND LIBS ${LibPulse_LIBRARIES})
+endif()
+
# Headers that need MOC need to be defined separately
file(GLOB MOC_HEADER_FILES "editorapp.hh" "notelabel.hh" "notegraphwidget.hh")
diff --git a/cmake/FindLibPulse.cmake b/cmake/FindLibPulse.cmake
new file mode 100644
index 0000000..aebeac0
--- /dev/null
+++ b/cmake/FindLibPulse.cmake
@@ -0,0 +1,28 @@
+# - Try to find LibPulse
+# Once done, this will define
+#
+# LibPulse_FOUND - system has LibPulse
+# LibPulse_INCLUDE_DIRS - the LibPulse include directories
+# LibPulse_LIBRARIES - link these to use LibPulse
+#
+# See documentation on how to write CMake scripts at
+# http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries
+
+include(LibFindMacros)
+
+libfind_pkg_check_modules(LibPulse_PKGCONF libpulse)
+
+find_path(LibPulse_INCLUDE_DIR
+ NAMES pulse/pulseaudio.h
+ PATHS ${LibPulse_PKGCONF_INCLUDE_DIRS}
+)
+
+find_library(LibPulse_LIBRARY
+ NAMES pulse
+ PATHS ${LibPulse_PKGCONF_LIBRARY_DIRS}
+)
+
+set(LibPulse_PROCESS_INCLUDES LibPulse_INCLUDE_DIR)
+set(LibPulse_PROCESS_LIBS LibPulse_LIBRARY)
+libfind_process(LibPulse)
+
diff --git a/cmake/LibFindMacros.cmake b/cmake/LibFindMacros.cmake
new file mode 100644
index 0000000..83b68b5
--- /dev/null
+++ b/cmake/LibFindMacros.cmake
@@ -0,0 +1,76 @@
+# Works the same as find_package, but forwards the "REQUIRED" argument used for
+# the current package and always uses the "QUIET" flag. For this to work, the
+# first parameter must be the prefix of the current package, then the prefix of
+# the new package etc, which are passed to find_package.
+macro (libfind_package PREFIX)
+ set (LIBFIND_PACKAGE_ARGS ${ARGN} QUIET)
+ if (${PREFIX}_FIND_REQUIRED)
+ set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} REQUIRED)
+ endif (${PREFIX}_FIND_REQUIRED)
+ find_package(${LIBFIND_PACKAGE_ARGS})
+endmacro (libfind_package)
+
+# Damn CMake developers made the UsePkgConfig system deprecated in the same release (2.6)
+# where they added pkg_check_modules. Consequently I need to support both in my scripts
+# to avoid those deprecated warnings. Here's a helper that does just that.
+# Works identically to pkg_check_modules, except that no checks are needed prior to use.
+macro (libfind_pkg_check_modules PREFIX PKGNAME)
+ if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+ include(UsePkgConfig)
+ pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS)
+ else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+ find_package(PkgConfig)
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(${PREFIX} ${PKGNAME})
+ endif (PKG_CONFIG_FOUND)
+ endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+endmacro (libfind_pkg_check_modules)
+
+# Do the final processing once the paths have been detected.
+# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain
+# all the variables, each of which contain one include directory.
+# Ditto for ${PREFIX}_PROCESS_LIBS and library files.
+# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.
+# Also handles errors in case library detection was required, etc.
+macro (libfind_process PREFIX)
+ # Skip processing if already processed during this run
+ if (NOT ${PREFIX}_FOUND)
+ # Start with the assumption that the library was found
+ set (${PREFIX}_FOUND TRUE)
+
+ # Process all includes and set _FOUND to false if any are missing
+ foreach (i ${${PREFIX}_PROCESS_INCLUDES})
+ if (${i})
+ set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}})
+ mark_as_advanced(${i})
+ else (${i})
+ set (${PREFIX}_FOUND FALSE)
+ endif (${i})
+ endforeach (i)
+
+ # Process all libraries and set _FOUND to false if any are missing
+ foreach (i ${${PREFIX}_PROCESS_LIBS})
+ if (${i})
+ set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}})
+ mark_as_advanced(${i})
+ else (${i})
+ set (${PREFIX}_FOUND FALSE)
+ endif (${i})
+ endforeach (i)
+
+ # Print message and/or exit on fatal error
+ if (${PREFIX}_FOUND)
+ if (NOT ${PREFIX}_FIND_QUIETLY)
+ message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}")
+ endif (NOT ${PREFIX}_FIND_QUIETLY)
+ else (${PREFIX}_FOUND)
+ if (${PREFIX}_FIND_REQUIRED)
+ foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS})
+ message("${i}=${${i}}")
+ endforeach (i)
+ message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.")
+ endif (${PREFIX}_FIND_REQUIRED)
+ endif (${PREFIX}_FOUND)
+ endif (NOT ${PREFIX}_FOUND)
+endmacro (libfind_process)
+
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-18 10:22:38
|
Module: editor
Branch: master
Commit: 321270d0c09c85ec40bd9253f1bdf14d1e5df411
Author: Lasse Karkkainen <tro...@tr...>
Date: Tue Jan 18 11:22:24 2011 +0100
Always bomb on missing Qt components (doesn't respect the REQUIRED tag)
---
cmake/UseQt4.cmake | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/cmake/UseQt4.cmake b/cmake/UseQt4.cmake
index 858250c..cee5823 100644
--- a/cmake/UseQt4.cmake
+++ b/cmake/UseQt4.cmake
@@ -89,7 +89,7 @@ FOREACH(module QT3SUPPORT QTOPENGL QTASSISTANT QTDESIGNER QTMOTIF QTNSPLUGIN
SET(QT_USE_${depend_module}_DEPENDS 1)
ENDFOREACH(depend_module ${QT_${module}_MODULE_DEPENDS})
ELSE (QT_${module}_FOUND)
- MESSAGE("Qt ${module} library not found.")
+ MESSAGE(FATAL_ERROR "Qt ${module} library not found.")
ENDIF (QT_${module}_FOUND)
ENDIF (QT_USE_${module} OR QT_USE_${module}_DEPENDS)
|
|
From: Tapio V. <aa...@us...> - 2011-01-18 08:31:10
|
Module: editor
Branch: master
Commit: 735348034931f386d042eb1fb7f011f561d54faa
Author: Tapio Vierros <tap...@gm...>
Date: Tue Jan 18 10:30:06 2011 +0200
Refactor prompting for saving unsaved changes.
---
editorapp.cc | 51 +++++++++++++++++++++------------------------------
editorapp.hh | 6 +++++-
2 files changed, 26 insertions(+), 31 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 0ad985a..de36fac 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -132,21 +132,7 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
void EditorApp::on_actionNew_triggered()
{
- // TODO: Check if a save prompt is in order
- if (hasUnsavedChanges) {
- QMessageBox::StandardButton b = QMessageBox::question(this, tr("Unsaved changes"),
- tr("There are unsaved changes. Do you wish to save before creating a new project?"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
- switch(b) {
- case QMessageBox::Yes:
- on_actionSave_triggered();
- case QMessageBox::No:
- noteGraph->clear();
- projectFileName = "";
- break;
- default: break;
- }
- } else {
+ if (promptSaving()) {
noteGraph->clear();
projectFileName = "";
}
@@ -155,6 +141,8 @@ void EditorApp::on_actionNew_triggered()
void EditorApp::on_actionOpen_triggered()
{
+ if (!promptSaving()) return;
+
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
QDir::homePath(),
tr("All supported formats") + "(*." + PROJECT_SAVE_FILE_EXTENSION + " *.xml *.mid *.ini *.txt);;" +
@@ -234,6 +222,23 @@ void EditorApp::on_actionSaveAs_triggered()
}
}
+bool EditorApp::promptSaving()
+{
+ if (hasUnsavedChanges) {
+ QMessageBox::StandardButton b = QMessageBox::question(this, tr("Unsaved changes"),
+ tr("There are unsaved changes, which would be lost. Save now?"),
+ QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
+ switch(b) {
+ case QMessageBox::Yes:
+ on_actionSave_triggered();
+ case QMessageBox::No:
+ return true;
+ default: break;
+ }
+ }
+ return false;
+}
+
void EditorApp::saveProject(QString fileName)
{
QFile f(fileName);
@@ -285,21 +290,7 @@ void EditorApp::on_actionFoFMIDI_triggered()
void EditorApp::on_actionExit_triggered()
{
- // TODO: Check if a save prompt is in order
- if (hasUnsavedChanges) {
- QMessageBox::StandardButton b = QMessageBox::question(this, tr("Unsaved changes"),
- tr("There are unsaved changes. Do you wish to save before quitting?"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
- switch(b) {
- case QMessageBox::Yes:
- on_actionSave_triggered();
- case QMessageBox::No:
- close(); break;
- default: break;
- }
- } else {
- close();
- }
+ if (promptSaving()) close();
}
void EditorApp::on_actionUndo_triggered()
diff --git a/editorapp.hh b/editorapp.hh
index 81b400d..4f72627 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -1,6 +1,7 @@
#pragma once
#include <QtMultimediaKit/QMediaPlayer>
+#include <QMessageBox>
#include "ui_editor.h"
#include "operation.hh"
#include "song.hh"
@@ -17,9 +18,12 @@ public:
EditorApp(QWidget *parent = 0);
void updateSongMeta(bool readFromSongToUI = false);
+ void updateMenuStates();
+
+private:
+ bool promptSaving();
void saveProject(QString fileName);
void doOpStack();
- void updateMenuStates();
public slots:
void operationDone(const Operation &op);
|
|
From: Tapio V. <aa...@us...> - 2011-01-18 08:31:09
|
Module: editor
Branch: master
Commit: 99613e7fed6b4a8efec05dd604e11f14b4bbfabd
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 17 23:19:29 2011 +0200
Detect unsaved changes.
Display star in title bar and disable menu item accordingly.
Also makes the on_exit and on_new prompts actually do something.
---
editorapp.cc | 40 ++++++++++++++++++++++++++++------------
editorapp.hh | 3 ++-
2 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 915fce7..0ad985a 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -12,7 +12,7 @@ namespace {
static const QDataStream::Version PROJECT_SAVE_FILE_STREAM_VERSION = QDataStream::Qt_4_7;
}
-EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName()
+EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName(), hasUnsavedChanges()
{
showMaximized();
ui.setupUi(this);
@@ -64,7 +64,7 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName()
void EditorApp::operationDone(const Operation &op)
{
//std::cout << "Push op: " << op.dump() << std::endl;
- if (player) std::cout << player->isMetaDataAvailable() << std::endl;
+ hasUnsavedChanges = true;
opStack.push(op);
updateMenuStates();
redoStack.clear();
@@ -88,6 +88,10 @@ void EditorApp::doOpStack()
void EditorApp::updateMenuStates()
{
+ // Save menu
+ if (hasUnsavedChanges)
+ ui.actionSave->setEnabled(true);
+ else ui.actionSave->setEnabled(false);
// Undo menu
if (opStack.isEmpty() || opStack.top().op() == "BLOCK")
ui.actionUndo->setEnabled(false);
@@ -96,6 +100,11 @@ void EditorApp::updateMenuStates()
if (redoStack.isEmpty())
ui.actionRedo->setEnabled(false);
else ui.actionRedo->setEnabled(true);
+ // Window title
+ QFileInfo finfo(projectFileName);
+ QString proName = finfo.fileName().isEmpty() ? tr("Untitled") : finfo.fileName();
+ if (hasUnsavedChanges) proName += "*";
+ setWindowTitle("Editor - " + proName);
}
void EditorApp::updateNoteInfo(NoteLabel *note)
@@ -119,28 +128,29 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
ui.cmbNoteType->setEnabled(false);
ui.chkFloating->setEnabled(false);
}
- QFileInfo finfo(projectFileName);
- QString proName = finfo.fileName().isEmpty() ? tr("Untitled") : finfo.fileName();
- setWindowTitle("Editor - " + proName);
}
void EditorApp::on_actionNew_triggered()
{
// TODO: Check if a save prompt is in order
- if (true) {
+ if (hasUnsavedChanges) {
QMessageBox::StandardButton b = QMessageBox::question(this, tr("Unsaved changes"),
tr("There are unsaved changes. Do you wish to save before creating a new project?"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
switch(b) {
case QMessageBox::Yes:
- // TODO: Save
+ on_actionSave_triggered();
case QMessageBox::No:
- noteGraph->clear(); break;
+ noteGraph->clear();
+ projectFileName = "";
+ break;
default: break;
}
} else {
noteGraph->clear();
+ projectFileName = "";
}
+ updateMenuStates();
}
void EditorApp::on_actionOpen_triggered()
@@ -234,9 +244,10 @@ void EditorApp::saveProject(QString fileName)
foreach (Operation op, opStack)
out << op;
projectFileName = fileName;
- updateNoteInfo(NULL); // Title bar
+ hasUnsavedChanges = false;
} else
QMessageBox::critical(this, tr("Error saving file!"), tr("Couldn't open file %1 for saving.").arg(fileName));
+ updateMenuStates();
}
void EditorApp::on_actionSingStarXML_triggered()
@@ -275,13 +286,13 @@ void EditorApp::on_actionFoFMIDI_triggered()
void EditorApp::on_actionExit_triggered()
{
// TODO: Check if a save prompt is in order
- if (false) {
+ if (hasUnsavedChanges) {
QMessageBox::StandardButton b = QMessageBox::question(this, tr("Unsaved changes"),
tr("There are unsaved changes. Do you wish to save before quitting?"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
switch(b) {
case QMessageBox::Yes:
- // TODO: Save
+ on_actionSave_triggered();
case QMessageBox::No:
close(); break;
default: break;
@@ -340,7 +351,12 @@ void EditorApp::on_actionMusicFile_triggered()
ui.valMusicFile->setText(fileName);
ui.tabWidget->setCurrentIndex(1); // Switch to song properties tab
// Metadata is updated when it becomes available (signal)
- player->setMedia(QUrl::fromLocalFile(fileName));
+ QBuffer stream;
+ stream.open(QBuffer::ReadWrite);
+ player->setMedia(QUrl::fromLocalFile(fileName), &stream);
+ std::cout << stream.size() << std::endl;
+ char lol;
+ stream.getChar(&lol);
// FIXME: Temporary test
player->setVolume(50);
player->play();
diff --git a/editorapp.hh b/editorapp.hh
index 9a3a53f..81b400d 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -65,6 +65,7 @@ private:
OperationStack opStack;
OperationStack redoStack;
QScopedPointer<Song> song;
- QString projectFileName;
QScopedPointer<QMediaPlayer> player;
+ QString projectFileName;
+ bool hasUnsavedChanges;
};
|
|
From: Tapio V. <aa...@us...> - 2011-01-17 19:24:00
|
Module: editor
Branch: master
Commit: 9fb945a2850429d30f0fff3e95ad87ac95a67280
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 17 21:22:06 2011 +0200
Inserting a music file populates textboxes from meta data.
Also removed previous test hack.
---
editorapp.cc | 36 +++++++++++++++++++++++++-----------
editorapp.hh | 4 ++++
2 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index ca187e2..915fce7 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -1,5 +1,4 @@
#include <QtGui>
-#include <QtMultimediaKit/QMediaPlayer>
#include <iostream>
#include "editorapp.hh"
#include "notelabel.hh"
@@ -44,6 +43,8 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName()
updateNoteInfo(NULL);
song.reset(new Song);
+ player.reset(new QMediaPlayer);
+ connect(player.data(), SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged()));
// Some icons to menus to make them prettier
ui.actionNew->setIcon(QIcon::fromTheme("document-new"));
@@ -58,19 +59,12 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName()
ui.actionLyricsFromFile->setIcon(QIcon::fromTheme("insert-text"));
ui.actionLyricsFromClipboard->setIcon(QIcon::fromTheme("insert-text"));
ui.actionAbout->setIcon(QIcon::fromTheme("help-about"));
-
- // FIXME: This is temporary test hack
- QMediaPlayer *player = new QMediaPlayer;
- //connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
- player->setMedia(QUrl::fromLocalFile("/tmp/music.mp3"));
- player->setVolume(50);
- player->play();
}
-
void EditorApp::operationDone(const Operation &op)
{
//std::cout << "Push op: " << op.dump() << std::endl;
+ if (player) std::cout << player->isMetaDataAvailable() << std::endl;
opStack.push(op);
updateMenuStates();
redoStack.clear();
@@ -344,8 +338,13 @@ void EditorApp::on_actionMusicFile_triggered()
if (!fileName.isNull()) {
ui.valMusicFile->setText(fileName);
- ui.tabWidget->setCurrentIndex(1); // Swicth to song properties tab
- // TODO: Do something with the file
+ ui.tabWidget->setCurrentIndex(1); // Switch to song properties tab
+ // Metadata is updated when it becomes available (signal)
+ player->setMedia(QUrl::fromLocalFile(fileName));
+ // FIXME: Temporary test
+ player->setVolume(50);
+ player->play();
+ // TODO: Extract the raw data and fire up an analyzer
}
}
@@ -427,6 +426,21 @@ void EditorApp::updateSongMeta(bool readFromSongToUI)
}
}
+void EditorApp::metaDataChanged()
+{
+ if (!player.isNull()) {
+ if (player->metaData(QtMultimediaKit::Title).isValid())
+ song->title = player->metaData(QtMultimediaKit::Title).toString().toStdString();
+ if (player->metaData(QtMultimediaKit::AlbumArtist).isValid())
+ song->artist = player->metaData(QtMultimediaKit::AlbumArtist).toString().toStdString();
+ if (player->metaData(QtMultimediaKit::Genre).isValid())
+ song->genre = player->metaData(QtMultimediaKit::Genre).toString().toStdString();
+ if (player->metaData(QtMultimediaKit::Year).isValid())
+ song->year = player->metaData(QtMultimediaKit::Year).toString().toStdString();
+ updateSongMeta(true);
+ }
+}
+
void EditorApp::on_txtTitle_editingFinished() { updateSongMeta(); }
void EditorApp::on_txtArtist_editingFinished() { updateSongMeta(); }
void EditorApp::on_txtGenre_editingFinished() { updateSongMeta(); }
diff --git a/editorapp.hh b/editorapp.hh
index 719df6e..9a3a53f 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -1,11 +1,13 @@
#pragma once
+#include <QtMultimediaKit/QMediaPlayer>
#include "ui_editor.h"
#include "operation.hh"
#include "song.hh"
class NoteLabel;
class NoteGraphWidget;
+class QMediaPlayer;
class EditorApp: public QMainWindow
{
@@ -22,6 +24,7 @@ public:
public slots:
void operationDone(const Operation &op);
void updateNoteInfo(NoteLabel *note);
+ void metaDataChanged();
// Automatic slots
@@ -63,4 +66,5 @@ private:
OperationStack redoStack;
QScopedPointer<Song> song;
QString projectFileName;
+ QScopedPointer<QMediaPlayer> player;
};
|
|
From: Tapio V. <aa...@us...> - 2011-01-17 18:16:14
|
Module: editor Branch: master Commit: c62a16416a5074553b192b03471702b2d760de65 Author: Tapio Vierros <tap...@gm...> Date: Mon Jan 17 20:14:52 2011 +0200 Added QtMultimediaKit. 1. Import all Qt CMake scripts. 2. Hack QtMultimediaKit detection into them. 3. Add a quick test for verifying linking & audio playback. --- CMakeLists.txt | 7 +- cmake/Copyright.txt | 15 + cmake/FindQt.cmake | 160 +++++ cmake/FindQt4.cmake | 1171 ++++++++++++++++++++++++++++++++ cmake/Qt4ConfigDependentSettings.cmake | 278 ++++++++ cmake/Qt4Macros.cmake | 402 +++++++++++ cmake/UseQt4.cmake | 97 +++ editorapp.cc | 8 + 8 files changed, 2136 insertions(+), 2 deletions(-) |
|
From: Tapio V. <aa...@us...> - 2011-01-17 11:15:37
|
Module: editor
Branch: master
Commit: c26829c64f9f8e1b7cbea5934bb4d2d680c88494
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 17 13:14:17 2011 +0200
Redo shortcut: Ctrl+Shift+Z
---
editor.ui | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/editor.ui b/editor.ui
index 58c840a..a9f09c1 100644
--- a/editor.ui
+++ b/editor.ui
@@ -430,6 +430,9 @@
<property name="text">
<string>&Redo</string>
</property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+Z</string>
+ </property>
</action>
<action name="actionPreferences">
<property name="text">
|
|
From: Tapio V. <aa...@us...> - 2011-01-17 11:07:32
|
Module: editor
Branch: master
Commit: c483fec6c119d10c4ae8438bdc678cb4f49214e6
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 17 13:07:02 2011 +0200
Redo.
---
editorapp.cc | 34 +++++++++++++++++++++++++++++++---
editorapp.hh | 2 ++
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 84fddc8..d4eb5ce 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -65,6 +65,7 @@ void EditorApp::operationDone(const Operation &op)
//std::cout << "Push op: " << op.dump() << std::endl;
opStack.push(op);
updateMenuStates();
+ redoStack.clear();
}
void EditorApp::doOpStack()
@@ -85,9 +86,14 @@ void EditorApp::doOpStack()
void EditorApp::updateMenuStates()
{
+ // Undo menu
if (opStack.isEmpty() || opStack.top().op() == "BLOCK")
ui.actionUndo->setEnabled(false);
else ui.actionUndo->setEnabled(true);
+ // Redo menu
+ if (redoStack.isEmpty())
+ ui.actionRedo->setEnabled(false);
+ else ui.actionRedo->setEnabled(true);
}
void EditorApp::updateNoteInfo(NoteLabel *note)
@@ -291,15 +297,37 @@ void EditorApp::on_actionUndo_triggered()
updateMenuStates();
return;
} else if (opStack.top().op() == "COMBINER") {
+ // Special handling to add the ops in the right order
int count = opStack.top().i(1);
- for (int i = 0; i < count; ++i) opStack.pop();
- // TODO: Redo handling
+ int start = opStack.size() - count - 1;
+ for (int i = start; i < start + count; ++i) {
+ redoStack.push(opStack.at(i));
+ }
+ opStack.remove(start, count);
}
- // TODO: Move popped to redo stack
+ redoStack.push(opStack.top());
opStack.pop();
doOpStack();
}
+void EditorApp::on_actionRedo_triggered()
+{
+ if (redoStack.isEmpty())
+ return;
+ else if (redoStack.top().op() == "COMBINER") {
+ // Special handling to add the ops in the right order
+ int count = redoStack.top().i(1);
+ int start = redoStack.size() - count - 1;
+ for (int i = start; i < start + count; ++i) {
+ opStack.push(redoStack.at(i));
+ }
+ redoStack.remove(start, count);
+ }
+ opStack.push(redoStack.top());
+ redoStack.pop();
+ doOpStack();
+}
+
void EditorApp::on_actionMusicFile_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
diff --git a/editorapp.hh b/editorapp.hh
index 310f470..719df6e 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -37,6 +37,7 @@ public slots:
// Edit menu
void on_actionUndo_triggered();
+ void on_actionRedo_triggered();
// Insert menu
void on_actionMusicFile_triggered();
@@ -59,6 +60,7 @@ private:
Ui::EditorApp ui;
NoteGraphWidget* noteGraph;
OperationStack opStack;
+ OperationStack redoStack;
QScopedPointer<Song> song;
QString projectFileName;
};
|
|
From: Tapio V. <aa...@us...> - 2011-01-17 09:19:25
|
Module: editor
Branch: master
Commit: 20947d8d172c5fd45677167f6688a586d8ab1043
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 17 11:18:09 2011 +0200
Note floating status change through moving is now properly recorded.
---
notegraphwidget.cc | 12 ++++++++++--
notelabel.cc | 2 --
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index f27487b..882c813 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -258,11 +258,19 @@ void NoteGraphWidget::mouseReleaseEvent(QMouseEvent *event)
m_selectedNote->move(m_selectedNote->pos().x(), n2px(px2n(m_selectedNote->pos().y())));
if (m_actionHappened) {
// Operation for undo stack & saving
+ int notelabelid = getNoteLabelId(m_selectedNote);
Operation op("SETGEOM");
- op << getNoteLabelId(m_selectedNote)
+ op << notelabelid
<< m_selectedNote->x() << m_selectedNote->y()
<< m_selectedNote->width() << m_selectedNote->height();
doOperation(op, Operation::NO_EXEC);
+ // See if it needs to be unfloated
+ if (m_selectedNote->isFloating()) {
+ Operation fop("FLOATING"); fop << notelabelid << false;
+ Operation combiner("COMBINER"); combiner << 2;
+ doOperation(fop);
+ doOperation(combiner);
+ }
}
}
m_selectedAction = NONE;
@@ -366,7 +374,7 @@ void NoteGraphWidget::doOperation(const Operation& op, Operation::OperationFlags
{
if (!(flags & Operation::NO_EXEC)) {
std::string action = op.op().toStdString();
- if (action == "BLOCK") {
+ if (action == "BLOCK" || action == "COMBINER") {
; // No op
} else if (action == "NEW") {
NoteLabel *newLabel = new NoteLabel(
diff --git a/notelabel.cc b/notelabel.cc
index c2d08ce..7a7ff05 100644
--- a/notelabel.cc
+++ b/notelabel.cc
@@ -97,14 +97,12 @@ void NoteLabel::mouseMoveEvent(QMouseEvent *event)
else
resize(event->pos().x(), height());
if (ngw) ngw->updateNotes();
- setFloating(false);
} else if (!m_hotspot.isNull()) {
// Moving
QPoint newpos = pos() + event->pos() - m_hotspot;
move(newpos);
if (ngw) ngw->updateNotes();
- setFloating(false);
// Check if we need a new hotspot, because the note was constrained
if (pos().x() != newpos.x()) m_hotspot.rx() = event->x();
|
|
From: Tapio V. <aa...@us...> - 2011-01-17 09:19:22
|
Module: editor
Branch: master
Commit: 4f8f804fc531f0de8806b6b8bac31df5d97f9344
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 17 11:07:37 2011 +0200
Undo menu becomes disabled when undo is not available.
---
editor.ui | 3 +++
editorapp.cc | 14 ++++++++++++--
editorapp.hh | 1 +
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/editor.ui b/editor.ui
index c43993b..58c840a 100644
--- a/editor.ui
+++ b/editor.ui
@@ -413,6 +413,9 @@
</property>
</action>
<action name="actionUndo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>&Undo</string>
</property>
diff --git a/editorapp.cc b/editorapp.cc
index 03591a7..84fddc8 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -64,6 +64,7 @@ void EditorApp::operationDone(const Operation &op)
{
//std::cout << "Push op: " << op.dump() << std::endl;
opStack.push(op);
+ updateMenuStates();
}
void EditorApp::doOpStack()
@@ -79,6 +80,14 @@ void EditorApp::doOpStack()
noteGraph->doOperation(*opit, Operation::NO_EMIT);
} catch (std::exception& e) { std::cout << e.what() << std::endl; }
}
+ updateMenuStates();
+}
+
+void EditorApp::updateMenuStates()
+{
+ if (opStack.isEmpty() || opStack.top().op() == "BLOCK")
+ ui.actionUndo->setEnabled(false);
+ else ui.actionUndo->setEnabled(true);
}
void EditorApp::updateNoteInfo(NoteLabel *note)
@@ -278,9 +287,10 @@ void EditorApp::on_actionUndo_triggered()
{
if (opStack.isEmpty())
return;
- if (opStack.top().op() == "BLOCK")
+ if (opStack.top().op() == "BLOCK") {
+ updateMenuStates();
return;
- else if (opStack.top().op() == "COMBINER") {
+ } else if (opStack.top().op() == "COMBINER") {
int count = opStack.top().i(1);
for (int i = 0; i < count; ++i) opStack.pop();
// TODO: Redo handling
diff --git a/editorapp.hh b/editorapp.hh
index 23bf8be..310f470 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -17,6 +17,7 @@ public:
void updateSongMeta(bool readFromSongToUI = false);
void saveProject(QString fileName);
void doOpStack();
+ void updateMenuStates();
public slots:
void operationDone(const Operation &op);
|
|
From: Tapio V. <aa...@us...> - 2011-01-17 09:19:19
|
Module: editor
Branch: master
Commit: 838324eb5e2a041d6030b498cd67e36cad21aa81
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 17 10:50:02 2011 +0200
Opening a file can be undone in one step.
Doesn't bring back the old notes though.
---
editorapp.cc | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index e541701..03591a7 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -174,7 +174,10 @@ void EditorApp::on_actionOpen_triggered()
song.reset(new Song(QString(finfo.path()+"/").toStdString(), finfo.fileName().toStdString()));
noteGraph->setLyrics(song->getVocalTrack());
updateSongMeta(true);
- noteGraph->doOperation(Operation("BLOCK")); // Lock the undo stack
+ // Combine the import into one undo action
+ Operation combiner("COMBINER"); combiner << opStack.size();
+ operationDone(combiner);
+ //noteGraph->doOperation(Operation("BLOCK")); // Lock the undo stack
}
} catch (const std::exception& e) {
QMessageBox::critical(this, tr("Error loading file!"), e.what());
@@ -273,6 +276,8 @@ void EditorApp::on_actionExit_triggered()
void EditorApp::on_actionUndo_triggered()
{
+ if (opStack.isEmpty())
+ return;
if (opStack.top().op() == "BLOCK")
return;
else if (opStack.top().op() == "COMBINER") {
@@ -280,7 +285,6 @@ void EditorApp::on_actionUndo_triggered()
for (int i = 0; i < count; ++i) opStack.pop();
// TODO: Redo handling
}
-
// TODO: Move popped to redo stack
opStack.pop();
doOpStack();
|
|
From: Tapio V. <aa...@us...> - 2011-01-17 09:19:17
|
Module: editor
Branch: master
Commit: 674793c6bf7429ccd0467a75c4a1c3eb3c147cdc
Author: Tapio Vierros <tap...@gm...>
Date: Mon Jan 17 10:37:29 2011 +0200
Use Qt's list serialization instead of own.
---
operation.cc | 18 ++----------------
operation.hh | 1 +
2 files changed, 3 insertions(+), 16 deletions(-)
diff --git a/operation.cc b/operation.cc
index e8f80a9..e9099bd 100644
--- a/operation.cc
+++ b/operation.cc
@@ -1,28 +1,14 @@
#include "operation.hh"
-#include <stdexcept>
-namespace {
- static const int MAX_PARAMS = 10;
-}
QDataStream& operator<<(QDataStream& stream, const Operation& op)
{
- if (op.m_params.size() > MAX_PARAMS)
- throw std::runtime_error("Operation has too many parameters");
- int i = 0;
- for (i; i < op.m_params.size(); ++i)
- stream << op.m_params[i];
- for (i; i < MAX_PARAMS; ++i)
- stream << QVariant(0);
+ stream << op.m_params;
return stream;
}
QDataStream& operator>>(QDataStream& stream, Operation& op)
{
- for (int i = 0; i < MAX_PARAMS; ++i ) {
- QVariant qv;
- stream >> qv;
- op << qv;
- }
+ stream >> op.m_params;
return stream;
}
diff --git a/operation.hh b/operation.hh
index 4bcf05b..7b25ff5 100644
--- a/operation.hh
+++ b/operation.hh
@@ -53,6 +53,7 @@ struct Operation
}
friend QDataStream& operator<<(QDataStream&, const Operation&);
+ friend QDataStream& operator>>(QDataStream& stream, Operation& op);
private:
QList<QVariant> m_params;
|
|
From: Tapio V. <aa...@us...> - 2011-01-14 13:01:19
|
Module: editor
Branch: master
Commit: 331eb6136c063df078a3ec449c6b50d9450766b2
Author: Tapio Vierros <tap...@gm...>
Date: Fri Jan 14 15:00:43 2011 +0200
Improve save/open.
* Add magic number for file format detection.
* Add version number for future.
* Set fixed QDataStream version.
---
editorapp.cc | 34 ++++++++++++++++++++++++----------
1 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index ed258de..e541701 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -7,6 +7,9 @@
namespace {
static const QString PROJECT_SAVE_FILE_EXTENSION = "songproject"; // FIXME: Nice extension here
+ static const quint32 PROJECT_SAVE_FILE_MAGIC = 0x50455350;
+ static const quint32 PROJECT_SAVE_FILE_VERSION = 100; // File format version 1.00
+ static const QDataStream::Version PROJECT_SAVE_FILE_STREAM_VERSION = QDataStream::Qt_4_7;
}
EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName()
@@ -144,17 +147,26 @@ void EditorApp::on_actionOpen_triggered()
if (f.open(QFile::ReadOnly)) {
opStack.clear();
QDataStream in(&f);
- while (!in.atEnd()) {
- Operation op;
- in >> op;
- std::cout << "Loaded op: " << op.dump() << std::endl;
- opStack.push(op);
- }
- doOpStack();
- projectFileName = fileName;
- updateNoteInfo(NULL); // Title bar
+ quint32 magic; in >> magic;
+ if (magic == PROJECT_SAVE_FILE_MAGIC) {
+ quint32 version; in >> version;
+ if (version == PROJECT_SAVE_FILE_VERSION) {
+ in.setVersion(PROJECT_SAVE_FILE_STREAM_VERSION);
+ while (!in.atEnd()) {
+ Operation op;
+ in >> op;
+ std::cout << "Loaded op: " << op.dump() << std::endl;
+ opStack.push(op);
+ }
+ doOpStack();
+ projectFileName = fileName;
+ updateNoteInfo(NULL); // Title bar
+ } else
+ QMessageBox::critical(this, tr("Error opening file!"), tr("File %1 has unsupported format version.").arg(fileName));
+ } else
+ QMessageBox::critical(this, tr("Error opening file!"), tr("File %1 doesn't look like a project file.").arg(fileName));
} else
- QMessageBox::critical(this, tr("Error saving file!"), tr("Couldn't open file %1 for saving.").arg(fileName));
+ QMessageBox::critical(this, tr("Error opening file!"), tr("Couldn't open file %1 for reading.").arg(fileName));
} else {
@@ -197,6 +209,8 @@ void EditorApp::saveProject(QString fileName)
QFile f(fileName);
if (f.open(QFile::WriteOnly)) {
QDataStream out(&f);
+ out.setVersion(PROJECT_SAVE_FILE_STREAM_VERSION);
+ out << PROJECT_SAVE_FILE_MAGIC << PROJECT_SAVE_FILE_VERSION;
foreach (Operation op, opStack)
out << op;
projectFileName = fileName;
|
|
From: Tapio V. <aa...@us...> - 2011-01-14 11:36:01
|
Module: editor
Branch: master
Commit: f0d2ea33511487e1a7a6afb0566052a0f382517e
Author: Tapio Vierros <tap...@gm...>
Date: Fri Jan 14 13:34:18 2011 +0200
SingStar exporter stuff.
* No 0-length pauses between notes.
* Attempt at duration conversion (doesn't work).
* SLEEP notes not exported anymore.
---
songwriter-xml.cc | 56 +++++++++++++++++++++++++++++-----------------------
songwriter.hh | 4 ++-
2 files changed, 34 insertions(+), 26 deletions(-)
diff --git a/songwriter-xml.cc b/songwriter-xml.cc
index 14f6562..96458da 100644
--- a/songwriter-xml.cc
+++ b/songwriter-xml.cc
@@ -1,13 +1,9 @@
#include "songwriter.hh"
+#include "util.hh"
#include <QtXml/QDomDocument>
#include <QTextStream>
#include <iostream>
-namespace {
- int sec2dur(double sec) {
- return sec; // FIXME: Implement
- }
-}
void SingStarXMLWriter::writeXML() {
QDomDocument doc("");
@@ -15,9 +11,9 @@ void SingStarXMLWriter::writeXML() {
root.setAttribute("xmlns", "http://www.singstargame.com");
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.setAttribute("Version", "1");
- root.setAttribute("Tempo", "120"); // FIXME!
+ root.setAttribute("Tempo", QString::number(tempo));
root.setAttribute("FixedTempo", "Yes");
- root.setAttribute("Resolution", "Demisemiquaver"); //?
+ root.setAttribute("Resolution", "Semiquaver"); // Demisemiquaver = 2x tempo
root.setAttribute("Genre", QString::fromStdString(s.genre));
root.setAttribute("Year", QString::fromStdString(s.year));
root.setAttribute("xsi:schemaLocation", "http://www.singstargame.com http://15GMS-SINGSQL/xml_schema/melody.xsd");
@@ -52,29 +48,35 @@ void SingStarXMLWriter::writeXML() {
sentenceElem = doc.createElement("SENTENCE");
sentenceComment = doc.createComment(QString("Track %1, Sentence %2").arg(tracknum).arg(sentencenum));
sentenceElem.appendChild(sentenceComment);
- }
- // Construct the note element
- QDomElement noteElem = doc.createElement("NOTE");
- noteElem.setAttribute("MidiNote", QString::number(n.note));
- noteElem.setAttribute("Duration", QString::number(sec2dur(n.length())));
- noteElem.setAttribute("Lyric", QString::fromStdString(n.syllable));
- if (n.type == Note::GOLDEN) noteElem.setAttribute("Bonus", "Yes");
- if (n.type == Note::FREESTYLE) noteElem.setAttribute("FreeStyle", "Yes");
- sentenceElem.appendChild(noteElem);
+ } else { // Regular note handling
- // Construct a second note element, indicationg the pause before next note
- QDomElement pauseElem = doc.createElement("NOTE");
- double pauseLen = 1; // FIXME: This should be the duration from last note end to song end
- if (i < notes.size() - 1)
- pauseLen = notes[i+1].begin - n.end; // Difference to next note
- pauseElem.setAttribute("MidiNote", "0");
- pauseElem.setAttribute("Duration", QString::number(sec2dur(pauseLen)));
- pauseElem.setAttribute("Lyric", "");
- sentenceElem.appendChild(pauseElem);
+ // Construct the note element
+ QDomElement noteElem = doc.createElement("NOTE");
+ noteElem.setAttribute("MidiNote", QString::number(n.note));
+ noteElem.setAttribute("Duration", QString::number(sec2dur(n.length())));
+ noteElem.setAttribute("Lyric", QString::fromStdString(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 second note element, indicationg the pause before next note
+ // This is only done if the pause has duration
+ int pauseLen = 0;
+ if (i < notes.size() - 1)
+ pauseLen = sec2dur(notes[i+1].begin - n.end); // Difference to next note
+ if (pauseLen > 0) {
+ QDomElement pauseElem = doc.createElement("NOTE");
+ pauseElem.setAttribute("MidiNote", "0");
+ pauseElem.setAttribute("Duration", QString::number(sec2dur(pauseLen)));
+ pauseElem.setAttribute("Lyric", "");
+ sentenceElem.appendChild(pauseElem);
+ }
+ }
}
+ // TODO: Needs a last dummy sentence
+
root.appendChild(trackElem);
// Get the xml data
@@ -86,3 +88,7 @@ void SingStarXMLWriter::writeXML() {
out << xml;
} else throw std::runtime_error("Couldn't open target file notes.xml");
}
+
+int SingStarXMLWriter::sec2dur(double sec) {
+ return round(tempo / 60.0 * sec);
+}
diff --git a/songwriter.hh b/songwriter.hh
index 6e9ec1d..a8e11db 100644
--- a/songwriter.hh
+++ b/songwriter.hh
@@ -13,9 +13,11 @@ struct SongWriter
struct SingStarXMLWriter: public SongWriter
{
SingStarXMLWriter(const Song& s_, const QString& path_)
- : SongWriter(s_, path_) { writeXML(); }
+ : SongWriter(s_, path_), tempo(240) { writeXML(); }
private:
void writeXML();
+ int sec2dur(double sec);
+ int tempo;
};
struct UltraStarTXTWriter: public SongWriter
|
|
From: Tapio V. <aa...@us...> - 2011-01-14 11:08:09
|
Module: editor
Branch: master
Commit: bec3bca04110aa34da02cc5dd1fbb84976baf58c
Author: Tapio Vierros <tap...@gm...>
Date: Fri Jan 14 13:07:37 2011 +0200
SingStar exporter: not ready yet but the output already looks quite convincing.
---
songwriter-xml.cc | 70 +++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 55 insertions(+), 15 deletions(-)
diff --git a/songwriter-xml.cc b/songwriter-xml.cc
index e5137c4..14f6562 100644
--- a/songwriter-xml.cc
+++ b/songwriter-xml.cc
@@ -3,6 +3,12 @@
#include <QTextStream>
#include <iostream>
+namespace {
+ int sec2dur(double sec) {
+ return sec; // FIXME: Implement
+ }
+}
+
void SingStarXMLWriter::writeXML() {
QDomDocument doc("");
QDomElement root = doc.createElement("MELODY");
@@ -24,25 +30,59 @@ void SingStarXMLWriter::writeXML() {
root.appendChild(artistComment);
root.appendChild(titleComment);
- QString xml = doc.toString(4);
+ int tracknum = 1;
+ QDomElement trackElem = doc.createElement("TRACK");
+ trackElem.setAttribute("Name", "Player1");
+ trackElem.setAttribute("Artist", QString::fromStdString(s.artist));
- QFile f(path + "/notes.xml");
- if (f.open(QFile::WriteOnly)) {
- QTextStream out(&f);
- out << xml;
- } else throw std::runtime_error("Couldn't open target file notes.xml");
+ int sentencenum = 1;
+ QDomElement sentenceElem = doc.createElement("SENTENCE"); // FIXME: Should there be Singer and Part attributes?
+ QDomComment sentenceComment = doc.createComment(QString("Track %1, Sentence %2").arg(tracknum).arg(sentencenum));
+ trackElem.appendChild(sentenceComment);
- // FIXME: The following is just an example and doesn't actually output XML format
- /*
- char buf[1024] = {};
+ // Iterate all notes
Notes const& notes = s.getVocalTrack().notes;
- std::cout << notes.size() << std::endl;
for (unsigned int i = 0; i < notes.size(); ++i) {
Note const& n = notes[i];
- buf[0] = 0xFF;
- buf[1] = n.note; // MIDI note value
- // Others are n.begin, n.end, n.type etc. (see notes.hh)
- f.write(buf, 1024);
- }*/
+ // SLEEP notes indicate sentence end
+ if (n.type == Note::SLEEP) {
+ trackElem.appendChild(sentenceElem);
+ ++sentencenum;
+ sentenceElem = doc.createElement("SENTENCE");
+ sentenceComment = doc.createComment(QString("Track %1, Sentence %2").arg(tracknum).arg(sentencenum));
+ sentenceElem.appendChild(sentenceComment);
+ }
+
+ // Construct the note element
+ QDomElement noteElem = doc.createElement("NOTE");
+ noteElem.setAttribute("MidiNote", QString::number(n.note));
+ noteElem.setAttribute("Duration", QString::number(sec2dur(n.length())));
+ noteElem.setAttribute("Lyric", QString::fromStdString(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 second note element, indicationg the pause before next note
+ QDomElement pauseElem = doc.createElement("NOTE");
+ double pauseLen = 1; // FIXME: This should be the duration from last note end to song end
+ if (i < notes.size() - 1)
+ pauseLen = notes[i+1].begin - n.end; // Difference to next note
+ pauseElem.setAttribute("MidiNote", "0");
+ pauseElem.setAttribute("Duration", QString::number(sec2dur(pauseLen)));
+ pauseElem.setAttribute("Lyric", "");
+ sentenceElem.appendChild(pauseElem);
+
+ }
+
+ root.appendChild(trackElem);
+
+ // Get the xml data
+ QString xml = doc.toString(4);
+ // Write to file
+ QFile f(path + "/notes.xml");
+ if (f.open(QFile::WriteOnly)) {
+ QTextStream out(&f);
+ out << xml;
+ } else throw std::runtime_error("Couldn't open target file notes.xml");
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 20:24:10
|
Module: editor
Branch: master
Commit: b7e0cf32e92ae49910af4244d93e7803ce1b59a2
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 22:23:46 2011 +0200
Add QtXML to CMake.
---
CMakeLists.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 77e4f92..a67cf26 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,7 +18,7 @@ find_package(Boost 1.36 REQUIRED COMPONENTS regex filesystem system)
include_directories(${Boost_INCLUDE_DIRS})
list(APPEND LIBS ${Boost_LIBRARIES})
-find_package(Qt4 REQUIRED) # find and setup Qt4 for this project
+find_package(Qt4 COMPONENTS QtCore QtGui QtXml REQUIRED) # find and setup Qt4 for this project
include(${QT_USE_FILE})
# Headers that need MOC need to be defined separately
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 20:21:52
|
Module: editor Branch: master Commit: dcc9d31d68bd3390ab808fa1ed38b38ea60609d7 Author: Tapio Vierros <tap...@gm...> Date: Thu Jan 13 22:21:22 2011 +0200 Fix bad filename. --- songwriter-xml .cc => songwriter-xml.cc | 0 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/songwriter-xml .cc b/songwriter-xml.cc similarity index 100% rename from songwriter-xml .cc rename to songwriter-xml.cc |
|
From: Tapio V. <aa...@us...> - 2011-01-13 20:01:57
|
Module: editor
Branch: master
Commit: a434204f30b1ec16b31e69f6347d051c57f23664
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 22:00:21 2011 +0200
File I/O to saving & loading.
Projects can now be saved and opened.
Achieved by implementing Operator serialization to QDataStream.
---
editorapp.cc | 34 +++++++++++++++++++++++++++++-----
operation.cc | 26 ++++++++++++++++++++++++++
operation.hh | 6 ++++++
3 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index f697b4d..ed258de 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -138,10 +138,27 @@ void EditorApp::on_actionOpen_triggered()
QFileInfo finfo(fileName);
try {
if (finfo.suffix() == PROJECT_SAVE_FILE_EXTENSION) {
- opStack.clear();
- // TODO: Load opstack
- doOpStack();
+
+ // Project file loading
+ QFile f(fileName);
+ if (f.open(QFile::ReadOnly)) {
+ opStack.clear();
+ QDataStream in(&f);
+ while (!in.atEnd()) {
+ Operation op;
+ in >> op;
+ std::cout << "Loaded op: " << op.dump() << std::endl;
+ opStack.push(op);
+ }
+ doOpStack();
+ projectFileName = fileName;
+ updateNoteInfo(NULL); // Title bar
+ } else
+ QMessageBox::critical(this, tr("Error saving file!"), tr("Couldn't open file %1 for saving.").arg(fileName));
+
} else {
+
+ // Song import
song.reset(new Song(QString(finfo.path()+"/").toStdString(), finfo.fileName().toStdString()));
noteGraph->setLyrics(song->getVocalTrack());
updateSongMeta(true);
@@ -177,8 +194,15 @@ void EditorApp::on_actionSaveAs_triggered()
void EditorApp::saveProject(QString fileName)
{
- projectFileName = fileName;
- updateNoteInfo(NULL); // Title bar
+ QFile f(fileName);
+ if (f.open(QFile::WriteOnly)) {
+ QDataStream out(&f);
+ foreach (Operation op, opStack)
+ out << op;
+ projectFileName = fileName;
+ updateNoteInfo(NULL); // Title bar
+ } else
+ QMessageBox::critical(this, tr("Error saving file!"), tr("Couldn't open file %1 for saving.").arg(fileName));
}
void EditorApp::on_actionSingStarXML_triggered()
diff --git a/operation.cc b/operation.cc
index 6385362..e8f80a9 100644
--- a/operation.cc
+++ b/operation.cc
@@ -1,2 +1,28 @@
#include "operation.hh"
+#include <stdexcept>
+namespace {
+ static const int MAX_PARAMS = 10;
+}
+
+QDataStream& operator<<(QDataStream& stream, const Operation& op)
+{
+ if (op.m_params.size() > MAX_PARAMS)
+ throw std::runtime_error("Operation has too many parameters");
+ int i = 0;
+ for (i; i < op.m_params.size(); ++i)
+ stream << op.m_params[i];
+ for (i; i < MAX_PARAMS; ++i)
+ stream << QVariant(0);
+ return stream;
+}
+
+QDataStream& operator>>(QDataStream& stream, Operation& op)
+{
+ for (int i = 0; i < MAX_PARAMS; ++i ) {
+ QVariant qv;
+ stream >> qv;
+ op << qv;
+ }
+ return stream;
+}
diff --git a/operation.hh b/operation.hh
index 2b0769f..4bcf05b 100644
--- a/operation.hh
+++ b/operation.hh
@@ -3,6 +3,7 @@
#include <QStack>
#include <QVariant>
#include <QTextStream>
+#include <QDataStream>
#include <ostream>
struct Operation
@@ -51,9 +52,14 @@ struct Operation
return st.toStdString();
}
+ friend QDataStream& operator<<(QDataStream&, const Operation&);
+
private:
QList<QVariant> m_params;
};
typedef QStack<Operation> OperationStack;
+// Serialization operators
+QDataStream& operator<<(QDataStream& stream, const Operation& op);
+QDataStream& operator>>(QDataStream& stream, Operation& op);
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 20:01:55
|
Module: editor
Branch: master
Commit: fb009574dc1ce3afae5ad8ba0d356e89f436b5f2
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 21:01:02 2011 +0200
Project save/load framework; only file I/O missing.
---
editorapp.cc | 94 ++++++++++++++++++++++++++++++++++++++++-----------------
editorapp.hh | 5 +++
2 files changed, 71 insertions(+), 28 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 89374e1..f697b4d 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -5,8 +5,11 @@
#include "notegraphwidget.hh"
#include "songwriter.hh"
+namespace {
+ static const QString PROJECT_SAVE_FILE_EXTENSION = "songproject"; // FIXME: Nice extension here
+}
-EditorApp::EditorApp(QWidget *parent): QMainWindow(parent)
+EditorApp::EditorApp(QWidget *parent): QMainWindow(parent), projectFileName()
{
showMaximized();
ui.setupUi(this);
@@ -60,6 +63,21 @@ void EditorApp::operationDone(const Operation &op)
opStack.push(op);
}
+void EditorApp::doOpStack()
+{
+ noteGraph->clear();
+ // Re-apply all operations in the stack
+ // FIXME: This technique cannot work quickly enough, since analyzing would also be started from scratch
+ for (OperationStack::const_iterator opit = opStack.begin(); opit != opStack.end(); ++opit) {
+ std::cout << "Doing op: " << opit->dump() << std::endl;
+ // FIXME: This should check from the operation what class will implement it
+ // and call the appropriate object. QObject meta info could be very useful.
+ try {
+ noteGraph->doOperation(*opit, Operation::NO_EMIT);
+ } catch (std::exception& e) { std::cout << e.what() << std::endl; }
+ }
+}
+
void EditorApp::updateNoteInfo(NoteLabel *note)
{
if (note) {
@@ -81,6 +99,9 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
ui.cmbNoteType->setEnabled(false);
ui.chkFloating->setEnabled(false);
}
+ QFileInfo finfo(projectFileName);
+ QString proName = finfo.fileName().isEmpty() ? tr("Untitled") : finfo.fileName();
+ setWindowTitle("Editor - " + proName);
}
void EditorApp::on_actionNew_triggered()
@@ -106,22 +127,26 @@ void EditorApp::on_actionOpen_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
QDir::homePath(),
- tr("All supported formats (*.TBD!!! *.xml *.mid *.ini *.txt)") + ";;" +
- tr("Project files (*.TBD!!!)") + ";;" + // FIXME: Project file extension
- tr("SingStar XML (*.xml)") + ";;" +
- tr("Frets on Fire MIDI (*.mid *.ini)") + ";;" +
- tr("UltraStar TXT (*.txt)") + ";;" +
- tr("All files (*)")
- );
+ tr("All supported formats") + "(*." + PROJECT_SAVE_FILE_EXTENSION + " *.xml *.mid *.ini *.txt);;" +
+ tr("Project files") +" (*." + PROJECT_SAVE_FILE_EXTENSION + ") ;;" +
+ tr("SingStar XML") + " (*.xml);;" +
+ tr("Frets on Fire MIDI") + " (*.mid *.ini);;" +
+ tr("UltraStar TXT") + " (*.txt);;" +
+ tr("All files") + " (*)");
if (!fileName.isNull()) {
QFileInfo finfo(fileName);
try {
- song.reset(new Song(QString(finfo.path()+"/").toStdString(), finfo.fileName().toStdString()));
- noteGraph->setLyrics(song->getVocalTrack());
- updateSongMeta(true);
- noteGraph->doOperation(Operation("BLOCK")); // Lock the undo stack
- ui.tabWidget->setCurrentIndex(1); // Swicth to song properties tab
+ if (finfo.suffix() == PROJECT_SAVE_FILE_EXTENSION) {
+ opStack.clear();
+ // TODO: Load opstack
+ doOpStack();
+ } else {
+ song.reset(new Song(QString(finfo.path()+"/").toStdString(), finfo.fileName().toStdString()));
+ noteGraph->setLyrics(song->getVocalTrack());
+ updateSongMeta(true);
+ noteGraph->doOperation(Operation("BLOCK")); // Lock the undo stack
+ }
} catch (const std::exception& e) {
QMessageBox::critical(this, tr("Error loading file!"), e.what());
}
@@ -129,6 +154,33 @@ void EditorApp::on_actionOpen_triggered()
}
}
+void EditorApp::on_actionSave_triggered()
+{
+ if (projectFileName.isEmpty()) on_actionSaveAs_triggered();
+ else saveProject(projectFileName);
+}
+
+void EditorApp::on_actionSaveAs_triggered()
+{
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Save Project"),
+ QDir::homePath(),
+ tr("Project files ") + "(*." + PROJECT_SAVE_FILE_EXTENSION + ");;" +
+ tr("All files") + " (*)");
+ if (!fileName.isNull()) {
+ // Add the correct suffix if it is missing
+ QFileInfo finfo(fileName);
+ if (finfo.suffix() != PROJECT_SAVE_FILE_EXTENSION)
+ fileName += "." + PROJECT_SAVE_FILE_EXTENSION;
+ saveProject(fileName);
+ }
+}
+
+void EditorApp::saveProject(QString fileName)
+{
+ projectFileName = fileName;
+ updateNoteInfo(NULL); // Title bar
+}
+
void EditorApp::on_actionSingStarXML_triggered()
{
QString path = QFileDialog::getExistingDirectory(this, tr("Export SingStar XML"), QDir::homePath());
@@ -193,21 +245,7 @@ void EditorApp::on_actionUndo_triggered()
// TODO: Move popped to redo stack
opStack.pop();
- std::cout << "Undo!" << std::endl;
- noteGraph->clear();
- //noteGraph = new NoteGraphWidget(NULL);
- //ui.noteGraphScroller->setWidget(noteGraph);
- // Re-apply all operations in the stack
- // FIXME: This technique cannot work quickly enough, since analyzing would also be started from scratch
- for (OperationStack::const_iterator opit = opStack.begin(); opit != opStack.end(); ++opit) {
- std::cout << "Doing op: " << opit->dump() << std::endl;
- // FIXME: This should check from the operation what class will implement it
- // and call the appropriate object. QObject meta info could be very useful.
- try {
- noteGraph->doOperation(*opit, Operation::NO_EMIT);
- } catch (std::exception& e) { std::cout << e.what() << std::endl;
- } catch (...) { std::cout << "UNDO ERROR!" << std::endl; }
- }
+ doOpStack();
}
void EditorApp::on_actionMusicFile_triggered()
diff --git a/editorapp.hh b/editorapp.hh
index 9a3b53a..23bf8be 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -15,6 +15,8 @@ public:
EditorApp(QWidget *parent = 0);
void updateSongMeta(bool readFromSongToUI = false);
+ void saveProject(QString fileName);
+ void doOpStack();
public slots:
void operationDone(const Operation &op);
@@ -25,6 +27,8 @@ public slots:
// File menu
void on_actionNew_triggered();
void on_actionOpen_triggered();
+ void on_actionSave_triggered();
+ void on_actionSaveAs_triggered();
void on_actionSingStarXML_triggered();
void on_actionUltraStarTXT_triggered();
void on_actionFoFMIDI_triggered();
@@ -55,4 +59,5 @@ private:
NoteGraphWidget* noteGraph;
OperationStack opStack;
QScopedPointer<Song> song;
+ QString projectFileName;
};
|
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-13 17:23:01
|
Module: editor Branch: master Commit: a94754771b85d5fb8830ccc2565b57e4b5bda1ee Author: Lasse Kärkkäinen <tronic+ndrm at trn.iki.fi> Date: Thu Jan 13 18:19:48 2011 +0100 Improve filtering stability; revert semitone rounding --- pitch.cc | 2 +- pitch.hh | 2 +- pitchvis.cc | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pitch.cc b/pitch.cc index 2c4bfb8..b3da8a1 100644 --- a/pitch.cc +++ b/pitch.cc @@ -197,7 +197,7 @@ void Analyzer::mergeWithOld(Tones& tones) const { // Merge the old tone into the new tone it->age = oldit->age + 1; it->stabledb = 0.8 * oldit->stabledb + 0.2 * it->db; - //it->freq = 0.5 * oldit->freq + 0.5 * it->freq; + it->freq = 0.5 * oldit->freq + 0.5 * it->freq; } else if (oldit->db > -80.0) { // Insert a decayed version of the old tone into new tones Tone& t = *tones.insert(it, *oldit); diff --git a/pitch.hh b/pitch.hh index cff9b22..cff8cf3 100644 --- a/pitch.hh +++ b/pitch.hh @@ -12,7 +12,7 @@ static inline double dB2magn(double db) { return std::pow(10.0, db / 20.0); } /// A tone is a collection of a base frequency (freq) and all its harmonics struct Tone { - static const std::size_t MAXHARM = 8; ///< The maximum number of harmonics tracked + static const std::size_t MAXHARM = 16; ///< The maximum number of harmonics tracked static const std::size_t MINAGE = 6; ///< The minimum age required for a tone to be output double freq; ///< Frequency (Hz) double db; ///< Level (dB) diff --git a/pitchvis.cc b/pitchvis.cc index bc97bca..e4b29f9 100644 --- a/pitchvis.cc +++ b/pitchvis.cc @@ -38,7 +38,6 @@ PitchVis::PitchVis(std::string const& filename): height(1024) { analyzer.input(data.begin() + x * step, data.begin() + (x + 1) * step); analyzer.process(); - /* Analyzer::Peaks peaks = analyzer.getPeaks(); for (unsigned i = 0; i < peaks.size(); ++i) { unsigned y = height - static_cast<unsigned>(16.0 * scale.getNote(peaks[i].freq)); @@ -53,11 +52,11 @@ PitchVis::PitchVis(std::string const& filename): height(1024) { (*this)(x, y + 1) += p; (*this)(x, y - 1) += p; } - */ Analyzer::Tones tones = analyzer.getTones(); unsigned int i = 0; for (Analyzer::Tones::const_iterator it = tones.begin(), itend = tones.end(); it != itend && i < 3; ++it) { - unsigned y = height - static_cast<unsigned>(16.0 * scale.getNoteId(it->freq)); + if (it->age < Tone::MINAGE) continue; + unsigned y = height - static_cast<unsigned>(16.0 * scale.getNote(it->freq)); if (y == 0 || y >= height - 1) continue; float value = 0.003 * (it->db + 80.0); if (value <= 0.0) continue; |
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-13 17:22:59
|
Module: editor Branch: master Commit: 13ef377272a695b3fc50d7673736c051dd7d864b Author: Lasse Kärkkäinen <tronic+ndrm at trn.iki.fi> Date: Thu Jan 13 18:12:06 2011 +0100 Optimizing pitch analyzer performance and attempting to reduce noise --- pitch.cc | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pitch.cc b/pitch.cc index fdb9bf3..2c4bfb8 100644 --- a/pitch.cc +++ b/pitch.cc @@ -6,13 +6,13 @@ #include <iomanip> #include <numeric> -static const unsigned FFT_P = 10; // FFT size setting, will use 2^FFT_P sample FFT +static const unsigned FFT_P = 11; // FFT size setting, will use 2^FFT_P sample FFT static const std::size_t FFT_N = 1 << FFT_P; // FFT size in samples -static const std::size_t FFT_STEP = 256; // Step size in samples, should be <= 0.25 * FFT_N. Low values cause high CPU usage. +static const std::size_t FFT_STEP = 512; // Step size in samples, should be <= 0.25 * FFT_N. Low values cause high CPU usage. // Limit the range to avoid noise and useless computation static const double FFT_MINFREQ = 45.0; -static const double FFT_MAXFREQ = 5000.0; +static const double FFT_MAXFREQ = 3000.0; Tone::Tone(): freq(0.0), @@ -132,6 +132,8 @@ void Analyzer::calcTones() { for (Combos::iterator it = combos.begin(), end = combos.end(); it != end; ++it) it->freq /= it->magnitude; // Strongest first std::sort(combos.rbegin(), combos.rend()); + // Keep only a reasonable amount of strongest frequencies. + if (combos.size() > 10) combos.resize(10); // Try to combine combos into tones (collections of harmonics) Tones tones; for (Combos::const_iterator it = combos.begin(), end = combos.end(); it != end; ++it) { @@ -145,7 +147,7 @@ void Analyzer::calcTones() { int score = 0; size_t misses = 0; t.db = 0.0; // Using db field for magnitude - for (std::size_t n = 1; n <= Tone::MAXHARM && misses < 2; ++n) { + for (std::size_t n = 1; n <= Tone::MAXHARM && misses < 3; ++n) { double hfreq = n * freq; bool miss = true; for (Combos::const_iterator harm = combos.begin(), harmend = combos.end(); harm != harmend; ++harm) { |
|
From: Tapio V. <aa...@us...> - 2011-01-13 17:11:10
|
Module: editor
Branch: master
Commit: 7f2131c7c08b2a8f8eba0aa902fa53512985379e
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 19:10:09 2011 +0200
XML exporter now writes header info (testing QtXml).
---
songwriter-ini.cc | 8 +++++---
songwriter-txt.cc | 3 ++-
songwriter-xml .cc | 38 +++++++++++++++++++++++++++++++++-----
songwriter.hh | 4 ++--
4 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/songwriter-ini.cc b/songwriter-ini.cc
index b9b1cf1..1ed0021 100644
--- a/songwriter-ini.cc
+++ b/songwriter-ini.cc
@@ -4,7 +4,7 @@
void FoFMIDIWriter::writeMIDI() {
throw std::runtime_error("MIDI export is not implemented.");
- std::ofstream f((path + "notes.mid").c_str(), std::ios::binary);
+ /*std::ofstream f((path + "notes.mid").c_str(), std::ios::binary);
// FIXME: The following is just an example and doesn't actually output MID format
char buf[1024] = {};
Notes const& notes = s.getVocalTrack().notes;
@@ -15,15 +15,17 @@ void FoFMIDIWriter::writeMIDI() {
buf[1] = n.note; // MIDI note value
// Others are n.begin, n.end, n.type etc. (see notes.hh)
f.write(buf, 1024);
- }
+ }*/
}
void FoFMIDIWriter::writeINI() {
- std::ofstream f((path + "song.ini").c_str(), std::ios::binary);
+ /*
+ std::ofstream f((path.toStdString() + "song.ini").c_str(), std::ios::binary);
f << "[song]\n";
f << "name = " << s.title << std::endl;
f << "artist = " << s.artist << std::endl;
f << "genre = " << s.genre << std::endl;
f << "year = " << s.year << std::endl;
+ */
}
diff --git a/songwriter-txt.cc b/songwriter-txt.cc
index ffa6e7e..3e2455b 100644
--- a/songwriter-txt.cc
+++ b/songwriter-txt.cc
@@ -4,6 +4,7 @@
void UltraStarTXTWriter::writeTXT() {
throw std::runtime_error("TXT export is not implemented.");
+/*
std::ofstream f((path + "notes.txt").c_str(), std::ios::binary);
// FIXME: The following is just an example and doesn't actually output TXT format
char buf[1024] = {};
@@ -15,5 +16,5 @@ void UltraStarTXTWriter::writeTXT() {
buf[1] = n.note; // MIDI note value
// Others are n.begin, n.end, n.type etc. (see notes.hh)
f.write(buf, 1024);
- }
+ }*/
}
diff --git a/songwriter-xml .cc b/songwriter-xml .cc
index 71d2581..e5137c4 100644
--- a/songwriter-xml .cc
+++ b/songwriter-xml .cc
@@ -1,12 +1,39 @@
#include "songwriter.hh"
-#include <fstream>
+#include <QtXml/QDomDocument>
+#include <QTextStream>
#include <iostream>
void SingStarXMLWriter::writeXML() {
- throw std::runtime_error("XML export is not implemented.");
- // FIXME: Use QtXML
- std::ofstream f((path + "notes.xml").c_str(), std::ios::binary);
+ QDomDocument doc("");
+ QDomElement root = doc.createElement("MELODY");
+ root.setAttribute("xmlns", "http://www.singstargame.com");
+ root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+ root.setAttribute("Version", "1");
+ root.setAttribute("Tempo", "120"); // FIXME!
+ root.setAttribute("FixedTempo", "Yes");
+ root.setAttribute("Resolution", "Demisemiquaver"); //?
+ root.setAttribute("Genre", QString::fromStdString(s.genre));
+ root.setAttribute("Year", QString::fromStdString(s.year));
+ root.setAttribute("xsi:schemaLocation", "http://www.singstargame.com http://15GMS-SINGSQL/xml_schema/melody.xsd");
+ root.setAttribute("m2xVersion", "060110"); //?
+ root.setAttribute("audioVersion", "2"); //?
+ doc.appendChild(root);
+
+ QDomComment artistComment = doc.createComment(QString("Artist: ") + QString::fromStdString(s.artist));
+ QDomComment titleComment = doc.createComment(QString("Title: ") + QString::fromStdString(s.title));
+ root.appendChild(artistComment);
+ root.appendChild(titleComment);
+
+ QString xml = doc.toString(4);
+
+ QFile f(path + "/notes.xml");
+ if (f.open(QFile::WriteOnly)) {
+ QTextStream out(&f);
+ out << xml;
+ } else throw std::runtime_error("Couldn't open target file notes.xml");
+
// FIXME: The following is just an example and doesn't actually output XML format
+ /*
char buf[1024] = {};
Notes const& notes = s.getVocalTrack().notes;
std::cout << notes.size() << std::endl;
@@ -16,5 +43,6 @@ void SingStarXMLWriter::writeXML() {
buf[1] = n.note; // MIDI note value
// Others are n.begin, n.end, n.type etc. (see notes.hh)
f.write(buf, 1024);
- }
+ }*/
+
}
diff --git a/songwriter.hh b/songwriter.hh
index 3d06e60..6e9ec1d 100644
--- a/songwriter.hh
+++ b/songwriter.hh
@@ -5,9 +5,9 @@
struct SongWriter
{
SongWriter(const Song& s_, const QString& path_)
- : s(s_), path(path_.toStdString()) { QDir dir; dir.mkpath(path_); }
+ : s(s_), path(path_) { QDir dir; dir.mkpath(path_); }
const Song& s;
- std::string path;
+ QString path;
};
struct SingStarXMLWriter: public SongWriter
|