annotate transform/RealTimePluginTransform.cpp @ 25:e74f508db18c

* Add setRatio method to the time stretcher, and make it possible to change the ratio without having to construct and replace the time stretcher. This means we can do it seamlessly. Add a lot more ratios to the time stretch control in the main window
author Chris Cannam
date Fri, 15 Sep 2006 15:35:06 +0000
parents 40116f709d3b
children d88d117e0c34
rev   line source
Chris@0 1
Chris@0 2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 3
Chris@0 4 /*
Chris@0 5 Sonic Visualiser
Chris@0 6 An audio file viewer and annotation editor.
Chris@0 7 Centre for Digital Music, Queen Mary, University of London.
Chris@0 8 This file copyright 2006 Chris Cannam.
Chris@0 9
Chris@0 10 This program is free software; you can redistribute it and/or
Chris@0 11 modify it under the terms of the GNU General Public License as
Chris@0 12 published by the Free Software Foundation; either version 2 of the
Chris@0 13 License, or (at your option) any later version. See the file
Chris@0 14 COPYING included with this distribution for more information.
Chris@0 15 */
Chris@0 16
Chris@0 17 #include "RealTimePluginTransform.h"
Chris@0 18
Chris@0 19 #include "plugin/RealTimePluginFactory.h"
Chris@0 20 #include "plugin/RealTimePluginInstance.h"
Chris@0 21 #include "plugin/PluginXml.h"
Chris@0 22
Chris@1 23 #include "data/model/Model.h"
Chris@1 24 #include "data/model/SparseTimeValueModel.h"
Chris@1 25 #include "data/model/DenseTimeValueModel.h"
Chris@0 26
Chris@0 27 #include <iostream>
Chris@0 28
Chris@0 29 RealTimePluginTransform::RealTimePluginTransform(Model *inputModel,
Chris@0 30 QString pluginId,
Chris@0 31 int channel,
Chris@0 32 QString configurationXml,
Chris@0 33 QString units,
Chris@0 34 int output) :
Chris@0 35 Transform(inputModel),
Chris@0 36 m_plugin(0),
Chris@0 37 m_channel(channel),
Chris@0 38 m_outputNo(output)
Chris@0 39 {
Chris@0 40 std::cerr << "RealTimePluginTransform::RealTimePluginTransform: plugin " << pluginId.toStdString() << ", output " << output << std::endl;
Chris@0 41
Chris@0 42 RealTimePluginFactory *factory =
Chris@0 43 RealTimePluginFactory::instanceFor(pluginId);
Chris@0 44
Chris@0 45 if (!factory) {
Chris@0 46 std::cerr << "RealTimePluginTransform: No factory available for plugin id \""
Chris@0 47 << pluginId.toStdString() << "\"" << std::endl;
Chris@0 48 return;
Chris@0 49 }
Chris@0 50
Chris@0 51 DenseTimeValueModel *input = getInput();
Chris@0 52 if (!input) return;
Chris@0 53
Chris@0 54 m_plugin = factory->instantiatePlugin(pluginId, 0, 0, m_input->getSampleRate(),
Chris@0 55 1024, //!!! wants to be configurable
Chris@0 56 input->getChannelCount());
Chris@0 57
Chris@0 58 if (!m_plugin) {
Chris@0 59 std::cerr << "RealTimePluginTransform: Failed to instantiate plugin \""
Chris@0 60 << pluginId.toStdString() << "\"" << std::endl;
Chris@0 61 return;
Chris@0 62 }
Chris@0 63
Chris@0 64 if (configurationXml != "") {
Chris@0 65 PluginXml(m_plugin).setParametersFromXml(configurationXml);
Chris@0 66 }
Chris@0 67
Chris@0 68 if (m_outputNo >= m_plugin->getControlOutputCount()) {
Chris@0 69 std::cerr << "RealTimePluginTransform: Plugin has fewer than desired " << m_outputNo << " control outputs" << std::endl;
Chris@0 70 return;
Chris@0 71 }
Chris@0 72
Chris@0 73 SparseTimeValueModel *model = new SparseTimeValueModel
Chris@0 74 (input->getSampleRate(), 1024, //!!!
Chris@0 75 0.0, 0.0, false);
Chris@0 76
Chris@0 77 if (units != "") model->setScaleUnits(units);
Chris@0 78
Chris@0 79 m_output = model;
Chris@0 80 }
Chris@0 81
Chris@0 82 RealTimePluginTransform::~RealTimePluginTransform()
Chris@0 83 {
Chris@0 84 delete m_plugin;
Chris@0 85 }
Chris@0 86
Chris@0 87 DenseTimeValueModel *
Chris@0 88 RealTimePluginTransform::getInput()
Chris@0 89 {
Chris@0 90 DenseTimeValueModel *dtvm =
Chris@0 91 dynamic_cast<DenseTimeValueModel *>(getInputModel());
Chris@0 92 if (!dtvm) {
Chris@0 93 std::cerr << "RealTimePluginTransform::getInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl;
Chris@0 94 }
Chris@0 95 return dtvm;
Chris@0 96 }
Chris@0 97
Chris@0 98 void
Chris@0 99 RealTimePluginTransform::run()
Chris@0 100 {
Chris@0 101 DenseTimeValueModel *input = getInput();
Chris@0 102 if (!input) return;
Chris@0 103
Chris@0 104 SparseTimeValueModel *model = dynamic_cast<SparseTimeValueModel *>(m_output);
Chris@0 105 if (!model) return;
Chris@0 106
Chris@0 107 if (m_outputNo >= m_plugin->getControlOutputCount()) return;
Chris@0 108
Chris@0 109 size_t sampleRate = input->getSampleRate();
Chris@0 110 int channelCount = input->getChannelCount();
Chris@0 111 if (m_channel != -1) channelCount = 1;
Chris@0 112
Chris@0 113 size_t blockSize = m_plugin->getBufferSize();
Chris@0 114
Chris@0 115 float **buffers = m_plugin->getAudioInputBuffers();
Chris@0 116
Chris@0 117 size_t startFrame = m_input->getStartFrame();
Chris@0 118 size_t endFrame = m_input->getEndFrame();
Chris@0 119 size_t blockFrame = startFrame;
Chris@0 120
Chris@0 121 size_t prevCompletion = 0;
Chris@0 122
Chris@0 123 int i = 0;
Chris@0 124
Chris@0 125 while (blockFrame < endFrame) {
Chris@0 126
Chris@0 127 size_t completion =
Chris@0 128 (((blockFrame - startFrame) / blockSize) * 99) /
Chris@0 129 ( (endFrame - startFrame) / blockSize);
Chris@0 130
Chris@0 131 size_t got = 0;
Chris@0 132
Chris@0 133 if (channelCount == 1) {
Chris@0 134 got = input->getValues
Chris@0 135 (m_channel, blockFrame, blockFrame + blockSize, buffers[0]);
Chris@0 136 while (got < blockSize) {
Chris@0 137 buffers[0][got++] = 0.0;
Chris@0 138 }
Chris@0 139 if (m_channel == -1 && channelCount > 1) {
Chris@0 140 // use mean instead of sum, as plugin input
Chris@0 141 for (size_t i = 0; i < got; ++i) {
Chris@0 142 buffers[0][i] /= channelCount;
Chris@0 143 }
Chris@0 144 }
Chris@0 145 } else {
Chris@0 146 for (size_t ch = 0; ch < channelCount; ++ch) {
Chris@0 147 got = input->getValues
Chris@0 148 (ch, blockFrame, blockFrame + blockSize, buffers[ch]);
Chris@0 149 while (got < blockSize) {
Chris@0 150 buffers[ch][got++] = 0.0;
Chris@0 151 }
Chris@0 152 }
Chris@0 153 }
Chris@0 154
Chris@0 155 m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
Chris@0 156
Chris@0 157 float value = m_plugin->getControlOutputValue(m_outputNo);
Chris@0 158
Chris@0 159 model->addPoint(SparseTimeValueModel::Point
Chris@0 160 (blockFrame - m_plugin->getLatency(), value, ""));
Chris@0 161
Chris@0 162 if (blockFrame == startFrame || completion > prevCompletion) {
Chris@0 163 model->setCompletion(completion);
Chris@0 164 prevCompletion = completion;
Chris@0 165 }
Chris@0 166
Chris@0 167 blockFrame += blockSize;
Chris@0 168 }
Chris@0 169
Chris@0 170 model->setCompletion(100);
Chris@0 171 }
Chris@0 172