aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
authorTobias Gunkel2011-12-21 10:10:42 +0100
committerTobias Gunkel2011-12-22 12:08:28 +0100
commitf7a869ccc5c22212768c43f258a7fbf7dddb758f (patch)
treeb0afdff0275cd05d0d4d3e7577e98d8fc22bb872 /engines/scumm
parent3a9f2c5f5bb817b4acbe279aedae938679634257 (diff)
downloadscummvm-rg350-f7a869ccc5c22212768c43f258a7fbf7dddb758f.tar.gz
scummvm-rg350-f7a869ccc5c22212768c43f258a7fbf7dddb758f.tar.bz2
scummvm-rg350-f7a869ccc5c22212768c43f258a7fbf7dddb758f.zip
SCUMM: Optimize player_appleII sample buffer
The AppleII sound player works in two phases: writing samples to the sample buffer (sample generation) or reading samples from the buffer and passing it to ScummVM's output callback. The sample buffer is read completely in the reading phase so the entries of the already read samples of the buffer can be reused again during the next write phase.
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/player_appleII.h84
1 files changed, 50 insertions, 34 deletions
diff --git a/engines/scumm/player_appleII.h b/engines/scumm/player_appleII.h
index f0b148ef86..1f53b6a8dc 100644
--- a/engines/scumm/player_appleII.h
+++ b/engines/scumm/player_appleII.h
@@ -35,13 +35,20 @@ namespace Scumm {
class ScummEngine;
-class DynamicMemoryStream {
+/*
+ * Optimized for use with periodical read/write phases when the buffer
+ * is filled in a write phase and completely read in a read phase.
+ * The growing strategy is optimized for repeated small (e.g. 2 bytes)
+ * single writes resulting in large buffers
+ * (avg.: 4KB, max: 18KB @ 16bit/22.050kHz (MM sound21)).
+ */
+class SampleBuffer {
public:
- DynamicMemoryStream() : _data(0) {
+ SampleBuffer() : _data(0) {
clear();
}
- ~DynamicMemoryStream() {
+ ~SampleBuffer() {
free(_data);
}
@@ -49,50 +56,61 @@ public:
free(_data);
_data = 0;
_capacity = 0;
- _size = 0;
- _ptr = 0;
- _pos = 0;
+ _writePos = 0;
_readPos = 0;
}
- void ensureCapacity(uint32 new_len) {
- if (new_len <= _capacity)
+ void ensureFree(uint32 needed) {
+ // if data was read completely, reset read/write pos to front
+ if ((_writePos != 0) && (_writePos == _readPos)) {
+ _writePos = 0;
+ _readPos = 0;
+ }
+
+ // check for enough space at end of buffer
+ uint32 freeEndCnt = _capacity - _writePos;
+ if (needed <= freeEndCnt)
return;
- byte *old_data = _data;
+ uint32 avail = availableSize();
+
+ // check for enough space at beginning and end of buffer
+ if (needed <= _readPos + freeEndCnt) {
+ // move unread data to front of buffer
+ memmove(_data, _data + _readPos, avail);
+ _writePos = avail;
+ _readPos = 0;
+ } else { // needs a grow
+ byte *old_data = _data;
+ uint32 new_len = avail + needed;
- _capacity *= 2;
- if (_capacity < new_len + 2048)
_capacity = new_len + 2048;
- _data = (byte *)malloc(_capacity);
- _ptr = _data + _pos;
-
- if (old_data) {
- // Copy old data
- memcpy(_data, old_data, _size);
- free(old_data);
+ _data = (byte *)malloc(_capacity);
+
+ if (old_data) {
+ // copy old unread data to front of new buffer
+ memcpy(_data, old_data + _readPos, avail);
+ free(old_data);
+ _writePos = avail;
+ _readPos = 0;
+ }
}
-
- _size = new_len;
}
uint32 availableSize() const {
- if (_readPos >= _size)
+ if (_readPos >= _writePos)
return 0;
- return _size - _readPos;
+ return _writePos - _readPos;
}
virtual uint32 write(const void *dataPtr, uint32 dataSize) {
- ensureCapacity(_pos + dataSize);
- memcpy(_ptr, dataPtr, dataSize);
- _ptr += dataSize;
- _pos += dataSize;
- if (_pos > _size)
- _size = _pos;
+ ensureFree(dataSize);
+ memcpy(_data + _writePos, dataPtr, dataSize);
+ _writePos += dataSize;
return dataSize;
}
- uint32 read(byte *dataPtr, uint32 dataSize) const {
+ uint32 read(byte *dataPtr, uint32 dataSize) {
uint32 avail = availableSize();
if (avail == 0)
return 0;
@@ -104,12 +122,10 @@ public:
}
private:
- mutable uint32 _readPos;
+ uint32 _writePos;
+ uint32 _readPos;
uint32 _capacity;
- uint32 _size;
- byte *_ptr;
byte *_data;
- uint32 _pos;
};
// CPU_CLOCK according to AppleWin
@@ -214,7 +230,7 @@ private:
int _sampleCyclesSumFP; /* (fixed precision) */
int _volume; /* 0 - 256 */
static const int _maxVolume = 256;
- DynamicMemoryStream _buffer;
+ SampleBuffer _buffer;
};
class AppleII_SoundFunction;