changeset 300:5877d68815c7

* Change WaveFileModel API from getValues(start,end) to getData(start,count). It's much less error-prone to pass in frame counts instead of start/end locations. Should have done this ages ago. This closes #1794563. * Add option to apply a transform to only the selection region, instead of the whole audio. * (to make the above work properly) Add start frame offset to wave models
author Chris Cannam
date Mon, 01 Oct 2007 13:48:38 +0000
parents 576be0d0d218
children 73537d900d4b
files base/Selection.cpp base/Selection.h data/fft/FFTDataServer.cpp data/fileio/WavFileWriter.cpp data/model/AggregateWaveModel.cpp data/model/AggregateWaveModel.h data/model/DenseTimeValueModel.h data/model/RangeSummarisableTimeValueModel.h data/model/WaveFileModel.cpp data/model/WaveFileModel.h data/model/WritableWaveFileModel.cpp data/model/WritableWaveFileModel.h
diffstat 12 files changed, 202 insertions(+), 136 deletions(-) [+]
line wrap: on
line diff
--- a/base/Selection.cpp	Fri Sep 28 16:15:06 2007 +0000
+++ b/base/Selection.cpp	Mon Oct 01 13:48:38 2007 +0000
@@ -172,6 +172,25 @@
     }
 }
 
+void
+MultiSelection::getExtents(size_t &startFrame, size_t &endFrame) const
+{
+    startFrame = 0;
+    endFrame = 0;
+    
+    for (SelectionList::const_iterator i = m_selections.begin();
+	 i != m_selections.end(); ++i) {
+
+        if (i == m_selections.begin() || i->getStartFrame() < startFrame) {
+            startFrame = i->getStartFrame();
+        }
+
+        if (i == m_selections.begin() || i->getEndFrame() > endFrame) {
+            endFrame = i->getEndFrame();
+        }
+    }
+}
+
 Selection
 MultiSelection::getContainingSelection(size_t frame, bool defaultToFollowing) const
 {
--- a/base/Selection.h	Fri Sep 28 16:15:06 2007 +0000
+++ b/base/Selection.h	Mon Oct 01 13:48:38 2007 +0000
@@ -57,6 +57,8 @@
     void removeSelection(const Selection &selection);
     void clearSelections();
 
+    void getExtents(size_t &startFrame, size_t &endFrame) const;
+
     /**
      * Return the selection that contains a given frame.
      * If defaultToFollowing is true, and if the frame is not in a
--- a/data/fft/FFTDataServer.cpp	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/fft/FFTDataServer.cpp	Mon Oct 01 13:48:38 2007 +0000
@@ -1056,8 +1056,11 @@
               << " from channel " << m_channel << std::endl;
 #endif
 
-    size_t got = m_model->getValues(m_channel, startFrame + pfx,
-				    endFrame, m_fftInput + off + pfx);
+    size_t count = 0;
+    if (endFrame > startFrame + pfx) count = endFrame - (startFrame + pfx);
+
+    size_t got = m_model->getData(m_channel, startFrame + pfx,
+                                  count, m_fftInput + off + pfx);
 
     while (got + pfx < m_windowSize) {
 	m_fftInput[off + got + pfx] = 0.0;
--- a/data/fileio/WavFileWriter.cpp	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/fileio/WavFileWriter.cpp	Mon Oct 01 13:48:38 2007 +0000
@@ -103,7 +103,7 @@
 	    size_t n = std::min(bs, f1 - f);
 
 	    for (int c = 0; c < int(m_channels); ++c) {
-		source->getValues(c, f, f + n, ub);
+		source->getData(c, f, n, ub);
 		for (size_t i = 0; i < n; ++i) {
 		    ib[i * m_channels + c] = ub[i];
 		}
--- a/data/model/AggregateWaveModel.cpp	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/model/AggregateWaveModel.cpp	Mon Oct 01 13:48:38 2007 +0000
@@ -97,8 +97,8 @@
 }
 
 size_t
-AggregateWaveModel::getValues(int channel, size_t start, size_t end,
-                              float *buffer) const
+AggregateWaveModel::getData(int channel, size_t start, size_t count,
+                            float *buffer) const
 {
     int ch0 = channel, ch1 = channel;
     bool mixing = false;
@@ -110,22 +110,22 @@
 
     float *readbuf = buffer;
     if (mixing) {
-        readbuf = new float[end - start];
-        for (size_t i = 0; i < end - start; ++i) {
+        readbuf = new float[count];
+        for (size_t i = 0; i < count; ++i) {
             buffer[i] = 0.f;
         }
     }
 
-    size_t sz = end - start;
-    
+    size_t sz = count;
+
     for (int c = ch0; c <= ch1; ++c) {
         size_t szHere = 
-            m_components[c].model->getValues(m_components[c].channel,
-                                             start, end,
-                                             readbuf);
+            m_components[c].model->getData(m_components[c].channel,
+                                           start, count,
+                                           readbuf);
         if (szHere < sz) sz = szHere;
         if (mixing) {
-            for (size_t i = 0; i < end - start; ++i) {
+            for (size_t i = 0; i < count; ++i) {
                 buffer[i] += readbuf[i];
             }
         }
@@ -136,8 +136,8 @@
 }
          
 size_t
-AggregateWaveModel::getValues(int channel, size_t start, size_t end,
-                              double *buffer) const
+AggregateWaveModel::getData(int channel, size_t start, size_t count,
+                            double *buffer) const
 {
     int ch0 = channel, ch1 = channel;
     bool mixing = false;
@@ -149,22 +149,22 @@
 
     double *readbuf = buffer;
     if (mixing) {
-        readbuf = new double[end - start];
-        for (size_t i = 0; i < end - start; ++i) {
-            buffer[i] = 0.f;
+        readbuf = new double[count];
+        for (size_t i = 0; i < count; ++i) {
+            buffer[i] = 0.0;
         }
     }
 
-    size_t sz = end - start;
+    size_t sz = count;
     
     for (int c = ch0; c <= ch1; ++c) {
         size_t szHere = 
-            m_components[c].model->getValues(m_components[c].channel,
-                                             start, end,
-                                             readbuf);
+            m_components[c].model->getData(m_components[c].channel,
+                                           start, count,
+                                           readbuf);
         if (szHere < sz) sz = szHere;
         if (mixing) {
-            for (size_t i = 0; i < end - start; ++i) {
+            for (size_t i = 0; i < count; ++i) {
                 buffer[i] += readbuf[i];
             }
         }
@@ -175,14 +175,14 @@
 }
         
 void
-AggregateWaveModel::getRanges(size_t channel, size_t start, size_t end,
-                              RangeBlock &ranges, size_t &blockSize) const
+AggregateWaveModel::getSummaries(size_t channel, size_t start, size_t count,
+                                 RangeBlock &ranges, size_t &blockSize) const
 {
     //!!! complete
 }
 
 AggregateWaveModel::Range
-AggregateWaveModel::getRange(size_t channel, size_t start, size_t end) const
+AggregateWaveModel::getSummary(size_t channel, size_t start, size_t count) const
 {
     //!!! complete
     return Range();
--- a/data/model/AggregateWaveModel.h	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/model/AggregateWaveModel.h	Mon Oct 01 13:48:38 2007 +0000
@@ -59,17 +59,17 @@
     virtual size_t getStartFrame() const { return 0; }
     virtual size_t getEndFrame() const { return getFrameCount(); }
 
-    virtual size_t getValues(int channel, size_t start, size_t end,
-			     float *buffer) const;
+    virtual size_t getData(int channel, size_t start, size_t count,
+                           float *buffer) const;
 
-    virtual size_t getValues(int channel, size_t start, size_t end,
-			     double *buffer) const;
+    virtual size_t getData(int channel, size_t start, size_t count,
+                           double *buffer) const;
 
-    virtual void getRanges(size_t channel, size_t start, size_t end,
-                           RangeBlock &ranges,
-                           size_t &blockSize) const;
+    virtual void getSummaries(size_t channel, size_t start, size_t count,
+                              RangeBlock &ranges,
+                              size_t &blockSize) const;
 
-    virtual Range getRange(size_t channel, size_t start, size_t end) const;
+    virtual Range getSummary(size_t channel, size_t start, size_t count) const;
 
     virtual void toXml(QTextStream &out,
                        QString indent = "",
--- a/data/model/DenseTimeValueModel.h	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/model/DenseTimeValueModel.h	Mon Oct 01 13:48:38 2007 +0000
@@ -58,8 +58,8 @@
      * If the channel is given as -1, mix all available channels and
      * return the result.
      */
-    virtual size_t getValues(int channel, size_t start, size_t end,
-			     float *buffer) const = 0;
+    virtual size_t getData(int channel, size_t start, size_t count,
+                           float *buffer) const = 0;
 
     /**
      * Get the specified set of samples from the given channel of the
@@ -68,8 +68,8 @@
      * If the channel is given as -1, mix all available channels and
      * return the result.
      */
-    virtual size_t getValues(int channel, size_t start, size_t end,
-			     double *buffer) const = 0;
+    virtual size_t getData(int channel, size_t start, size_t count,
+                           double *buffer) const = 0;
 };
 
 #endif
--- a/data/model/RangeSummarisableTimeValueModel.h	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/model/RangeSummarisableTimeValueModel.h	Mon Oct 01 13:48:38 2007 +0000
@@ -53,25 +53,26 @@
     typedef std::vector<Range> RangeBlock;
 
     /**
-     * Return ranges between the given start and end frames,
-     * summarised at the given block size.  ((end - start + 1) /
-     * blockSize) ranges should ideally be returned.
+     * Return ranges from the given start frame, corresponding to the
+     * given number of underlying sample frames, summarised at the
+     * given block size.  duration / blockSize ranges should ideally
+     * be returned.
      *
      * If the given block size is not supported by this model
      * (according to its zoom constraint), also modify the blockSize
      * parameter so as to return the block size that was actually
      * obtained.
      */
-    virtual void getRanges(size_t channel, size_t start, size_t end,
-                           RangeBlock &ranges,
-                           size_t &blockSize) const = 0;
+    virtual void getSummaries(size_t channel, size_t start, size_t count,
+                              RangeBlock &ranges,
+                              size_t &blockSize) const = 0;
 
     /**
-     * Return the range between the given start and end frames,
-     * summarised at a block size equal to the distance between start
-     * and end frames.
+     * Return the range from the given start frame, corresponding to
+     * the given number of underlying sample frames, summarised at a
+     * block size equal to the distance between start and end frames.
      */
-    virtual Range getRange(size_t channel, size_t start, size_t end) const = 0;
+    virtual Range getSummary(size_t channel, size_t start, size_t count) const = 0;
 
     virtual void setAlignment(AlignmentModel *alignment); // I take ownership
     virtual const Model *getAlignmentReference() const;
--- a/data/model/WaveFileModel.cpp	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/model/WaveFileModel.cpp	Mon Oct 01 13:48:38 2007 +0000
@@ -41,6 +41,7 @@
 WaveFileModel::WaveFileModel(QString path, size_t targetRate) :
     m_path(path),
     m_myReader(true),
+    m_startFrame(0),
     m_fillThread(0),
     m_updateTimer(0),
     m_lastFillExtent(0),
@@ -56,6 +57,7 @@
 WaveFileModel::WaveFileModel(QString path, QString originalLocation, size_t targetRate) :
     m_path(originalLocation),
     m_myReader(true),
+    m_startFrame(0),
     m_fillThread(0),
     m_updateTimer(0),
     m_lastFillExtent(0),
@@ -71,6 +73,7 @@
 WaveFileModel::WaveFileModel(QString path, AudioFileReader *reader) :
     m_path(path),
     m_myReader(false),
+    m_startFrame(0),
     m_fillThread(0),
     m_updateTimer(0),
     m_lastFillExtent(0),
@@ -162,20 +165,29 @@
 }
 
 size_t
-WaveFileModel::getValues(int channel, size_t start, size_t end,
-			 float *buffer) const
+WaveFileModel::getData(int channel, size_t start, size_t count,
+                       float *buffer) 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)
 
-    if (end < start) {
-	std::cerr << "ERROR: WaveFileModel::getValues[float]: end < start ("
-		  << end << " < " << start << ")" << std::endl;
-	assert(end >= start);
+    if (start > m_startFrame) {
+        start -= m_startFrame;
+    } else {
+        for (size_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()) return 0;
+    if (!m_reader || !m_reader->isOK() || count == 0) {
+        for (size_t i = 0; i < count; ++i) buffer[i] = 0.f;
+        return 0;
+    }
 
 #ifdef DEBUG_WAVE_FILE_MODEL
 //    std::cerr << "WaveFileModel::getValues(" << channel << ", "
@@ -183,7 +195,7 @@
 #endif
 
     SampleBlock frames;
-    m_reader->getInterleavedFrames(start, end - start, frames);
+    m_reader->getInterleavedFrames(start, count, frames);
 
     size_t i = 0;
 
@@ -193,7 +205,7 @@
 	ch1 = channels - 1;
     }
     
-    while (i < end - start) {
+    while (i < count) {
 
 	buffer[i] = 0.0;
 
@@ -213,19 +225,28 @@
 }
 
 size_t
-WaveFileModel::getValues(int channel, size_t start, size_t end,
-			 double *buffer) const
+WaveFileModel::getData(int channel, size_t start, size_t count,
+                       double *buffer) const
 {
-    if (end < start) {
-	std::cerr << "ERROR: WaveFileModel::getValues[double]: end < start ("
-		  << end << " < " << start << ")" << std::endl;
-	assert(end >= start);
+    if (start > m_startFrame) {
+        start -= m_startFrame;
+    } else {
+        for (size_t i = 0; i < count; ++i) buffer[i] = 0.0;
+        if (count <= m_startFrame - start) {
+            return 0;
+        } else {
+            count -= (m_startFrame - start);
+            start = 0;
+        }
     }
 
-    if (!m_reader || !m_reader->isOK()) return 0;
+    if (!m_reader || !m_reader->isOK() || count == 0) {
+        for (size_t i = 0; i < count; ++i) buffer[i] = 0.0;
+        return 0;
+    }
 
     SampleBlock frames;
-    m_reader->getInterleavedFrames(start, end - start, frames);
+    m_reader->getInterleavedFrames(start, count, frames);
 
     size_t i = 0;
 
@@ -235,7 +256,7 @@
 	ch1 = channels - 1;
     }
 
-    while (i < end - start) {
+    while (i < count) {
 
 	buffer[i] = 0.0;
 
@@ -255,15 +276,17 @@
 }
 
 void
-WaveFileModel::getRanges(size_t channel, size_t start, size_t end,
-                         RangeBlock &ranges, size_t &blockSize) const
+WaveFileModel::getSummaries(size_t channel, size_t start, size_t count,
+                            RangeBlock &ranges, size_t &blockSize) const
 {
     ranges.clear();
     if (!isOK()) return;
 
-    if (end <= start) {
-	std::cerr << "WARNING: Internal error: end <= start in WaveFileModel::getRanges (end = " << end << ", start = " << start << ", blocksize = " << blockSize << ")" << std::endl;
-	return;
+    if (start > m_startFrame) start -= m_startFrame;
+    else if (count <= m_startFrame - start) return;
+    else {
+        count -= (m_startFrame - start);
+        start = 0;
     }
 
     int cacheType = 0;
@@ -284,32 +307,32 @@
 	// for short queries.
 
 	SampleBlock frames;
-	m_reader->getInterleavedFrames(start, end - start, frames);
+	m_reader->getInterleavedFrames(start, count, frames);
 	float max = 0.0, min = 0.0, total = 0.0;
-	size_t i = 0, count = 0;
+	size_t i = 0, got = 0;
 
-	while (i < end - start) {
+	while (i < count) {
 
 	    size_t index = i * channels + channel;
 	    if (index >= frames.size()) break;
             
 	    float sample = frames[index];
-            if (sample > max || count == 0) max = sample;
-	    if (sample < min || count == 0) min = sample;
+            if (sample > max || got == 0) max = sample;
+	    if (sample < min || got == 0) min = sample;
             total += fabsf(sample);
 	    
 	    ++i;
-            ++count;
+            ++got;
             
-            if (count == blockSize) {
-                ranges.push_back(Range(min, max, total / count));
+            if (got == blockSize) {
+                ranges.push_back(Range(min, max, total / got));
                 min = max = total = 0.0f;
-                count = 0;
+                got = 0;
 	    }
 	}
 
-	if (count > 0) {
-            ranges.push_back(Range(min, max, total / count));
+	if (got > 0) {
+            ranges.push_back(Range(min, max, total / got));
 	}
 
 	return;
@@ -331,37 +354,37 @@
 	}
 
 	size_t startIndex = start / cacheBlock;
-	size_t endIndex = end / cacheBlock;
+	size_t endIndex = (start + count) / cacheBlock;
 
 	float max = 0.0, min = 0.0, total = 0.0;
-	size_t i = 0, count = 0;
+	size_t i = 0, got = 0;
 
 #ifdef DEBUG_WAVE_FILE_MODEL
-	cerr << "blockSize is " << blockSize << ", cacheBlock " << cacheBlock << ", start " << start << ", end " << end << " (frame count " << getFrameCount() << "), power is " << power << ", div is " << div << ", startIndex " << startIndex << ", endIndex " << endIndex << endl;
+	cerr << "blockSize is " << blockSize << ", cacheBlock " << cacheBlock << ", start " << start << ", count " << count << " (frame count " << getFrameCount() << "), power is " << power << ", div is " << div << ", startIndex " << startIndex << ", endIndex " << endIndex << endl;
 #endif
 
-	for (i = 0; i < endIndex - startIndex; ) {
+	for (i = 0; i <= endIndex - startIndex; ) {
         
 	    size_t index = (i + startIndex) * channels + channel;
 	    if (index >= cache.size()) break;
             
             const Range &range = cache[index];
-            if (range.max > max || count == 0) max = range.max;
-            if (range.min < min || count == 0) min = range.min;
+            if (range.max > max || got == 0) max = range.max;
+            if (range.min < min || got == 0) min = range.min;
             total += range.absmean;
             
 	    ++i;
-            ++count;
+            ++got;
             
-	    if (count == div) {
-		ranges.push_back(Range(min, max, total / count));
+	    if (got == div) {
+		ranges.push_back(Range(min, max, total / got));
                 min = max = total = 0.0f;
-                count = 0;
+                got = 0;
 	    }
 	}
 		
-	if (count > 0) {
-            ranges.push_back(Range(min, max, total / count));
+	if (got > 0) {
+            ranges.push_back(Range(min, max, total / got));
 	}
     }
 
@@ -372,30 +395,32 @@
 }
 
 WaveFileModel::Range
-WaveFileModel::getRange(size_t channel, size_t start, size_t end) const
+WaveFileModel::getSummary(size_t channel, size_t start, size_t count) const
 {
     Range range;
     if (!isOK()) return range;
 
-    if (end <= start) {
-	std::cerr << "WARNING: Internal error: end <= start in WaveFileModel::getRange (end = " << end << ", start = " << start << ")" << std::endl;
-	return range;
+    if (start > m_startFrame) start -= m_startFrame;
+    else if (count <= m_startFrame - start) return range;
+    else {
+        count -= (m_startFrame - start);
+        start = 0;
     }
 
     size_t blockSize;
-    for (blockSize = 1; blockSize <= end - start; blockSize *= 2);
-    blockSize /= 2;
+    for (blockSize = 1; blockSize <= count; blockSize *= 2);
+    if (blockSize > 1) blockSize /= 2;
 
     bool first = false;
 
     size_t blockStart = (start / blockSize) * blockSize;
-    size_t blockEnd = (end / blockSize) * blockSize;
+    size_t blockEnd = ((start + count) / blockSize) * blockSize;
 
     if (blockStart < start) blockStart += blockSize;
         
     if (blockEnd > blockStart) {
         RangeBlock ranges;
-        getRanges(channel, blockStart, blockEnd, ranges, blockSize);
+        getSummaries(channel, blockStart, blockEnd - blockStart, ranges, blockSize);
         for (size_t i = 0; i < ranges.size(); ++i) {
             if (first || ranges[i].min < range.min) range.min = ranges[i].min;
             if (first || ranges[i].max > range.max) range.max = ranges[i].max;
@@ -405,14 +430,14 @@
     }
 
     if (blockStart > start) {
-        Range startRange = getRange(channel, start, blockStart);
+        Range startRange = getSummary(channel, start, blockStart - start);
         range.min = std::min(range.min, startRange.min);
         range.max = std::max(range.max, startRange.max);
         range.absmean = std::min(range.absmean, startRange.absmean);
     }
 
-    if (blockEnd < end) {
-        Range endRange = getRange(channel, blockEnd, end);
+    if (blockEnd < start + count) {
+        Range endRange = getSummary(channel, blockEnd, start + count - blockEnd);
         range.min = std::min(range.min, endRange.min);
         range.max = std::max(range.max, endRange.max);
         range.absmean = std::min(range.absmean, endRange.absmean);
--- a/data/model/WaveFileModel.h	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/model/WaveFileModel.h	Mon Oct 01 13:48:38 2007 +0000
@@ -52,20 +52,22 @@
     float getValueMinimum() const { return -1.0f; }
     float getValueMaximum() const { return  1.0f; }
 
-    virtual size_t getStartFrame() const { return 0; }
-    virtual size_t getEndFrame() const { return getFrameCount(); }
+    virtual size_t getStartFrame() const { return m_startFrame; }
+    virtual size_t getEndFrame() const { return m_startFrame + getFrameCount(); }
 
-    virtual size_t getValues(int channel, size_t start, size_t end,
-			     float *buffer) const;
+    void setStartFrame(size_t startFrame) { m_startFrame = startFrame; }
 
-    virtual size_t getValues(int channel, size_t start, size_t end,
-			     double *buffer) const;
+    virtual size_t getData(int channel, size_t start, size_t count,
+                           float *buffer) const;
 
-    virtual void getRanges(size_t channel, size_t start, size_t end,
-                           RangeBlock &ranges,
-                           size_t &blockSize) const;
+    virtual size_t getData(int channel, size_t start, size_t count,
+                           double *buffer) const;
 
-    virtual Range getRange(size_t channel, size_t start, size_t end) const;
+    virtual void getSummaries(size_t channel, size_t start, size_t count,
+                              RangeBlock &ranges,
+                              size_t &blockSize) const;
+
+    virtual Range getSummary(size_t channel, size_t start, size_t count) const;
 
     virtual void toXml(QTextStream &out,
                        QString indent = "",
@@ -105,6 +107,8 @@
     AudioFileReader *m_reader;
     bool m_myReader;
 
+    size_t m_startFrame;
+
     RangeBlock m_cache[2]; // interleaved at two base resolutions
     mutable QMutex m_mutex;
     RangeCacheFillThread *m_fillThread;
--- a/data/model/WritableWaveFileModel.cpp	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/model/WritableWaveFileModel.cpp	Mon Oct 01 13:48:38 2007 +0000
@@ -37,6 +37,7 @@
     m_sampleRate(sampleRate),
     m_channels(channels),
     m_frameCount(0),
+    m_startFrame(0),
     m_completion(0)
 {
     if (path.isEmpty()) {
@@ -75,6 +76,7 @@
         m_reader = 0;
         return;
     }
+    m_model->setStartFrame(m_startFrame);
 
     connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
     connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
@@ -88,6 +90,13 @@
     delete m_reader;
 }
 
+void
+WritableWaveFileModel::setStartFrame(size_t startFrame)
+{
+    m_startFrame = startFrame;
+    if (m_model) m_model->setStartFrame(startFrame);
+}
+
 bool
 WritableWaveFileModel::addSamples(float **samples, size_t count)
 {
@@ -161,38 +170,38 @@
 }
 
 size_t
-WritableWaveFileModel::getValues(int channel, size_t start, size_t end,
-                                 float *buffer) const
+WritableWaveFileModel::getData(int channel, size_t start, size_t count,
+                               float *buffer) const
 {
     if (!m_model || m_model->getChannelCount() == 0) return 0;
-    return m_model->getValues(channel, start, end, buffer);
+    return m_model->getData(channel, start, count, buffer);
 }
 
 size_t
-WritableWaveFileModel::getValues(int channel, size_t start, size_t end,
-                                 double *buffer) const
+WritableWaveFileModel::getData(int channel, size_t start, size_t count,
+                               double *buffer) const
 {
     if (!m_model || m_model->getChannelCount() == 0) return 0;
 //    std::cerr << "WritableWaveFileModel::getValues(" << channel << ", "
 //              << start << ", " << end << "): calling model" << std::endl;
-    return m_model->getValues(channel, start, end, buffer);
+    return m_model->getData(channel, start, count, buffer);
 }
 
 void
-WritableWaveFileModel::getRanges(size_t channel, size_t start, size_t end,
-                                 RangeBlock &ranges,
-                                 size_t &blockSize) const
+WritableWaveFileModel::getSummaries(size_t channel, size_t start, size_t count,
+                                    RangeBlock &ranges,
+                                    size_t &blockSize) const
 {
     ranges.clear();
     if (!m_model || m_model->getChannelCount() == 0) return;
-    m_model->getRanges(channel, start, end, ranges, blockSize);
+    m_model->getSummaries(channel, start, count, ranges, blockSize);
 }
 
 WritableWaveFileModel::Range
-WritableWaveFileModel::getRange(size_t channel, size_t start, size_t end) const
+WritableWaveFileModel::getSummary(size_t channel, size_t start, size_t count) const
 {
     if (!m_model || m_model->getChannelCount() == 0) return Range();
-    return m_model->getRange(channel, start, end);
+    return m_model->getSummary(channel, start, count);
 }
 
 void
--- a/data/model/WritableWaveFileModel.h	Fri Sep 28 16:15:06 2007 +0000
+++ b/data/model/WritableWaveFileModel.h	Mon Oct 01 13:48:38 2007 +0000
@@ -57,19 +57,21 @@
     float getValueMinimum() const { return -1.0f; }
     float getValueMaximum() const { return  1.0f; }
 
-    virtual size_t getStartFrame() const { return 0; }
-    virtual size_t getEndFrame() const { return getFrameCount(); }
+    virtual size_t getStartFrame() const { return m_startFrame; }
+    virtual size_t getEndFrame() const { return m_startFrame + getFrameCount(); }
 
-    virtual size_t getValues(int channel, size_t start, size_t end,
-			     float *buffer) const;
+    void setStartFrame(size_t startFrame);
 
-    virtual size_t getValues(int channel, size_t start, size_t end,
-			     double *buffer) const;
+    virtual size_t getData(int channel, size_t start, size_t count,
+                           float *buffer) const;
 
-    virtual void getRanges(size_t channel, size_t start, size_t end,
-                           RangeBlock &ranges, size_t &blockSize) const;
+    virtual size_t getData(int channel, size_t start, size_t count,
+                           double *buffer) const;
 
-    virtual Range getRange(size_t channel, size_t start, size_t end) const;
+    virtual void getSummaries(size_t channel, size_t start, size_t count,
+                              RangeBlock &ranges, size_t &blockSize) const;
+
+    virtual Range getSummary(size_t channel, size_t start, size_t count) const;
 
     virtual void toXml(QTextStream &out,
                        QString indent = "",
@@ -82,6 +84,7 @@
     size_t m_sampleRate;
     size_t m_channels;
     size_t m_frameCount;
+    size_t m_startFrame;
     int m_completion;
 };