annotate src/vamp-hostsdk/PluginChannelAdapter.cpp @ 287:f3b1ba71a305

* When calculating timestamps in order to write them into features that previously lacked them, from a buffering adapter, we need to take into account any timestamp adjustment used by other wrappers that are being wrapped by this one (i.e. input domain adapter)
author cannam
date Thu, 10 Sep 2009 15:21:34 +0000
parents e0b7a35ea18e
children c97e70ed5abc
rev   line source
cannam@233 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@233 2
cannam@233 3 /*
cannam@233 4 Vamp
cannam@233 5
cannam@233 6 An API for audio analysis and feature extraction plugins.
cannam@233 7
cannam@233 8 Centre for Digital Music, Queen Mary, University of London.
cannam@233 9 Copyright 2006-2007 Chris Cannam and QMUL.
cannam@233 10
cannam@233 11 Permission is hereby granted, free of charge, to any person
cannam@233 12 obtaining a copy of this software and associated documentation
cannam@233 13 files (the "Software"), to deal in the Software without
cannam@233 14 restriction, including without limitation the rights to use, copy,
cannam@233 15 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@233 16 of the Software, and to permit persons to whom the Software is
cannam@233 17 furnished to do so, subject to the following conditions:
cannam@233 18
cannam@233 19 The above copyright notice and this permission notice shall be
cannam@233 20 included in all copies or substantial portions of the Software.
cannam@233 21
cannam@233 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@233 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@233 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@233 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@233 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@233 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@233 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@233 29
cannam@233 30 Except as contained in this notice, the names of the Centre for
cannam@233 31 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@233 32 shall not be used in advertising or otherwise to promote the sale,
cannam@233 33 use or other dealings in this Software without prior written
cannam@233 34 authorization.
cannam@233 35 */
cannam@233 36
cannam@233 37 #include <vamp-hostsdk/PluginChannelAdapter.h>
cannam@233 38
cannam@263 39 _VAMP_SDK_HOSTSPACE_BEGIN(PluginChannelAdapter.cpp)
cannam@263 40
cannam@233 41 namespace Vamp {
cannam@233 42
cannam@233 43 namespace HostExt {
cannam@233 44
cannam@233 45 class PluginChannelAdapter::Impl
cannam@233 46 {
cannam@233 47 public:
cannam@233 48 Impl(Plugin *plugin);
cannam@233 49 ~Impl();
cannam@233 50
cannam@233 51 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
cannam@233 52
cannam@233 53 FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
cannam@233 54 FeatureSet processInterleaved(const float *inputBuffers, RealTime timestamp);
cannam@233 55
cannam@233 56 protected:
cannam@233 57 Plugin *m_plugin;
cannam@233 58 size_t m_blockSize;
cannam@233 59 size_t m_inputChannels;
cannam@233 60 size_t m_pluginChannels;
cannam@233 61 float **m_buffer;
cannam@233 62 float **m_deinterleave;
cannam@233 63 const float **m_forwardPtrs;
cannam@233 64 };
cannam@233 65
cannam@233 66 PluginChannelAdapter::PluginChannelAdapter(Plugin *plugin) :
cannam@233 67 PluginWrapper(plugin)
cannam@233 68 {
cannam@233 69 m_impl = new Impl(plugin);
cannam@233 70 }
cannam@233 71
cannam@233 72 PluginChannelAdapter::~PluginChannelAdapter()
cannam@233 73 {
cannam@233 74 delete m_impl;
cannam@233 75 }
cannam@233 76
cannam@233 77 bool
cannam@233 78 PluginChannelAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@233 79 {
cannam@233 80 return m_impl->initialise(channels, stepSize, blockSize);
cannam@233 81 }
cannam@233 82
cannam@233 83 PluginChannelAdapter::FeatureSet
cannam@233 84 PluginChannelAdapter::process(const float *const *inputBuffers,
cannam@233 85 RealTime timestamp)
cannam@233 86 {
cannam@233 87 return m_impl->process(inputBuffers, timestamp);
cannam@233 88 }
cannam@233 89
cannam@233 90 PluginChannelAdapter::FeatureSet
cannam@233 91 PluginChannelAdapter::processInterleaved(const float *inputBuffers,
cannam@233 92 RealTime timestamp)
cannam@233 93 {
cannam@233 94 return m_impl->processInterleaved(inputBuffers, timestamp);
cannam@233 95 }
cannam@233 96
cannam@233 97 PluginChannelAdapter::Impl::Impl(Plugin *plugin) :
cannam@233 98 m_plugin(plugin),
cannam@233 99 m_blockSize(0),
cannam@233 100 m_inputChannels(0),
cannam@233 101 m_pluginChannels(0),
cannam@233 102 m_buffer(0),
cannam@233 103 m_deinterleave(0),
cannam@233 104 m_forwardPtrs(0)
cannam@233 105 {
cannam@233 106 }
cannam@233 107
cannam@233 108 PluginChannelAdapter::Impl::~Impl()
cannam@233 109 {
cannam@233 110 // the adapter will delete the plugin
cannam@233 111
cannam@233 112 if (m_buffer) {
cannam@233 113 if (m_inputChannels > m_pluginChannels) {
cannam@233 114 delete[] m_buffer[0];
cannam@233 115 } else {
cannam@233 116 for (size_t i = 0; i < m_pluginChannels - m_inputChannels; ++i) {
cannam@233 117 delete[] m_buffer[i];
cannam@233 118 }
cannam@233 119 }
cannam@233 120 delete[] m_buffer;
cannam@233 121 m_buffer = 0;
cannam@233 122 }
cannam@233 123
cannam@233 124 if (m_deinterleave) {
cannam@233 125 for (size_t i = 0; i < m_inputChannels; ++i) {
cannam@233 126 delete[] m_deinterleave[i];
cannam@233 127 }
cannam@233 128 delete[] m_deinterleave;
cannam@233 129 m_deinterleave = 0;
cannam@233 130 }
cannam@233 131
cannam@233 132 if (m_forwardPtrs) {
cannam@233 133 delete[] m_forwardPtrs;
cannam@233 134 m_forwardPtrs = 0;
cannam@233 135 }
cannam@233 136 }
cannam@233 137
cannam@233 138 bool
cannam@233 139 PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@233 140 {
cannam@233 141 m_blockSize = blockSize;
cannam@233 142
cannam@233 143 size_t minch = m_plugin->getMinChannelCount();
cannam@233 144 size_t maxch = m_plugin->getMaxChannelCount();
cannam@233 145
cannam@233 146 m_inputChannels = channels;
cannam@233 147
cannam@233 148 if (m_inputChannels < minch) {
cannam@233 149
cannam@233 150 m_forwardPtrs = new const float *[minch];
cannam@233 151
cannam@233 152 if (m_inputChannels > 1) {
cannam@233 153 // We need a set of zero-valued buffers to add to the
cannam@233 154 // forwarded pointers
cannam@233 155 m_buffer = new float*[minch - channels];
cannam@233 156 for (size_t i = 0; i < minch; ++i) {
cannam@233 157 m_buffer[i] = new float[blockSize];
cannam@233 158 for (size_t j = 0; j < blockSize; ++j) {
cannam@233 159 m_buffer[i][j] = 0.f;
cannam@233 160 }
cannam@233 161 }
cannam@233 162 }
cannam@233 163
cannam@233 164 m_pluginChannels = minch;
cannam@233 165
cannam@282 166 // std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
cannam@233 167
cannam@233 168 } else if (m_inputChannels > maxch) {
cannam@233 169
cannam@233 170 // We only need m_buffer if we are mixing down to a single
cannam@233 171 // channel -- otherwise we can just forward the same float* as
cannam@233 172 // passed in to process(), expecting the excess to be ignored
cannam@233 173
cannam@233 174 if (maxch == 1) {
cannam@233 175 m_buffer = new float *[1];
cannam@233 176 m_buffer[0] = new float[blockSize];
cannam@233 177
cannam@282 178 // std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl;
cannam@233 179
cannam@233 180 } else {
cannam@233 181
cannam@282 182 // std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
cannam@233 183 }
cannam@233 184
cannam@233 185 m_pluginChannels = maxch;
cannam@233 186
cannam@233 187 } else {
cannam@233 188
cannam@282 189 // std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl;
cannam@233 190 m_pluginChannels = m_inputChannels;
cannam@233 191 }
cannam@233 192
cannam@233 193 return m_plugin->initialise(m_pluginChannels, stepSize, blockSize);
cannam@233 194 }
cannam@233 195
cannam@233 196 PluginChannelAdapter::FeatureSet
cannam@233 197 PluginChannelAdapter::Impl::processInterleaved(const float *inputBuffers,
cannam@233 198 RealTime timestamp)
cannam@233 199 {
cannam@233 200 if (!m_deinterleave) {
cannam@233 201 m_deinterleave = new float *[m_inputChannels];
cannam@233 202 for (size_t i = 0; i < m_inputChannels; ++i) {
cannam@233 203 m_deinterleave[i] = new float[m_blockSize];
cannam@233 204 }
cannam@233 205 }
cannam@233 206
cannam@233 207 for (size_t i = 0; i < m_inputChannels; ++i) {
cannam@233 208 for (size_t j = 0; j < m_blockSize; ++j) {
cannam@233 209 m_deinterleave[i][j] = inputBuffers[j * m_inputChannels + i];
cannam@233 210 }
cannam@233 211 }
cannam@233 212
cannam@233 213 return process(m_deinterleave, timestamp);
cannam@233 214 }
cannam@233 215
cannam@233 216 PluginChannelAdapter::FeatureSet
cannam@233 217 PluginChannelAdapter::Impl::process(const float *const *inputBuffers,
cannam@233 218 RealTime timestamp)
cannam@233 219 {
cannam@233 220 // std::cerr << "PluginChannelAdapter::process: " << m_inputChannels << " -> " << m_pluginChannels << " channels" << std::endl;
cannam@233 221
cannam@233 222 if (m_inputChannels < m_pluginChannels) {
cannam@233 223
cannam@233 224 if (m_inputChannels == 1) {
cannam@233 225 for (size_t i = 0; i < m_pluginChannels; ++i) {
cannam@233 226 m_forwardPtrs[i] = inputBuffers[0];
cannam@233 227 }
cannam@233 228 } else {
cannam@233 229 for (size_t i = 0; i < m_inputChannels; ++i) {
cannam@233 230 m_forwardPtrs[i] = inputBuffers[i];
cannam@233 231 }
cannam@233 232 for (size_t i = m_inputChannels; i < m_pluginChannels; ++i) {
cannam@233 233 m_forwardPtrs[i] = m_buffer[i - m_inputChannels];
cannam@233 234 }
cannam@233 235 }
cannam@233 236
cannam@233 237 return m_plugin->process(m_forwardPtrs, timestamp);
cannam@233 238
cannam@233 239 } else if (m_inputChannels > m_pluginChannels) {
cannam@233 240
cannam@233 241 if (m_pluginChannels == 1) {
cannam@233 242 for (size_t j = 0; j < m_blockSize; ++j) {
cannam@233 243 m_buffer[0][j] = inputBuffers[0][j];
cannam@233 244 }
cannam@233 245 for (size_t i = 1; i < m_inputChannels; ++i) {
cannam@233 246 for (size_t j = 0; j < m_blockSize; ++j) {
cannam@233 247 m_buffer[0][j] += inputBuffers[i][j];
cannam@233 248 }
cannam@233 249 }
cannam@233 250 for (size_t j = 0; j < m_blockSize; ++j) {
cannam@233 251 m_buffer[0][j] /= m_inputChannels;
cannam@233 252 }
cannam@233 253 return m_plugin->process(m_buffer, timestamp);
cannam@233 254 } else {
cannam@233 255 return m_plugin->process(inputBuffers, timestamp);
cannam@233 256 }
cannam@233 257
cannam@233 258 } else {
cannam@233 259
cannam@233 260 return m_plugin->process(inputBuffers, timestamp);
cannam@233 261 }
cannam@233 262 }
cannam@233 263
cannam@233 264 }
cannam@233 265
cannam@233 266 }
cannam@233 267
cannam@263 268 _VAMP_SDK_HOSTSPACE_END(PluginChannelAdapter.cpp)
cannam@233 269
cannam@263 270