annotate transform/RealTimePluginTransform.cpp @ 115:90ade4fa63be

* Fix serious failure to reload "imported" (i.e. all non-derived non-main) models from .sv file * Give a short playback duration to notes with formal duration of 0 or 1 * Show crosshairs on spectrogram even when there is another layer on top (if it isn't opaque) * Always paste to the same time in the layer as the cut/copy was from, rather than to the playback pointer -- less flexible, but more predictable and less annoying. We probably need a way to get the old behaviour if pasting from somewhere else in the future (e.g. from a text file), but we can't do that yet anyway * Use a compound operation for dragging and resizing selections, so as to ensure a single undo operation works * Use a note model as the target for feature extraction plugins that output variable samplerate data with more than one value per feature * Avoid possible crashes in cut/paste if a layer proves to have no model
author Chris Cannam
date Thu, 11 May 2006 11:35:46 +0000
parents 47fd14e29813
children
rev   line source
Chris@60 1
Chris@60 2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@60 3
Chris@60 4 /*
Chris@60 5 Sonic Visualiser
Chris@60 6 An audio file viewer and annotation editor.
Chris@60 7 Centre for Digital Music, Queen Mary, University of London.
Chris@60 8 This file copyright 2006 Chris Cannam.
Chris@60 9
Chris@60 10 This program is free software; you can redistribute it and/or
Chris@60 11 modify it under the terms of the GNU General Public License as
Chris@60 12 published by the Free Software Foundation; either version 2 of the
Chris@60 13 License, or (at your option) any later version. See the file
Chris@60 14 COPYING included with this distribution for more information.
Chris@60 15 */
Chris@60 16
Chris@60 17 #include "RealTimePluginTransform.h"
Chris@60 18
Chris@60 19 #include "plugin/RealTimePluginFactory.h"
Chris@60 20 #include "plugin/RealTimePluginInstance.h"
Chris@66 21 #include "plugin/PluginXml.h"
Chris@60 22
Chris@60 23 #include "base/Model.h"
Chris@60 24 #include "model/SparseTimeValueModel.h"
Chris@60 25 #include "model/DenseTimeValueModel.h"
Chris@60 26
Chris@60 27 #include <iostream>
Chris@60 28
Chris@60 29 RealTimePluginTransform::RealTimePluginTransform(Model *inputModel,
Chris@60 30 QString pluginId,
Chris@64 31 int channel,
Chris@60 32 QString configurationXml,
Chris@63 33 QString units,
Chris@60 34 int output) :
Chris@60 35 Transform(inputModel),
Chris@60 36 m_plugin(0),
Chris@64 37 m_channel(channel),
Chris@60 38 m_outputNo(output)
Chris@60 39 {
Chris@60 40 std::cerr << "RealTimePluginTransform::RealTimePluginTransform: plugin " << pluginId.toStdString() << ", output " << output << std::endl;
Chris@60 41
Chris@60 42 RealTimePluginFactory *factory =
Chris@60 43 RealTimePluginFactory::instanceFor(pluginId);
Chris@60 44
Chris@60 45 if (!factory) {
Chris@60 46 std::cerr << "RealTimePluginTransform: No factory available for plugin id \""
Chris@60 47 << pluginId.toStdString() << "\"" << std::endl;
Chris@60 48 return;
Chris@60 49 }
Chris@60 50
Chris@60 51 DenseTimeValueModel *input = getInput();
Chris@60 52 if (!input) return;
Chris@60 53
Chris@60 54 m_plugin = factory->instantiatePlugin(pluginId, 0, 0, m_input->getSampleRate(),
Chris@60 55 1024, //!!! wants to be configurable
Chris@60 56 input->getChannelCount());
Chris@60 57
Chris@60 58 if (!m_plugin) {
Chris@60 59 std::cerr << "RealTimePluginTransform: Failed to instantiate plugin \""
Chris@60 60 << pluginId.toStdString() << "\"" << std::endl;
Chris@60 61 return;
Chris@60 62 }
Chris@60 63
Chris@60 64 if (configurationXml != "") {
Chris@66 65 PluginXml(m_plugin).setParametersFromXml(configurationXml);
Chris@60 66 }
Chris@60 67
Chris@60 68 if (m_outputNo >= m_plugin->getControlOutputCount()) {
Chris@60 69 std::cerr << "RealTimePluginTransform: Plugin has fewer than desired " << m_outputNo << " control outputs" << std::endl;
Chris@60 70 return;
Chris@60 71 }
Chris@60 72
Chris@63 73 SparseTimeValueModel *model = new SparseTimeValueModel
Chris@63 74 (input->getSampleRate(), 1024, //!!!
Chris@63 75 0.0, 0.0, false);
Chris@63 76
Chris@63 77 if (units != "") model->setScaleUnits(units);
Chris@63 78
Chris@63 79 m_output = model;
Chris@60 80 }
Chris@60 81
Chris@60 82 RealTimePluginTransform::~RealTimePluginTransform()
Chris@60 83 {
Chris@60 84 delete m_plugin;
Chris@60 85 }
Chris@60 86
Chris@60 87 DenseTimeValueModel *
Chris@60 88 RealTimePluginTransform::getInput()
Chris@60 89 {
Chris@60 90 DenseTimeValueModel *dtvm =
Chris@60 91 dynamic_cast<DenseTimeValueModel *>(getInputModel());
Chris@60 92 if (!dtvm) {
Chris@60 93 std::cerr << "RealTimePluginTransform::getInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl;
Chris@60 94 }
Chris@60 95 return dtvm;
Chris@60 96 }
Chris@60 97
Chris@60 98 void
Chris@60 99 RealTimePluginTransform::run()
Chris@60 100 {
Chris@60 101 DenseTimeValueModel *input = getInput();
Chris@60 102 if (!input) return;
Chris@60 103
Chris@60 104 SparseTimeValueModel *model = dynamic_cast<SparseTimeValueModel *>(m_output);
Chris@60 105 if (!model) return;
Chris@60 106
Chris@60 107 if (m_outputNo >= m_plugin->getControlOutputCount()) return;
Chris@60 108
Chris@60 109 size_t sampleRate = input->getSampleRate();
Chris@60 110 int channelCount = input->getChannelCount();
Chris@64 111 if (m_channel != -1) channelCount = 1;
Chris@64 112
Chris@60 113 size_t blockSize = m_plugin->getBufferSize();
Chris@60 114
Chris@60 115 float **buffers = m_plugin->getAudioInputBuffers();
Chris@60 116
Chris@60 117 size_t startFrame = m_input->getStartFrame();
Chris@60 118 size_t endFrame = m_input->getEndFrame();
Chris@60 119 size_t blockFrame = startFrame;
Chris@60 120
Chris@60 121 size_t prevCompletion = 0;
Chris@60 122
Chris@60 123 int i = 0;
Chris@60 124
Chris@60 125 while (blockFrame < endFrame) {
Chris@60 126
Chris@60 127 size_t completion =
Chris@60 128 (((blockFrame - startFrame) / blockSize) * 99) /
Chris@60 129 ( (endFrame - startFrame) / blockSize);
Chris@60 130
Chris@60 131 size_t got = 0;
Chris@60 132
Chris@60 133 if (channelCount == 1) {
Chris@60 134 got = input->getValues
Chris@64 135 (m_channel, blockFrame, blockFrame + blockSize, buffers[0]);
Chris@60 136 while (got < blockSize) {
Chris@60 137 buffers[0][got++] = 0.0;
Chris@60 138 }
Chris@74 139 if (m_channel == -1 && channelCount > 1) {
Chris@74 140 // use mean instead of sum, as plugin input
Chris@74 141 for (size_t i = 0; i < got; ++i) {
Chris@74 142 buffers[0][i] /= channelCount;
Chris@74 143 }
Chris@74 144 }
Chris@60 145 } else {
Chris@60 146 for (size_t ch = 0; ch < channelCount; ++ch) {
Chris@60 147 got = input->getValues
Chris@60 148 (ch, blockFrame, blockFrame + blockSize, buffers[ch]);
Chris@60 149 while (got < blockSize) {
Chris@60 150 buffers[ch][got++] = 0.0;
Chris@60 151 }
Chris@60 152 }
Chris@60 153 }
Chris@60 154
Chris@66 155 m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
Chris@60 156
Chris@60 157 float value = m_plugin->getControlOutputValue(m_outputNo);
Chris@60 158
Chris@61 159 model->addPoint(SparseTimeValueModel::Point
Chris@61 160 (blockFrame - m_plugin->getLatency(), value, ""));
Chris@60 161
Chris@60 162 if (blockFrame == startFrame || completion > prevCompletion) {
Chris@60 163 model->setCompletion(completion);
Chris@60 164 prevCompletion = completion;
Chris@60 165 }
Chris@60 166
Chris@60 167 blockFrame += blockSize;
Chris@60 168 }
Chris@60 169
Chris@60 170 model->setCompletion(100);
Chris@60 171 }
Chris@60 172