aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/scumm/player_appleII.cpp199
-rw-r--r--engines/scumm/player_appleII.h41
2 files changed, 177 insertions, 63 deletions
diff --git a/engines/scumm/player_appleII.cpp b/engines/scumm/player_appleII.cpp
index 0c34c906a6..a4111c5109 100644
--- a/engines/scumm/player_appleII.cpp
+++ b/engines/scumm/player_appleII.cpp
@@ -28,11 +28,10 @@
namespace Scumm {
Player_AppleII::Player_AppleII(ScummEngine *scumm, Audio::Mixer *mixer) {
- _speakerState = 0;
- _soundNr = 0;
-
_mixer = mixer;
_vm = scumm;
+
+ resetState();
setSampleRate(_mixer->getOutputRate());
@@ -70,18 +69,23 @@ void logSounds() {
void Player_AppleII::startSound(int nr) {
Common::StackLock lock(_mutex);
- _soundNr = nr;
- _sampleConverter.reset();
+ resetState();
byte *data = _vm->getResourceAddress(rtSound, nr);
assert(data);
-
byte *ptr1 = data + 4;
_state.type = ptr1[0];
- if (_state.type == 0)
+ if (_state.type == 0) {
+ // nothing to play
+ resetState();
return;
-
+ }
+
+ _state.soundNr = nr;
+ _state.finished = false;
+ initFuncState();
+
_state.loop = ptr1[1];
assert(_state.loop > 0);
@@ -89,44 +93,86 @@ void Player_AppleII::startSound(int nr) {
debug(4, "startSound %d: type %d, loop %d",
nr, _state.type, _state.loop);
-
- do {
- switch (_state.type) {
- case 1: // freq up/down
- soundFunc1();
- break;
- case 2: // symmetric wave (~)
- soundFunc2();
- break;
- case 3: // asymmetric wave (__-)
- soundFunc3();
- break;
- case 4: // polyphone (2 voices)
- soundFunc4();
- break;
- case 5: // periodic noise
- soundFunc5();
- break;
- }
+}
+
+void Player_AppleII::initFuncState() {
+ switch (_state.type) {
+ case 2: case 3:
+ _state.func23.pos = 1;
+ break;
+ case 4:
+ _state.func4.updateRemain1 = 80;
+ _state.func4.updateRemain2 = 10;
+ break;
+ case 5:
+ _state.func5.index = 0;
+ break;
+ }
+}
+
+bool Player_AppleII::updateSound() {
+ if (!_state.soundNr || _state.finished)
+ return false;
+
+ bool done = false;
+ switch (_state.type) {
+ case 1: // freq up/down
+ done = soundFunc1();
+ break;
+ case 2: // symmetric wave (~)
+ done = soundFunc2();
+ break;
+ case 3: // asymmetric wave (__-)
+ done = soundFunc3();
+ break;
+ case 4: // polyphone (2 voices)
+ done = soundFunc4();
+ break;
+ case 5: // periodic noise
+ done = soundFunc5();
+ break;
+ }
+
+ if (done) {
--_state.loop;
- } while (_state.loop > 0);
+ if (_state.loop <= 0) {
+ _state.finished = true;
+ } else {
+ // reset function state on each loop
+ initFuncState();
+ }
+ }
+
+ return true;
+}
+
+void Player_AppleII::resetState() {
+ _state.soundNr = 0;
+ _state.type = 0;
+ _state.loop = 0;
+ _state.params = NULL;
+ _state.localParams = NULL;
+ _state.speakerState = 0;
+ _state.finished = true;
+
+ _sampleConverter.reset();
}
void Player_AppleII::stopAllSounds() {
Common::StackLock lock(_mutex);
- _sampleConverter.reset();
+ resetState();
}
void Player_AppleII::stopSound(int nr) {
Common::StackLock lock(_mutex);
- if (_soundNr == nr) {
- _sampleConverter.reset();
+ if (_state.soundNr == nr) {
+ resetState();
}
}
int Player_AppleII::getSoundStatus(int nr) const {
Common::StackLock lock(_mutex);
- return (_sampleConverter.availableSize() > 0 ? 1 : 0);
+ return (_state.soundNr == nr);
}
int Player_AppleII::getMusicTimer() {
@@ -136,7 +182,22 @@ int Player_AppleII::getMusicTimer() {
int Player_AppleII::readBuffer(int16 *buffer, const int numSamples) {
Common::StackLock lock(_mutex);
- return _sampleConverter.readSamples(buffer, numSamples);
+
+ if (!_state.soundNr)
+ return 0;
+
+ int samplesLeft = numSamples;
+ do {
+ int nSamplesRead = _sampleConverter.readSamples(buffer, samplesLeft);
+ samplesLeft -= nSamplesRead;
+ buffer += nSamplesRead;
+ } while ((samplesLeft > 0) && updateSound());
+
+ // reset state if sound is played completely
+ if (_state.finished && (_sampleConverter.availableSize() == 0))
+ resetState();
+
+ return numSamples - samplesLeft;
}
/************************************
@@ -145,11 +206,11 @@ int Player_AppleII::readBuffer(int16 *buffer, const int numSamples) {
// toggle speaker on/off
void Player_AppleII::speakerToggle() {
- _speakerState ^= 0x1;
+ _state.speakerState ^= 0x1;
}
void Player_AppleII::generateSamples(int cycles) {
- _sampleConverter.addCycles(_speakerState, cycles);
+ _sampleConverter.addCycles(_state.speakerState, cycles);
}
void Player_AppleII::wait(int interval, int count /*y*/) {
@@ -168,7 +229,7 @@ void Player_AppleII::_soundFunc1(int interval /*a*/, int count /*y*/) { // D076
}
}
-void Player_AppleII::soundFunc1() { // D085
+bool Player_AppleII::soundFunc1() { // D085
const int delta = _state.params[0];
const int count = _state.params[1];
byte interval = _state.params[2]; // must be byte ("interval < delta" possible)
@@ -186,6 +247,8 @@ void Player_AppleII::soundFunc1() { // D085
interval += delta;
} while (interval < limit);
}
+
+ return true;
}
void Player_AppleII::_soundFunc2(int interval /*a*/, int count) { // D0EF
@@ -206,13 +269,18 @@ void Player_AppleII::_soundFunc2(int interval /*a*/, int count) { // D0EF
}
}
-void Player_AppleII::soundFunc2() { // D0D6
- for (int pos = 1; pos < 256; ++pos) {
- byte interval = _state.params[pos];
+bool Player_AppleII::soundFunc2() { // D0D6
+ // while (pos = 1; pos < 256; ++pos)
+ if (_state.func23.pos < 256) {
+ byte interval = _state.params[_state.func23.pos];
if (interval == 0xFF)
- return;
+ return true;
_soundFunc2(interval, _state.params[0] /*, LD12F=interval*/);
- }
+
+ ++_state.func23.pos;
+ return false;
+ }
+ return true;
}
void Player_AppleII::_soundFunc3(int interval /*a*/, int count /*LD12D*/) { // D14B
@@ -229,13 +297,18 @@ void Player_AppleII::_soundFunc3(int interval /*a*/, int count /*LD12D*/) { // D
}
}
-void Player_AppleII::soundFunc3() { // D132
- for (int pos = 1; pos < 256; ++pos) {
- byte interval = _state.params[pos];
+bool Player_AppleII::soundFunc3() { // D132
+ // while (pos = 1; pos < 256; ++pos)
+ if (_state.func23.pos < 256) {
+ byte interval = _state.params[_state.func23.pos];
if (interval == 0xFF)
- return;
+ return true;
_soundFunc3(interval, _state.params[0]);
+
+ ++_state.func23.pos;
+ return false;
}
+ return true;
}
void Player_AppleII::_soundFunc4(byte param0, byte param1, byte param2) { // D1A2
@@ -258,8 +331,8 @@ void Player_AppleII::_soundFunc4(byte param0, byte param1, byte param2) { // D1A
}
byte speakerShiftReg = 0;
- static byte updateRemain1 = 80;
- static byte updateRemain2 = 10;
+ byte updateRemain1 = _state.func4.updateRemain1;
+ byte updateRemain2 = _state.func4.updateRemain2;
while (true) {
--updateRemain1;
@@ -285,17 +358,26 @@ void Player_AppleII::_soundFunc4(byte param0, byte param1, byte param2) { // D1A
++count;
if (count == 0) {
+ _state.func4.updateRemain1 = updateRemain1;
+ _state.func4.updateRemain2 = updateRemain2;
return;
}
}
}
-void Player_AppleII::soundFunc4() { // D170
- const byte *params = _state.params;
- while (params[0] != 0x01) {
- _soundFunc4(params[0], params[1], params[2]);
- params += 3;
+bool Player_AppleII::soundFunc4() { // D170
+ if (!_state.localParams)
+ _state.localParams = _state.params;
+
+ // while (_state.params[0] != 0x01)
+ if (_state.localParams[0] != 0x01) {
+ _soundFunc4(_state.localParams[0], _state.localParams[1], _state.localParams[2]);
+ _state.localParams += 3;
+ return false;
}
+
+ _state.localParams = NULL;
+ return true;
}
void Player_AppleII::_soundFunc5(int interval /*a*/, int count) { // D270
@@ -339,20 +421,27 @@ byte /*a*/ Player_AppleII::noise() { // D261
return result;
}
-void Player_AppleII::soundFunc5() { // D222
+bool Player_AppleII::soundFunc5() { // D222
const byte noiseMask[] = {
0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F
};
int param0 = _state.params[0];
assert(param0 > 0);
- for (int i = 0; i < 10; ++i) {
+
+ // while (i = 0; i < 10; ++i)
+ if (_state.func5.index < 10) {
int count = param0;
do {
- _soundFunc5(noise() & noiseMask[i], 1);
+ _soundFunc5(noise() & noiseMask[_state.func5.index], 1);
--count;
} while (count > 0);
+
+ ++_state.func5.index;
+ return false;
}
+
+ return true;
}
} // End of namespace Scumm
diff --git a/engines/scumm/player_appleII.h b/engines/scumm/player_appleII.h
index 7cc02b1f01..eb4a99c4bd 100644
--- a/engines/scumm/player_appleII.h
+++ b/engines/scumm/player_appleII.h
@@ -241,10 +241,34 @@ public:
int getRate() const { return _sampleRate; }
private:
- struct state_t {
+ struct sound_state {
+ // sound number
+ int soundNr;
+ // type of sound
int type;
+ // number of loops left
int loop;
+ // global sound param list
const byte *params;
+ // local sound param list
+ const byte *localParams;
+ // speaker toggle state (0 / 1)
+ byte speakerState;
+ // processing complete
+ bool finished;
+ // sound type specific data
+ union {
+ struct {
+ byte updateRemain1;
+ byte updateRemain2;
+ } func4;
+ struct {
+ int pos;
+ } func23;
+ struct {
+ int index;
+ } func5;
+ };
} _state;
ScummEngine *_vm;
@@ -254,25 +278,26 @@ private:
Common::Mutex _mutex;
private:
- byte _speakerState;
- int _soundNr;
SampleConverter _sampleConverter;
private:
+ void resetState();
+ void initFuncState();
+ bool updateSound();
void speakerToggle();
void generateSamples(int cycles);
void wait(int interval, int count);
byte noise();
- void soundFunc1();
+ bool soundFunc1();
void _soundFunc1(int interval, int count);
- void soundFunc2();
+ bool soundFunc2();
void _soundFunc2(int interval, int count);
- void soundFunc3();
+ bool soundFunc3();
void _soundFunc3(int interval, int count);
- void soundFunc4();
+ bool soundFunc4();
void _soundFunc4(byte param0, byte param1, byte param2);
- void soundFunc5();
+ bool soundFunc5();
void _soundFunc5(int interval, int count);
};