aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
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;