[Scummvm-cvs-logs] scummvm master -> 5ad589da061b7d193aaa9a4f7960da9e60aaa7bf
lordhoto
lordhoto at gmail.com
Wed Jun 4 01:52:53 CEST 2014
This automated email contains information about 24 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
e71c841ca0 SCUMM: Small cleanup in SFX note setup in AD code.
703f1eef48 SCUMM: Slight cleanup in SFX register code in AD player.
13af131775 SCUMM: Introduce symbolic names for channel/note states in AD code.
ffbd6a8432 SCUMM: Only keep music data variable for music around in AD code.
70789f3964 SCUMM: Further SFX note related cleanup in AD player.
a1d36da506 SCUMM: Move notes into SFX channel structure in AD player.
7b96217c11 SCUMM: Fix sfx resource unlocking in AD player.
f95d28b74e SCUMM: Replace some more constants with named enum values in AD code.
fa6779c7a7 SCUMM: Store hardware channel number explicitly in Channel structure in AD code.
c50f6af8f7 SCUMM: Always work directly on Channel data in AD code.
7ad0e135e6 SCUMM: Further refactor AD SFX code.
99f9756992 SCUMM: Further cleanup in AD SFX code.
ecabacaddd SCUMM: Properly unlock sound resources when reusing sfx slots in AD code.
b5ca6b01f9 SCUMM: Clean up how SFX are stopped in the AD player.
02f47dd497 SCUMM: Allow multiple SFX to be played at once with AD.
f78e12cd5c SCUMM: Dynamically allocate hw channels for SFX in AD player.
a6ec34f424 SCUMM: Let music in AD code use the same HW channel allocation as SFX.
707cfd07ac SCUMM: Only stop music when requested in AD code.
5ab61bcea5 SCUMM: Allow music and sfx to be played at the same time in AD player.
c281da662e SCUMM: Only reset rhythm state when music is stopped.
d18c31e2eb SCUMM: Fix volume levels when playing SFX and music at the same time in AD player.
46a95fa157 SCUMM: Make sound completely silent for volume level 0 in AD code.
efe5348d25 SCUMM: Only stop music instead of all sounds in music handling of AD player.
5ad589da06 SCUMM: Fix music looping in AD player.
Commit: e71c841ca06a8d4a047d7ee6096ea56c2c028781
https://github.com/scummvm/scummvm/commit/e71c841ca06a8d4a047d7ee6096ea56c2c028781
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:29+02:00
Commit Message:
SCUMM: Small cleanup in SFX note setup in AD code.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 7b52511..0612c81 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -662,8 +662,8 @@ void Player_AD::parseSlot(int channel) {
++curOffset;
_channels[channel].state = 2;
noteOffOn(channel);
- parseNote(channel, 0, curOffset);
- parseNote(channel, 1, curOffset);
+ parseNote(channel, 0, curOffset + 0);
+ parseNote(channel, 1, curOffset + 5);
return;
case 0x80:
@@ -708,7 +708,7 @@ void Player_AD::updateSlot(int channel) {
updateNote = true;
}
} else {
- updateNote = processNoteEnvelope(note, _notes[note].instrumentValue);
+ updateNote = processNoteEnvelope(&_notes[note]);
if (_notes[note].bias) {
writeRegisterSpecial(note, _notes[note].bias - _notes[note].instrumentValue, *curOffset & 0x07);
@@ -740,10 +740,6 @@ void Player_AD::updateSlot(int channel) {
}
void Player_AD::parseNote(int channel, int num, const byte *offset) {
- if (num) {
- offset += 5;
- }
-
if (*offset & 0x80) {
const int note = channel * 2 + num;
_notes[note].state = -1;
@@ -793,7 +789,7 @@ bool Player_AD::processNote(int note, const byte *offset) {
}
int adjustValue = ((_noteAdjustTable[timer2] * _noteAdjustScaleTable[instrumentDataOffset]) >> 16) - noteInstrumentValue;
- setupNoteEnvelopeState(note, _numStepsTable[timer1], adjustValue);
+ setupNoteEnvelopeState(&_notes[note], _numStepsTable[timer1], adjustValue);
}
return false;
@@ -858,39 +854,39 @@ uint8 Player_AD::readRegisterSpecial(int note, uint8 defaultValue, int offset) {
return regValue;
}
-void Player_AD::setupNoteEnvelopeState(int note, int steps, int adjust) {
- _notes[note].preIncrease = 0;
+void Player_AD::setupNoteEnvelopeState(Note *note, int steps, int adjust) {
+ note->preIncrease = 0;
if (ABS(adjust) > steps) {
- _notes[note].preIncrease = 1;
- _notes[note].adjust = adjust / steps;
- _notes[note].envelope.stepIncrease = ABS(adjust % steps);
+ note->preIncrease = 1;
+ note->adjust = adjust / steps;
+ note->envelope.stepIncrease = ABS(adjust % steps);
} else {
- _notes[note].adjust = adjust;
- _notes[note].envelope.stepIncrease = ABS(adjust);
+ note->adjust = adjust;
+ note->envelope.stepIncrease = ABS(adjust);
}
- _notes[note].envelope.step = steps;
- _notes[note].envelope.stepCounter = 0;
- _notes[note].envelope.timer = steps;
+ note->envelope.step = steps;
+ note->envelope.stepCounter = 0;
+ note->envelope.timer = steps;
}
-bool Player_AD::processNoteEnvelope(int note, int &instrumentValue) {
- if (_notes[note].preIncrease) {
- instrumentValue += _notes[note].adjust;
+bool Player_AD::processNoteEnvelope(Note *note) {
+ if (note->preIncrease) {
+ note->instrumentValue += note->adjust;
}
- _notes[note].envelope.stepCounter += _notes[note].envelope.stepIncrease;
- if (_notes[note].envelope.stepCounter >= _notes[note].envelope.step) {
- _notes[note].envelope.stepCounter -= _notes[note].envelope.step;
+ note->envelope.stepCounter += note->envelope.stepIncrease;
+ if (note->envelope.stepCounter >= note->envelope.step) {
+ note->envelope.stepCounter -= note->envelope.step;
- if (_notes[note].adjust < 0) {
- --instrumentValue;
+ if (note->adjust < 0) {
+ --note->instrumentValue;
} else {
- ++instrumentValue;
+ ++note->instrumentValue;
}
}
- if (--_notes[note].envelope.timer) {
+ if (--note->envelope.timer) {
return false;
} else {
return true;
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index fbb65fb..d03d5e7 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -127,6 +127,23 @@ private:
static const uint _rhythmChannelTable[6];
// SFX handling
+ struct Note {
+ int state;
+ int playTime;
+ int sustainTimer;
+ int instrumentValue;
+ int bias;
+ int preIncrease;
+ int adjust;
+
+ struct Envelope {
+ int stepIncrease;
+ int step;
+ int stepCounter;
+ int timer;
+ } envelope;
+ };
+
void startSfx();
void updateSfx();
void clearChannel(int channel);
@@ -138,8 +155,8 @@ private:
void noteOffOn(int channel);
void writeRegisterSpecial(int note, uint8 value, int offset);
uint8 readRegisterSpecial(int note, uint8 defaultValue, int offset);
- void setupNoteEnvelopeState(int note, int steps, int adjust);
- bool processNoteEnvelope(int note, int &instrumentValue);
+ void setupNoteEnvelopeState(Note *note, int steps, int adjust);
+ bool processNoteEnvelope(Note *note);
int _sfxTimer;
@@ -156,22 +173,7 @@ private:
uint8 _rndSeed;
uint8 getRnd();
- struct Note {
- int state;
- int playTime;
- int sustainTimer;
- int instrumentValue;
- int bias;
- int preIncrease;
- int adjust;
-
- struct Envelope {
- int stepIncrease;
- int step;
- int stepCounter;
- int timer;
- } envelope;
- } _notes[22];
+ Note _notes[22];
static const uint _noteBiasTable[7];
static const uint _numStepsTable[16];
Commit: 703f1eef484e826c29be73a86a91521071dc801b
https://github.com/scummvm/scummvm/commit/703f1eef484e826c29be73a86a91521071dc801b
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:29+02:00
Commit Message:
SCUMM: Slight cleanup in SFX register code in AD player.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 0612c81..6729809 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -711,9 +711,9 @@ void Player_AD::updateSlot(int channel) {
updateNote = processNoteEnvelope(&_notes[note]);
if (_notes[note].bias) {
- writeRegisterSpecial(note, _notes[note].bias - _notes[note].instrumentValue, *curOffset & 0x07);
+ writeRegisterSpecial(channel, _notes[note].bias - _notes[note].instrumentValue, *curOffset & 0x07);
} else {
- writeRegisterSpecial(note, _notes[note].instrumentValue, *curOffset & 0x07);
+ writeRegisterSpecial(channel, _notes[note].instrumentValue, *curOffset & 0x07);
}
}
@@ -766,7 +766,7 @@ bool Player_AD::processNote(int note, const byte *offset) {
instrumentDataValue = _channels[note / 2].instrumentData[instrumentDataOffset];
}
- uint8 noteInstrumentValue = readRegisterSpecial(note, instrumentDataValue, instrumentDataOffset);
+ uint8 noteInstrumentValue = readRegisterSpecial(note / 2, instrumentDataValue, instrumentDataOffset);
if (_notes[note].bias) {
noteInstrumentValue = _notes[note].bias - noteInstrumentValue;
}
@@ -801,19 +801,16 @@ void Player_AD::noteOffOn(int channel) {
writeReg(0xB0 | channel, regValue | 0x20);
}
-void Player_AD::writeRegisterSpecial(int note, uint8 value, int offset) {
+void Player_AD::writeRegisterSpecial(int channel, uint8 value, int offset) {
if (offset == 6) {
return;
}
- // Division by 2 extracts the channel number out of the note.
- note /= 2;
-
uint8 regNum;
if (_useOperatorTable[offset]) {
- regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2];
+ regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + channel * 2];
} else {
- regNum = _channelOffsetTable[note];
+ regNum = _channelOffsetTable[channel];
}
regNum += _baseRegisterTable[offset];
@@ -824,19 +821,16 @@ void Player_AD::writeRegisterSpecial(int note, uint8 value, int offset) {
writeReg(regNum, regValue);
}
-uint8 Player_AD::readRegisterSpecial(int note, uint8 defaultValue, int offset) {
+uint8 Player_AD::readRegisterSpecial(int channel, uint8 defaultValue, int offset) {
if (offset == 6) {
return 0;
}
- // Division by 2 extracts the channel number out of the note.
- note /= 2;
-
uint8 regNum;
if (_useOperatorTable[offset]) {
- regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2];
+ regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + channel * 2];
} else {
- regNum = _channelOffsetTable[note];
+ regNum = _channelOffsetTable[channel];
}
regNum += _baseRegisterTable[offset];
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index d03d5e7..06dfb70 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -153,8 +153,8 @@ private:
void parseNote(int channel, int num, const byte *offset);
bool processNote(int note, const byte *offset);
void noteOffOn(int channel);
- void writeRegisterSpecial(int note, uint8 value, int offset);
- uint8 readRegisterSpecial(int note, uint8 defaultValue, int offset);
+ void writeRegisterSpecial(int channel, uint8 value, int offset);
+ uint8 readRegisterSpecial(int channel, uint8 defaultValue, int offset);
void setupNoteEnvelopeState(Note *note, int steps, int adjust);
bool processNoteEnvelope(Note *note);
Commit: 13af131775bc7f56e8f81ed1fa4aa19c84fc118a
https://github.com/scummvm/scummvm/commit/13af131775bc7f56e8f81ed1fa4aa19c84fc118a
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Introduce symbolic names for channel/note states in AD code.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 6729809..964cf19 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -560,9 +560,9 @@ void Player_AD::startSfx() {
const int startChannel = _resource[1] * 3;
// Clear the channel.
- _channels[startChannel + 0].state = 0;
- _channels[startChannel + 1].state = 0;
- _channels[startChannel + 2].state = 0;
+ _channels[startChannel + 0].state = kChannelStateOff;
+ _channels[startChannel + 1].state = kChannelStateOff;
+ _channels[startChannel + 2].state = kChannelStateOff;
clearChannel(startChannel + 0);
clearChannel(startChannel + 1);
@@ -570,7 +570,7 @@ void Player_AD::startSfx() {
// Set up the first channel to pick up playback.
_channels[startChannel].currentOffset = _channels[startChannel].startOffset = _resource + 2;
- _channels[startChannel].state = 1;
+ _channels[startChannel].state = kChannelStateParse;
// Scan for the start of the other channels and set them up if required.
int curChannel = startChannel + 1;
@@ -598,7 +598,7 @@ void Player_AD::startSfx() {
bufferPosition += 1;
_channels[curChannel].currentOffset = bufferPosition;
_channels[curChannel].startOffset = bufferPosition;
- _channels[curChannel].state = 1;
+ _channels[curChannel].state = kChannelStateParse;
++curChannel;
break;
}
@@ -626,7 +626,7 @@ void Player_AD::clearChannel(int channel) {
}
void Player_AD::updateChannel(int channel) {
- if (_channels[channel].state == 1) {
+ if (_channels[channel].state == kChannelStateParse) {
parseSlot(channel);
} else {
updateSlot(channel);
@@ -660,7 +660,7 @@ void Player_AD::parseSlot(int channel) {
case 2:
// NOTE DEFINITION
++curOffset;
- _channels[channel].state = 2;
+ _channels[channel].state = kChannelStatePlay;
noteOffOn(channel);
parseNote(channel, 0, curOffset + 0);
parseNote(channel, 1, curOffset + 5);
@@ -677,7 +677,7 @@ void Player_AD::parseSlot(int channel) {
// it means that the current channel is finished. Thus, we will
// stop it.
clearChannel(channel);
- _channels[channel].state = 0;
+ _channels[channel].state = kChannelStateOff;
// If no channel of the sound effect is playing anymore, unlock
// the resource.
@@ -703,7 +703,7 @@ void Player_AD::updateSlot(int channel) {
const int note = channel * 2 + num;
bool updateNote = false;
- if (_notes[note].state == 2) {
+ if (_notes[note].state == kNoteStateSustain) {
if (!--_notes[note].sustainTimer) {
updateNote = true;
}
@@ -721,20 +721,20 @@ void Player_AD::updateSlot(int channel) {
if (processNote(note, curOffset)) {
if (!(*curOffset & 0x08)) {
_channels[channel].currentOffset += 11;
- _channels[channel].state = 1;
+ _channels[channel].state = kChannelStateParse;
continue;
} else if (*curOffset & 0x10) {
noteOffOn(channel);
}
- _notes[note].state = -1;
+ _notes[note].state = kNoteStatePreInit;
processNote(note, curOffset);
}
}
if ((*curOffset & 0x20) && !--_notes[note].playTime) {
_channels[channel].currentOffset += 11;
- _channels[channel].state = 1;
+ _channels[channel].state = kChannelStateParse;
}
}
}
@@ -742,7 +742,7 @@ void Player_AD::updateSlot(int channel) {
void Player_AD::parseNote(int channel, int num, const byte *offset) {
if (*offset & 0x80) {
const int note = channel * 2 + num;
- _notes[note].state = -1;
+ _notes[note].state = kNoteStatePreInit;
processNote(note, offset);
_notes[note].playTime = 0;
@@ -754,7 +754,7 @@ void Player_AD::parseNote(int channel, int num, const byte *offset) {
}
bool Player_AD::processNote(int note, const byte *offset) {
- if (++_notes[note].state == 4) {
+ if (++_notes[note].state == kNoteStateOff) {
return true;
}
@@ -762,7 +762,7 @@ bool Player_AD::processNote(int note, const byte *offset) {
_notes[note].bias = _noteBiasTable[instrumentDataOffset];
uint8 instrumentDataValue = 0;
- if (_notes[note].state == 0) {
+ if (_notes[note].state == kNoteStateAttack) {
instrumentDataValue = _channels[note / 2].instrumentData[instrumentDataOffset];
}
@@ -772,7 +772,7 @@ bool Player_AD::processNote(int note, const byte *offset) {
}
_notes[note].instrumentValue = noteInstrumentValue;
- if (_notes[note].state == 2) {
+ if (_notes[note].state == kNoteStateSustain) {
_notes[note].sustainTimer = _numStepsTable[*(offset + 3) >> 4];
if (*offset & 0x40) {
@@ -780,7 +780,7 @@ bool Player_AD::processNote(int note, const byte *offset) {
}
} else {
int timer1, timer2;
- if (_notes[note].state == 3) {
+ if (_notes[note].state == kNoteStateRelease) {
timer1 = *(offset + 3) & 0x0F;
timer2 = 0;
} else {
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 06dfb70..94d42d0 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -127,6 +127,15 @@ private:
static const uint _rhythmChannelTable[6];
// SFX handling
+ enum {
+ kNoteStatePreInit = -1,
+ kNoteStateAttack = 0,
+ kNoteStateDecay = 1,
+ kNoteStateSustain = 2,
+ kNoteStateRelease = 3,
+ kNoteStateOff = 4
+ };
+
struct Note {
int state;
int playTime;
@@ -163,6 +172,12 @@ private:
int _sfxResource[3];
int _sfxPriority[3];
+ enum {
+ kChannelStateOff = 0,
+ kChannelStateParse = 1,
+ kChannelStatePlay = 2
+ };
+
struct Channel {
int state;
const byte *currentOffset;
Commit: ffbd6a8432e89df0f2d0a76d8e62567fa3a8ef03
https://github.com/scummvm/scummvm/commit/ffbd6a8432e89df0f2d0a76d8e62567fa3a8ef03
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Only keep music data variable for music around in AD code.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 964cf19..f76abc0 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -98,7 +98,7 @@ void Player_AD::startSound(int sound) {
_vm->_res->lock(rtSound, _soundPlaying);
// Start the new music resource
- _resource = res;
+ _musicData = res;
startMusic();
} else {
// Only try to start a sfx when no music is playing.
@@ -128,8 +128,7 @@ void Player_AD::startSound(int sound) {
_vm->_res->lock(rtSound, sound);
// Start the actual sfx resource
- _resource = res;
- startSfx();
+ startSfx(res);
}
}
@@ -316,12 +315,12 @@ void Player_AD::startMusic() {
memset(_channelB0Reg, 0, sizeof(_channelB0Reg));
_voiceChannels = 0;
- uint instruments = _resource[10];
+ uint instruments = _musicData[10];
for (uint i = 0; i < instruments; ++i) {
- const int instrIndex = _resource[11 + i] - 1;
+ const int instrIndex = _musicData[11 + i] - 1;
if (0 <= instrIndex && instrIndex < 16) {
_instrumentOffset[instrIndex] = i * 16 + 16 + 3;
- _voiceChannels |= _resource[_instrumentOffset[instrIndex] + 13];
+ _voiceChannels |= _musicData[_instrumentOffset[instrIndex] + 13];
}
}
@@ -344,9 +343,9 @@ void Player_AD::startMusic() {
const bool isLoom = (_vm->_game.id == GID_LOOM);
_timerLimit = isLoom ? 473 : 256;
- _musicTicks = _resource[3] * (isLoom ? 2 : 1);
- _loopFlag = (_resource[4] == 0);
- _musicLoopStart = READ_LE_UINT16(_resource + 5);
+ _musicTicks = _musicData[3] * (isLoom ? 2 : 1);
+ _loopFlag = (_musicData[4] == 0);
+ _musicLoopStart = READ_LE_UINT16(_musicData + 5);
}
void Player_AD::updateMusic() {
@@ -368,11 +367,11 @@ void Player_AD::updateMusic() {
}
while (true) {
- uint command = _resource[_curOffset++];
+ uint command = _musicData[_curOffset++];
if (command == 0xFF) {
// META EVENT
// Get the command number.
- command = _resource[_curOffset++];
+ command = _musicData[_curOffset++];
if (command == 47) {
// End of track
if (_loopFlag) {
@@ -391,14 +390,14 @@ void Player_AD::updateMusic() {
_curOffset += 5;
} else if (command == 81) {
// Change tempo. This is used exclusively in Loom.
- const uint timing = _resource[_curOffset + 2] | (_resource[_curOffset + 1] << 8);
+ const uint timing = _musicData[_curOffset + 2] | (_musicData[_curOffset + 1] << 8);
_musicTicks = 0x73000 / timing;
- command = _resource[_curOffset++];
+ command = _musicData[_curOffset++];
_curOffset += command;
} else {
// In case an unknown meta event occurs just skip over the
// data by using the length supplied.
- command = _resource[_curOffset++];
+ command = _musicData[_curOffset++];
_curOffset += command;
}
} else {
@@ -409,22 +408,22 @@ void Player_AD::updateMusic() {
const uint instrOffset = _instrumentOffset[command];
if (instrOffset) {
- if (_resource[instrOffset + 13] != 0) {
- setupRhythm(_resource[instrOffset + 13], instrOffset);
+ if (_musicData[instrOffset + 13] != 0) {
+ setupRhythm(_musicData[instrOffset + 13], instrOffset);
} else {
int channel = findFreeChannel();
if (channel != -1) {
noteOff(channel);
- setupChannel(channel, instrOffset);
+ setupChannel(channel, _musicData + instrOffset);
_channelLastEvent[channel] = command + 0x90;
- _channelFrequency[channel] = _resource[_curOffset];
- setupFrequency(channel, _resource[_curOffset]);
+ _channelFrequency[channel] = _musicData[_curOffset];
+ setupFrequency(channel, _musicData[_curOffset]);
}
}
}
} else {
// NOTE OFF
- const uint note = _resource[_curOffset];
+ const uint note = _musicData[_curOffset];
command += 0x10;
// Find the output channel which plays the note.
@@ -445,8 +444,8 @@ void Player_AD::updateMusic() {
// rhythm instrument played on the channel.
command -= 0x90;
const uint instrOffset = _instrumentOffset[command];
- if (instrOffset && _resource[instrOffset + 13] != 0) {
- const uint rhythmInstr = _resource[instrOffset + 13];
+ if (instrOffset && _musicData[instrOffset + 13] != 0) {
+ const uint rhythmInstr = _musicData[instrOffset + 13];
if (rhythmInstr < 6) {
_mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF;
writeReg(0xBD, _mdvdrState);
@@ -459,17 +458,17 @@ void Player_AD::updateMusic() {
}
// In case there is a delay till the next event stop handling.
- if (_resource[_curOffset] != 0) {
+ if (_musicData[_curOffset] != 0) {
break;
}
++_curOffset;
}
- _nextEventTimer = _resource[_curOffset++];
+ _nextEventTimer = _musicData[_curOffset++];
if (_nextEventTimer & 0x80) {
_nextEventTimer -= 0x80;
_nextEventTimer <<= 7;
- _nextEventTimer |= _resource[_curOffset++];
+ _nextEventTimer |= _musicData[_curOffset++];
}
_nextEventTimer >>= (_vm->_game.id == GID_LOOM) ? 2 : 1;
@@ -516,17 +515,17 @@ void Player_AD::setupFrequency(uint channel, int8 frequency) {
void Player_AD::setupRhythm(uint rhythmInstr, uint instrOffset) {
if (rhythmInstr == 1) {
- setupChannel(6, instrOffset);
- writeReg(0xA6, _resource[instrOffset++]);
- writeReg(0xB6, _resource[instrOffset] & 0xDF);
+ setupChannel(6, _musicData + instrOffset);
+ writeReg(0xA6, _musicData[instrOffset++]);
+ writeReg(0xB6, _musicData[instrOffset] & 0xDF);
_mdvdrState |= 0x10;
writeReg(0xBD, _mdvdrState);
} else if (rhythmInstr < 6) {
- const byte *secondOperatorOffset = _resource + instrOffset + 8;
+ const byte *secondOperatorOffset = _musicData + instrOffset + 8;
setupOperator(_rhythmOperatorTable[rhythmInstr], secondOperatorOffset);
- writeReg(0xA0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++]);
- writeReg(0xB0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++] & 0xDF);
- writeReg(0xC0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset]);
+ writeReg(0xA0 + _rhythmChannelTable[rhythmInstr], _musicData[instrOffset++]);
+ writeReg(0xB0 + _rhythmChannelTable[rhythmInstr], _musicData[instrOffset++] & 0xDF);
+ writeReg(0xC0 + _rhythmChannelTable[rhythmInstr], _musicData[instrOffset]);
_mdvdrState |= _mdvdrTable[rhythmInstr];
writeReg(0xBD, _mdvdrState);
}
@@ -552,12 +551,12 @@ const uint Player_AD::_rhythmChannelTable[6] = {
// SFX
-void Player_AD::startSfx() {
+void Player_AD::startSfx(const byte *resource) {
writeReg(0xBD, 0x00);
// The second byte of the resource defines the logical channel where
// the sound effect should be played.
- const int startChannel = _resource[1] * 3;
+ const int startChannel = resource[1] * 3;
// Clear the channel.
_channels[startChannel + 0].state = kChannelStateOff;
@@ -569,12 +568,12 @@ void Player_AD::startSfx() {
clearChannel(startChannel + 2);
// Set up the first channel to pick up playback.
- _channels[startChannel].currentOffset = _channels[startChannel].startOffset = _resource + 2;
+ _channels[startChannel].currentOffset = _channels[startChannel].startOffset = resource + 2;
_channels[startChannel].state = kChannelStateParse;
// Scan for the start of the other channels and set them up if required.
int curChannel = startChannel + 1;
- const byte *bufferPosition = _resource + 2;
+ const byte *bufferPosition = resource + 2;
uint8 command = 0;
while ((command = *bufferPosition) != 0xFF) {
switch (command) {
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 94d42d0..dc5ba5e 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -86,16 +86,10 @@ private:
uint8 readReg(int r) const;
// Instrument setup
- void setupChannel(const uint channel, uint instrOffset) {
- setupChannel(channel, _resource + instrOffset);
- }
void setupChannel(const uint channel, const byte *instrOffset);
void setupOperator(const uint opr, const byte *&instrOffset);
static const int _operatorOffsetTable[18];
- // Sound data
- const byte *_resource;
-
// Music handling
void startMusic();
void updateMusic();
@@ -104,6 +98,7 @@ private:
void setupFrequency(uint channel, int8 frequency);
void setupRhythm(uint rhythmInstr, uint instrOffset);
+ const byte *_musicData;
uint _timerLimit;
uint _musicTicks;
uint _musicTimer;
@@ -153,7 +148,7 @@ private:
} envelope;
};
- void startSfx();
+ void startSfx(const byte *resource);
void updateSfx();
void clearChannel(int channel);
void updateChannel(int channel);
Commit: 70789f39642cc6bfeb9e3c567539249e6ee15cc3
https://github.com/scummvm/scummvm/commit/70789f39642cc6bfeb9e3c567539249e6ee15cc3
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Further SFX note related cleanup in AD player.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index f76abc0..9dd25c4 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -661,8 +661,8 @@ void Player_AD::parseSlot(int channel) {
++curOffset;
_channels[channel].state = kChannelStatePlay;
noteOffOn(channel);
- parseNote(channel, 0, curOffset + 0);
- parseNote(channel, 1, curOffset + 5);
+ parseNote(&_notes[channel * 2 + 0], channel, curOffset + 0);
+ parseNote(&_notes[channel * 2 + 1], channel, curOffset + 5);
return;
case 0x80:
@@ -699,25 +699,25 @@ void Player_AD::updateSlot(int channel) {
continue;
}
- const int note = channel * 2 + num;
+ Note *const note = &_notes[channel * 2 + num];
bool updateNote = false;
- if (_notes[note].state == kNoteStateSustain) {
- if (!--_notes[note].sustainTimer) {
+ if (note->state == kNoteStateSustain) {
+ if (!--note->sustainTimer) {
updateNote = true;
}
} else {
- updateNote = processNoteEnvelope(&_notes[note]);
+ updateNote = processNoteEnvelope(note);
- if (_notes[note].bias) {
- writeRegisterSpecial(channel, _notes[note].bias - _notes[note].instrumentValue, *curOffset & 0x07);
+ if (note->bias) {
+ writeRegisterSpecial(channel, note->bias - note->instrumentValue, *curOffset & 0x07);
} else {
- writeRegisterSpecial(channel, _notes[note].instrumentValue, *curOffset & 0x07);
+ writeRegisterSpecial(channel, note->instrumentValue, *curOffset & 0x07);
}
}
if (updateNote) {
- if (processNote(note, curOffset)) {
+ if (processNote(note, channel, curOffset)) {
if (!(*curOffset & 0x08)) {
_channels[channel].currentOffset += 11;
_channels[channel].state = kChannelStateParse;
@@ -726,69 +726,68 @@ void Player_AD::updateSlot(int channel) {
noteOffOn(channel);
}
- _notes[note].state = kNoteStatePreInit;
- processNote(note, curOffset);
+ note->state = kNoteStatePreInit;
+ processNote(note, channel, curOffset);
}
}
- if ((*curOffset & 0x20) && !--_notes[note].playTime) {
+ if ((*curOffset & 0x20) && !--note->playTime) {
_channels[channel].currentOffset += 11;
_channels[channel].state = kChannelStateParse;
}
}
}
-void Player_AD::parseNote(int channel, int num, const byte *offset) {
+void Player_AD::parseNote(Note *note, int channel, const byte *offset) {
if (*offset & 0x80) {
- const int note = channel * 2 + num;
- _notes[note].state = kNoteStatePreInit;
- processNote(note, offset);
- _notes[note].playTime = 0;
+ note->state = kNoteStatePreInit;
+ processNote(note, channel, offset);
+ note->playTime = 0;
if (*offset & 0x20) {
- _notes[note].playTime = (*(offset + 4) >> 4) * 118;
- _notes[note].playTime += (*(offset + 4) & 0x0F) * 8;
+ note->playTime = (*(offset + 4) >> 4) * 118;
+ note->playTime += (*(offset + 4) & 0x0F) * 8;
}
}
}
-bool Player_AD::processNote(int note, const byte *offset) {
- if (++_notes[note].state == kNoteStateOff) {
+bool Player_AD::processNote(Note *note, int channel, const byte *offset) {
+ if (++note->state == kNoteStateOff) {
return true;
}
const int instrumentDataOffset = *offset & 0x07;
- _notes[note].bias = _noteBiasTable[instrumentDataOffset];
+ note->bias = _noteBiasTable[instrumentDataOffset];
uint8 instrumentDataValue = 0;
- if (_notes[note].state == kNoteStateAttack) {
- instrumentDataValue = _channels[note / 2].instrumentData[instrumentDataOffset];
+ if (note->state == kNoteStateAttack) {
+ instrumentDataValue = _channels[channel].instrumentData[instrumentDataOffset];
}
- uint8 noteInstrumentValue = readRegisterSpecial(note / 2, instrumentDataValue, instrumentDataOffset);
- if (_notes[note].bias) {
- noteInstrumentValue = _notes[note].bias - noteInstrumentValue;
+ uint8 noteInstrumentValue = readRegisterSpecial(channel, instrumentDataValue, instrumentDataOffset);
+ if (note->bias) {
+ noteInstrumentValue = note->bias - noteInstrumentValue;
}
- _notes[note].instrumentValue = noteInstrumentValue;
+ note->instrumentValue = noteInstrumentValue;
- if (_notes[note].state == kNoteStateSustain) {
- _notes[note].sustainTimer = _numStepsTable[*(offset + 3) >> 4];
+ if (note->state == kNoteStateSustain) {
+ note->sustainTimer = _numStepsTable[*(offset + 3) >> 4];
if (*offset & 0x40) {
- _notes[note].sustainTimer = (((getRnd() << 8) * _notes[note].sustainTimer) >> 16) + 1;
+ note->sustainTimer = (((getRnd() << 8) * note->sustainTimer) >> 16) + 1;
}
} else {
int timer1, timer2;
- if (_notes[note].state == kNoteStateRelease) {
+ if (note->state == kNoteStateRelease) {
timer1 = *(offset + 3) & 0x0F;
timer2 = 0;
} else {
- timer1 = *(offset + _notes[note].state + 1) >> 4;
- timer2 = *(offset + _notes[note].state + 1) & 0x0F;
+ timer1 = *(offset + note->state + 1) >> 4;
+ timer2 = *(offset + note->state + 1) & 0x0F;
}
int adjustValue = ((_noteAdjustTable[timer2] * _noteAdjustScaleTable[instrumentDataOffset]) >> 16) - noteInstrumentValue;
- setupNoteEnvelopeState(&_notes[note], _numStepsTable[timer1], adjustValue);
+ setupNoteEnvelopeState(note, _numStepsTable[timer1], adjustValue);
}
return false;
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index dc5ba5e..f5342d9 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -154,8 +154,8 @@ private:
void updateChannel(int channel);
void parseSlot(int channel);
void updateSlot(int channel);
- void parseNote(int channel, int num, const byte *offset);
- bool processNote(int note, const byte *offset);
+ void parseNote(Note *note, int channel, const byte *offset);
+ bool processNote(Note *note, int channel, const byte *offset);
void noteOffOn(int channel);
void writeRegisterSpecial(int channel, uint8 value, int offset);
uint8 readRegisterSpecial(int channel, uint8 defaultValue, int offset);
Commit: a1d36da506d60dd6a83d422f98c9db5fcb962ede
https://github.com/scummvm/scummvm/commit/a1d36da506d60dd6a83d422f98c9db5fcb962ede
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Move notes into SFX channel structure in AD player.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 9dd25c4..be17562 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -661,8 +661,8 @@ void Player_AD::parseSlot(int channel) {
++curOffset;
_channels[channel].state = kChannelStatePlay;
noteOffOn(channel);
- parseNote(&_notes[channel * 2 + 0], channel, curOffset + 0);
- parseNote(&_notes[channel * 2 + 1], channel, curOffset + 5);
+ parseNote(&_channels[channel].notes[0], channel, curOffset + 0);
+ parseNote(&_channels[channel].notes[1], channel, curOffset + 5);
return;
case 0x80:
@@ -699,7 +699,7 @@ void Player_AD::updateSlot(int channel) {
continue;
}
- Note *const note = &_notes[channel * 2 + num];
+ Note *const note = &_channels[channel].notes[num];
bool updateNote = false;
if (note->state == kNoteStateSustain) {
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index f5342d9..6d7d28f 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -178,13 +178,13 @@ private:
const byte *currentOffset;
const byte *startOffset;
uint8 instrumentData[7];
+
+ Note notes[2];
} _channels[11];
uint8 _rndSeed;
uint8 getRnd();
- Note _notes[22];
-
static const uint _noteBiasTable[7];
static const uint _numStepsTable[16];
static const uint _noteAdjustScaleTable[7];
Commit: 7b96217c11a6601dc36f0d11a7884ed033999ba3
https://github.com/scummvm/scummvm/commit/7b96217c11a6601dc36f0d11a7884ed033999ba3
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Fix sfx resource unlocking in AD player.
Changed paths:
engines/scumm/players/player_ad.cpp
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index be17562..3c40c1b 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -681,9 +681,9 @@ void Player_AD::parseSlot(int channel) {
// If no channel of the sound effect is playing anymore, unlock
// the resource.
channel /= 3;
- if (!_channels[channel + 0].state
- && !_channels[channel + 1].state
- && !_channels[channel + 2].state) {
+ if (!_channels[channel * 3 + 0].state
+ && !_channels[channel * 3 + 1].state
+ && !_channels[channel * 3 + 2].state) {
_vm->_res->unlock(rtSound, _sfxResource[channel]);
}
return;
Commit: f95d28b74eeabd1fc21b7df576d19d6eddaca9fa
https://github.com/scummvm/scummvm/commit/f95d28b74eeabd1fc21b7df576d19d6eddaca9fa
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Replace some more constants with named enum values in AD code.
Changed paths:
engines/scumm/players/player_ad.cpp
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 3c40c1b..a353f38 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -151,9 +151,9 @@ void Player_AD::stopSound(int sound) {
_vm->_res->unlock(rtSound, sound);
// Stop the actual sfx playback
- _channels[i * 3 + 0].state = 0;
- _channels[i * 3 + 1].state = 0;
- _channels[i * 3 + 2].state = 0;
+ _channels[i * 3 + 0].state = kChannelStateOff;
+ _channels[i * 3 + 1].state = kChannelStateOff;
+ _channels[i * 3 + 2].state = kChannelStateOff;
clearChannel(i * 3 + 0);
clearChannel(i * 3 + 1);
clearChannel(i * 3 + 2);
@@ -184,7 +184,7 @@ void Player_AD::stopAllSounds() {
// Reset all the sfx channels
for (int i = 0; i < 9; ++i) {
- _channels[i].state = 0;
+ _channels[i].state = kChannelStateOff;
clearChannel(i);
}
Commit: fa6779c7a789f2bf8120553bb7f020a37bc5279f
https://github.com/scummvm/scummvm/commit/fa6779c7a789f2bf8120553bb7f020a37bc5279f
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Store hardware channel number explicitly in Channel structure in AD code.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index a353f38..631a86e 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -63,6 +63,9 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
_rndSeed = 1;
memset(_channels, 0, sizeof(_channels));
+ for (int i = 0; i < ARRAYSIZE(_channels); ++i) {
+ _channels[i].hardwareChannel = i;
+ }
memset(_sfxResource, 0, sizeof(_sfxResource));
memset(_sfxPriority, 0, sizeof(_sfxPriority));
}
@@ -710,9 +713,9 @@ void Player_AD::updateSlot(int channel) {
updateNote = processNoteEnvelope(note);
if (note->bias) {
- writeRegisterSpecial(channel, note->bias - note->instrumentValue, *curOffset & 0x07);
+ writeRegisterSpecial(_channels[channel].hardwareChannel, note->bias - note->instrumentValue, *curOffset & 0x07);
} else {
- writeRegisterSpecial(channel, note->instrumentValue, *curOffset & 0x07);
+ writeRegisterSpecial(_channels[channel].hardwareChannel, note->instrumentValue, *curOffset & 0x07);
}
}
@@ -764,7 +767,7 @@ bool Player_AD::processNote(Note *note, int channel, const byte *offset) {
instrumentDataValue = _channels[channel].instrumentData[instrumentDataOffset];
}
- uint8 noteInstrumentValue = readRegisterSpecial(channel, instrumentDataValue, instrumentDataOffset);
+ uint8 noteInstrumentValue = readRegisterSpecial(_channels[channel].hardwareChannel, instrumentDataValue, instrumentDataOffset);
if (note->bias) {
noteInstrumentValue = note->bias - noteInstrumentValue;
}
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 6d7d28f..29b6e51 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -180,6 +180,8 @@ private:
uint8 instrumentData[7];
Note notes[2];
+
+ int hardwareChannel;
} _channels[11];
uint8 _rndSeed;
Commit: c50f6af8f794aa009142e4ebe2f934565d0bde0a
https://github.com/scummvm/scummvm/commit/c50f6af8f794aa009142e4ebe2f934565d0bde0a
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Always work directly on Channel data in AD code.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 631a86e..73eb893 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -157,9 +157,9 @@ void Player_AD::stopSound(int sound) {
_channels[i * 3 + 0].state = kChannelStateOff;
_channels[i * 3 + 1].state = kChannelStateOff;
_channels[i * 3 + 2].state = kChannelStateOff;
- clearChannel(i * 3 + 0);
- clearChannel(i * 3 + 1);
- clearChannel(i * 3 + 2);
+ clearChannel(_channels[i * 3 + 0]);
+ clearChannel(_channels[i * 3 + 1]);
+ clearChannel(_channels[i * 3 + 2]);
}
}
}
@@ -188,7 +188,7 @@ void Player_AD::stopAllSounds() {
// Reset all the sfx channels
for (int i = 0; i < 9; ++i) {
_channels[i].state = kChannelStateOff;
- clearChannel(i);
+ clearChannel(_channels[i]);
}
writeReg(0xBD, 0x00);
@@ -566,9 +566,9 @@ void Player_AD::startSfx(const byte *resource) {
_channels[startChannel + 1].state = kChannelStateOff;
_channels[startChannel + 2].state = kChannelStateOff;
- clearChannel(startChannel + 0);
- clearChannel(startChannel + 1);
- clearChannel(startChannel + 2);
+ clearChannel(_channels[startChannel + 0]);
+ clearChannel(_channels[startChannel + 1]);
+ clearChannel(_channels[startChannel + 2]);
// Set up the first channel to pick up playback.
_channels[startChannel].currentOffset = _channels[startChannel].startOffset = resource + 2;
@@ -618,91 +618,94 @@ void Player_AD::updateSfx() {
continue;
}
- updateChannel(i);
+ updateChannel(&_channels[i]);
}
}
-void Player_AD::clearChannel(int channel) {
- writeReg(0xA0 + channel, 0x00);
- writeReg(0xB0 + channel, 0x00);
+void Player_AD::clearChannel(const Channel &channel) {
+ writeReg(0xA0 + channel.hardwareChannel, 0x00);
+ writeReg(0xB0 + channel.hardwareChannel, 0x00);
}
-void Player_AD::updateChannel(int channel) {
- if (_channels[channel].state == kChannelStateParse) {
+void Player_AD::updateChannel(Channel *channel) {
+ if (channel->state == kChannelStateParse) {
parseSlot(channel);
} else {
updateSlot(channel);
}
}
-void Player_AD::parseSlot(int channel) {
+void Player_AD::parseSlot(Channel *channel) {
while (true) {
- const byte *curOffset = _channels[channel].currentOffset;
+ const byte *curOffset = channel->currentOffset;
switch (*curOffset) {
case 1:
// INSTRUMENT DEFINITION
++curOffset;
- _channels[channel].instrumentData[0] = *(curOffset + 0);
- _channels[channel].instrumentData[1] = *(curOffset + 2);
- _channels[channel].instrumentData[2] = *(curOffset + 9);
- _channels[channel].instrumentData[3] = *(curOffset + 8);
- _channels[channel].instrumentData[4] = *(curOffset + 4);
- _channels[channel].instrumentData[5] = *(curOffset + 3);
- _channels[channel].instrumentData[6] = 0;
+ channel->instrumentData[0] = *(curOffset + 0);
+ channel->instrumentData[1] = *(curOffset + 2);
+ channel->instrumentData[2] = *(curOffset + 9);
+ channel->instrumentData[3] = *(curOffset + 8);
+ channel->instrumentData[4] = *(curOffset + 4);
+ channel->instrumentData[5] = *(curOffset + 3);
+ channel->instrumentData[6] = 0;
- setupChannel(channel, curOffset);
+ setupChannel(channel->hardwareChannel, curOffset);
- writeReg(0xA0 + channel, *(curOffset + 0));
- writeReg(0xB0 + channel, *(curOffset + 1) & 0xDF);
+ writeReg(0xA0 + channel->hardwareChannel, *(curOffset + 0));
+ writeReg(0xB0 + channel->hardwareChannel, *(curOffset + 1) & 0xDF);
- _channels[channel].currentOffset += 15;
+ channel->currentOffset += 15;
break;
case 2:
// NOTE DEFINITION
++curOffset;
- _channels[channel].state = kChannelStatePlay;
- noteOffOn(channel);
- parseNote(&_channels[channel].notes[0], channel, curOffset + 0);
- parseNote(&_channels[channel].notes[1], channel, curOffset + 5);
+ channel->state = kChannelStatePlay;
+ noteOffOn(channel->hardwareChannel);
+ parseNote(&channel->notes[0], *channel, curOffset + 0);
+ parseNote(&channel->notes[1], *channel, curOffset + 5);
return;
case 0x80:
// LOOP
- _channels[channel].currentOffset = _channels[channel].startOffset;
+ channel->currentOffset = channel->startOffset;
break;
- default:
+ default: {
// START OF CHANNEL
// When we encounter a start of another channel while playback
// it means that the current channel is finished. Thus, we will
// stop it.
- clearChannel(channel);
- _channels[channel].state = kChannelStateOff;
+ clearChannel(*channel);
+ channel->state = kChannelStateOff;
// If no channel of the sound effect is playing anymore, unlock
// the resource.
- channel /= 3;
- if (!_channels[channel * 3 + 0].state
- && !_channels[channel * 3 + 1].state
- && !_channels[channel * 3 + 2].state) {
- _vm->_res->unlock(rtSound, _sfxResource[channel]);
+ // HACK: We shouldn't rely on the hardware channel to match the
+ // logical channel...
+ const int logChannel = channel->hardwareChannel / 3;
+ if (!_channels[logChannel * 3 + 0].state
+ && !_channels[logChannel * 3 + 1].state
+ && !_channels[logChannel * 3 + 2].state) {
+ _vm->_res->unlock(rtSound, _sfxResource[logChannel]);
}
return;
+ }
}
}
}
-void Player_AD::updateSlot(int channel) {
- const byte *curOffset = _channels[channel].currentOffset + 1;
+void Player_AD::updateSlot(Channel *channel) {
+ const byte *curOffset = channel->currentOffset + 1;
for (int num = 0; num <= 1; ++num, curOffset += 5) {
if (!(*curOffset & 0x80)) {
continue;
}
- Note *const note = &_channels[channel].notes[num];
+ Note *const note = &channel->notes[num];
bool updateNote = false;
if (note->state == kNoteStateSustain) {
@@ -713,35 +716,35 @@ void Player_AD::updateSlot(int channel) {
updateNote = processNoteEnvelope(note);
if (note->bias) {
- writeRegisterSpecial(_channels[channel].hardwareChannel, note->bias - note->instrumentValue, *curOffset & 0x07);
+ writeRegisterSpecial(channel->hardwareChannel, note->bias - note->instrumentValue, *curOffset & 0x07);
} else {
- writeRegisterSpecial(_channels[channel].hardwareChannel, note->instrumentValue, *curOffset & 0x07);
+ writeRegisterSpecial(channel->hardwareChannel, note->instrumentValue, *curOffset & 0x07);
}
}
if (updateNote) {
- if (processNote(note, channel, curOffset)) {
+ if (processNote(note, *channel, curOffset)) {
if (!(*curOffset & 0x08)) {
- _channels[channel].currentOffset += 11;
- _channels[channel].state = kChannelStateParse;
+ channel->currentOffset += 11;
+ channel->state = kChannelStateParse;
continue;
} else if (*curOffset & 0x10) {
- noteOffOn(channel);
+ noteOffOn(channel->hardwareChannel);
}
note->state = kNoteStatePreInit;
- processNote(note, channel, curOffset);
+ processNote(note, *channel, curOffset);
}
}
if ((*curOffset & 0x20) && !--note->playTime) {
- _channels[channel].currentOffset += 11;
- _channels[channel].state = kChannelStateParse;
+ channel->currentOffset += 11;
+ channel->state = kChannelStateParse;
}
}
}
-void Player_AD::parseNote(Note *note, int channel, const byte *offset) {
+void Player_AD::parseNote(Note *note, const Channel &channel, const byte *offset) {
if (*offset & 0x80) {
note->state = kNoteStatePreInit;
processNote(note, channel, offset);
@@ -754,7 +757,7 @@ void Player_AD::parseNote(Note *note, int channel, const byte *offset) {
}
}
-bool Player_AD::processNote(Note *note, int channel, const byte *offset) {
+bool Player_AD::processNote(Note *note, const Channel &channel, const byte *offset) {
if (++note->state == kNoteStateOff) {
return true;
}
@@ -764,10 +767,10 @@ bool Player_AD::processNote(Note *note, int channel, const byte *offset) {
uint8 instrumentDataValue = 0;
if (note->state == kNoteStateAttack) {
- instrumentDataValue = _channels[channel].instrumentData[instrumentDataOffset];
+ instrumentDataValue = channel.instrumentData[instrumentDataOffset];
}
- uint8 noteInstrumentValue = readRegisterSpecial(_channels[channel].hardwareChannel, instrumentDataValue, instrumentDataOffset);
+ uint8 noteInstrumentValue = readRegisterSpecial(channel.hardwareChannel, instrumentDataValue, instrumentDataOffset);
if (note->bias) {
noteInstrumentValue = note->bias - noteInstrumentValue;
}
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 29b6e51..95c779f 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -148,25 +148,6 @@ private:
} envelope;
};
- void startSfx(const byte *resource);
- void updateSfx();
- void clearChannel(int channel);
- void updateChannel(int channel);
- void parseSlot(int channel);
- void updateSlot(int channel);
- void parseNote(Note *note, int channel, const byte *offset);
- bool processNote(Note *note, int channel, const byte *offset);
- void noteOffOn(int channel);
- void writeRegisterSpecial(int channel, uint8 value, int offset);
- uint8 readRegisterSpecial(int channel, uint8 defaultValue, int offset);
- void setupNoteEnvelopeState(Note *note, int steps, int adjust);
- bool processNoteEnvelope(Note *note);
-
- int _sfxTimer;
-
- int _sfxResource[3];
- int _sfxPriority[3];
-
enum {
kChannelStateOff = 0,
kChannelStateParse = 1,
@@ -184,6 +165,25 @@ private:
int hardwareChannel;
} _channels[11];
+ void startSfx(const byte *resource);
+ void updateSfx();
+ void clearChannel(const Channel &channel);
+ void updateChannel(Channel *channel);
+ void parseSlot(Channel *channel);
+ void updateSlot(Channel *channel);
+ void parseNote(Note *note, const Channel &channel, const byte *offset);
+ bool processNote(Note *note, const Channel &channel, const byte *offset);
+ void noteOffOn(int channel);
+ void writeRegisterSpecial(int channel, uint8 value, int offset);
+ uint8 readRegisterSpecial(int channel, uint8 defaultValue, int offset);
+ void setupNoteEnvelopeState(Note *note, int steps, int adjust);
+ bool processNoteEnvelope(Note *note);
+
+ int _sfxTimer;
+
+ int _sfxResource[3];
+ int _sfxPriority[3];
+
uint8 _rndSeed;
uint8 getRnd();
Commit: 7ad0e135e67599991c4b13700511706d5b83236c
https://github.com/scummvm/scummvm/commit/7ad0e135e67599991c4b13700511706d5b83236c
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Further refactor AD SFX code.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 73eb893..5eafb7d 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -62,12 +62,13 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
_sfxTimer = 4;
_rndSeed = 1;
- memset(_channels, 0, sizeof(_channels));
- for (int i = 0; i < ARRAYSIZE(_channels); ++i) {
- _channels[i].hardwareChannel = i;
+ memset(_sfx, 0, sizeof(_sfx));
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ _sfx[i].resource = -1;
+ for (int j = 0; j < ARRAYSIZE(_sfx[i].channels); ++j) {
+ _sfx[i].channels[j].hardwareChannel = i * 3 + j;
+ }
}
- memset(_sfxResource, 0, sizeof(_sfxResource));
- memset(_sfxPriority, 0, sizeof(_sfxPriority));
}
Player_AD::~Player_AD() {
@@ -117,17 +118,15 @@ void Player_AD::startSound(int sound) {
// Check whether the channel is free or the priority of the new
// sfx resource is above the old one.
- if (_channels[channel * 3 + 0].state
- || _channels[channel * 3 + 1].state
- || _channels[channel * 3 + 2].state) {
- if (_sfxPriority[channel] > priority) {
+ if (_sfx[channel].resource != -1) {
+ if (_sfx[channel].priority > priority) {
return;
}
}
// Lock the new resource
- _sfxResource[channel] = sound;
- _sfxPriority[channel] = priority;
+ _sfx[channel].resource = sound;
+ _sfx[channel].priority = priority;
_vm->_res->lock(rtSound, sound);
// Start the actual sfx resource
@@ -146,20 +145,21 @@ void Player_AD::stopSound(int sound) {
stopAllSounds();
} else {
for (int i = 0; i < 3; ++i) {
- if (_sfxResource[i] == sound) {
- if (_channels[i * 3 + 0].state
- || _channels[i * 3 + 1].state
- || _channels[i * 3 + 2].state) {
+ if (_sfx[i].resource == sound) {
+ if (_sfx[i].channels[0].state
+ || _sfx[i].channels[1].state
+ || _sfx[i].channels[2].state) {
// Unlock the sound resource
_vm->_res->unlock(rtSound, sound);
// Stop the actual sfx playback
- _channels[i * 3 + 0].state = kChannelStateOff;
- _channels[i * 3 + 1].state = kChannelStateOff;
- _channels[i * 3 + 2].state = kChannelStateOff;
- clearChannel(_channels[i * 3 + 0]);
- clearChannel(_channels[i * 3 + 1]);
- clearChannel(_channels[i * 3 + 2]);
+ _sfx[i].channels[0].state = kChannelStateOff;
+ _sfx[i].channels[1].state = kChannelStateOff;
+ _sfx[i].channels[2].state = kChannelStateOff;
+ clearChannel(_sfx[i].channels[i * 3 + 0]);
+ clearChannel(_sfx[i].channels[i * 3 + 1]);
+ clearChannel(_sfx[i].channels[i * 3 + 2]);
+ _sfx[i].resource = -1;
}
}
}
@@ -179,16 +179,21 @@ void Player_AD::stopAllSounds() {
_curOffset = 0;
// Unloack all used sfx resources
- for (int i = 0; i < 3; ++i) {
- if (_channels[i * 3 + 0].state || _channels[i * 3 + 1].state || _channels[i * 3 + 2].state) {
- _vm->_res->unlock(rtSound, _sfxResource[i]);
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ SfxSlot &sfx = _sfx[i];
+ if (sfx.resource != -1) {
+ _vm->_res->unlock(rtSound, sfx.resource);
+ sfx.resource = -1;
}
}
// Reset all the sfx channels
- for (int i = 0; i < 9; ++i) {
- _channels[i].state = kChannelStateOff;
- clearChannel(_channels[i]);
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ SfxSlot &sfx = _sfx[i];
+ for (int j = 0; j < ARRAYSIZE(sfx.channels); ++j) {
+ sfx.channels[j].state = kChannelStateOff;
+ clearChannel(sfx.channels[j]);
+ }
}
writeReg(0xBD, 0x00);
@@ -559,23 +564,23 @@ void Player_AD::startSfx(const byte *resource) {
// The second byte of the resource defines the logical channel where
// the sound effect should be played.
- const int startChannel = resource[1] * 3;
+ SfxSlot &sfx = _sfx[resource[1]];
// Clear the channel.
- _channels[startChannel + 0].state = kChannelStateOff;
- _channels[startChannel + 1].state = kChannelStateOff;
- _channels[startChannel + 2].state = kChannelStateOff;
+ sfx.channels[0].state = kChannelStateOff;
+ sfx.channels[1].state = kChannelStateOff;
+ sfx.channels[2].state = kChannelStateOff;
- clearChannel(_channels[startChannel + 0]);
- clearChannel(_channels[startChannel + 1]);
- clearChannel(_channels[startChannel + 2]);
+ clearChannel(sfx.channels[0]);
+ clearChannel(sfx.channels[1]);
+ clearChannel(sfx.channels[2]);
// Set up the first channel to pick up playback.
- _channels[startChannel].currentOffset = _channels[startChannel].startOffset = resource + 2;
- _channels[startChannel].state = kChannelStateParse;
+ sfx.channels[0].currentOffset = sfx.channels[0].startOffset = resource + 2;
+ sfx.channels[0].state = kChannelStateParse;
// Scan for the start of the other channels and set them up if required.
- int curChannel = startChannel + 1;
+ int curChannel = 1;
const byte *bufferPosition = resource + 2;
uint8 command = 0;
while ((command = *bufferPosition) != 0xFF) {
@@ -598,9 +603,12 @@ void Player_AD::startSfx(const byte *resource) {
default:
// START OF CHANNEL
bufferPosition += 1;
- _channels[curChannel].currentOffset = bufferPosition;
- _channels[curChannel].startOffset = bufferPosition;
- _channels[curChannel].state = kChannelStateParse;
+ if (curChannel >= 3) {
+ error("AD SFX resource %d uses more than 3 channels", sfx.resource);
+ }
+ sfx.channels[curChannel].currentOffset = bufferPosition;
+ sfx.channels[curChannel].startOffset = bufferPosition;
+ sfx.channels[curChannel].state = kChannelStateParse;
++curChannel;
break;
}
@@ -613,12 +621,16 @@ void Player_AD::updateSfx() {
}
_sfxTimer = 4;
- for (int i = 0; i <= 9; ++i) {
- if (!_channels[i].state) {
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ if (_sfx[i].resource == -1) {
continue;
}
- updateChannel(&_channels[i]);
+ for (int j = 0; j < ARRAYSIZE(_sfx[i].channels); ++j) {
+ if (_sfx[i].channels[j].state) {
+ updateChannel(&_sfx[i].channels[j]);
+ }
+ }
}
}
@@ -686,10 +698,11 @@ void Player_AD::parseSlot(Channel *channel) {
// HACK: We shouldn't rely on the hardware channel to match the
// logical channel...
const int logChannel = channel->hardwareChannel / 3;
- if (!_channels[logChannel * 3 + 0].state
- && !_channels[logChannel * 3 + 1].state
- && !_channels[logChannel * 3 + 2].state) {
- _vm->_res->unlock(rtSound, _sfxResource[logChannel]);
+ if (!_sfx[logChannel].channels[0].state
+ && !_sfx[logChannel].channels[1].state
+ && !_sfx[logChannel].channels[2].state) {
+ _vm->_res->unlock(rtSound, _sfx[logChannel].resource);
+ _sfx[logChannel].resource = -1;
}
return;
}
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 95c779f..7d6f4f7 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -163,7 +163,14 @@ private:
Note notes[2];
int hardwareChannel;
- } _channels[11];
+ };
+
+ struct SfxSlot {
+ int resource;
+ int priority;
+
+ Channel channels[3];
+ } _sfx[3];
void startSfx(const byte *resource);
void updateSfx();
@@ -181,9 +188,6 @@ private:
int _sfxTimer;
- int _sfxResource[3];
- int _sfxPriority[3];
-
uint8 _rndSeed;
uint8 getRnd();
Commit: 99f97569924664a6f1f996426999ede592bc0723
https://github.com/scummvm/scummvm/commit/99f97569924664a6f1f996426999ede592bc0723
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:30+02:00
Commit Message:
SCUMM: Further cleanup in AD SFX code.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 5eafb7d..7596a3f 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -130,7 +130,7 @@ void Player_AD::startSound(int sound) {
_vm->_res->lock(rtSound, sound);
// Start the actual sfx resource
- startSfx(res);
+ startSfx(&_sfx[channel], res);
}
}
@@ -144,23 +144,9 @@ void Player_AD::stopSound(int sound) {
if (sound == _soundPlaying) {
stopAllSounds();
} else {
- for (int i = 0; i < 3; ++i) {
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
if (_sfx[i].resource == sound) {
- if (_sfx[i].channels[0].state
- || _sfx[i].channels[1].state
- || _sfx[i].channels[2].state) {
- // Unlock the sound resource
- _vm->_res->unlock(rtSound, sound);
-
- // Stop the actual sfx playback
- _sfx[i].channels[0].state = kChannelStateOff;
- _sfx[i].channels[1].state = kChannelStateOff;
- _sfx[i].channels[2].state = kChannelStateOff;
- clearChannel(_sfx[i].channels[i * 3 + 0]);
- clearChannel(_sfx[i].channels[i * 3 + 1]);
- clearChannel(_sfx[i].channels[i * 3 + 2]);
- _sfx[i].resource = -1;
- }
+ stopSfx(&_sfx[i]);
}
}
}
@@ -178,22 +164,9 @@ void Player_AD::stopAllSounds() {
// Stop the music playback
_curOffset = 0;
- // Unloack all used sfx resources
- for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
- SfxSlot &sfx = _sfx[i];
- if (sfx.resource != -1) {
- _vm->_res->unlock(rtSound, sfx.resource);
- sfx.resource = -1;
- }
- }
-
- // Reset all the sfx channels
+ // Stop all the sfx playback
for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
- SfxSlot &sfx = _sfx[i];
- for (int j = 0; j < ARRAYSIZE(sfx.channels); ++j) {
- sfx.channels[j].state = kChannelStateOff;
- clearChannel(sfx.channels[j]);
- }
+ stopSfx(&_sfx[i]);
}
writeReg(0xBD, 0x00);
@@ -559,25 +532,21 @@ const uint Player_AD::_rhythmChannelTable[6] = {
// SFX
-void Player_AD::startSfx(const byte *resource) {
+void Player_AD::startSfx(SfxSlot *sfx, const byte *resource) {
writeReg(0xBD, 0x00);
- // The second byte of the resource defines the logical channel where
- // the sound effect should be played.
- SfxSlot &sfx = _sfx[resource[1]];
-
// Clear the channel.
- sfx.channels[0].state = kChannelStateOff;
- sfx.channels[1].state = kChannelStateOff;
- sfx.channels[2].state = kChannelStateOff;
+ sfx->channels[0].state = kChannelStateOff;
+ sfx->channels[1].state = kChannelStateOff;
+ sfx->channels[2].state = kChannelStateOff;
- clearChannel(sfx.channels[0]);
- clearChannel(sfx.channels[1]);
- clearChannel(sfx.channels[2]);
+ clearChannel(sfx->channels[0]);
+ clearChannel(sfx->channels[1]);
+ clearChannel(sfx->channels[2]);
// Set up the first channel to pick up playback.
- sfx.channels[0].currentOffset = sfx.channels[0].startOffset = resource + 2;
- sfx.channels[0].state = kChannelStateParse;
+ sfx->channels[0].currentOffset = sfx->channels[0].startOffset = resource + 2;
+ sfx->channels[0].state = kChannelStateParse;
// Scan for the start of the other channels and set them up if required.
int curChannel = 1;
@@ -604,17 +573,35 @@ void Player_AD::startSfx(const byte *resource) {
// START OF CHANNEL
bufferPosition += 1;
if (curChannel >= 3) {
- error("AD SFX resource %d uses more than 3 channels", sfx.resource);
+ error("AD SFX resource %d uses more than 3 channels", sfx->resource);
}
- sfx.channels[curChannel].currentOffset = bufferPosition;
- sfx.channels[curChannel].startOffset = bufferPosition;
- sfx.channels[curChannel].state = kChannelStateParse;
+ sfx->channels[curChannel].currentOffset = bufferPosition;
+ sfx->channels[curChannel].startOffset = bufferPosition;
+ sfx->channels[curChannel].state = kChannelStateParse;
++curChannel;
break;
}
}
}
+void Player_AD::stopSfx(SfxSlot *sfx) {
+ if (sfx->resource == -1) {
+ return;
+ }
+
+ // 1. step: Clear all the channels.
+ for (int i = 0; i < ARRAYSIZE(sfx->channels); ++i) {
+ if (sfx->channels[i].state) {
+ clearChannel(sfx->channels[i]);
+ sfx->channels[i].state = kChannelStateOff;
+ }
+ }
+
+ // 2. step: Unlock the resource.
+ _vm->_res->unlock(rtSound, sfx->resource);
+ sfx->resource = -1;
+}
+
void Player_AD::updateSfx() {
if (--_sfxTimer) {
return;
@@ -701,8 +688,7 @@ void Player_AD::parseSlot(Channel *channel) {
if (!_sfx[logChannel].channels[0].state
&& !_sfx[logChannel].channels[1].state
&& !_sfx[logChannel].channels[2].state) {
- _vm->_res->unlock(rtSound, _sfx[logChannel].resource);
- _sfx[logChannel].resource = -1;
+ stopSfx(&_sfx[logChannel]);
}
return;
}
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 7d6f4f7..c4292fc 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -172,7 +172,9 @@ private:
Channel channels[3];
} _sfx[3];
- void startSfx(const byte *resource);
+ void startSfx(SfxSlot *sfx, const byte *resource);
+ void stopSfx(SfxSlot *sfx);
+
void updateSfx();
void clearChannel(const Channel &channel);
void updateChannel(Channel *channel);
Commit: ecabacaddd0a89b0aa83c9b176891c5c4f47aafc
https://github.com/scummvm/scummvm/commit/ecabacaddd0a89b0aa83c9b176891c5c4f47aafc
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Properly unlock sound resources when reusing sfx slots in AD code.
Changed paths:
engines/scumm/players/player_ad.cpp
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 7596a3f..fdd6255 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -121,6 +121,11 @@ void Player_AD::startSound(int sound) {
if (_sfx[channel].resource != -1) {
if (_sfx[channel].priority > priority) {
return;
+ } else {
+ // If we overwrite a channel we will properly stop the old
+ // sfx slot first. This makes sure that the resource is
+ // unlocked properly.
+ stopSfx(&_sfx[channel]);
}
}
Commit: b5ca6b01f9e6748908f5acdcdb08e0dd448e60f1
https://github.com/scummvm/scummvm/commit/b5ca6b01f9e6748908f5acdcdb08e0dd448e60f1
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Clean up how SFX are stopped in the AD player.
Changed paths:
engines/scumm/players/player_ad.cpp
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index fdd6255..3f805fe 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -618,11 +618,18 @@ void Player_AD::updateSfx() {
continue;
}
+ bool hasActiveChannel = false;
for (int j = 0; j < ARRAYSIZE(_sfx[i].channels); ++j) {
if (_sfx[i].channels[j].state) {
+ hasActiveChannel = true;
updateChannel(&_sfx[i].channels[j]);
}
}
+
+ // In case no channel is active we will stop the sfx.
+ if (!hasActiveChannel) {
+ stopSfx(&_sfx[i]);
+ }
}
}
@@ -677,26 +684,14 @@ void Player_AD::parseSlot(Channel *channel) {
channel->currentOffset = channel->startOffset;
break;
- default: {
+ default:
// START OF CHANNEL
// When we encounter a start of another channel while playback
// it means that the current channel is finished. Thus, we will
// stop it.
clearChannel(*channel);
channel->state = kChannelStateOff;
-
- // If no channel of the sound effect is playing anymore, unlock
- // the resource.
- // HACK: We shouldn't rely on the hardware channel to match the
- // logical channel...
- const int logChannel = channel->hardwareChannel / 3;
- if (!_sfx[logChannel].channels[0].state
- && !_sfx[logChannel].channels[1].state
- && !_sfx[logChannel].channels[2].state) {
- stopSfx(&_sfx[logChannel]);
- }
return;
- }
}
}
}
Commit: 02f47dd497710330f89c28d640e21623da180c06
https://github.com/scummvm/scummvm/commit/02f47dd497710330f89c28d640e21623da180c06
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Allow multiple SFX to be played at once with AD.
Actually, even before this change it was possible. However, since we formerly
used the original channel specification it was not possible when two sfx were
started on the same channel. Now we can play such sounds simultaneously again.
This is a first step towards a AdLib support level we had when we tried to
convert SFX to MIDI to play it through iMuse. However, now we still play the
sound effects properly, i.e. they still sound like in the original.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 3f805fe..33dbd0b 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -108,34 +108,26 @@ void Player_AD::startSound(int sound) {
// Only try to start a sfx when no music is playing.
if (_soundPlaying == -1) {
const byte priority = res[0];
- const byte channel = res[1];
-
- // Check for out of bounds access
- if (channel >= 3) {
- warning("AdLib sfx resource %d uses channel %d", sound, channel);
+ // The original specified the channel to use in the sound
+ // resource. However, since we play as much as possible we sill
+ // ignore it and simply use the priority value to determine
+ // whether the sfx can be played or not.
+ //const byte channel = res[1];
+
+ // Try to allocate a sfx slot for playback.
+ SfxSlot *sfx = allocateSfxSlot(priority);
+ if (!sfx) {
+ ::debugC(3, DEBUG_SOUND, "AdLib: No free sfx slot for sound %d", sound);
return;
}
- // Check whether the channel is free or the priority of the new
- // sfx resource is above the old one.
- if (_sfx[channel].resource != -1) {
- if (_sfx[channel].priority > priority) {
- return;
- } else {
- // If we overwrite a channel we will properly stop the old
- // sfx slot first. This makes sure that the resource is
- // unlocked properly.
- stopSfx(&_sfx[channel]);
- }
- }
-
// Lock the new resource
- _sfx[channel].resource = sound;
- _sfx[channel].priority = priority;
+ sfx->resource = sound;
+ sfx->priority = priority;
_vm->_res->lock(rtSound, sound);
// Start the actual sfx resource
- startSfx(&_sfx[channel], res);
+ startSfx(sfx, res);
}
}
@@ -537,6 +529,26 @@ const uint Player_AD::_rhythmChannelTable[6] = {
// SFX
+Player_AD::SfxSlot *Player_AD::allocateSfxSlot(int priority) {
+ // First pass: Check whether there's a unused slot
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ if (_sfx[i].resource == -1) {
+ return &_sfx[i];
+ }
+ }
+
+ // Second pass: Look for a slot with lower priority
+ for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
+ if (_sfx[i].priority <= priority) {
+ // Stop the old sfx
+ stopSfx(&_sfx[i]);
+ return &_sfx[i];
+ }
+ }
+
+ return nullptr;
+}
+
void Player_AD::startSfx(SfxSlot *sfx, const byte *resource) {
writeReg(0xBD, 0x00);
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index c4292fc..73f3f86 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -172,6 +172,7 @@ private:
Channel channels[3];
} _sfx[3];
+ SfxSlot *allocateSfxSlot(int priority);
void startSfx(SfxSlot *sfx, const byte *resource);
void stopSfx(SfxSlot *sfx);
Commit: f78e12cd5c5abd99a0e505e77bbadeb3398f9c06
https://github.com/scummvm/scummvm/commit/f78e12cd5c5abd99a0e505e77bbadeb3398f9c06
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Dynamically allocate hw channels for SFX in AD player.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 33dbd0b..6c3c7f9 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -66,9 +66,11 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
_sfx[i].resource = -1;
for (int j = 0; j < ARRAYSIZE(_sfx[i].channels); ++j) {
- _sfx[i].channels[j].hardwareChannel = i * 3 + j;
+ _sfx[i].channels[j].hardwareChannel = -1;
}
}
+
+ memset(_hwChannels, 0, sizeof(_hwChannels));
}
Player_AD::~Player_AD() {
@@ -121,13 +123,13 @@ void Player_AD::startSound(int sound) {
return;
}
- // Lock the new resource
+ // Try to start sfx playback
sfx->resource = sound;
sfx->priority = priority;
- _vm->_res->lock(rtSound, sound);
-
- // Start the actual sfx resource
- startSfx(sfx, res);
+ if (startSfx(sfx, res)) {
+ // Lock the new resource
+ _vm->_res->lock(rtSound, sound);
+ }
}
}
@@ -246,6 +248,43 @@ void Player_AD::setupVolume() {
}
}
+int Player_AD::allocateHWChannel(int priority, SfxSlot *owner) {
+ // First pass: Check whether there's any unallocated channel
+ for (int i = 0; i < ARRAYSIZE(_hwChannels); ++i) {
+ if (!_hwChannels[i].allocated) {
+ _hwChannels[i].allocated = true;
+ _hwChannels[i].priority = priority;
+ _hwChannels[i].sfxOwner = owner;
+ return i;
+ }
+ }
+
+ // Second pass: Reassign channels based on priority
+ for (int i = 0; i < ARRAYSIZE(_hwChannels); ++i) {
+ if (_hwChannels[i].priority <= priority) {
+ // In case the HW channel belongs to a SFX we will completely
+ // stop playback of that SFX.
+ // TODO: Maybe be more fine grained in the future and allow
+ // detachment of individual channels of a SFX?
+ if (_hwChannels[i].sfxOwner) {
+ stopSfx(_hwChannels[i].sfxOwner);
+ }
+ _hwChannels[i].allocated = true;
+ _hwChannels[i].priority = priority;
+ _hwChannels[i].sfxOwner = owner;
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void Player_AD::freeHWChannel(int channel) {
+ assert(_hwChannels[channel].allocated);
+ _hwChannels[channel].allocated = false;
+ _hwChannels[channel].sfxOwner = nullptr;
+}
+
void Player_AD::writeReg(int r, int v) {
if (r >= 0 && r < ARRAYSIZE(_registerBackUpTable)) {
_registerBackUpTable[r] = v;
@@ -549,19 +588,21 @@ Player_AD::SfxSlot *Player_AD::allocateSfxSlot(int priority) {
return nullptr;
}
-void Player_AD::startSfx(SfxSlot *sfx, const byte *resource) {
+bool Player_AD::startSfx(SfxSlot *sfx, const byte *resource) {
writeReg(0xBD, 0x00);
- // Clear the channel.
+ // Clear the channels.
sfx->channels[0].state = kChannelStateOff;
sfx->channels[1].state = kChannelStateOff;
sfx->channels[2].state = kChannelStateOff;
- clearChannel(sfx->channels[0]);
- clearChannel(sfx->channels[1]);
- clearChannel(sfx->channels[2]);
-
// Set up the first channel to pick up playback.
+ // Try to allocate a hardware channel.
+ sfx->channels[0].hardwareChannel = allocateHWChannel(sfx->priority, sfx);
+ if (sfx->channels[0].hardwareChannel == -1) {
+ ::debugC(3, DEBUG_SOUND, "AD No hardware channel available");
+ return false;
+ }
sfx->channels[0].currentOffset = sfx->channels[0].startOffset = resource + 2;
sfx->channels[0].state = kChannelStateParse;
@@ -592,6 +633,11 @@ void Player_AD::startSfx(SfxSlot *sfx, const byte *resource) {
if (curChannel >= 3) {
error("AD SFX resource %d uses more than 3 channels", sfx->resource);
}
+ sfx->channels[curChannel].hardwareChannel = allocateHWChannel(sfx->priority, sfx);
+ if (sfx->channels[curChannel].hardwareChannel == -1) {
+ ::debugC(3, DEBUG_SOUND, "AD No hardware channel available");
+ return false;
+ }
sfx->channels[curChannel].currentOffset = bufferPosition;
sfx->channels[curChannel].startOffset = bufferPosition;
sfx->channels[curChannel].state = kChannelStateParse;
@@ -599,6 +645,8 @@ void Player_AD::startSfx(SfxSlot *sfx, const byte *resource) {
break;
}
}
+
+ return true;
}
void Player_AD::stopSfx(SfxSlot *sfx) {
@@ -612,6 +660,11 @@ void Player_AD::stopSfx(SfxSlot *sfx) {
clearChannel(sfx->channels[i]);
sfx->channels[i].state = kChannelStateOff;
}
+
+ if (sfx->channels[i].hardwareChannel != -1) {
+ freeHWChannel(sfx->channels[i].hardwareChannel);
+ sfx->channels[i].hardwareChannel = -1;
+ }
}
// 2. step: Unlock the resource.
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 73f3f86..8994be7 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -80,6 +80,17 @@ private:
int _soundPlaying;
int _engineMusicTimer;
+ struct SfxSlot;
+
+ struct HardwareChannel {
+ bool allocated;
+ int priority;
+ SfxSlot *sfxOwner;
+ } _hwChannels[9];
+
+ int allocateHWChannel(int priority, SfxSlot *owner = nullptr);
+ void freeHWChannel(int channel);
+
// AdLib register utilities
uint8 _registerBackUpTable[256];
void writeReg(int r, int v);
@@ -173,7 +184,7 @@ private:
} _sfx[3];
SfxSlot *allocateSfxSlot(int priority);
- void startSfx(SfxSlot *sfx, const byte *resource);
+ bool startSfx(SfxSlot *sfx, const byte *resource);
void stopSfx(SfxSlot *sfx);
void updateSfx();
Commit: a6ec34f4242ebb4cc3e0795e4186729302b43b9c
https://github.com/scummvm/scummvm/commit/a6ec34f4242ebb4cc3e0795e4186729302b43b9c
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Let music in AD code use the same HW channel allocation as SFX.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 6c3c7f9..6083283 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -71,6 +71,12 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
}
memset(_hwChannels, 0, sizeof(_hwChannels));
+ _numHWChannels = ARRAYSIZE(_hwChannels);
+
+ memset(_voiceChannels, 0, sizeof(_voiceChannels));
+ for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
+ _voiceChannels[i].hardwareChannel = -1;
+ }
}
Player_AD::~Player_AD() {
@@ -163,6 +169,13 @@ void Player_AD::stopAllSounds() {
// Stop the music playback
_curOffset = 0;
+ // Stop all music voice channels
+ for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
+ if (_voiceChannels[i].lastEvent) {
+ noteOff(i);
+ }
+ }
+
// Stop all the sfx playback
for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
stopSfx(&_sfx[i]);
@@ -250,7 +263,7 @@ void Player_AD::setupVolume() {
int Player_AD::allocateHWChannel(int priority, SfxSlot *owner) {
// First pass: Check whether there's any unallocated channel
- for (int i = 0; i < ARRAYSIZE(_hwChannels); ++i) {
+ for (int i = 0; i < _numHWChannels; ++i) {
if (!_hwChannels[i].allocated) {
_hwChannels[i].allocated = true;
_hwChannels[i].priority = priority;
@@ -260,7 +273,7 @@ int Player_AD::allocateHWChannel(int priority, SfxSlot *owner) {
}
// Second pass: Reassign channels based on priority
- for (int i = 0; i < ARRAYSIZE(_hwChannels); ++i) {
+ for (int i = 0; i < _numHWChannels; ++i) {
if (_hwChannels[i].priority <= priority) {
// In case the HW channel belongs to a SFX we will completely
// stop playback of that SFX.
@@ -285,6 +298,15 @@ void Player_AD::freeHWChannel(int channel) {
_hwChannels[channel].sfxOwner = nullptr;
}
+void Player_AD::limitHWChannels(int newCount) {
+ for (int i = newCount; i < ARRAYSIZE(_hwChannels); ++i) {
+ if (_hwChannels[i].allocated) {
+ freeHWChannel(i);
+ }
+ }
+ _numHWChannels = newCount;
+}
+
void Player_AD::writeReg(int r, int v) {
if (r >= 0 && r < ARRAYSIZE(_registerBackUpTable)) {
_registerBackUpTable[r] = v;
@@ -327,26 +349,23 @@ const int Player_AD::_operatorOffsetTable[18] = {
void Player_AD::startMusic() {
memset(_instrumentOffset, 0, sizeof(_instrumentOffset));
- memset(_channelLastEvent, 0, sizeof(_channelLastEvent));
- memset(_channelFrequency, 0, sizeof(_channelFrequency));
- memset(_channelB0Reg, 0, sizeof(_channelB0Reg));
- _voiceChannels = 0;
+ bool hasRhythmData = false;
uint instruments = _musicData[10];
for (uint i = 0; i < instruments; ++i) {
const int instrIndex = _musicData[11 + i] - 1;
if (0 <= instrIndex && instrIndex < 16) {
_instrumentOffset[instrIndex] = i * 16 + 16 + 3;
- _voiceChannels |= _musicData[_instrumentOffset[instrIndex] + 13];
+ hasRhythmData |= (_musicData[_instrumentOffset[instrIndex] + 13] != 0);
}
}
- if (_voiceChannels) {
+ if (hasRhythmData) {
_mdvdrState = 0x20;
- _voiceChannels = 6;
+ limitHWChannels(6);
} else {
_mdvdrState = 0;
- _voiceChannels = 9;
+ limitHWChannels(9);
}
_curOffset = 0x93;
@@ -428,12 +447,11 @@ void Player_AD::updateMusic() {
if (_musicData[instrOffset + 13] != 0) {
setupRhythm(_musicData[instrOffset + 13], instrOffset);
} else {
- int channel = findFreeChannel();
+ int channel = allocateVoiceChannel();
if (channel != -1) {
- noteOff(channel);
- setupChannel(channel, _musicData + instrOffset);
- _channelLastEvent[channel] = command + 0x90;
- _channelFrequency[channel] = _musicData[_curOffset];
+ setupChannel(_voiceChannels[channel].hardwareChannel, _musicData + instrOffset);
+ _voiceChannels[channel].lastEvent = command + 0x90;
+ _voiceChannels[channel].frequency = _musicData[_curOffset];
setupFrequency(channel, _musicData[_curOffset]);
}
}
@@ -445,8 +463,8 @@ void Player_AD::updateMusic() {
// Find the output channel which plays the note.
uint channel = 0xFF;
- for (uint i = 0; i < _voiceChannels; ++i) {
- if (_channelFrequency[i] == note && _channelLastEvent[i] == command) {
+ for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
+ if (_voiceChannels[i].frequency == note && _voiceChannels[i].lastEvent == command) {
channel = i;
break;
}
@@ -495,18 +513,9 @@ void Player_AD::updateMusic() {
}
void Player_AD::noteOff(uint channel) {
- _channelLastEvent[channel] = 0;
- writeReg(0xB0 + channel, _channelB0Reg[channel] & 0xDF);
-}
-
-int Player_AD::findFreeChannel() {
- for (uint i = 0; i < _voiceChannels; ++i) {
- if (!_channelLastEvent[i]) {
- return i;
- }
- }
-
- return -1;
+ VoiceChannel &vChannel = _voiceChannels[channel];
+ writeReg(0xB0 + vChannel.hardwareChannel, vChannel.b0Reg & 0xDF);
+ freeVoiceChannel(channel);
}
void Player_AD::setupFrequency(uint channel, int8 frequency) {
@@ -521,13 +530,14 @@ void Player_AD::setupFrequency(uint channel, int8 frequency) {
++octave;
}
+ VoiceChannel &vChannel = _voiceChannels[channel];
const uint noteFrequency = _noteFrequencies[frequency];
octave <<= 2;
octave |= noteFrequency >> 8;
octave |= 0x20;
- writeReg(0xA0 + channel, noteFrequency & 0xFF);
- _channelB0Reg[channel] = octave;
- writeReg(0xB0 + channel, octave);
+ writeReg(0xA0 + vChannel.hardwareChannel, noteFrequency & 0xFF);
+ vChannel.b0Reg = octave;
+ writeReg(0xB0 + vChannel.hardwareChannel, octave);
}
void Player_AD::setupRhythm(uint rhythmInstr, uint instrOffset) {
@@ -548,6 +558,34 @@ void Player_AD::setupRhythm(uint rhythmInstr, uint instrOffset) {
}
}
+int Player_AD::allocateVoiceChannel() {
+ for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
+ if (!_voiceChannels[i].lastEvent) {
+ // 256 makes sure it's a higher prority than any SFX
+ _voiceChannels[i].hardwareChannel = allocateHWChannel(256);
+ if (_voiceChannels[i].hardwareChannel != -1) {
+ return i;
+ } else {
+ // No free HW channels => cancel
+ return -1;
+ }
+ }
+ }
+
+ return -1;
+}
+
+void Player_AD::freeVoiceChannel(uint channel) {
+ VoiceChannel &vChannel = _voiceChannels[channel];
+ assert(vChannel.hardwareChannel != -1);
+
+ freeHWChannel(vChannel.hardwareChannel);
+ vChannel.hardwareChannel = -1;
+ vChannel.lastEvent = 0;
+ vChannel.b0Reg = 0;
+ vChannel.frequency = 0;
+}
+
const uint Player_AD::_noteFrequencies[12] = {
0x200, 0x21E, 0x23F, 0x261,
0x285, 0x2AB, 0x2D4, 0x300,
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 8994be7..f8504c4 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -87,9 +87,11 @@ private:
int priority;
SfxSlot *sfxOwner;
} _hwChannels[9];
+ int _numHWChannels;
int allocateHWChannel(int priority, SfxSlot *owner = nullptr);
void freeHWChannel(int channel);
+ void limitHWChannels(int newCount);
// AdLib register utilities
uint8 _registerBackUpTable[256];
@@ -105,7 +107,6 @@ private:
void startMusic();
void updateMusic();
void noteOff(uint channel);
- int findFreeChannel();
void setupFrequency(uint channel, int8 frequency);
void setupRhythm(uint rhythmInstr, uint instrOffset);
@@ -117,13 +118,19 @@ private:
bool _loopFlag;
uint _musicLoopStart;
uint _instrumentOffset[16];
- uint _channelLastEvent[9];
- uint _channelFrequency[9];
- uint _channelB0Reg[9];
+
+ struct VoiceChannel {
+ uint lastEvent;
+ uint frequency;
+ uint b0Reg;
+
+ int hardwareChannel;
+ } _voiceChannels[9];
+ int allocateVoiceChannel();
+ void freeVoiceChannel(uint channel);
uint _mdvdrState;
- uint _voiceChannels;
-
+
uint _curOffset;
uint _nextEventTimer;
Commit: 707cfd07ac373dd30e71bb33d3dec8c1d14a386c
https://github.com/scummvm/scummvm/commit/707cfd07ac373dd30e71bb33d3dec8c1d14a386c
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Only stop music when requested in AD code.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 6083283..dfd4d7f 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -147,7 +147,7 @@ void Player_AD::stopSound(int sound) {
Common::StackLock lock(_mutex);
if (sound == _soundPlaying) {
- stopAllSounds();
+ stopMusic();
} else {
for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
if (_sfx[i].resource == sound) {
@@ -160,21 +160,8 @@ void Player_AD::stopSound(int sound) {
void Player_AD::stopAllSounds() {
Common::StackLock lock(_mutex);
- // Unlock the music resource if present
- if (_soundPlaying != -1) {
- _vm->_res->unlock(rtSound, _soundPlaying);
- _soundPlaying = -1;
- }
-
- // Stop the music playback
- _curOffset = 0;
-
- // Stop all music voice channels
- for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
- if (_voiceChannels[i].lastEvent) {
- noteOff(i);
- }
- }
+ // Stop the music
+ stopMusic();
// Stop all the sfx playback
for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
@@ -384,6 +371,26 @@ void Player_AD::startMusic() {
_musicLoopStart = READ_LE_UINT16(_musicData + 5);
}
+void Player_AD::stopMusic() {
+ if (_soundPlaying == -1) {
+ return;
+ }
+
+ // Unlock the music resource if present
+ _vm->_res->unlock(rtSound, _soundPlaying);
+ _soundPlaying = -1;
+
+ // Stop the music playback
+ _curOffset = 0;
+
+ // Stop all music voice channels
+ for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
+ if (_voiceChannels[i].lastEvent) {
+ noteOff(i);
+ }
+ }
+}
+
void Player_AD::updateMusic() {
_musicTimer += _musicTicks;
if (_musicTimer < _timerLimit) {
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index f8504c4..fbf604e 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -105,6 +105,7 @@ private:
// Music handling
void startMusic();
+ void stopMusic();
void updateMusic();
void noteOff(uint channel);
void setupFrequency(uint channel, int8 frequency);
Commit: 5ab61bcea5b656ac17115f2359ffc65c5ac15df2
https://github.com/scummvm/scummvm/commit/5ab61bcea5b656ac17115f2359ffc65c5ac15df2
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Allow music and sfx to be played at the same time in AD player.
Changed paths:
engines/scumm/players/player_ad.cpp
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index dfd4d7f..aa6f044 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -113,29 +113,26 @@ void Player_AD::startSound(int sound) {
_musicData = res;
startMusic();
} else {
- // Only try to start a sfx when no music is playing.
- if (_soundPlaying == -1) {
- const byte priority = res[0];
- // The original specified the channel to use in the sound
- // resource. However, since we play as much as possible we sill
- // ignore it and simply use the priority value to determine
- // whether the sfx can be played or not.
- //const byte channel = res[1];
-
- // Try to allocate a sfx slot for playback.
- SfxSlot *sfx = allocateSfxSlot(priority);
- if (!sfx) {
- ::debugC(3, DEBUG_SOUND, "AdLib: No free sfx slot for sound %d", sound);
- return;
- }
+ const byte priority = res[0];
+ // The original specified the channel to use in the sound
+ // resource. However, since we play as much as possible we sill
+ // ignore it and simply use the priority value to determine
+ // whether the sfx can be played or not.
+ //const byte channel = res[1];
+
+ // Try to allocate a sfx slot for playback.
+ SfxSlot *sfx = allocateSfxSlot(priority);
+ if (!sfx) {
+ ::debugC(3, DEBUG_SOUND, "AdLib: No free sfx slot for sound %d", sound);
+ return;
+ }
- // Try to start sfx playback
- sfx->resource = sound;
- sfx->priority = priority;
- if (startSfx(sfx, res)) {
- // Lock the new resource
- _vm->_res->lock(rtSound, sound);
- }
+ // Try to start sfx playback
+ sfx->resource = sound;
+ sfx->priority = priority;
+ if (startSfx(sfx, res)) {
+ // Lock the new resource
+ _vm->_res->lock(rtSound, sound);
}
}
@@ -200,14 +197,12 @@ int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
while (len > 0) {
if (!_samplesTillCallback) {
- // Run the update callback for music or sfx depending on which is
- // active.
if (_curOffset) {
updateMusic();
- } else {
- updateSfx();
}
+ updateSfx();
+
_samplesTillCallback = _samplesPerCallback;
_samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
if (_samplesTillCallbackRemainder >= AD_CALLBACK_FREQUENCY) {
Commit: c281da662e0c11bf4f2f24d3346f0d55fc71112d
https://github.com/scummvm/scummvm/commit/c281da662e0c11bf4f2f24d3346f0d55fc71112d
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Only reset rhythm state when music is stopped.
Changed paths:
engines/scumm/players/player_ad.cpp
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index aa6f044..16e03d1 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -164,8 +164,6 @@ void Player_AD::stopAllSounds() {
for (int i = 0; i < ARRAYSIZE(_sfx); ++i) {
stopSfx(&_sfx[i]);
}
-
- writeReg(0xBD, 0x00);
}
int Player_AD::getMusicTimer() {
@@ -384,6 +382,10 @@ void Player_AD::stopMusic() {
noteOff(i);
}
}
+
+ // Reset rhythm state
+ writeReg(0xBD, 0x00);
+ limitHWChannels(9);
}
void Player_AD::updateMusic() {
Commit: d18c31e2eb9d62d9b551c520bf95847a858ce090
https://github.com/scummvm/scummvm/commit/d18c31e2eb9d62d9b551c520bf95847a858ce090
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Fix volume levels when playing SFX and music at the same time in AD player.
This sadly decreases the granularity of volume control since AdLib has far
less distinct volume levels as we. However, having music and sfx at the same
time increases the overall experience.
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 16e03d1..6225efe 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -77,6 +77,8 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) {
_voiceChannels[i].hardwareChannel = -1;
}
+
+ _musicVolume = _sfxVolume = 255;
}
Player_AD::~Player_AD() {
@@ -98,6 +100,9 @@ void Player_AD::setMusicVolume(int vol) {
void Player_AD::startSound(int sound) {
Common::StackLock lock(_mutex);
+ // Setup the sound volume
+ setupVolume();
+
// Query the sound resource
const byte *res = _vm->getResourceAddress(rtSound, sound);
@@ -135,9 +140,6 @@ void Player_AD::startSound(int sound) {
_vm->_res->lock(rtSound, sound);
}
}
-
- // Setup the sound volume
- setupVolume();
}
void Player_AD::stopSound(int sound) {
@@ -222,22 +224,20 @@ int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
void Player_AD::setupVolume() {
// Setup the correct volume
- int soundVolumeMusic = CLIP<int>(ConfMan.getInt("music_volume"), 0, Audio::Mixer::kMaxChannelVolume);
- int soundVolumeSfx = CLIP<int>(ConfMan.getInt("sfx_volume"), 0, Audio::Mixer::kMaxChannelVolume);
+ _musicVolume = CLIP<int>(ConfMan.getInt("music_volume"), 0, Audio::Mixer::kMaxChannelVolume);
+ _sfxVolume = CLIP<int>(ConfMan.getInt("sfx_volume"), 0, Audio::Mixer::kMaxChannelVolume);
+
if (ConfMan.hasKey("mute")) {
if (ConfMan.getBool("mute")) {
- soundVolumeMusic = 0;
- soundVolumeSfx = 0;
+ _musicVolume = 0;
+ _sfxVolume = 0;
}
}
- // In case a music is being played set the music volume. Set the sfx
- // volume otherwise. This is safe because in the latter case either
- // sfx are playing or there is no sound being played at all.
- if (_soundPlaying != -1) {
- _mixer->setChannelVolume(_soundHandle, soundVolumeMusic);
- } else {
- _mixer->setChannelVolume(_soundHandle, soundVolumeSfx);
+ // Update current output levels
+ for (int i = 0; i < ARRAYSIZE(_operatorOffsetTable); ++i) {
+ const uint reg = 0x40 + _operatorOffsetTable[i];
+ writeReg(reg, readReg(reg));
}
}
@@ -287,10 +287,42 @@ void Player_AD::limitHWChannels(int newCount) {
_numHWChannels = newCount;
}
+const int Player_AD::_operatorOffsetToChannel[22] = {
+ 0, 1, 2, 0, 1, 2, -1, -1,
+ 3, 4, 5, 3, 4, 5, -1, -1,
+ 6, 7, 8, 6, 7, 8
+};
+
void Player_AD::writeReg(int r, int v) {
if (r >= 0 && r < ARRAYSIZE(_registerBackUpTable)) {
_registerBackUpTable[r] = v;
}
+
+ // Handle volume scaling depending on the sound type.
+ if (r >= 0x40 && r <= 0x55) {
+ const int operatorOffset = r - 0x40;
+ const int channel = _operatorOffsetToChannel[operatorOffset];
+ if (channel != -1) {
+ const bool twoOPOutput = (readReg(0xC0 + channel) & 0x01) != 0;
+
+ int scale = Audio::Mixer::kMaxChannelVolume;
+ // We only scale the volume of operator 2 unless both operators
+ // are set to directly produce sound.
+ if (twoOPOutput || operatorOffset == _operatorOffsetTable[channel * 2 + 1]) {
+ if (_hwChannels[channel].sfxOwner) {
+ scale = _sfxVolume;
+ } else {
+ scale = _musicVolume;
+ }
+ }
+
+ int vol = 0x3F - (v & 0x3F);
+ vol = vol * scale / Audio::Mixer::kMaxChannelVolume;
+ v &= 0xA0;
+ v |= (0x3F - vol);
+ }
+ }
+
_opl2->writeReg(r, v);
}
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index fbf604e..0a0ba8a 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -68,7 +68,10 @@ private:
Audio::Mixer *const _mixer;
const int _rate;
Audio::SoundHandle _soundHandle;
+
void setupVolume();
+ int _musicVolume;
+ int _sfxVolume;
OPL::OPL *_opl2;
@@ -88,6 +91,7 @@ private:
SfxSlot *sfxOwner;
} _hwChannels[9];
int _numHWChannels;
+ static const int _operatorOffsetToChannel[22];
int allocateHWChannel(int priority, SfxSlot *owner = nullptr);
void freeHWChannel(int channel);
Commit: 46a95fa157b70a06a6b2c67fe5070629d322a9f5
https://github.com/scummvm/scummvm/commit/46a95fa157b70a06a6b2c67fe5070629d322a9f5
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Make sound completely silent for volume level 0 in AD code.
Changed paths:
engines/scumm/players/player_ad.cpp
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 6225efe..e864fe4 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -239,6 +239,12 @@ void Player_AD::setupVolume() {
const uint reg = 0x40 + _operatorOffsetTable[i];
writeReg(reg, readReg(reg));
}
+
+ // Reset note on status
+ for (int i = 0; i < ARRAYSIZE(_hwChannels); ++i) {
+ const uint reg = 0xB0 + i;
+ writeReg(reg, readReg(reg));
+ }
}
int Player_AD::allocateHWChannel(int priority, SfxSlot *owner) {
@@ -323,6 +329,26 @@ void Player_AD::writeReg(int r, int v) {
}
}
+ // Since AdLib's lowest volume level does not imply that the sound is
+ // completely silent we ignore key on in such a case.
+ if (r >= 0xB0 && r <= 0xB8) {
+ const int channel = r - 0xB0;
+ bool mute = false;
+ if (_hwChannels[channel].sfxOwner) {
+ if (!_sfxVolume) {
+ mute = true;
+ }
+ } else {
+ if (!_musicVolume) {
+ mute = true;
+ }
+ }
+
+ if (mute) {
+ v &= ~0x20;
+ }
+ }
+
_opl2->writeReg(r, v);
}
Commit: efe5348d25a507845a6567ea7654ad42b0b4d5be
https://github.com/scummvm/scummvm/commit/efe5348d25a507845a6567ea7654ad42b0b4d5be
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:31+02:00
Commit Message:
SCUMM: Only stop music instead of all sounds in music handling of AD player.
Changed paths:
engines/scumm/players/player_ad.cpp
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index e864fe4..4f3a17f 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -108,7 +108,7 @@ void Player_AD::startSound(int sound) {
if (res[2] == 0x80) {
// Stop the current sounds
- stopAllSounds();
+ stopMusic();
// Lock the new music resource
_soundPlaying = sound;
@@ -478,7 +478,7 @@ void Player_AD::updateMusic() {
_nextEventTimer = 0;
} else {
// Otherwise completely stop playback.
- stopAllSounds();
+ stopMusic();
}
return;
} else if (command == 88) {
Commit: 5ad589da061b7d193aaa9a4f7960da9e60aaa7bf
https://github.com/scummvm/scummvm/commit/5ad589da061b7d193aaa9a4f7960da9e60aaa7bf
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2014-06-04T01:49:32+02:00
Commit Message:
SCUMM: Fix music looping in AD player.
Changed paths:
engines/scumm/players/player_ad.cpp
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 4f3a17f..3b86c56 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -419,7 +419,7 @@ void Player_AD::startMusic() {
_timerLimit = isLoom ? 473 : 256;
_musicTicks = _musicData[3] * (isLoom ? 2 : 1);
_loopFlag = (_musicData[4] == 0);
- _musicLoopStart = READ_LE_UINT16(_musicData + 5);
+ _musicLoopStart = _curOffset + READ_LE_UINT16(_musicData + 5);
}
void Player_AD::stopMusic() {
@@ -476,6 +476,7 @@ void Player_AD::updateMusic() {
// In case the track is looping jump to the start.
_curOffset = _musicLoopStart;
_nextEventTimer = 0;
+ continue;
} else {
// Otherwise completely stop playback.
stopMusic();
More information about the Scummvm-git-logs
mailing list