Mercurial > hg > vamp-plugin-sdk
diff src/vamp-hostsdk/PluginInputDomainAdapter.cpp @ 289:3e5ab1c7ea8c
* Implementation of ShiftData process method
author | cannam |
---|---|
date | Wed, 16 Sep 2009 11:27:15 +0000 |
parents | 283e15f6e548 |
children | c97e70ed5abc |
line wrap: on
line diff
--- a/src/vamp-hostsdk/PluginInputDomainAdapter.cpp Tue Sep 15 16:24:53 2009 +0000 +++ b/src/vamp-hostsdk/PluginInputDomainAdapter.cpp Wed Sep 16 11:27:15 2009 +0000 @@ -108,8 +108,9 @@ ProcessTimestampMethod m_method; int m_processCount; - FeatureSet prepadProcess(const float *const *inputBuffers, - RealTime timestamp); + float **m_shiftBuffers; +// FeatureSet prepadProcess(const float *const *inputBuffers, +// RealTime timestamp); #ifdef HAVE_FFTW3 fftw_plan m_plan; @@ -121,6 +122,9 @@ double *ri, double *ii, double *ro, double *io); #endif + FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp); + FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp); + size_t makeBlockSizeAcceptable(size_t) const; }; @@ -201,6 +205,7 @@ m_window(0), m_method(ShiftTimestamp), m_processCount(0), + m_shiftBuffers(0), #ifdef HAVE_FFTW3 m_plan(0), m_cbuf(0) @@ -215,6 +220,13 @@ { // the adapter will delete the plugin + if (m_shiftBuffers) { + for (int c = 0; c < m_channels; ++c) { + delete[] m_shiftBuffers[c]; + } + delete[] m_shiftBuffers; + } + if (m_channels > 0) { for (int c = 0; c < m_channels; ++c) { delete[] m_freqbuf[c]; @@ -396,6 +408,8 @@ { if (m_plugin->getInputDomain() == TimeDomain) { return RealTime::zeroTime; + } else if (m_method == ShiftData) { + return RealTime::zeroTime; } else { return RealTime::frame2RealTime (m_blockSize/2, int(m_inputSampleRate + 0.5)); @@ -422,61 +436,18 @@ return m_plugin->process(inputBuffers, timestamp); } - // The timestamp supplied should be (according to the Vamp::Plugin - // spec) the time of the start of the time-domain input block. - // However, we want to pass to the plugin an FFT output calculated - // from the block of samples _centred_ on that timestamp. - // - // We have two options: - // - // 1. Buffer the input, calculating the fft of the values at the - // passed-in block minus blockSize/2 rather than starting at the - // passed-in block. So each time we call process on the plugin, - // we are passing in the same timestamp as was passed to our own - // process plugin, but not (the frequency domain representation - // of) the same set of samples. Advantages: avoids confusion in - // the host by ensuring the returned values have timestamps - // comparable with that passed in to this function (in fact this - // is pretty much essential for one-value-per-block outputs); - // consistent with hosts such as SV that deal with the - // frequency-domain transform themselves. Disadvantages: means - // making the not necessarily correct assumption that the samples - // preceding the first official block are all zero (or some other - // known value). - // - // 2. Increase the passed-in timestamps by half the blocksize. So - // when we call process, we are passing in the frequency domain - // representation of the same set of samples as passed to us, but - // with a different timestamp. Advantages: simplicity; avoids - // iffy assumption mentioned above. Disadvantages: inconsistency - // with SV in cases where stepSize != blockSize/2; potential - // confusion arising from returned timestamps being calculated - // from the adjusted input timestamps rather than the original - // ones (and inaccuracy where the returned timestamp is implied, - // as in one-value-per-block). - // - // Neither way is ideal, but I don't think either is strictly - // incorrect either. I think this is just a case where the same - // plugin can legitimately produce differing results from the same - // input data, depending on how that data is packaged. - // - // We'll go for option 2, adjusting the timestamps. Note in - // particular that this means some results can differ from those - // produced by SV. + if (m_method == ShiftTimestamp) { + return processShiftingTimestamp(inputBuffers, timestamp); + } else { + return processShiftingData(inputBuffers, timestamp); + } +} -// std::cerr << "PluginInputDomainAdapter: sampleRate " << m_inputSampleRate << ", blocksize " << m_blockSize << ", adjusting time from " << timestamp; - - //!!! update the above comment for ProcessTimestampMethod - - FeatureSet fs; - if (m_method == ShiftTimestamp) { - timestamp = timestamp + getTimestampAdjustment(); - } else if (m_processCount == 0) { - fs = prepadProcess(inputBuffers, timestamp); - } - ++m_processCount; - -// std::cerr << " to " << timestamp << std::endl; +Plugin::FeatureSet +PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers, + RealTime timestamp) +{ + timestamp = timestamp + getTimestampAdjustment(); for (int c = 0; c < m_channels; ++c) { @@ -492,48 +463,85 @@ } #ifdef HAVE_FFTW3 - fftw_execute(m_plan); for (int i = 0; i <= m_blockSize/2; ++i) { m_freqbuf[c][i * 2] = float(m_cbuf[i][0]); m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]); } - #else - fft(m_blockSize, false, m_ri, 0, m_ro, m_io); for (int i = 0; i <= m_blockSize/2; ++i) { m_freqbuf[c][i * 2] = float(m_ro[i]); m_freqbuf[c][i * 2 + 1] = float(m_io[i]); } - #endif } - FeatureSet pfs(m_plugin->process(m_freqbuf, timestamp)); - - if (!fs.empty()) { // add any prepad results back in - for (FeatureSet::const_iterator i = pfs.begin(); i != pfs.end(); ++i) { - for (FeatureList::const_iterator j = i->second.begin(); - j != i->second.end(); ++j) { - fs[i->first].push_back(*j); - } - } - pfs = fs; - } - - return pfs; + return m_plugin->process(m_freqbuf, timestamp); } Plugin::FeatureSet -PluginInputDomainAdapter::Impl::prepadProcess(const float *const *inputBuffers, - RealTime timestamp) +PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers, + RealTime timestamp) { - FeatureSet fs; - //!!! - return fs; + if (m_processCount == 0) { + if (!m_shiftBuffers) { + m_shiftBuffers = new float *[m_channels]; + for (int c = 0; c < m_channels; ++c) { + m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2]; + } + } + for (int c = 0; c < m_channels; ++c) { + for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) { + m_shiftBuffers[c][i] = 0.f; + } + } + } + + for (int c = 0; c < m_channels; ++c) { + for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) { + m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i]; + } + for (int i = 0; i < m_blockSize; ++i) { + m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i]; + } + } + + for (int c = 0; c < m_channels; ++c) { + + for (int i = 0; i < m_blockSize; ++i) { + m_ri[i] = double(m_shiftBuffers[c][i]) * m_window[i]; + } + + for (int i = 0; i < m_blockSize/2; ++i) { + // FFT shift + double value = m_ri[i]; + m_ri[i] = m_ri[i + m_blockSize/2]; + m_ri[i + m_blockSize/2] = value; + } + +#ifdef HAVE_FFTW3 + fftw_execute(m_plan); + + for (int i = 0; i <= m_blockSize/2; ++i) { + m_freqbuf[c][i * 2] = float(m_cbuf[i][0]); + m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]); + } +#else + fft(m_blockSize, false, m_ri, 0, m_ro, m_io); + + for (int i = 0; i <= m_blockSize/2; ++i) { + m_freqbuf[c][i * 2] = float(m_ro[i]); + m_freqbuf[c][i * 2 + 1] = float(m_io[i]); + } +#endif + } + + ++m_processCount; + + return m_plugin->process(m_freqbuf, timestamp); } #ifndef HAVE_FFTW3