Mercurial > hg > svcore
changeset 1096:4d9816ba0ebe simple-fft-model
Rework audio file reader API to prefer using std containers
line wrap: on
line diff
--- a/data/fileio/AudioFileReader.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/fileio/AudioFileReader.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -17,15 +17,17 @@ using std::vector; -vector<SampleBlock> +vector<vector<float>> AudioFileReader::getDeInterleavedFrames(sv_frame_t start, sv_frame_t count) const { - SampleBlock interleaved = getInterleavedFrames(start, count); + vector<float> interleaved = getInterleavedFrames(start, count); int channels = getChannelCount(); + if (channels == 1) return { interleaved }; + sv_frame_t rc = interleaved.size() / channels; - vector<SampleBlock> frames(channels, SampleBlock(rc, 0.f)); + vector<vector<float>> frames(channels, vector<float>(rc, 0.f)); for (int c = 0; c < channels; ++c) { for (sv_frame_t i = 0; i < rc; ++i) {
--- a/data/fileio/AudioFileReader.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/fileio/AudioFileReader.h Mon Jun 15 12:19:47 2015 +0100 @@ -24,8 +24,6 @@ #include <vector> #include <map> -typedef std::vector<float> SampleBlock; - class AudioFileReader : public QObject { Q_OBJECT @@ -85,16 +83,14 @@ /** * Return interleaved samples for count frames from index start. - * The resulting sample block will contain count * - * getChannelCount() samples (or fewer if end of file is - * reached). The caller does not need to allocate space and any - * existing content in the SampleBlock will be erased. + * The resulting vector will contain count * getChannelCount() + * samples (or fewer if end of file is reached). * * The subclass implementations of this function must be * thread-safe -- that is, safe to call from multiple threads with * different arguments on the same object at the same time. */ - virtual SampleBlock getInterleavedFrames(sv_frame_t start, sv_frame_t count) const = 0; + virtual std::vector<float> getInterleavedFrames(sv_frame_t start, sv_frame_t count) const = 0; /** * Return de-interleaved samples for count frames from index @@ -103,7 +99,7 @@ * will contain getChannelCount() sample blocks of count samples * each (or fewer if end of file is reached). */ - virtual std::vector<SampleBlock> getDeInterleavedFrames(sv_frame_t start, sv_frame_t count) const; + virtual std::vector<std::vector<float> > getDeInterleavedFrames(sv_frame_t start, sv_frame_t count) const; // only subclasses that do not know exactly how long the audio // file is until it's been completely decoded should implement this
--- a/data/fileio/CodedAudioFileReader.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/fileio/CodedAudioFileReader.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -27,6 +27,8 @@ #include <QDir> #include <QMutexLocker> +using namespace std; + CodedAudioFileReader::CodedAudioFileReader(CacheMode cacheMode, sv_samplerate_t targetRate, bool normalised) : @@ -242,7 +244,7 @@ } void -CodedAudioFileReader::addSamplesToDecodeCache(const SampleBlock &samples) +CodedAudioFileReader::addSamplesToDecodeCache(const vector<float> &samples) { QMutexLocker locker(&m_cacheMutex); @@ -352,9 +354,7 @@ case CacheInMemory: m_dataLock.lockForWrite(); - for (sv_frame_t s = 0; s < count; ++s) { - m_data.push_back(buffer[s]); - } + m_data.insert(m_data.end(), buffer, buffer + count); m_dataLock.unlock(); break; } @@ -408,7 +408,7 @@ } } -SampleBlock +vector<float> CodedAudioFileReader::getInterleavedFrames(sv_frame_t start, sv_frame_t count) const { // Lock is only required in CacheInMemory mode (the cache file @@ -417,10 +417,10 @@ if (!m_initialised) { SVDEBUG << "CodedAudioFileReader::getInterleavedFrames: not initialised" << endl; - return SampleBlock(); + return {}; } - SampleBlock frames; + vector<float> frames; switch (m_cacheMode) { @@ -432,8 +432,8 @@ case CacheInMemory: { - if (!isOK()) return SampleBlock(); - if (count == 0) return SampleBlock(); + if (!isOK()) return {}; + if (count == 0) return {}; sv_frame_t idx = start * m_channelCount; sv_frame_t i = 0;
--- a/data/fileio/CodedAudioFileReader.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/fileio/CodedAudioFileReader.h Mon Jun 15 12:19:47 2015 +0100 @@ -38,7 +38,7 @@ CacheInMemory }; - virtual SampleBlock getInterleavedFrames(sv_frame_t start, sv_frame_t count) const; + virtual std::vector<float> getInterleavedFrames(sv_frame_t start, sv_frame_t count) const; virtual sv_samplerate_t getNativeRate() const { return m_fileRate; } @@ -60,7 +60,7 @@ // may throw InsufficientDiscSpace: void addSamplesToDecodeCache(float **samples, sv_frame_t nframes); void addSamplesToDecodeCache(float *samplesInterleaved, sv_frame_t nframes); - void addSamplesToDecodeCache(const SampleBlock &interleaved); + void addSamplesToDecodeCache(const std::vector<float> &interleaved); // may throw InsufficientDiscSpace: void finishDecodeCache(); @@ -78,7 +78,7 @@ protected: QMutex m_cacheMutex; CacheMode m_cacheMode; - SampleBlock m_data; + std::vector<float> m_data; mutable QReadWriteLock m_dataLock; bool m_initialised; Serialiser *m_serialiser;
--- a/data/fileio/DecodingWavFileReader.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/fileio/DecodingWavFileReader.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -21,6 +21,8 @@ #include <QFileInfo> +using namespace std; + DecodingWavFileReader::DecodingWavFileReader(FileSource source, ResampleMode resampleMode, CacheMode mode, @@ -67,7 +69,7 @@ sv_frame_t blockSize = 16384; sv_frame_t total = m_original->getFrameCount(); - SampleBlock block; + vector<float> block; for (sv_frame_t i = 0; i < total; i += blockSize) { @@ -124,7 +126,7 @@ sv_frame_t blockSize = 16384; sv_frame_t total = m_reader->m_original->getFrameCount(); - SampleBlock block; + vector<float> block; for (sv_frame_t i = 0; i < total; i += blockSize) { @@ -147,7 +149,7 @@ } void -DecodingWavFileReader::addBlock(const SampleBlock &frames) +DecodingWavFileReader::addBlock(const vector<float> &frames) { addSamplesToDecodeCache(frames); @@ -167,7 +169,7 @@ } void -DecodingWavFileReader::getSupportedExtensions(std::set<QString> &extensions) +DecodingWavFileReader::getSupportedExtensions(set<QString> &extensions) { WavFileReader::getSupportedExtensions(extensions); }
--- a/data/fileio/DecodingWavFileReader.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/fileio/DecodingWavFileReader.h Mon Jun 15 12:19:47 2015 +0100 @@ -69,7 +69,7 @@ WavFileReader *m_original; ProgressReporter *m_reporter; - void addBlock(const SampleBlock &frames); + void addBlock(const std::vector<float> &frames); class DecodeThread : public Thread {
--- a/data/fileio/WavFileReader.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/fileio/WavFileReader.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -20,6 +20,8 @@ #include <QMutexLocker> #include <QFileInfo> +using namespace std; + WavFileReader::WavFileReader(FileSource source, bool fileUpdating) : m_file(0), m_source(source), @@ -119,53 +121,56 @@ m_updating = false; } -SampleBlock +vector<float> WavFileReader::getInterleavedFrames(sv_frame_t start, sv_frame_t count) const { - if (count == 0) return SampleBlock(); + if (count == 0) return {}; QMutexLocker locker(&m_mutex); if (!m_file || !m_channelCount) { - return SampleBlock(); + return {}; } if (start >= m_fileInfo.frames) { // SVDEBUG << "WavFileReader::getInterleavedFrames: " << start // << " > " << m_fileInfo.frames << endl; - return SampleBlock(); + return {}; } if (start + count > m_fileInfo.frames) { count = m_fileInfo.frames - start; } - if (start != m_lastStart || count != m_lastCount) { - - if (sf_seek(m_file, start, SEEK_SET) < 0) { - return SampleBlock(); - } - - sv_frame_t n = count * m_fileInfo.channels; - m_buffer.resize(n); - - sf_count_t readCount = 0; - - if ((readCount = sf_readf_float(m_file, m_buffer.data(), count)) < 0) { - return SampleBlock(); - } - - m_buffer.resize(readCount * m_fileInfo.channels); - - m_lastStart = start; - m_lastCount = readCount; + // Because WaveFileModel::getSummaries() is called separately for + // individual channels, it's quite common for us to be called + // repeatedly for the same data. So this is worth cacheing. + if (start == m_lastStart && count == m_lastCount) { + return m_buffer; + } + + if (sf_seek(m_file, start, SEEK_SET) < 0) { + return {}; } - return m_buffer; + vector<float> data; + sv_frame_t n = count * m_fileInfo.channels; + data.resize(n); + + m_buffer = data; + m_lastStart = start; + m_lastCount = count; + + sf_count_t readCount = 0; + if ((readCount = sf_readf_float(m_file, data.data(), count)) < 0) { + return {}; + } + + return data; } void -WavFileReader::getSupportedExtensions(std::set<QString> &extensions) +WavFileReader::getSupportedExtensions(set<QString> &extensions) { int count; @@ -196,7 +201,7 @@ bool WavFileReader::supportsExtension(QString extension) { - std::set<QString> extensions; + set<QString> extensions; getSupportedExtensions(extensions); return (extensions.find(extension.toLower()) != extensions.end()); }
--- a/data/fileio/WavFileReader.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/fileio/WavFileReader.h Mon Jun 15 12:19:47 2015 +0100 @@ -50,7 +50,7 @@ * Must be safe to call from multiple threads with different * arguments on the same object at the same time. */ - virtual SampleBlock getInterleavedFrames(sv_frame_t start, sv_frame_t count) const; + virtual std::vector<float> getInterleavedFrames(sv_frame_t start, sv_frame_t count) const; static void getSupportedExtensions(std::set<QString> &extensions); static bool supportsExtension(QString ext); @@ -75,8 +75,7 @@ bool m_seekable; mutable QMutex m_mutex; - mutable SampleBlock m_buffer; - mutable sv_frame_t m_bufsiz; + mutable std::vector<float> m_buffer; mutable sv_frame_t m_lastStart; mutable sv_frame_t m_lastCount;
--- a/data/fileio/WavFileWriter.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/fileio/WavFileWriter.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -25,6 +25,8 @@ #include <iostream> #include <cmath> +using namespace std; + WavFileWriter::WavFileWriter(QString path, sv_samplerate_t sampleRate, int channels, @@ -129,8 +131,6 @@ } sv_frame_t bs = 2048; - float *ub = new float[bs]; // uninterleaved buffer (one channel) - float *ib = new float[bs * m_channels]; // interleaved buffer for (MultiSelection::SelectionList::iterator i = selection->getSelections().begin(); @@ -140,16 +140,17 @@ for (sv_frame_t f = f0; f < f1; f += bs) { - sv_frame_t n = std::min(bs, f1 - f); + sv_frame_t n = min(bs, f1 - f); + vector<float> interleaved(n * m_channels, 0.f); for (int c = 0; c < int(m_channels); ++c) { - source->getData(c, f, n, ub); - for (int i = 0; i < n; ++i) { - ib[i * m_channels + c] = ub[i]; + vector<float> chanbuf = source->getData(c, f, n); + for (int i = 0; in_range_for(chanbuf, i); ++i) { + interleaved[i * m_channels + c] = chanbuf[i]; } } - sf_count_t written = sf_writef_float(m_file, ib, n); + sf_count_t written = sf_writef_float(m_file, interleaved.data(), n); if (written < n) { m_error = QString("Only wrote %1 of %2 frames at file frame %3") @@ -159,8 +160,6 @@ } } - delete[] ub; - delete[] ib; if (ownSelection) delete selection; return isOK();
--- a/data/model/AggregateWaveModel.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/AggregateWaveModel.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -19,6 +19,8 @@ #include <QTextStream> +using namespace std; + PowerOfSqrtTwoZoomConstraint AggregateWaveModel::m_zoomConstraint; @@ -92,65 +94,54 @@ return m_components.begin()->model->getSampleRate(); } -sv_frame_t -AggregateWaveModel::getData(int channel, sv_frame_t start, sv_frame_t count, - float *buffer) const +vector<float> +AggregateWaveModel::getData(int channel, sv_frame_t start, sv_frame_t count) const { int ch0 = channel, ch1 = channel; - bool mixing = false; if (channel == -1) { ch0 = 0; ch1 = getChannelCount()-1; - mixing = true; } - float *readbuf = buffer; - if (mixing) { - readbuf = new float[count]; - for (sv_frame_t i = 0; i < count; ++i) { - buffer[i] = 0.f; - } - } + vector<float> result(count, 0.f); sv_frame_t longest = 0; for (int c = ch0; c <= ch1; ++c) { - sv_frame_t here = - m_components[c].model->getData(m_components[c].channel, - start, count, - readbuf); - if (here > longest) { - longest = here; + + auto here = m_components[c].model->getData(m_components[c].channel, + start, count); + if (here.size() > longest) { + longest = here.size(); } - if (here < count) { - for (sv_frame_t i = here; i < count; ++i) { - readbuf[i] = 0.f; - } - } - if (mixing) { - for (sv_frame_t i = 0; i < count; ++i) { - buffer[i] += readbuf[i]; - } + for (sv_frame_t i = 0; in_range_for(here, i); ++i) { + result[i] += here[i]; } } - if (mixing) delete[] readbuf; - return longest; + result.resize(longest); + return result; } -sv_frame_t +vector<vector<float>> AggregateWaveModel::getMultiChannelData(int fromchannel, int tochannel, - sv_frame_t start, sv_frame_t count, - float **buffer) const + sv_frame_t start, sv_frame_t count) const { sv_frame_t min = count; + vector<vector<float>> result; + for (int c = fromchannel; c <= tochannel; ++c) { - sv_frame_t here = getData(c, start, count, buffer[c - fromchannel]); - if (here < min) min = here; + auto here = getData(c, start, count); + if (here.size() < min) min = here.size(); + result.push_back(here); + } + + if (min < count) { + for (auto &v : result) v.resize(min); } - return min; + return result; } int
--- a/data/model/AggregateWaveModel.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/AggregateWaveModel.h Mon Jun 15 12:19:47 2015 +0100 @@ -59,12 +59,9 @@ virtual sv_frame_t getStartFrame() const { return 0; } virtual sv_frame_t getEndFrame() const { return getFrameCount(); } - virtual sv_frame_t getData(int channel, sv_frame_t start, sv_frame_t count, - float *buffer) const; + virtual std::vector<float> getData(int channel, sv_frame_t start, sv_frame_t count) const; - virtual sv_frame_t getMultiChannelData(int fromchannel, int tochannel, - sv_frame_t start, sv_frame_t count, - float **buffer) const; + virtual std::vector<std::vector<float>> getMultiChannelData(int fromchannel, int tochannel, sv_frame_t start, sv_frame_t count) const; virtual int getSummaryBlockSize(int desired) const;
--- a/data/model/DenseTimeValueModel.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/DenseTimeValueModel.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -37,27 +37,19 @@ if (f1 <= f0) return ""; - float **all = new float *[ch]; - for (int c = 0; c < ch; ++c) { - all[c] = new float[f1 - f0]; - } + auto data = getMultiChannelData(0, ch - 1, f0, f1 - f0); - sv_frame_t n = getMultiChannelData(0, ch - 1, f0, f1 - f0, all); - + if (data.empty() || data[0].empty()) return ""; + QStringList list; - for (sv_frame_t i = 0; i < n; ++i) { + for (sv_frame_t i = 0; in_range_for(data[0], i); ++i) { QStringList parts; parts << QString("%1").arg(f0 + i); - for (int c = 0; c < ch; ++c) { - parts << QString("%1").arg(all[c][i]); + for (int c = 0; in_range_for(data, c); ++c) { + parts << QString("%1").arg(data[c][i]); } list << parts.join(delimiter); } - for (int c = 0; c < ch; ++c) { - delete[] all[c]; - } - delete[] all; - return list.join("\n"); }
--- a/data/model/DenseTimeValueModel.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/DenseTimeValueModel.h Mon Jun 15 12:19:47 2015 +0100 @@ -57,22 +57,22 @@ /** * Get the specified set of samples from the given channel of the - * model in single-precision floating-point format. Return the - * number of samples actually retrieved. + * model in single-precision floating-point format. Returned + * vector may have fewer samples than requested, if the end of + * file was reached. + * * If the channel is given as -1, mix all available channels and * return the result. */ - virtual sv_frame_t getData(int channel, sv_frame_t start, sv_frame_t count, - float *buffer) const = 0; + virtual std::vector<float> getData(int channel, sv_frame_t start, sv_frame_t count) const = 0; /** - * Get the specified set of samples from given contiguous range - * of channels of the model in single-precision floating-point - * format. Return the number of sample frames actually retrieved. + * Get the specified set of samples from given contiguous range of + * channels of the model in single-precision floating-point + * format. Returned vector may have fewer samples than requested, + * if the end of file was reached. */ - virtual sv_frame_t getMultiChannelData(int fromchannel, int tochannel, - sv_frame_t start, sv_frame_t count, - float **buffers) const = 0; + virtual std::vector<std::vector<float>> getMultiChannelData(int fromchannel, int tochannel, sv_frame_t start, sv_frame_t count) const = 0; virtual bool canPlay() const { return true; } virtual QString getDefaultPlayClipId() const { return ""; }
--- a/data/model/FFTModel.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/FFTModel.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -256,22 +256,31 @@ vector<float> FFTModel::getSourceDataUncached(pair<sv_frame_t, sv_frame_t> range) const { - vector<float> data(range.second - range.first, 0.f); decltype(range.first) pfx = 0; if (range.first < 0) { pfx = -range.first; range = { 0, range.second }; } -// cerr << "requesting " << range.second - range.first << " from file" << endl; - (void) m_model->getData(m_channel, - range.first, - range.second - range.first, - &data[pfx]); + + auto data = m_model->getData(m_channel, + range.first, + range.second - range.first); + + // don't return a partial frame + data.resize(range.second - range.first, 0.f); + + if (pfx > 0) { + vector<float> pad(pfx, 0.f); + data.insert(data.begin(), pad.begin(), pad.end()); + } + if (m_channel == -1) { int channels = m_model->getChannelCount(); if (channels > 1) { - for (int i = 0; in_range_for(data, i); ++i) { - data[i] /= float(channels); + int n = int(data.size()); + float factor = 1.f / float(channels); + for (int i = 0; i < n; ++i) { + data[i] *= factor; } } }
--- a/data/model/Model.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/Model.h Mon Jun 15 12:19:47 2015 +0100 @@ -24,8 +24,6 @@ #include "base/BaseTypes.h" #include "base/DataExportOptions.h" -typedef std::vector<float> SampleBlock; - class ZoomConstraint; class AlignmentModel;
--- a/data/model/WaveFileModel.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/WaveFileModel.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -32,6 +32,8 @@ #include <cassert> +using namespace std; + //#define DEBUG_WAVE_FILE_MODEL 1 PowerOfSqrtTwoZoomConstraint @@ -107,7 +109,7 @@ if (m_reader) { int decodeCompletion = m_reader->getDecodeCompletion(); if (decodeCompletion < 90) *completion = decodeCompletion; - else *completion = std::min(*completion, decodeCompletion); + else *completion = min(*completion, decodeCompletion); } if (*completion != 0 && *completion != 100 && @@ -184,77 +186,47 @@ return ""; } -sv_frame_t -WaveFileModel::getData(int channel, sv_frame_t start, sv_frame_t count, - float *buffer) const +vector<float> +WaveFileModel::getData(int channel, sv_frame_t start, sv_frame_t count) const { // Always read these directly from the file. - // This is used for e.g. audio playback. - // Could be much more efficient (although compiler optimisation will help) + // This is used for e.g. audio playback or input to transforms. #ifdef DEBUG_WAVE_FILE_MODEL cout << "WaveFileModel::getData[" << this << "]: " << channel << ", " << start << ", " << count << ", " << buffer << endl; #endif - if (start >= m_startFrame) { - start -= m_startFrame; - } else { - for (sv_frame_t i = 0; i < count; ++i) { - buffer[i] = 0.f; - } - if (count <= m_startFrame - start) { - return 0; - } else { - count -= (m_startFrame - start); - start = 0; + if (!m_reader || !m_reader->isOK() || count == 0) { + return {}; + } + + if (channel != -1) { + // get a single channel + auto data = getMultiChannelData(channel, channel, start, count); + if (data.empty()) return {}; + else return data[0]; + } + + // channel == -1, mix down all channels + + auto all = getMultiChannelData(0, getChannelCount()-1, start, count); + if (all.empty()) return {}; + + sv_frame_t n = all[0].size(); + vector<float> result(n, 0.f); + + for (int c = 0; in_range_for(all, c); ++c) { + for (sv_frame_t i = 0; i < n; ++i) { + result[i] += all[c][i]; } } - if (!m_reader || !m_reader->isOK() || count == 0) { - for (sv_frame_t i = 0; i < count; ++i) buffer[i] = 0.f; - return 0; - } - -#ifdef DEBUG_WAVE_FILE_MODEL -// SVDEBUG << "WaveFileModel::getValues(" << channel << ", " -// << start << ", " << end << "): calling reader" << endl; -#endif - - int channels = getChannelCount(); - - SampleBlock frames = m_reader->getInterleavedFrames(start, count); - - sv_frame_t i = 0; - - int ch0 = channel, ch1 = channel; - if (channel == -1) { - ch0 = 0; - ch1 = channels - 1; - } - - while (i < count) { - - buffer[i] = 0.0; - - for (int ch = ch0; ch <= ch1; ++ch) { - - sv_frame_t index = i * channels + ch; - if (index >= (sv_frame_t)frames.size()) break; - - float sample = frames[index]; - buffer[i] += sample; - } - - ++i; - } - - return i; + return result; } -sv_frame_t +vector<vector<float>> WaveFileModel::getMultiChannelData(int fromchannel, int tochannel, - sv_frame_t start, sv_frame_t count, - float **buffer) const + sv_frame_t start, sv_frame_t count) const { #ifdef DEBUG_WAVE_FILE_MODEL cout << "WaveFileModel::getData[" << this << "]: " << fromchannel << "," << tochannel << ", " << start << ", " << count << ", " << buffer << endl; @@ -266,73 +238,47 @@ cerr << "ERROR: WaveFileModel::getData: fromchannel (" << fromchannel << ") > tochannel (" << tochannel << ")" << endl; - return 0; + return {}; } if (tochannel >= channels) { cerr << "ERROR: WaveFileModel::getData: tochannel (" << tochannel << ") >= channel count (" << channels << ")" << endl; - return 0; + return {}; } - if (fromchannel == tochannel) { - return getData(fromchannel, start, count, buffer[0]); + if (!m_reader || !m_reader->isOK() || count == 0) { + return {}; } int reqchannels = (tochannel - fromchannel) + 1; - // Always read these directly from the file. - // This is used for e.g. audio playback. - // Could be much more efficient (although compiler optimisation will help) - if (start >= m_startFrame) { start -= m_startFrame; } else { - for (int c = 0; c < reqchannels; ++c) { - for (sv_frame_t i = 0; i < count; ++i) buffer[c][i] = 0.f; - } if (count <= m_startFrame - start) { - return 0; + return {}; } else { count -= (m_startFrame - start); start = 0; } } - if (!m_reader || !m_reader->isOK() || count == 0) { - for (int c = 0; c < reqchannels; ++c) { - for (sv_frame_t i = 0; i < count; ++i) buffer[c][i] = 0.f; + vector<float> interleaved = m_reader->getInterleavedFrames(start, count); + if (channels == 1) return { interleaved }; + + sv_frame_t obtained = interleaved.size() / channels; + vector<vector<float>> result(reqchannels, vector<float>(obtained, 0.f)); + + for (int c = fromchannel; c <= tochannel; ++c) { + int destc = c - fromchannel; + for (int i = 0; i < obtained; ++i) { + result[destc][i] = interleaved[i * channels + c]; } - return 0; } - - SampleBlock frames = m_reader->getInterleavedFrames(start, count); - - sv_frame_t i = 0; - - sv_frame_t index = 0, available = frames.size(); - - while (i < count) { - - if (index >= available) break; - - int destc = 0; - - for (int c = 0; c < channels; ++c) { - - if (c >= fromchannel && c <= tochannel) { - buffer[destc][i] = frames[index]; - ++destc; - } - - ++index; - } - - ++i; - } - - return i; + + return result; } int @@ -521,16 +467,16 @@ if (blockStart > start) { Range startRange = getSummary(channel, start, blockStart - start); - range.setMin(std::min(range.min(), startRange.min())); - range.setMax(std::max(range.max(), startRange.max())); - range.setAbsmean(std::min(range.absmean(), startRange.absmean())); + range.setMin(min(range.min(), startRange.min())); + range.setMax(max(range.max(), startRange.max())); + range.setAbsmean(min(range.absmean(), startRange.absmean())); } if (blockEnd < start + count) { Range endRange = getSummary(channel, blockEnd, start + count - blockEnd); - range.setMin(std::min(range.min(), endRange.min())); - range.setMax(std::max(range.max(), endRange.max())); - range.setAbsmean(std::min(range.absmean(), endRange.absmean())); + range.setMin(min(range.min(), endRange.min())); + range.setMax(max(range.max(), endRange.max())); + range.setAbsmean(min(range.absmean(), endRange.absmean())); } return range; @@ -605,7 +551,7 @@ sv_frame_t frame = 0; const sv_frame_t readBlockSize = 16384; - SampleBlock block; + vector<float> block; if (!m_model.isOK()) return;
--- a/data/model/WaveFileModel.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/WaveFileModel.h Mon Jun 15 12:19:47 2015 +0100 @@ -62,12 +62,9 @@ void setStartFrame(sv_frame_t startFrame) { m_startFrame = startFrame; } - virtual sv_frame_t getData(int channel, sv_frame_t start, sv_frame_t count, - float *buffer) const; + virtual std::vector<float> getData(int channel, sv_frame_t start, sv_frame_t count) const; - virtual sv_frame_t getMultiChannelData(int fromchannel, int tochannel, - sv_frame_t start, sv_frame_t count, - float **buffers) const; + virtual std::vector<std::vector<float>> getMultiChannelData(int fromchannel, int tochannel, sv_frame_t start, sv_frame_t count) const; virtual int getSummaryBlockSize(int desired) const; @@ -123,7 +120,7 @@ bool m_exiting; static PowerOfSqrtTwoZoomConstraint m_zoomConstraint; - mutable SampleBlock m_directRead; + mutable std::vector<float> m_directRead; mutable sv_frame_t m_lastDirectReadStart; mutable sv_frame_t m_lastDirectReadCount; mutable QMutex m_directReadMutex;
--- a/data/model/WritableWaveFileModel.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/WritableWaveFileModel.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -28,6 +28,8 @@ #include <iostream> #include <stdint.h> +using namespace std; + //#define DEBUG_WRITABLE_WAVE_FILE_MODEL 1 WritableWaveFileModel::WritableWaveFileModel(sv_samplerate_t sampleRate, @@ -169,21 +171,19 @@ return m_frameCount; } -sv_frame_t -WritableWaveFileModel::getData(int channel, sv_frame_t start, sv_frame_t count, - float *buffer) const +vector<float> +WritableWaveFileModel::getData(int channel, sv_frame_t start, sv_frame_t count) const { - if (!m_model || m_model->getChannelCount() == 0) return 0; - return m_model->getData(channel, start, count, buffer); + if (!m_model || m_model->getChannelCount() == 0) return {}; + return m_model->getData(channel, start, count); } -sv_frame_t +vector<vector<float>> WritableWaveFileModel::getMultiChannelData(int fromchannel, int tochannel, - sv_frame_t start, sv_frame_t count, - float **buffers) const + sv_frame_t start, sv_frame_t count) const { - if (!m_model || m_model->getChannelCount() == 0) return 0; - return m_model->getMultiChannelData(fromchannel, tochannel, start, count, buffers); + if (!m_model || m_model->getChannelCount() == 0) return {}; + return m_model->getMultiChannelData(fromchannel, tochannel, start, count); } int
--- a/data/model/WritableWaveFileModel.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/WritableWaveFileModel.h Mon Jun 15 12:19:47 2015 +0100 @@ -60,12 +60,9 @@ void setStartFrame(sv_frame_t startFrame); - virtual sv_frame_t getData(int channel, sv_frame_t start, sv_frame_t count, - float *buffer) const; + virtual std::vector<float> getData(int channel, sv_frame_t start, sv_frame_t count) const; - virtual sv_frame_t getMultiChannelData(int fromchannel, int tochannel, - sv_frame_t start, sv_frame_t count, - float **buffer) const; + virtual std::vector<std::vector<float>> getMultiChannelData(int fromchannel, int tochannel, sv_frame_t start, sv_frame_t count) const; virtual int getSummaryBlockSize(int desired) const;
--- a/data/model/test/MockWaveModel.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/test/MockWaveModel.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -24,40 +24,39 @@ } } -sv_frame_t -MockWaveModel::getData(int channel, sv_frame_t start, sv_frame_t count, - float *buffer) const +vector<float> +MockWaveModel::getData(int channel, sv_frame_t start, sv_frame_t count) const { sv_frame_t i = 0; // cerr << "MockWaveModel::getData(" << channel << "," << start << "," << count << "): "; + vector<float> data; + while (i < count) { sv_frame_t idx = start + i; if (!in_range_for(m_data[channel], idx)) break; - buffer[i] = m_data[channel][idx]; -// cerr << buffer[i] << " "; + data.push_back(m_data[channel][idx]); +// cerr << data[i] << " "; ++i; } // cerr << endl; - return i; + return data; } -sv_frame_t +vector<vector<float>> MockWaveModel::getMultiChannelData(int fromchannel, int tochannel, - sv_frame_t start, sv_frame_t count, - float **buffers) const + sv_frame_t start, sv_frame_t count) const { - sv_frame_t min = count; - + vector<vector<float>> data(tochannel - fromchannel + 1); + for (int c = fromchannel; c <= tochannel; ++c) { - sv_frame_t n = getData(c, start, count, buffers[c]); - if (n < min) min = n; + data.push_back(getData(c, start, count)); } - return min; + return data; } vector<float>
--- a/data/model/test/MockWaveModel.h Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/test/MockWaveModel.h Mon Jun 15 12:19:47 2015 +0100 @@ -41,11 +41,8 @@ virtual float getValueMaximum() const { return 1.f; } virtual int getChannelCount() const { return int(m_data.size()); } - virtual sv_frame_t getData(int channel, sv_frame_t start, sv_frame_t count, - float *buffer) const; - virtual sv_frame_t getMultiChannelData(int fromchannel, int tochannel, - sv_frame_t start, sv_frame_t count, - float **buffers) const; + virtual std::vector<float> getData(int channel, sv_frame_t start, sv_frame_t count) const; + virtual std::vector<std::vector<float>> getMultiChannelData(int fromchannel, int tochannel, sv_frame_t start, sv_frame_t count) const; virtual bool canPlay() const { return true; } virtual QString getDefaultPlayClipId() const { return ""; }
--- a/data/model/test/test.pro Sat Jun 13 08:47:05 2015 +0100 +++ b/data/model/test/test.pro Mon Jun 15 12:19:47 2015 +0100 @@ -61,7 +61,7 @@ !win32 { !macx* { - QMAKE_POST_LINK=./$${TARGET} + QMAKE_POST_LINK=valgrind ./$${TARGET} } macx* { QMAKE_POST_LINK=./$${TARGET}.app/Contents/MacOS/$${TARGET}
--- a/transform/FeatureExtractionModelTransformer.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/transform/FeatureExtractionModelTransformer.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -787,31 +787,28 @@ if (channelCount == 1) { - got = input->getData(m_input.getChannel(), startFrame, size, - buffers[0] + offset); + auto data = input->getData(m_input.getChannel(), startFrame, size); + got = data.size(); + + copy(data.begin(), data.end(), buffers[0] + offset); if (m_input.getChannel() == -1 && input->getChannelCount() > 1) { // use mean instead of sum, as plugin input float cc = float(input->getChannelCount()); - for (sv_frame_t i = 0; i < size; ++i) { + for (sv_frame_t i = 0; i < got; ++i) { buffers[0][i + offset] /= cc; } } } else { - float **writebuf = buffers; - if (offset > 0) { - writebuf = new float *[channelCount]; - for (int i = 0; i < channelCount; ++i) { - writebuf[i] = buffers[i] + offset; + auto data = input->getMultiChannelData(0, channelCount-1, startFrame, size); + if (!data.empty()) { + got = data[0].size(); + for (int c = 0; in_range_for(data, c); ++c) { + copy(data[c].begin(), data[c].end(), buffers[c] + offset); } } - - got = input->getMultiChannelData - (0, channelCount-1, startFrame, size, writebuf); - - if (writebuf != buffers) delete[] writebuf; } while (got < size) {
--- a/transform/RealTimeEffectModelTransformer.cpp Sat Jun 13 08:47:05 2015 +0100 +++ b/transform/RealTimeEffectModelTransformer.cpp Mon Jun 15 12:19:47 2015 +0100 @@ -191,10 +191,14 @@ if (channelCount == 1) { if (inbufs && inbufs[0]) { - got = input->getData - (m_input.getChannel(), blockFrame, blockSize, inbufs[0]); + auto data = input->getData + (m_input.getChannel(), blockFrame, blockSize); + got = data.size(); + for (sv_frame_t i = 0; i < got; ++i) { + inbufs[0][i] = data[i]; + } while (got < blockSize) { - inbufs[0][got++] = 0.0; + inbufs[0][got++] = 0.f; } for (int ch = 1; ch < (int)m_plugin->getAudioInputCount(); ++ch) { for (sv_frame_t i = 0; i < blockSize; ++i) { @@ -204,9 +208,14 @@ } } else { if (inbufs && inbufs[0]) { - got = input->getMultiChannelData(0, channelCount - 1, - blockFrame, blockSize, - inbufs); + auto data = input->getMultiChannelData + (0, channelCount - 1, blockFrame, blockSize); + if (!data.empty()) got = data[0].size(); + for (int ch = 0; ch < channelCount; ++ch) { + for (sv_frame_t i = 0; i < got; ++i) { + inbufs[ch][i] = data[ch][i]; + } + } while (got < blockSize) { for (int ch = 0; ch < channelCount; ++ch) { inbufs[ch][got] = 0.0;