Skip to content

Commit

Permalink
Merge pull request #5692 from igorkorsukov/audiveris_import
Browse files Browse the repository at this point in the history
Audiveris import
  • Loading branch information
anatoly-os committed Mar 18, 2020
2 parents f0cd7e9 + 87919f5 commit 475de86
Show file tree
Hide file tree
Showing 74 changed files with 5,288 additions and 70 deletions.
33 changes: 19 additions & 14 deletions CMakeLists.txt
Expand Up @@ -123,15 +123,16 @@ endif (NOT APPLE AND NOT MINGW AND NOT MSVC)
option(AEOLUS "Enable pipe organ synthesizer" OFF)
option(ZERBERUS "Enable experimental SFZ sampler" ON)
option(OSC "Enable OSC remote control protocol" ON)
option(OMR "Enable PDF import" OFF) # OMR - optical music recognition
option(AVSOMR "Enable AVSOMR import" OFF) # AVSOMR - optical music recognition by audirevis
option(OMR "Enable PDF import" OFF) # OMR - optical music recognition
# For installation see: http://ubuntuforums.org/showthread.php?t=1647350
option(OCR "Enable OCR, requires OMR" OFF) # Requires tesseract 3.0, needs work on mac/win
option(SOUNDFONT3 "Ogg Vorbis compressed fonts" ON) # Enable Ogg Vorbis compressed fonts, requires Ogg & Vorbis
option(HAS_AUDIOFILE "Enable audio export" ON) # Requires libsndfile
option(OCR "Enable OCR, requires OMR" OFF) # Requires tesseract 3.0, needs work on mac/win
option(SOUNDFONT3 "Ogg Vorbis compressed fonts" ON) # Enable Ogg Vorbis compressed fonts, requires Ogg & Vorbis
option(HAS_AUDIOFILE "Enable audio export" ON) # Requires libsndfile
option(USE_SYSTEM_QTSINGLEAPPLICATION "Use system QtSingleApplication" OFF)
option(USE_SYSTEM_FREETYPE "Use system FreeType" OFF) # requires freetype >= 2.5.2, does not work on win
option(USE_SYSTEM_POPPLER "Use system Poppler for OMR" OFF)
option(BUILD_LAME "Enable MP3 export" ON) # Requires libmp3lame, call CMake with -DBUILD_LAME="OFF" to disable
option(USE_SYSTEM_FREETYPE "Use system FreeType" OFF) # requires freetype >= 2.5.2, does not work on win
option(USE_SYSTEM_POPPLER "Use system Poppler for OMR" OFF)
option(BUILD_LAME "Enable MP3 export" ON) # Requires libmp3lame, call CMake with -DBUILD_LAME="OFF" to disable
option(DOWNLOAD_SOUNDFONT "Download the latest soundfont version as part of the build process" ON)

# licence incompatibility, must never be distributed
Expand Down Expand Up @@ -852,30 +853,34 @@ add_subdirectory(manual)
add_subdirectory(demos)

if (USE_PORTMIDI AND (MINGW OR APPLE OR MSVC))
subdirs (thirdparty/portmidi)
add_subdirectory(thirdparty/portmidi)
endif (USE_PORTMIDI AND (MINGW OR APPLE OR MSVC))

if (AEOLUS)
subdirs (aeolus)
add_subdirectory(aeolus)
endif (AEOLUS)

if (ZERBERUS)
subdirs (zerberus)
add_subdirectory(zerberus)
endif (ZERBERUS)

if (AVSOMR)
add_subdirectory(avsomr)
endif (AVSOMR)

if (OMR)
subdirs (omr)
add_subdirectory(omr)
if (NOT USE_SYSTEM_POPPLER)
subdirs (thirdparty/poppler)
add_subdirectory(thirdparty/poppler)
endif (NOT USE_SYSTEM_POPPLER)
endif (OMR)

if (OSC)
subdirs (thirdparty/ofqf)
add_subdirectory(thirdparty/ofqf)
endif (OSC)

if (NOT USE_SYSTEM_FREETYPE)
subdirs (thirdparty/freetype)
add_subdirectory(thirdparty/freetype)
endif (NOT USE_SYSTEM_FREETYPE)

##
Expand Down
4 changes: 4 additions & 0 deletions all.h
Expand Up @@ -95,6 +95,7 @@

#include <QPainterPath>
#include <QPixmap>
#include <QImage>
#include <QPainter>
#include <QKeyEvent>

Expand Down Expand Up @@ -185,6 +186,9 @@
#include <QSvgRenderer>
#include <QSvgGenerator>

#include <QFile>
#include <QFileInfo>

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkCookie>
Expand Down
95 changes: 95 additions & 0 deletions avsomr/CMakeLists.txt
@@ -0,0 +1,95 @@
#=============================================================================
# MuseScore
# Music Composition & Notation
#
# Copyright (C) 2020 MuseScore BVBA and others
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#=============================================================================

include (${PROJECT_SOURCE_DIR}/build/gch.cmake)

include_directories(
${PROJECT_SOURCE_DIR}
)

if (NOT MSVC)
set(_all_h_file "${PROJECT_BINARY_DIR}/all.h")
else (NOT MSVC)
set(_all_h_file "${PROJECT_SOURCE_DIR}/all.h")
endif (NOT MSVC)

add_library (
avsomr STATIC
${_all_h_file}
${PCH}
avsimport.cpp
avslog.h
ret.cpp
ret.h
avsomr.cpp
avsomr.h
avsomrreader.cpp
avsomrreader.h
msmrfile.cpp
msmrfile.h
msmrwriter.cpp
msmrwriter.h
avsomrdrawer.cpp
avsomrdrawer.h
iavsomrrecognizer.h
avsomrnetrecognizer.cpp
avsomrnetrecognizer.h
avsomrlocal.cpp
avsomrlocal.h
avsomrlocalrecognizer.cpp
avsomrlocalrecognizer.h
avsomrlocalinstaller.cpp
avsomrlocalinstaller.h
avsomrsetup.cpp
avsomrsetup.h
ui/recognitionproccessdialog.cpp
ui/recognitionproccessdialog.h
ui/taskbarprogress.cpp
ui/taskbarprogress.h
ui/infopopup.cpp
ui/infopopup.h
ui/setupavsomrview.cpp
ui/setupavsomrview.h
)

if (NOT MSVC)
set_target_properties (
avsomr
PROPERTIES
COMPILE_FLAGS "${PCH_INCLUDE} -g -Wall -Wextra -Winvalid-pch -Wno-unused-private-field"
)
else (NOT MSVC)
set_target_properties (
avsomr
PROPERTIES
COMPILE_FLAGS "${PCH_INCLUDE}" # TODO: Add disabling of unused private field warning?
)
endif (NOT MSVC)

xcode_pch(avsomr all)

# Use MSVC pre-compiled headers
vstudio_pch( avsomr )

# MSVC does not depend on mops1 & mops2 for PCH
if (NOT MSVC)
ADD_DEPENDENCIES(avsomr mops1)
ADD_DEPENDENCIES(avsomr mops2)
endif (NOT MSVC)

188 changes: 188 additions & 0 deletions avsomr/avsimport.cpp
@@ -0,0 +1,188 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================

#include <memory>
#include <QFileInfo>
#include <QByteArray>
#include <QIODevice>

#include "libmscore/score.h"
#include "libmscore/text.h"

#include "avslog.h"
#include "msmrfile.h"
#include "avsomr.h"
#include "avsomrreader.h"
#include "avsomrnetrecognizer.h"
#include "avsomrlocalrecognizer.h"
#include "avsomrlocal.h"
#include "ui/recognitionproccessdialog.h"
#include "ui/infopopup.h"

namespace Ms {

extern Score::FileError importMusicXml(MasterScore* score, QIODevice* dev, const QString& name);

//---------------------------------------------------------
// doImportMSMR
// return Score::FileError::FILE_* errors
//---------------------------------------------------------

static Score::FileError doImportMSMR(MasterScore* score
, QIODevice *data
, const QString& filePath
, bool created)
{
IF_ASSERT(score) {
return Score::FileError::FILE_ERROR;
}

IF_ASSERT(data) {
return Score::FileError::FILE_ERROR;
}

QString baseName = QFileInfo(filePath).baseName();
auto msmr = std::make_shared<Avs::MsmrFile>(data->readAll(), baseName);

// import score
QByteArray msczData = msmr->readMscz();
if (!msczData.isEmpty()) {
// read mscz
QBuffer msczBuf(&msczData);
msczBuf.open(QIODevice::ReadOnly);
Score::FileError err = score->loadMsc("score.mscz", &msczBuf, true);
if (err != Score::FileError::FILE_NO_ERROR)
return err;
}
else {
// import MusicXml
QByteArray muzicXmlData = msmr->readMuzicXml();
if (muzicXmlData.isEmpty())
return Score::FileError::FILE_BAD_FORMAT;

QBuffer muzicXmlBuf(&muzicXmlData);
muzicXmlBuf.open(QIODevice::ReadOnly);

Score::FileError err = importMusicXml(score, &muzicXmlBuf, baseName);
if (err != Score::FileError::FILE_NO_ERROR)
return err;

// corrections after import

//! NOTE Audiveris sets the title "[Audiveris detected movement]",
//! I decided it was not convenient for the user,
//! the file base name as title is more convenient.
QString titleText = baseName;
Text* title = score->getText(Tid::TITLE);
if (title)
title->setPlainText(titleText);

score->setMetaTag("movementNumber", "");
score->setMetaTag("movementTitle", "");
score->setMetaTag("source", QFileInfo(filePath).fileName());
score->setMetaTag("workTitle", title ? title->plainText() : titleText);
}

// import omr
QByteArray ormData = msmr->readOmr();
if (ormData.isEmpty()) {
return Score::FileError::FILE_BAD_FORMAT;
}

QBuffer ormBuf(&ormData);
Avs::AvsOmrReader reader;
std::shared_ptr<Avs::AvsOmr> omr = reader.read(&ormBuf);
if (!omr)
return Score::FileError::FILE_BAD_FORMAT;

omr->setMsmrFile(msmr);
score->setAvsOmr(omr);

// set format
score->setCreated(created);

//! NOTE format of file determined by .ext,
//! therefore setting .msmr for correctly saving
score->fileInfo()->setFile(QFileInfo(filePath).path() + "/" + baseName + ".msmr");

return Score::FileError::FILE_NO_ERROR;
}

//---------------------------------------------------------
// importMSMR
// return Score::FileError::FILE_* errors
//---------------------------------------------------------

Score::FileError importMSMR(MasterScore* score, const QString& filePath)
{
QFile file(filePath);
if (!file.exists()) {
LOGE() << "not exists file: " << filePath;
return Score::FileError::FILE_NOT_FOUND;
}

if (!file.open(QIODevice::ReadOnly)) {
LOGE() << "failed open file: " << filePath;
return Score::FileError::FILE_OPEN_ERROR;
}

return doImportMSMR(score, &file, filePath, false);
}

//---------------------------------------------------------
// loadAndImportMSMR
// return Score::FileError::FILE_* errors
//---------------------------------------------------------

Score::FileError loadAndImportMSMR(MasterScore* score, const QString& filePath)
{
Avs::RecognitionProccessDialog progDialog;

auto onStep = [&progDialog](const Avs::AvsOmrNetRecognizer::Step& step) {
progDialog.onStep(step);
};

std::shared_ptr<Avs::IAvsOmrRecognizer> recognizer;
bool useLocal = Avs::AvsOmrLocal::instance()->isUseLocal();
if (useLocal)
recognizer = std::make_shared<Avs::AvsOmrLocalRecognizer>();
else
recognizer = std::make_shared<Avs::AvsOmrNetRecognizer>();

LOGI() << "try use avs omr recognizer: " << recognizer->type();
progDialog.setType(recognizer->type());
progDialog.show();

QByteArray data;
bool ok = recognizer->recognize(filePath, &data, onStep);

progDialog.onFinished(ok);

if (!ok) {
//! NOTE A message has already been shown to the user
return Score::FileError::FILE_IGNORE_ERROR;
}

QBuffer buf(&data);
buf.open(QIODevice::ReadOnly);

return doImportMSMR(score, &buf, filePath, true);
}

}

0 comments on commit 475de86

Please sign in to comment.