# HG changeset patch # User Chris Cannam # Date 1373631028 -3600 # Node ID 54829c1e155e878bd37e931275208685c4634091 # Parent 5e9ff92ca05e1c0d5f807a1f8f79a352e29ba5d7# Parent 06c64a1c6785c3724b7bf37c84eb8532bfff65d7 Merge from the default branch diff -r 06c64a1c6785 -r 54829c1e155e base/PlayParameterRepository.cpp --- a/base/PlayParameterRepository.cpp Mon Jul 08 14:49:28 2013 +0100 +++ b/base/PlayParameterRepository.cpp Fri Jul 12 13:10:28 2013 +0100 @@ -35,14 +35,14 @@ void PlayParameterRepository::addPlayable(const Playable *playable) { -// std::cerr << "PlayParameterRepository:addPlayable " << playable << std::endl; + std::cerr << "PlayParameterRepository:addPlayable playable = " << playable << std::endl; if (!getPlayParameters(playable)) { // Give all playables the same type of play parameters for the // moment -// std::cerr << "PlayParameterRepository: Adding play parameters for " << playable << std::endl; + std::cerr << "PlayParameterRepository:addPlayable: Adding play parameters for " << playable << std::endl; PlayParameters *params = new PlayParameters; m_playParameters[playable] = params; @@ -62,8 +62,8 @@ connect(params, SIGNAL(playPluginConfigurationChanged(QString)), this, SLOT(playPluginConfigurationChanged(QString))); -// std::cerr << "Connected play parameters " << params << " for playable " -// << playable << " to this " << this << std::endl; + std::cerr << "Connected play parameters " << params << " for playable " + << playable << " to this " << this << std::endl; } } diff -r 06c64a1c6785 -r 54829c1e155e data/fileio/CoreAudioFileReader.cpp --- a/data/fileio/CoreAudioFileReader.cpp Mon Jul 08 14:49:28 2013 +0100 +++ b/data/fileio/CoreAudioFileReader.cpp Fri Jul 12 13:10:28 2013 +0100 @@ -89,16 +89,16 @@ //!!! how do we find out if the file open fails because of DRM protection? -#if (MACOSX_DEPLOYMENT_TARGET <= 1040 && MAC_OS_X_VERSION_MIN_REQUIRED <= 1040) - FSRef fsref; - if (!CFURLGetFSRef(url, &fsref)) { // returns Boolean, not error code - m_error = "CoreAudioReadStream: Error looking up FS ref (file not found?)"; - return; - } - m_d->err = ExtAudioFileOpen(&fsref, &m_d->file); -#else +//#if (MACOSX_DEPLOYMENT_TARGET <= 1040 && MAC_OS_X_VERSION_MIN_REQUIRED <= 1040) +// FSRef fsref; +// if (!CFURLGetFSRef(url, &fsref)) { // returns Boolean, not error code +// m_error = "CoreAudioReadStream: Error looking up FS ref (file not found?)"; +// return; +// } +// m_d->err = ExtAudioFileOpen(&fsref, &m_d->file); +//#else m_d->err = ExtAudioFileOpenURL(url, &m_d->file); -#endif +//#endif CFRelease(url); diff -r 06c64a1c6785 -r 54829c1e155e data/model/FlexiNoteModel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/model/FlexiNoteModel.h Fri Jul 12 13:10:28 2013 +0100 @@ -0,0 +1,234 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _FLEXINOTE_MODEL_H_ +#define _FLEXINOTE_MODEL_H_ + +// #include "NotelikeModel.h" // GF: reomved as this is an uncommitted experiment for now + +#include "IntervalModel.h" +#include "base/RealTime.h" +#include "base/PlayParameterRepository.h" + +/** + * FlexiNoteModel -- a concrete IntervalModel for notes. + */ + +/** + * Extension of the NoteModel for more flexible note interaction. + * The original NoteModel rationale is given below, will need to be + * updated for FlexiNoteModel: + * + * Note type for use in a sparse model. All we mean by a "note" is + * something that has an onset time, a single value, a duration, and a + * level. Like other points, it can also have a label. With this + * point type, the model can be thought of as representing a simple + * MIDI-type piano roll, except that the y coordinates (values) do not + * have to be discrete integers. + */ + +struct FlexiNote +{ +public: + FlexiNote(long _frame) : frame(_frame), value(0.0f), duration(0), level(1.f) { } + FlexiNote(long _frame, float _value, size_t _duration, float _level, QString _label) : + frame(_frame), value(_value), duration(_duration), level(_level), label(_label) { } + + int getDimensions() const { return 3; } + + long frame; + float value; + size_t duration; + float level; + QString label; + + QString getLabel() const { return label; } + + void toXml(QTextStream &stream, + QString indent = "", + QString extraAttributes = "") const + { + stream << + QString("%1\n") + .arg(indent).arg(frame).arg(value).arg(duration).arg(level) + .arg(XmlExportable::encodeEntities(label)).arg(extraAttributes); + } + + QString toDelimitedDataString(QString delimiter, size_t sampleRate) const + { + QStringList list; + list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str(); + list << QString("%1").arg(value); + list << RealTime::frame2RealTime(duration, sampleRate).toString().c_str(); + list << QString("%1").arg(level); + if (label != "") list << label; + return list.join(delimiter); + } + + struct Comparator { + bool operator()(const FlexiNote &p1, + const FlexiNote &p2) const { + if (p1.frame != p2.frame) return p1.frame < p2.frame; + if (p1.value != p2.value) return p1.value < p2.value; + if (p1.duration != p2.duration) return p1.duration < p2.duration; + if (p1.level != p2.level) return p1.level < p2.level; + return p1.label < p2.label; + } + }; + + struct OrderComparator { + bool operator()(const FlexiNote &p1, + const FlexiNote &p2) const { + return p1.frame < p2.frame; + } + }; +}; + + +class FlexiNoteModel : public IntervalModel +{ + Q_OBJECT + +public: + FlexiNoteModel(size_t sampleRate, size_t resolution, + bool notifyOnAdd = true) : + IntervalModel(sampleRate, resolution, notifyOnAdd), + m_valueQuantization(0) + { + PlayParameterRepository::getInstance()->addPlayable(this); + } + + FlexiNoteModel(size_t sampleRate, size_t resolution, + float valueMinimum, float valueMaximum, + bool notifyOnAdd = true) : + IntervalModel(sampleRate, resolution, + valueMinimum, valueMaximum, + notifyOnAdd), + m_valueQuantization(0) + { + PlayParameterRepository::getInstance()->addPlayable(this); + } + + virtual ~FlexiNoteModel() + { + PlayParameterRepository::getInstance()->removePlayable(this); + } + + float getValueQuantization() const { return m_valueQuantization; } + void setValueQuantization(float q) { m_valueQuantization = q; } + float getValueMinimum() const { return 33; } + float getValueMaximum() const { return 88; } + + QString getTypeName() const { return tr("FlexiNote"); } + + virtual bool canPlay() const { return true; } + + virtual QString getDefaultPlayPluginId() const + { + return "dssi:_builtin:sample_player"; + } + + virtual QString getDefaultPlayPluginConfiguration() const + { + return ""; + } + + virtual void toXml(QTextStream &out, + QString indent = "", + QString extraAttributes = "") const + { + std::cerr << "FlexiNoteModel::toXml: extraAttributes = \"" + << extraAttributes.toStdString() << std::endl; + + IntervalModel::toXml + (out, + indent, + QString("%1 subtype=\"note\" valueQuantization=\"%2\"") + .arg(extraAttributes).arg(m_valueQuantization)); + } + + /** + * TabularModel methods. + */ + + virtual int getColumnCount() const + { + return 6; + } + + virtual QString getHeading(int column) const + { + switch (column) { + case 0: return tr("Time"); + case 1: return tr("Frame"); + case 2: return tr("Pitch"); + case 3: return tr("Duration"); + case 4: return tr("Level"); + case 5: return tr("Label"); + default: return tr("Unknown"); + } + } + + virtual QVariant getData(int row, int column, int role) const + { + if (column < 4) { + return IntervalModel::getData(row, column, role); + } + + PointListConstIterator i = getPointListIteratorForRow(row); + if (i == m_points.end()) return QVariant(); + + switch (column) { + case 4: return i->level; + case 5: return i->label; + default: return QVariant(); + } + } + + virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role) + { + if (column < 4) { + return IntervalModel::getSetDataCommand + (row, column, value, role); + } + + if (role != Qt::EditRole) return 0; + PointListConstIterator i = getPointListIteratorForRow(row); + if (i == m_points.end()) return 0; + EditCommand *command = new EditCommand(this, tr("Edit Data")); + + Point point(*i); + command->deletePoint(point); + + switch (column) { + case 4: point.level = value.toDouble(); break; + case 5: point.label = value.toString(); break; + } + + command->addPoint(point); + return command->finish(); + } + + virtual SortType getSortType(int column) const + { + if (column == 5) return SortAlphabetical; + return SortNumeric; + } + +protected: + float m_valueQuantization; +}; + +#endif diff -r 06c64a1c6785 -r 54829c1e155e plugin/DSSIPluginInstance.cpp --- a/plugin/DSSIPluginInstance.cpp Mon Jul 08 14:49:28 2013 +0100 +++ b/plugin/DSSIPluginInstance.cpp Fri Jul 12 13:10:28 2013 +0100 @@ -34,7 +34,7 @@ #endif //#define DEBUG_DSSI 1 -//#define DEBUG_DSSI_PROCESS 1 +#define DEBUG_DSSI_PROCESS 1 #define EVENT_BUFFER_SIZE 1023 diff -r 06c64a1c6785 -r 54829c1e155e plugin/plugins/SamplePlayer.cpp --- a/plugin/plugins/SamplePlayer.cpp Mon Jul 08 14:49:28 2013 +0100 +++ b/plugin/plugins/SamplePlayer.cpp Fri Jul 12 13:10:28 2013 +0100 @@ -157,6 +157,7 @@ } SamplePlayer *player = new SamplePlayer(rate); + // std::cerr << "Instantiated sample player " << std::endl; if (hostDescriptor->request_non_rt_thread(player, workThreadCallback)) { SVDEBUG << "SamplePlayer::instantiate: Host rejected request_non_rt_thread call, not instantiating" << endl; diff -r 06c64a1c6785 -r 54829c1e155e svcore.pro --- a/svcore.pro Mon Jul 08 14:49:28 2013 +0100 +++ b/svcore.pro Fri Jul 12 13:10:28 2013 +0100 @@ -155,6 +155,7 @@ data/model/Model.h \ data/model/ModelDataTableModel.h \ data/model/NoteModel.h \ + data/model/FlexiNoteModel.h \ data/model/PathModel.h \ data/model/PowerOfSqrtTwoZoomConstraint.h \ data/model/PowerOfTwoZoomConstraint.h \ @@ -234,8 +235,8 @@ plugin/api/alsa/seq_event.h \ plugin/api/alsa/seq_midi_event.h \ plugin/api/alsa/sound/asequencer.h - - + + SOURCES += plugin/DSSIPluginFactory.cpp \ plugin/DSSIPluginInstance.cpp \ plugin/FeatureExtractionPluginFactory.cpp \ @@ -246,10 +247,10 @@ plugin/RealTimePluginFactory.cpp \ plugin/RealTimePluginInstance.cpp \ plugin/plugins/SamplePlayer.cpp - -!linux* { -SOURCES += plugin/api/dssi_alsa_compat.c -} + +!linux* { +SOURCES += plugin/api/dssi_alsa_compat.c +} HEADERS += rdf/PluginRDFIndexer.h \ rdf/PluginRDFDescription.h \ diff -r 06c64a1c6785 -r 54829c1e155e transform/FeatureExtractionModelTransformer.cpp --- a/transform/FeatureExtractionModelTransformer.cpp Mon Jul 08 14:49:28 2013 +0100 +++ b/transform/FeatureExtractionModelTransformer.cpp Fri Jul 12 13:10:28 2013 +0100 @@ -27,6 +27,7 @@ #include "data/model/EditableDenseThreeDimensionalModel.h" #include "data/model/DenseTimeValueModel.h" #include "data/model/NoteModel.h" +#include "data/model/FlexiNoteModel.h" #include "data/model/RegionModel.h" #include "data/model/FFTModel.h" #include "data/model/WaveFileModel.h" @@ -37,12 +38,14 @@ #include FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in, - const Transform &transform) : + const Transform &transform, + const PreferredOutputModel outputmodel) : ModelTransformer(in, transform), m_plugin(0), m_descriptor(0), m_outputNo(0), - m_fixedRateFeatureNo(-1) // we increment before use + m_fixedRateFeatureNo(-1), // we increment before use + m_preferredOutputModel(outputmodel) { // SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << pluginId << ", outputName " << m_transform.getOutput() << endl; @@ -295,15 +298,25 @@ // problem of determining whether to use that here (if bin // count > 1). But we don't. - if (isNoteModel) { + if (isNoteModel && m_preferredOutputModel == NoteOutputModel) { NoteModel *model; if (haveExtents) { - model = new NoteModel - (modelRate, modelResolution, minValue, maxValue, false); + model = new NoteModel (modelRate, modelResolution, minValue, maxValue, false); } else { - model = new NoteModel - (modelRate, modelResolution, false); + model = new NoteModel (modelRate, modelResolution, false); + } + model->setScaleUnits(m_descriptor->unit.c_str()); + m_output = model; + + // GF: FlexiNoteModel is selected if the m_preferredOutputModel is set + } else if (isNoteModel && m_preferredOutputModel == FlexiNoteOutputModel) { + + FlexiNoteModel *model; + if (haveExtents) { + model = new FlexiNoteModel (modelRate, modelResolution, minValue, maxValue, false); + } else { + model = new FlexiNoteModel (modelRate, modelResolution, false); } model->setScaleUnits(m_descriptor->unit.c_str()); m_output = model; @@ -715,7 +728,7 @@ model->addPoint(SparseTimeValueModel::Point(frame, value, label)); } - } else if (isOutput() || isOutput()) { + } else if (isOutput() || isOutput() || isOutput()) { //GF: Added Note Model int index = 0; @@ -732,8 +745,24 @@ duration = feature.values[index++]; } } - - if (isOutput()) { + + if (isOutput()) { // GF: added for flexi note model + + float velocity = 100; + if (feature.values.size() > index) { + velocity = feature.values[index++]; + } + if (velocity < 0) velocity = 127; + if (velocity > 127) velocity = 127; + + FlexiNoteModel *model = getConformingOutput(); + if (!model) return; + model->addPoint(FlexiNoteModel::Point(frame, value, // value is pitch + lrintf(duration), + velocity / 127.f, + feature.label.c_str())); + // GF: end -- added for flexi note model + } else if (isOutput()) { float velocity = 100; if (feature.values.size() > index) { @@ -749,6 +778,7 @@ velocity / 127.f, feature.label.c_str())); } else { + RegionModel *model = getConformingOutput(); if (!model) return; @@ -821,6 +851,12 @@ NoteModel *model = getConformingOutput(); if (!model) return; model->setCompletion(completion, true); + + } else if (isOutput()) { + + FlexiNoteModel *model = getConformingOutput(); + if (!model) return; + model->setCompletion(completion, true); } else if (isOutput()) { diff -r 06c64a1c6785 -r 54829c1e155e transform/FeatureExtractionModelTransformer.h --- a/transform/FeatureExtractionModelTransformer.h Mon Jul 08 14:49:28 2013 +0100 +++ b/transform/FeatureExtractionModelTransformer.h Fri Jul 12 13:10:28 2013 +0100 @@ -31,8 +31,16 @@ Q_OBJECT public: + enum PreferredOutputModel { + NoteOutputModel, + FlexiNoteOutputModel, + UndefinedOutputModel = 255 + }; + FeatureExtractionModelTransformer(Input input, - const Transform &transform); + const Transform &transform, + const PreferredOutputModel outputmodel); + virtual ~FeatureExtractionModelTransformer(); protected: @@ -42,6 +50,7 @@ Vamp::Plugin::OutputDescriptor *m_descriptor; int m_fixedRateFeatureNo; // to assign times to FixedSampleRate features int m_outputNo; + PreferredOutputModel m_preferredOutputModel; void createOutputModel(); diff -r 06c64a1c6785 -r 54829c1e155e transform/ModelTransformerFactory.cpp --- a/transform/ModelTransformerFactory.cpp Mon Jul 08 14:49:28 2013 +0100 +++ b/transform/ModelTransformerFactory.cpp Fri Jul 12 13:10:28 2013 +0100 @@ -173,7 +173,7 @@ if (FeatureExtractionPluginFactory::instanceFor(id)) { transformer = - new FeatureExtractionModelTransformer(input, transform); + new FeatureExtractionModelTransformer(input, transform, m_preferredOutputModel); } else if (RealTimePluginFactory::instanceFor(id)) { @@ -193,10 +193,13 @@ Model * ModelTransformerFactory::transform(const Transform &transform, const ModelTransformer::Input &input, - QString &message) + QString &message, + /* outputmodel default value = FeatureExtractionModelTransformer::NoteOutputModel */ + FeatureExtractionModelTransformer::PreferredOutputModel outputmodel) { SVDEBUG << "ModelTransformerFactory::transform: Constructing transformer with input model " << input.getModel() << endl; + m_preferredOutputModel = outputmodel; ModelTransformer *t = createTransformer(transform, input); if (!t) return 0; diff -r 06c64a1c6785 -r 54829c1e155e transform/ModelTransformerFactory.h --- a/transform/ModelTransformerFactory.h Mon Jul 08 14:49:28 2013 +0100 +++ b/transform/ModelTransformerFactory.h Fri Jul 12 13:10:28 2013 +0100 @@ -18,6 +18,7 @@ #include "Transform.h" #include "TransformDescription.h" +#include "FeatureExtractionModelTransformer.h" #include "ModelTransformer.h" @@ -83,9 +84,10 @@ * The returned model is owned by the caller and must be deleted * when no longer needed. */ - Model *transform(const Transform &transform, - const ModelTransformer::Input &input, - QString &message); + Model *transform(const Transform &transform, + const ModelTransformer::Input &input, + QString &message, + const FeatureExtractionModelTransformer::PreferredOutputModel outputmodel = FeatureExtractionModelTransformer::NoteOutputModel); protected slots: void transformerFinished(); @@ -103,6 +105,11 @@ TransformerSet m_runningTransformers; static ModelTransformerFactory *m_instance; + /** + * allows the FeatureExtractionModelTransformer output model to be selected externally, + * but only in case of the need for NoteModel or FlexiNoteModel + */ + FeatureExtractionModelTransformer::PreferredOutputModel m_preferredOutputModel ; };