[Scummvm-git-logs] scummvm master -> 24828afcc4b7de0f24e1e091c1930d33402b4ee7
sev-
noreply at scummvm.org
Thu Oct 12 21:54:37 UTC 2023
This automated email contains information about 22 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
94a8fc246b SWORD1: Begin sound engine rewrite
f0f23208ac SWORD1: SOUND: Wire up more functions and set up the fade timer thread
88dd4ee928 SWORD1: SOUND: Wire up some variables&funcs used externally
c03fe08881 SWORD1: SOUND: Implement sound effects playing and fading
4c0d127a62 SWORD1: SOUND: Reimplement speech
bcff798029 SWORD1: SOUND: Do a code clean-up pass
caaf249e09 SWORD1: SOUND: Implement music for DOS version
023426f90d SWORD1: Fix crashes and music pausing
5fbb2a281e SWORD1: SOUND: Clean-up and preparation for compressed music
6ee4a692de SWORD1: SOUND: Finish implementing support for compressed music
1490905ea0 SWORD1: SOUND: Implement PSX music
0f02b66ebe SWORD1: SOUND: Implement persistence of volume settings
a4d08cfc4c SWORD1: SOUND: Final code clean-up pass
5ecdcecf72 SWORD1: SOUND: Remove Music class and files
096da97262 SWORD1: SOUND: Fix warnings
acba0e6a0b SWORD1: SOUND: Fix typo which broke GMM interoperability
d7dda29c5c SWORD1: SOUND: Revert resource id hack (3451d1c)
598145cde0 SWORD1: SOUND: Remove hack in fnPlayMusic()
0d153d6e62 SWORD1: SOUND: Zero out speech sample buffer before filling it
a68051b2f0 SWORD1: SOUND: Move memset to after checking buffer availability
dea30b9673 SWORD1: SOUND: Stop music handle at the end of fade-out
24828afcc4 SWORD1: SOUND: Remove unnecessary debug print
Commit: 94a8fc246b9bb3d0f31d393d5d9c48bcf6aaa5b6
https://github.com/scummvm/scummvm/commit/94a8fc246b9bb3d0f31d393d5d9c48bcf6aaa5b6
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: Begin sound engine rewrite
Changed paths:
engines/sword1/control.cpp
engines/sword1/logic.cpp
engines/sword1/sound.cpp
engines/sword1/sound.h
engines/sword1/sword1.cpp
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index ed0fdc48b8d..469aca26f7a 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -249,7 +249,7 @@ void Control::getPlayerOptions() {
_screen->startFadePaletteDown(1);
_vm->waitForFade();
- _sound->quitScreen();
+ _sound->clearAllFx();
_keyPressed.reset();
while (SwordEngine::_systemVars.snrStatus != SNR_BLANK && !Engine::shouldQuit()) {
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index ef14824efec..2b4b2f7a13f 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -972,7 +972,7 @@ int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int3
// A cutscene usually (always?) means the room will change. In the
// meantime, we don't want any looping sound effects still playing.
- _sound->quitScreen();
+ _sound->clearAllFx();
MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _system);
if (player) {
@@ -1627,8 +1627,8 @@ int Logic::fnPlayFx(Object *cpt, int32 id, int32 fxNo, int32 b, int32 c, int32 d
}
int Logic::fnStopFx(Object *cpt, int32 id, int32 fxNo, int32 b, int32 c, int32 d, int32 z, int32 x) {
- _sound->fnStopFx(fxNo);
- //_sound->removeFromQueue(fxNo);
+ _sound->StopFX(fxNo);
+ _sound->removeFromQueue(fxNo);
return SCRIPT_CONT;
}
@@ -1640,13 +1640,14 @@ int Logic::fnPlayMusic(Object *cpt, int32 id, int32 tuneId, int32 loopFlag, int3
else
_scriptVars[CURRENT_MUSIC] = 0;
+ //_sound->StreamSample(tuneId, loopFlag);
_music->startMusic(tuneId, loopFlag);
return SCRIPT_CONT;
}
int Logic::fnStopMusic(Object *cpt, int32 id, int32 a, int32 b, int32 c, int32 d, int32 z, int32 x) {
_scriptVars[CURRENT_MUSIC] = 0;
- _music->fadeDown();
+ _sound->FadeMusicDown(1);
return SCRIPT_CONT;
}
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index cf3783ce571..0ea014f1d0e 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -171,38 +171,75 @@ double Sound::endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &max
return diff_sum / cpt;
}
-
-int Sound::addToQueue(int32 fxNo) {
+int Sound::addToQueue(uint32 fxNo) {
bool alreadyInQueue = false;
- for (uint8 cnt = 0; (cnt < _endOfQueue) && (!alreadyInQueue); cnt++)
- if (_fxQueue[cnt].id == (uint32)fxNo)
+ for (uint8 cnt = 0; cnt < _endOfQueue; cnt++) {
+ if (_fxQueue[cnt].id == fxNo) {
alreadyInQueue = true;
- if (!alreadyInQueue) {
+ break;
+ }
+ }
+
+ if (alreadyInQueue) {
+ debug(5, "Sound::addToQueue(): Sound %d is already in the queue, ignoring...", fxNo);
+ return 0;
+ } else {
if (_endOfQueue == MAX_FXQ_LENGTH) {
- warning("Sound queue overflow");
+ warning("Sound::addToQueue(): Sound queue overflow");
return 0;
}
+
uint32 sampleId = getSampleId(fxNo);
if ((sampleId & 0xFF) != 0xFF) {
_resMan->resOpen(sampleId);
_fxQueue[_endOfQueue].id = fxNo;
- if (_fxList[fxNo].type == FX_SPOT)
+
+ if (_fxList[fxNo].type == FX_SPOT) {
_fxQueue[_endOfQueue].delay = _fxList[fxNo].delay + 1;
- else
+ } else {
_fxQueue[_endOfQueue].delay = 1;
+ }
+
_endOfQueue++;
- return 1;
+ return 1; // Success!
}
+
return 0;
}
- return 0;
}
-void Sound::engine() {
- // TODO: FX fading step
+void Sound::removeFromQueue(uint32 fxNo) {
+ uint32 i, j;
+ bool alreadyInQueue = false;
+ uint8 cnt = 0;
+ for (cnt = 0; cnt < _endOfQueue; j++) {
+ if (_fxQueue[cnt].id == fxNo) {
+ alreadyInQueue = true;
+ break;
+ }
+ }
+
+ if (alreadyInQueue) {
+ _resMan->resClose(getSampleId(_fxQueue[cnt].id));
+
+ for (uint8 j = 0; j < _endOfQueue; j++) { // scan fxq from start to last element stored
+ if (_fxQueue[j].id == fxNo) { // if we've found the fxNo in question
+ for (i = j; i < (_endOfQueue - 1); i++) { // move all the others down one to fill this space
+ _fxQueue[i].id = _fxQueue[i + 1].id;
+ _fxQueue[i].delay = _fxQueue[i + 1].delay;
+ }
+ debug(5, "Sound::addToQueue(): Sound fxNo %d removed from _fxQueue[%d] (_endOfQueue = %d)\n", fxNo, j, _endOfQueue - 1);
+ _endOfQueue--; // decrement the end of queue element-number
- // first of all, add any random sfx to the queue...
+ break;
+ }
+ }
+ }
+}
+
+void Sound::engine() {
+ // First of all, add any random sfx to the queue...
for (uint16 cnt = 0; cnt < TOTAL_FX_PER_ROOM; cnt++) {
uint16 fxNo = _roomsFixedFx[Logic::_scriptVars[SCREEN]][cnt];
if (fxNo) {
@@ -213,19 +250,19 @@ void Sound::engine() {
} else
break;
}
- // now process the queue
- for (uint8 cnt2 = 0; cnt2 < _endOfQueue; cnt2++) {
- if (_fxQueue[cnt2].delay > 0) {
- _fxQueue[cnt2].delay--;
- if (_fxQueue[cnt2].delay == 0)
- playSample(&_fxQueue[cnt2]);
- } else {
- if (!_mixer->isSoundHandleActive(_fxQueue[cnt2].handle)) { // sound finished
- _resMan->resClose(getSampleId(_fxQueue[cnt2].id));
- if (cnt2 != _endOfQueue - 1)
- _fxQueue[cnt2] = _fxQueue[_endOfQueue - 1];
- _endOfQueue--;
- }
+
+ // Now process the queue...
+ int32 fxNo = 0;
+ for (uint8 cnt = 0; cnt < _endOfQueue; cnt++) {
+ fxNo = _fxQueue[cnt].id;
+ if (_fxQueue[cnt].delay > 0) {
+ _fxQueue[cnt].delay--;
+ if (_fxQueue[cnt].delay == 0)
+ PlaySample(fxNo);
+ } else if (CheckSampleStatus(fxNo) == 1) {
+ // Delay countdown was already zero, so the sample has
+ // already been played, so check if it's finished...
+ removeFromQueue(fxNo);
}
}
}
@@ -244,9 +281,40 @@ void Sound::fnStopFx(int32 fxNo) {
debug(8, "fnStopFx: id not found in queue");
}
-bool Sound::amISpeaking() {
- _waveVolPos++;
- return _waveVolume[_waveVolPos - 1];
+bool Sound::amISpeaking(byte *buf) {
+ int16 *offset;
+ int16 count;
+ int32 readPos;
+
+ if (!speechSampleBusy)
+ return (0);
+
+ if (true /* AIL_sample_status(hSampleSpeech) != SMP_DONE*/) {
+
+ speechCount += 1;
+
+ readPos = speechCount * 919 * 2;
+
+ // Ensure that we don't read beyond the buffer
+ if (readPos + 150 * sizeof(int16) > speechSize)
+ return false;
+
+ offset = (int16 *)&buf[readPos];
+ count = 0;
+ for (int i = 0; i < 150; i++) {
+ if ((offset[i] < NEG_MOUTH_THRESHOLD) || (offset[i] > POS_MOUTH_THRESHOLD)) {
+ count += 1;
+ if (count == 50) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+
+ //_waveVolPos++;
+ //return _waveVolume[_waveVolPos - 1];
}
bool Sound::speechFinished() {
@@ -271,12 +339,6 @@ void Sound::newScreen(uint32 screen) {
}
}
-void Sound::quitScreen() {
- // stop all running SFX
- while (_endOfQueue)
- fnStopFx(_fxQueue[0].id);
-}
-
void Sound::playSample(QueueElement *elem) {
uint8 *sampleData = (uint8 *)_resMan->fetchRes(getSampleId(elem->id));
for (uint16 cnt = 0; cnt < MAX_ROOMS_PER_FX; cnt++) {
@@ -699,4 +761,178 @@ void Sound::closeCowSystem() {
_currentCowFile = 0;
}
+// New stuff
+
+// This function checks to see whether a specific sound effect has completed
+// playing yet. It returns 1 if finished, 0 if still playing
+//
+int32 Sound::CheckSampleStatus(int32 id) {
+ uint32 i = 0;
+ while (i < MAX_FX) {
+ if (fxSampleID[i] == id) {
+ //if ((AIL_sample_status(hSampleFX[i]) == SMP_DONE) && (fxSampleBusy[i]) && (!fxPaused[i])) {
+ fxSampleBusy[i] = 0;
+ return (1);
+ //} else {
+ // return (0);
+ //}
+ }
+ i += 1;
+ }
+
+ return (0);
+}
+
+int32 Sound::CheckSpeechStatus() {
+ if (!speechSampleBusy || speechSamplePaused)
+ return (1);
+
+ //if (AIL_sample_status(hSampleSpeech) == SMP_DONE) {
+ speechSampleBusy = 0;
+ RestoreMusicVolume();
+ return (1);
+ //}
+ //return (0);
+}
+
+void Sound::PlaySample(int32 fxNo) {
+}
+
+int32 Sound::StreamSample(char filename[], int32 looped) {
+ return int32();
+}
+
+void Sound::UpdateSampleStreaming() {
+}
+
+int32 Sound::PlayFX(int32 fxID, int32 type, void *wavData, uint32 vol[2]) {
+ return int32();
+}
+
+int32 Sound::StopFX(int32 fxID) {
+ for (uint32 i = 0; i < MAX_FX; i++) {
+ if (fxSampleID[i] == fxID) {
+ //if (AIL_sample_status(hSampleFX[i]) != SMP_DONE) {
+ // AIL_end_sample(hSampleFX[i]);
+ fxSampleBusy[i] = 0;
+ return (1);
+ //}
+ }
+ }
+ return (0);
+}
+
+void Sound::clearAllFx() {
+ for (int j = _endOfQueue - 1; j >= 0; j--) { // remove them from the end
+ if (CheckSampleStatus(_fxQueue[j].id) == 0) // delay countdown was already zero, so the sample has already been played, so check if it's finished
+ StopFX(_fxQueue[j].id);
+ removeFromQueue(_fxQueue[j].id);
+ }
+
+ _endOfQueue = 0; // just to be sure, like
+}
+
+void Sound::FadeVolumeDown(int32 rate) {
+ volumeFadingFlag = -1;
+ volumeFadingRate = 2 * rate;
+ volumeCount = 0;
+}
+
+void Sound::FadeVolumeUp(int32 rate) {
+ volumeFadingFlag = 1;
+ volumeFadingRate = 2 * rate;
+ volumeCount = 0;
+}
+
+void Sound::FadeMusicDown(int32 rate) {
+ streamSampleFading[1 - streamSamplePlaying[0]] = -12;
+}
+
+void Sound::FadeMusicUp(int32 rate) {
+ musicFadingFlag = 1;
+ musicFadingRate = 2 * rate;
+ musicCount = 0;
+}
+
+void Sound::FadeFxDown(int32 rate) {
+ fxFadingFlag = -1;
+ fxFadingRate = 2 * rate;
+ fxCount = 0;
+}
+
+void Sound::FadeFxUp(int32 rate) {
+ fxFadingFlag = 1;
+ fxFadingRate = 2 * rate;
+ fxCount = 0;
+}
+
+int32 Sound::GetSpeechSize(void *compData) {
+ return int32();
+}
+
+void Sound::ReduceMusicVolume() {
+ musicFadeVolume[0] = volMusic[0] * MUSIC_UNDERSCORE / 100;
+ musicFadeVolume[1] = volMusic[0] * MUSIC_UNDERSCORE / 100;
+
+ //AIL_set_sample_volume(hStreamSample[0], (musicFadeVolume[0] + musicFadeVolume[1]) * 3);
+}
+
+void Sound::RestoreMusicVolume() {
+ //AIL_set_sample_volume(hStreamSample[0], (volMusic[0] + volMusic[1]) * 3);
+}
+
+void Sound::SetCrossFadeIncrement() {
+ crossFadeIncrement = true;
+}
+
+void Sound::PauseSpeech() {
+ if ((speechSampleBusy) && (!speechSamplePaused)) {
+ speechSamplePaused = true;
+ //AIL_stop_sample(hSampleSpeech);
+ }
+}
+
+void Sound::UnpauseSpeech() {
+ if ((speechSampleBusy) && (speechSamplePaused)) {
+ speechSamplePaused = false;
+ //AIL_resume_sample(hSampleSpeech);
+ }
+}
+
+void Sound::PauseMusic() {
+ for (int32 i = 0; i < MAX_MUSIC; i++) {
+ if (streamSamplePlaying[i]) {
+ musicPaused[i] = true;
+ //AIL_stop_sample(hStreamSample[i]);
+ }
+ }
+}
+
+void Sound::UnpauseMusic() {
+ for (int32 i = 0; i < MAX_MUSIC; i++) {
+ if (musicPaused[i]) {
+ //AIL_resume_sample(hStreamSample[i]);
+ musicPaused[i] = false;
+ }
+ }
+}
+
+void Sound::PauseFx() {
+ for (uint32 i = 0; i < MAX_FX; i++) {
+ if (fxSampleBusy[i]) {
+ //AIL_stop_sample(hSampleFX[i]);
+ fxPaused[i] = true;
+ }
+ }
+}
+
+void Sound::UnpauseFx() {
+ for (uint32 i = 0; i < MAX_FX; i++) {
+ if (fxPaused[i]) {
+ //AIL_resume_sample(hSampleFX[i]);
+ fxPaused[i] = false;
+ }
+ }
+}
+
} // End of namespace Sword1
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index 093dfe0f79b..f1661f04e7c 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -39,8 +39,8 @@ namespace Sword1 {
#define MAX_ROOMS_PER_FX 7 // max no. of rooms in the fx's room,vol list
#define MAX_FXQ_LENGTH 32 // max length of sound queue - ie. max number of fx that can be stored up/playing together
-#define FX_SPOT 1
-#define FX_LOOP 2
+#define FX_SPOT 1
+#define FX_LOOP 2
#define FX_RANDOM 3
struct QueueElement {
@@ -67,6 +67,11 @@ struct FxDef {
class ResMan;
#define WAVE_VOL_TAB_LENGTH 480
#define WAVE_VOL_THRESHOLD 190000 //120000
+#define MUSIC_UNDERSCORE 50
+#define NEG_MOUTH_THRESHOLD (-750)
+#define POS_MOUTH_THRESHOLD 750
+#define MAX_FX 4
+#define MAX_MUSIC 2
enum CowMode {
CowWave = 0,
@@ -88,16 +93,17 @@ public:
void giveSpeechVol(uint8 *volL, uint8 *volR) { *volL = _speechVolL; *volR = _speechVolR; }
void giveSfxVol(uint8 *volL, uint8 *volR) { *volL = _sfxVolL; *volR = _sfxVolR; }
void newScreen(uint32 screen);
- void quitScreen();
+ void clearAllFx();
void closeCowSystem();
bool startSpeech(uint16 roomNo, uint16 localNo);
bool speechFinished();
void stopSpeech();
- bool amISpeaking();
+ bool amISpeaking(byte *buf);
void fnStopFx(int32 fxNo);
- int addToQueue(int32 fxNo);
+ int addToQueue(uint32 fxNo);
+ void removeFromQueue(uint32 fxNo);
void engine();
@@ -131,6 +137,77 @@ private:
static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
static const FxDef _fxList[312];
+ // New stuff
+public:
+ void PlaySample(int32 fxNo);
+
+ int32 StreamSample(char filename[], int32 looped);
+ void UpdateSampleStreaming();
+
+ int32 PlayFX(int32 fxID, int32 type, void *wavData, uint32 vol[2]);
+ int32 StopFX(int32 fxID);
+ int32 CheckSampleStatus(int32 id);
+ int32 CheckSpeechStatus();
+ int32 PlaySpeech(void *wavData, int32 size);
+ int32 StopSpeech();
+ void FadeVolumeDown(int32 rate);
+ void FadeVolumeUp(int32 rate);
+ void FadeMusicDown(int32 rate);
+ void FadeMusicUp(int32 rate);
+ void FadeFxDown(int32 rate);
+ void FadeFxUp(int32 rate);
+ int32 GetSpeechSize(void *compData);
+ void SetCrossFadeIncrement();
+ void PauseSpeech();
+ void UnpauseSpeech();
+ void PauseMusic();
+ void UnpauseMusic();
+ void PauseFx();
+ void UnpauseFx();
+
+ void ReduceMusicVolume();
+ void RestoreMusicVolume();
+
+ uint32 volFX[2] = { 0, 0 };
+ uint32 volSpeech[2] = { 0, 0 };
+ uint32 volMusic[2] = { 0, 0 };
+
+ // Volume variables
+ int32 volumeFadingFlag = 0;
+ int32 volumeFadingRate = 0;
+ int32 musicFadingFlag = 0;
+ int32 musicFadingRate = 0;
+ int32 fxFadingFlag = 0;
+ int32 fxFadingRate = 0;
+ int32 masterVolume[2] = { 0, 0 };
+ int32 fadeVolume[2] = { 0, 0 };
+ int32 musicFadeVolume[2] = { 0, 0 };
+ int32 fxFadeVolume[2] = { 0, 0 };
+ int32 volumeCount = 0;
+ int32 musicCount = 0;
+ int32 fxCount = 0;
+ int32 speechCount = 0;
+ int32 speechSize = 0;
+
+// Sample handles and information.
+
+ Audio::SoundHandle hSampleFX[MAX_FX];
+ Audio::SoundHandle hSampleSpeech;
+ Audio::SoundHandle hSampleMusic[MAX_MUSIC];
+ int32 streamSamplePlaying[MAX_MUSIC] = { 0, 0 };
+ int32 streamSampleFading[MAX_MUSIC] = { 0, 0 };
+ int32 streamLoopingFlag[MAX_MUSIC] = { 0, 0 };
+ Audio::SoundHandle hStreamSample[MAX_MUSIC];
+ int32 streamFile[MAX_MUSIC];
+ byte *streamBuffer[MAX_MUSIC][2];
+ int32 fxSampleBusy[MAX_FX] = { 0, 0, 0, 0 };
+ int32 fxSampleID[MAX_FX] = { 0, 0, 0, 0 };
+ int32 speechSampleBusy;
+ uint32 musicSamples = 0;
+ bool crossFadeIncrement = false;
+ bool speechSamplePaused = false;
+ bool fxPaused[MAX_FX] = { false, false, false, false };
+ bool musicPaused[MAX_MUSIC] = { false, false };
};
} // End of namespace Sword1
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 1f9ef16d10f..da34c73f163 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -181,7 +181,7 @@ Common::Error SwordEngine::init() {
}
void SwordEngine::reinitialize() {
- _sound->quitScreen();
+ _sound->clearAllFx();
_resMan->flush(); // free everything that's currently alloced and opened. (*evil*)
_logic->initialize(); // now reinitialize these objects as they (may) have locked
@@ -1103,7 +1103,7 @@ uint8 SwordEngine::mainLoop() {
_screen->quitScreen(); // Close graphic resources
waitForFade();
- _sound->quitScreen(); // Purge the sound AFTER they've been faded
+ _sound->clearAllFx(); // Purge the sound AFTER they've been faded
_objectMan->closeSection(Logic::_scriptVars[SCREEN]); // Close the section that PLAYER has just left, if it's empty now
} while ((_systemVars.saveGameFlag < SGF_RESTORE) && (!shouldQuit()));
Commit: f0f23208ac3247968946fa0c8abd1bcbadc13d8e
https://github.com/scummvm/scummvm/commit/f0f23208ac3247968946fa0c8abd1bcbadc13d8e
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Wire up more functions and set up the fade timer thread
Changed paths:
engines/sword1/logic.cpp
engines/sword1/sound.cpp
engines/sword1/sound.h
engines/sword1/sword1.cpp
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 2b4b2f7a13f..52c43fbf6fb 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -379,7 +379,7 @@ int Logic::speechDriver(Object *compact) {
compact->o_anim_pc++; // go to next frame of anim
if (_speechFinished || (compact->o_anim_pc >= numFrames) ||
- (_speechRunning && (_sound->amISpeaking() == 0)))
+ (_speechRunning && (_sound->amISpeaking(nullptr) == 0)))
compact->o_anim_pc = 0; //set to frame 0, closed mouth
AnimUnit *animPtr = (AnimUnit *)(animData + sizeof(AnimUnit) * compact->o_anim_pc);
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 0ea014f1d0e..1d7d48eddba 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -43,8 +43,9 @@ namespace Sword1 {
#define SOUND_SPEECH_ID 1
#define SPEECH_FLAGS (Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN)
-Sound::Sound(Audio::Mixer *mixer, ResMan *pResMan)
+Sound::Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan)
: _rnd("sword1sound") {
+ _vm = vm;
_mixer = mixer;
_resMan = pResMan;
_bigEndianSpeech = false;
@@ -768,6 +769,7 @@ void Sound::closeCowSystem() {
//
int32 Sound::CheckSampleStatus(int32 id) {
uint32 i = 0;
+ Common::StackLock lock(_soundMutex);
while (i < MAX_FX) {
if (fxSampleID[i] == id) {
//if ((AIL_sample_status(hSampleFX[i]) == SMP_DONE) && (fxSampleBusy[i]) && (!fxPaused[i])) {
@@ -795,21 +797,246 @@ int32 Sound::CheckSpeechStatus() {
//return (0);
}
+int32 Sound::PlaySpeech(void *wavData, int32 size) {
+ speechSize = size;
+ speechCount = 0;
+
+ // Check to see if the handle is free, else free it
+ if (speechSampleBusy)
+ StopSpeech();
+
+ // Reset the sample parameters
+ //AIL_init_sample(hSampleSpeech);
+ speechSampleBusy = 1;
+
+ // And point the sample to our new wav data
+ if (true/* AIL_set_sample_file(hSampleSpeech, wavData, -1) == 0*/) {
+ speechSampleBusy = 0;
+ return (0);
+ } else {
+ // We have found a free handle, and the wav file header
+ // has been successfully parsed.
+ //
+ // Modify the volume according to the master volume
+ //AIL_set_sample_volume(hSampleSpeech, 4 * (volSpeech[0] + volSpeech[1]));
+
+ // Now set the pan position for the sample
+ //AIL_set_sample_pan(hSampleSpeech, 64 + (4 * (volSpeech[1] - volSpeech[0])));
+
+ // Start the sample
+ //AIL_start_sample(hSampleSpeech);
+
+ ReduceMusicVolume();
+
+ // and exit the function.
+ return (1);
+ }
+}
+
+int32 Sound::StopSpeech() {
+ if (true/* AIL_sample_status(hSampleSpeech) != SMP_DONE*/) {
+ //AIL_end_sample(hSampleSpeech);
+ speechSampleBusy = 0;
+ RestoreMusicVolume();
+ return (1);
+ }
+ return (0);
+}
+
+static void soundCallback(void *refCon) {
+ Sound *snd = (Sound *)refCon;
+ Common::StackLock lock(snd->_soundMutex);
+
+ if (snd->volumeFadingFlag) {
+ snd->volumeCount += 1;
+ if (snd->volumeCount > 128 / snd->volumeFadingRate) {
+ snd->volumeFadingFlag = 0;
+ } else {
+ if (snd->volumeFadingFlag == 1) {
+ //Fade the volume up
+ snd->fadeVolume[0] = snd->masterVolume[0] * snd->volumeCount * snd->volumeFadingRate / 128;
+ snd->fadeVolume[1] = snd->masterVolume[1] * snd->volumeCount * snd->volumeFadingRate / 128;
+ } else {
+ //Fade the volume down
+ snd->fadeVolume[0] = snd->masterVolume[0] - (snd->masterVolume[0] * snd->volumeCount * snd->volumeFadingRate / 128);
+ snd->fadeVolume[1] = snd->masterVolume[1] - (snd->masterVolume[1] * snd->volumeFadingRate * snd->volumeCount / 128);
+ }
+
+ //AIL_set_digital_master_volume(hDigiDriver, (snd->fadeVolume[0] + snd->fadeVolume[1]) / 2);
+ }
+ }
+
+ if (snd->musicFadingFlag) {
+ snd->musicCount += 1;
+ if (snd->musicCount > 128 / snd->musicFadingRate) {
+ snd->musicFadingFlag = 0;
+ } else {
+ if (snd->musicFadingFlag == 1) {
+ //Fade the volume up
+ snd->musicFadeVolume[0] = 8 * snd->volMusic[0] * snd->musicCount * snd->musicFadingRate / 128;
+ snd->musicFadeVolume[1] = 8 * snd->volMusic[1] * snd->musicCount * snd->musicFadingRate / 128;
+ } else {
+ //Fade the volume down
+ snd->musicFadeVolume[0] = 8 * snd->volMusic[0] - (8 * snd->volMusic[0] * snd->musicCount * snd->musicFadingRate / 128);
+ snd->musicFadeVolume[1] = 8 * snd->volMusic[1] - (8 * snd->volMusic[1] * snd->musicFadingRate * snd->musicCount / 128);
+ }
+
+ for (int i = 0; i < MAX_MUSIC; i++) {
+ if (snd->streamSamplePlaying[i])
+ ;
+ //AIL_set_sample_volume(snd->hStreamSample[i], (snd->musicFadeVolume[0] + snd->musicFadeVolume[1]) / 2);
+ }
+
+ }
+ }
+
+ if (snd->fxFadingFlag) {
+ snd->fxCount += 1;
+ if (snd->fxCount > 128 / snd->fxFadingRate) {
+ snd->fxFadingFlag = 0;
+ } else {
+ if (snd->fxFadingFlag == 1) {
+ //Fade the volume up
+ snd->fxFadeVolume[0] = 8 * snd->volFX[0] * snd->fxCount * snd->fxFadingRate / 128;
+ snd->fxFadeVolume[1] = 8 * snd->volFX[1] * snd->fxCount * snd->fxFadingRate / 128;
+ } else {
+ //Fade the volume down
+ snd->fxFadeVolume[0] = 8 * snd->volFX[0] - (8 * snd->volFX[0] * snd->fxCount * snd->fxFadingRate / 128);
+ snd->fxFadeVolume[1] = 8 * snd->volFX[1] - (8 * snd->volFX[1] * snd->fxFadingRate * snd->fxCount / 128);
+ }
+ for (int i = 0; i < MAX_FX; i++) {
+ if (snd->fxSampleBusy[i])
+ ;
+ //AIL_set_sample_volume(hSampleFX[i], (fxFadeVolume[0] + fxFadeVolume[1]) / 2);
+ }
+ }
+ }
+}
+
+void Sound::installFadeTimer() {
+ _vm->getTimerManager()->installTimerProc(&soundCallback, 1000000 / TIMER_RATE, this, "AILFadeTimer");
+}
+
+void Sound::uninstallFadeTimer() {
+ _vm->getTimerManager()->removeTimerProc(&soundCallback);
+}
+
void Sound::PlaySample(int32 fxNo) {
+ uint8 *samplePtr;
+ uint32 vol[2] = { 0, 0 };
+ int32 screen = Logic::_scriptVars[SCREEN];
+
+ samplePtr = (uint8 *)_resMan->fetchRes(getSampleId(fxNo));
+
+ for (int i = 0; i < MAX_ROOMS_PER_FX; i++) {
+ if (_fxList[fxNo].roomVolList[i].roomNo != 0) {
+ if ((_fxList[fxNo].roomVolList[i].roomNo == screen) ||
+ (_fxList[fxNo].roomVolList[i].roomNo == -1)) { // -1 indicates 'all rooms'
+ vol[0] = (_fxList[fxNo].roomVolList[i].leftVol);
+ vol[1] = (_fxList[fxNo].roomVolList[i].rightVol);
+
+ debug(5, "Sound::PlaySample(): fxNo=%d, vol[0]=%d, vol[1]=%d)",fxNo,vol[0],vol[1]);
+ PlayFX(fxNo, _fxList[fxNo].type, samplePtr, vol);
+ break;
+ }
+ } else {
+ break;
+ }
+ }
}
int32 Sound::StreamSample(char filename[], int32 looped) {
- return int32();
+ return 0;
}
void Sound::UpdateSampleStreaming() {
+ Common::StackLock lock(_soundMutex);
+ for (int i = 0; i < MAX_MUSIC; i++) {
+ if ((streamSamplePlaying[i]) && (!musicPaused[i])) {
+ if (streamSampleFading[i]) {
+ if (crossFadeIncrement) {
+ crossFadeIncrement = false;
+
+ if (streamSampleFading[i] < 0) {
+ //AIL_set_sample_volume(hStreamSample[i], ((0 - streamSampleFading[i]) * 3 * (volMusic[0] + volMusic[1])) / 16);
+ streamSampleFading[i] += 1;
+ if (streamSampleFading[i] == 0) {
+ //AIL_stop_sample(hStreamSample[i]);
+ //AIL_release_sample_handle(hStreamSample[i]);
+ //close(streamFile[i]);
+ streamSamplePlaying[i] = 0;
+ //MEM_free_lock(streamBuffer[i][0], bufferSize);
+ //MEM_free_lock(streamBuffer[i][1], bufferSize);
+ }
+ } else {
+ //AIL_set_sample_volume(hStreamSample[i], (streamSampleFading[i] * 3 * (volMusic[0] + volMusic[1])) / 16);
+ streamSampleFading[i] += 1;
+ if (streamSampleFading[i] == 17) {
+ streamSampleFading[i] = 0;
+ }
+ }
+ }
+ }
+ //ServeSample(hStreamSample[i], streamBuffer[i], bufferSize, streamFile[i], i);
+ //if (AIL_sample_status(hStreamSample[i]) != SMP_PLAYING) {
+ // AIL_release_sample_handle(hStreamSample[i]);
+ // streamSamplePlaying[i] = FALSE;
+ // close(streamFile[i]);
+ // MEM_free_lock(streamBuffer[i][0], bufferSize);
+ // MEM_free_lock(streamBuffer[i][1], bufferSize);
+ //}
+ }
+ }
}
int32 Sound::PlayFX(int32 fxID, int32 type, void *wavData, uint32 vol[2]) {
- return int32();
+ int32 i = 0;
+ int32 v0, v1;
+ Common::StackLock lock(_soundMutex);
+ // Search through the fx sample handles for a free slot
+ while (i < MAX_FX) {
+ // Check to see if the handle is free
+ if (fxSampleBusy[i] == 0) {
+ // Reset the sample parameters
+ //AIL_init_sample(hSampleFX[i]);
+ fxSampleBusy[i] = 1;
+ fxSampleID[i] = fxID;
+
+ //if (type == FX_LOOP)
+ // AIL_set_sample_loop_count(hSampleFX[i], 0);
+
+ // And point the sample to our new wav data
+ if (true /* AIL_set_sample_file(hSampleFX[i], wavData, -1) == 0*/) {
+ return (0);
+ } else {
+ // We have found a free handle, and the wav file header
+ // has been successfully parsed.
+ //
+ // Modify the volume according to the master volume
+ v0 = volFX[0] * vol[0];
+ v1 = volFX[1] * vol[1];
+
+ //AIL_set_sample_volume(hSampleFX[i], (v0 + v1) / 8);
+
+ // Now set the pan position for the sample
+ //AIL_set_sample_pan(hSampleFX[i], 64 + ((v1 - v0) / 4));
+
+ // Start the sample
+ //AIL_start_sample(hSampleFX[i]);
+
+ // and exit the function.
+ return (1);
+ }
+ }
+ i += 1;
+
+ } // while
+
+ return (0);
}
int32 Sound::StopFX(int32 fxID) {
+ Common::StackLock lock(_soundMutex);
for (uint32 i = 0; i < MAX_FX; i++) {
if (fxSampleID[i] == fxID) {
//if (AIL_sample_status(hSampleFX[i]) != SMP_DONE) {
@@ -833,44 +1060,74 @@ void Sound::clearAllFx() {
}
void Sound::FadeVolumeDown(int32 rate) {
+ Common::StackLock lock(_soundMutex);
volumeFadingFlag = -1;
volumeFadingRate = 2 * rate;
volumeCount = 0;
}
void Sound::FadeVolumeUp(int32 rate) {
+ Common::StackLock lock(_soundMutex);
volumeFadingFlag = 1;
volumeFadingRate = 2 * rate;
volumeCount = 0;
}
void Sound::FadeMusicDown(int32 rate) {
+ Common::StackLock lock(_soundMutex);
streamSampleFading[1 - streamSamplePlaying[0]] = -12;
}
void Sound::FadeMusicUp(int32 rate) {
+ Common::StackLock lock(_soundMutex);
musicFadingFlag = 1;
musicFadingRate = 2 * rate;
musicCount = 0;
}
void Sound::FadeFxDown(int32 rate) {
+ Common::StackLock lock(_soundMutex);
fxFadingFlag = -1;
fxFadingRate = 2 * rate;
fxCount = 0;
}
void Sound::FadeFxUp(int32 rate) {
+ Common::StackLock lock(_soundMutex);
fxFadingFlag = 1;
fxFadingRate = 2 * rate;
fxCount = 0;
}
int32 Sound::GetSpeechSize(void *compData) {
- return int32();
+ typedef struct wavHeader {
+ char riff[4];
+ int fileLength;
+ char wavID[4];
+ char format[4];
+ int formatLen;
+ short int formatTag;
+ short int channels;
+ short int samplesPerSec;
+ short int avgBytesPerSec;
+ short int blockAlign;
+ short int formatSpecific;
+ short int unused[8];
+ } wavHeader;
+
+ wavHeader *head;
+
+ head = (wavHeader *)compData;
+
+ //Pdebug("Getting speech size : %d", head->fileLength + 8);
+ //Pdebug("riff %c%c%c%c", head->riff[0], head->riff[1], head->riff[2], head->riff[3]);
+ //Pdebug("file length %d\n", head->fileLength);
+
+ return (head->fileLength + 8);
}
void Sound::ReduceMusicVolume() {
+ Common::StackLock lock(_soundMutex);
musicFadeVolume[0] = volMusic[0] * MUSIC_UNDERSCORE / 100;
musicFadeVolume[1] = volMusic[0] * MUSIC_UNDERSCORE / 100;
@@ -878,6 +1135,7 @@ void Sound::ReduceMusicVolume() {
}
void Sound::RestoreMusicVolume() {
+ Common::StackLock lock(_soundMutex);
//AIL_set_sample_volume(hStreamSample[0], (volMusic[0] + volMusic[1]) * 3);
}
@@ -900,6 +1158,7 @@ void Sound::UnpauseSpeech() {
}
void Sound::PauseMusic() {
+ Common::StackLock lock(_soundMutex);
for (int32 i = 0; i < MAX_MUSIC; i++) {
if (streamSamplePlaying[i]) {
musicPaused[i] = true;
@@ -909,6 +1168,7 @@ void Sound::PauseMusic() {
}
void Sound::UnpauseMusic() {
+ Common::StackLock lock(_soundMutex);
for (int32 i = 0; i < MAX_MUSIC; i++) {
if (musicPaused[i]) {
//AIL_resume_sample(hStreamSample[i]);
@@ -918,6 +1178,7 @@ void Sound::UnpauseMusic() {
}
void Sound::PauseFx() {
+ Common::StackLock lock(_soundMutex);
for (uint32 i = 0; i < MAX_FX; i++) {
if (fxSampleBusy[i]) {
//AIL_stop_sample(hSampleFX[i]);
@@ -927,6 +1188,7 @@ void Sound::PauseFx() {
}
void Sound::UnpauseFx() {
+ Common::StackLock lock(_soundMutex);
for (uint32 i = 0; i < MAX_FX; i++) {
if (fxPaused[i]) {
//AIL_resume_sample(hSampleFX[i]);
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index f1661f04e7c..aedd491082c 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -24,9 +24,13 @@
#include "sword1/object.h"
#include "sword1/sworddefs.h"
+
#include "common/file.h"
-#include "common/util.h"
+#include "common/mutex.h"
#include "common/random.h"
+#include "common/timer.h"
+#include "common/util.h"
+
#include "audio/mixer.h"
namespace Audio {
@@ -65,6 +69,8 @@ struct FxDef {
};
class ResMan;
+class SwordEngine;
+
#define WAVE_VOL_TAB_LENGTH 480
#define WAVE_VOL_THRESHOLD 190000 //120000
#define MUSIC_UNDERSCORE 50
@@ -86,7 +92,7 @@ class Sound {
friend class SwordConsole;
friend class Control;
public:
- Sound(Audio::Mixer *mixer, ResMan *pResMan);
+ Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan);
~Sound();
void setSpeechVol(uint8 volL, uint8 volR) { _speechVolL = volL; _speechVolR = volR; }
void setSfxVol(uint8 volL, uint8 volR) { _sfxVolL = volL; _sfxVolR = volR; }
@@ -110,6 +116,8 @@ public:
void checkSpeechFileEndianness();
double endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &maxSamples);
+ Common::Mutex _soundMutex;
+
private:
uint8 _sfxVolL, _sfxVolR, _speechVolL, _speechVolR;
void playSample(QueueElement *elem);
@@ -131,7 +139,9 @@ private:
QueueElement _fxQueue[MAX_FXQ_LENGTH];
uint8 _endOfQueue;
Audio::Mixer *_mixer;
+ SwordEngine *_vm;
ResMan *_resMan;
+
bool _bigEndianSpeech;
static const char _musicList[270];
static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
@@ -139,6 +149,8 @@ private:
// New stuff
public:
+ void installFadeTimer();
+ void uninstallFadeTimer();
void PlaySample(int32 fxNo);
int32 StreamSample(char filename[], int32 looped);
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index da34c73f163..334b25cc7ed 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -102,7 +102,7 @@ Common::Error SwordEngine::init() {
_mouse = new Mouse(_system, _resMan, _objectMan);
_screen = new Screen(_system, _resMan, _objectMan);
_music = new Music(_mixer);
- _sound = new Sound(_mixer, _resMan);
+ _sound = new Sound(_mixer, this, _resMan);
_menu = new Menu(_screen, _mouse);
_logic = new Logic(this, _objectMan, _resMan, _screen, _mouse, _sound, _music, _menu, _system, _mixer);
_mouse->useLogicAndMenu(_logic, _menu);
@@ -1262,11 +1262,13 @@ void SwordEngine::installTimerRoutines() {
debug(2, "SwordEngine::installTimerRoutines(): Installing timers...");
_ticker = 0;
getTimerManager()->installTimerProc(&vblCallback, 1000000 / TIMER_RATE, this, "AILTimer");
+ _sound->installFadeTimer();
}
void SwordEngine::uninstallTimerRoutines() {
debug(2, "SwordEngine::uninstallTimerRoutines(): Uninstalling timers...");
getTimerManager()->removeTimerProc(&vblCallback);
+ _sound->uninstallFadeTimer();
}
} // End of namespace Sword1
Commit: 88dd4ee9280198777058a9345377bce64a716b2c
https://github.com/scummvm/scummvm/commit/88dd4ee9280198777058a9345377bce64a716b2c
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Wire up some variables&funcs used externally
Changed paths:
engines/sword1/control.cpp
engines/sword1/sword1.cpp
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 469aca26f7a..e94c7d5e453 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -255,12 +255,10 @@ void Control::getPlayerOptions() {
while (SwordEngine::_systemVars.snrStatus != SNR_BLANK && !Engine::shouldQuit()) {
delay(DEFAULT_FRAME_TIME / 2);
- // TODO: audio
- // SetCrossFadeIncrement();
+ _sound->SetCrossFadeIncrement();
_mouse->animate();
- // TODO: audio
- // UpdateSampleStreaming(); // stream music
+ _sound->UpdateSampleStreaming(); // stream music
saveRestoreScreen();
}
@@ -290,8 +288,7 @@ void Control::getPlayerOptions() {
if (SwordEngine::_systemVars.saveGameFlag == SGF_SAVE) {
saveGame();
} else if (SwordEngine::_systemVars.saveGameFlag == SGF_QUIT) {
- // TODO: audio
- // FadeMusicDown(1);
+ _sound->FadeMusicDown(1);
Engine::quitGame();
}
@@ -978,21 +975,18 @@ void Control::renderVolumeLight(int32 i) {
switch (i) {
case 0: //music
- _music->giveVolume(&vol[0], &vol[1]);
- //vol[0] = volMusic[0];
- //vol[1] = volMusic[1];
+ vol[0] = _sound->volMusic[0];
+ vol[1] = _sound->volMusic[1];
x = 158;
break;
case 1: //speech
- _sound->giveSpeechVol(&vol[0], &vol[1]);
- //vol[0] = volSpeech[0];
- //vol[1] = volSpeech[1];
+ vol[0] = _sound->volSpeech[0];
+ vol[1] = _sound->volSpeech[1];
x = 291;
break;
case 2: //fx
- _sound->giveSfxVol(&vol[0], &vol[1]);
- //vol[0] = volFX[0];
- //vol[1] = volFX[1];
+ vol[0] = _sound->volFX[0];
+ vol[1] = _sound->volFX[1];
x = 424;
break;
default:
@@ -1078,15 +1072,15 @@ void Control::volUp(int32 i, int32 j) {
switch (i) {
case 0:
_music->giveVolume((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &volMusic[j];
+ //vol = &_sound->volMusic[j];
break;
case 1:
_sound->giveSpeechVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &volSpeech[j];
+ //vol = &_sound->volSpeech[j];
break;
case 2:
_sound->giveSfxVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &volFX[j];
+ //vol = &_sound->volFX[j];
break;
}
@@ -1098,15 +1092,15 @@ void Control::volUp(int32 i, int32 j) {
switch (i) {
case 0:
_music->setVolume((uint8)vol[0], (uint8)vol[1]);
- //vol = &volMusic[j];
+ //vol = &_sound->volMusic[j];
break;
case 1:
_sound->setSpeechVol((uint8)vol[0], (uint8)vol[1]);
- //vol = &volSpeech[j];
+ //vol = &_sound->volSpeech[j];
break;
case 2:
_sound->setSfxVol((uint8)vol[0], (uint8)vol[1]);
- //vol = &volFX[j];
+ //vol = &_sound->volFX[j];
break;
}
}
@@ -1121,15 +1115,15 @@ void Control::volDown(int32 i, int32 j) {
switch (i) {
case 0:
_music->giveVolume((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &volMusic[j];
+ //vol = &_sound->volMusic[j];
break;
case 1:
_sound->giveSpeechVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &volSpeech[j];
+ //vol = &_sound->volSpeech[j];
break;
case 2:
_sound->giveSfxVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &volFX[j];
+ //vol = &_sound->volFX[j];
break;
}
@@ -1141,15 +1135,15 @@ void Control::volDown(int32 i, int32 j) {
switch (i) {
case 0:
_music->setVolume((uint8)vol[0], (uint8)vol[1]);
- //vol = &volMusic[j];
+ //vol = &_sound->volMusic[j];
break;
case 1:
_sound->setSpeechVol((uint8)vol[0], (uint8)vol[1]);
- //vol = &volSpeech[j];
+ //vol = &_sound->volSpeech[j];
break;
case 2:
_sound->setSfxVol((uint8)vol[0], (uint8)vol[1]);
- //vol = &volFX[j];
+ //vol = &_sound->volFX[j];
break;
}
}
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 334b25cc7ed..9826d3b5fdc 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -267,23 +267,18 @@ void SwordEngine::flagsToBool(bool *dest, uint8 flags) {
void SwordEngine::checkKeys() {
if (_systemVars.gamePaused) {
- // TODO: Audio
- //PauseSpeech();
- //PauseMusic();
- //PauseFx();
- _mixer->pauseAll(true);
+ _sound->PauseSpeech();
+ _sound->PauseMusic();
+ _sound->PauseFx();
while (_keyPressed.keycode != Common::KEYCODE_p && !Engine::shouldQuit()) {
pollInput(0);
- // TODO: Audio
- // UpdateSampleStreaming();
+ _sound->UpdateSampleStreaming();
}
- // TODO: Audio
- //UnpauseSpeech();
- //UnpauseMusic();
- //UnpauseFx();
- _mixer->pauseAll(false);
+ _sound->UnpauseSpeech();
+ _sound->UnpauseMusic();
+ _sound->UnpauseFx();
_systemVars.gamePaused = false;
_keyPressed.reset();
@@ -1203,13 +1198,13 @@ void SwordEngine::fadePaletteStep() {
void SwordEngine::startFadePaletteDown(int speed) {
_screen->startFadePaletteDown(speed);
- // TODO: Fade audio here
+ _sound->FadeFxDown(speed);
}
void SwordEngine::startFadePaletteUp(int speed) {
_screen->startFadePaletteUp(speed);
- // TODO: Fade audio here
+ _sound->FadeFxUp(speed);
}
static void vblCallback(void *refCon) {
@@ -1243,8 +1238,6 @@ static void vblCallback(void *refCon) {
vm->fadePaletteStep();
}
-
- // TODO: Volume fading here...
}
vm->_inTimer--;
Commit: c03fe08881c5191f08adcf339151b37cd141fff5
https://github.com/scummvm/scummvm/commit/c03fe08881c5191f08adcf339151b37cd141fff5
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Implement sound effects playing and fading
Changed paths:
engines/sword1/control.cpp
engines/sword1/screen.cpp
engines/sword1/screen.h
engines/sword1/sound.cpp
engines/sword1/sound.h
engines/sword1/sword1.cpp
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index e94c7d5e453..cab4aa0ec5d 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -247,7 +247,7 @@ void Control::getPlayerOptions() {
Logic::_scriptVars[CURRENT_MUSIC] = safeCurrentMusic;
- _screen->startFadePaletteDown(1);
+ _vm->startFadePaletteDown(1);
_vm->waitForFade();
_sound->clearAllFx();
_keyPressed.reset();
@@ -279,7 +279,7 @@ void Control::getPlayerOptions() {
_logic->fnStopMusic(nullptr, 0, 0, 0, 0, 0, 0, 0);
}
- _screen->startFadePaletteDown(1);
+ _vm->startFadePaletteDown(1);
_vm->waitForFade();
_logic->fnNormalMouse(nullptr, 0, 0, 0, 0, 0, 0, 0);
@@ -464,7 +464,7 @@ void Control::saveRestoreScreen() {
if (_newPal) {
_newPal = false;
- _screen->startFadePaletteUp(1);
+ _vm->startFadePaletteUp(1);
}
break;
@@ -1049,7 +1049,7 @@ void Control::setVolumes() {
if (volBalance != ConfMan.getInt("speech_balance"))
ConfMan.setInt("speech_balance", volBalance);
- _sound->giveSfxVol(&volL, &volR);
+ //_sound->giveSfxVol(&volL, &volR);
vol = (int)((volR + volL) / 2);
volBalance = volToBalance(volL, volR);
if (vol != ConfMan.getInt("sfx_volume"))
@@ -1063,89 +1063,41 @@ void Control::setVolumes() {
}
void Control::volUp(int32 i, int32 j) {
- // TODO: This function has been mangled to accomodate the current
- // audio engine, which will partly get rewritten in the immediate
- // future :)
-
- uint32 vol[2] = { 0, 0 };
+ uint32 *vol = nullptr;
switch (i) {
case 0:
- _music->giveVolume((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &_sound->volMusic[j];
+ vol = &_sound->volMusic[j];
break;
case 1:
- _sound->giveSpeechVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &_sound->volSpeech[j];
+ vol = &_sound->volSpeech[j];
break;
case 2:
- _sound->giveSfxVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &_sound->volFX[j];
+ vol = &_sound->volFX[j];
break;
}
- if ((vol[j] >> 4) < 16)
- vol[j] += 1 << 4;
-
- vol[j] = CLIP<uint32>(vol[j], 0, 255);
-
- switch (i) {
- case 0:
- _music->setVolume((uint8)vol[0], (uint8)vol[1]);
- //vol = &_sound->volMusic[j];
- break;
- case 1:
- _sound->setSpeechVol((uint8)vol[0], (uint8)vol[1]);
- //vol = &_sound->volSpeech[j];
- break;
- case 2:
- _sound->setSfxVol((uint8)vol[0], (uint8)vol[1]);
- //vol = &_sound->volFX[j];
- break;
- }
+ if (vol && *vol < 16)
+ *vol += 1;
}
void Control::volDown(int32 i, int32 j) {
- // TODO: This function has been mangled to accomodate the current
- // audio engine, which will partly get rewritten in the immediate
- // future :)
-
- uint32 vol[2] = {0, 0};
+ uint32 *vol = nullptr;
switch (i) {
case 0:
- _music->giveVolume((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &_sound->volMusic[j];
+ vol = &_sound->volMusic[j];
break;
case 1:
- _sound->giveSpeechVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &_sound->volSpeech[j];
+ vol = &_sound->volSpeech[j];
break;
case 2:
- _sound->giveSfxVol((uint8 *)&vol[0], (uint8 *)&vol[1]);
- //vol = &_sound->volFX[j];
+ vol = &_sound->volFX[j];
break;
}
- if (vol[j] > 1 << 4)
- vol[j] -= 1 << 4;
-
- vol[j] = CLIP<uint32>(vol[j], 0, 255);
-
- switch (i) {
- case 0:
- _music->setVolume((uint8)vol[0], (uint8)vol[1]);
- //vol = &_sound->volMusic[j];
- break;
- case 1:
- _sound->setSpeechVol((uint8)vol[0], (uint8)vol[1]);
- //vol = &_sound->volSpeech[j];
- break;
- case 2:
- _sound->setSfxVol((uint8)vol[0], (uint8)vol[1]);
- //vol = &_sound->volFX[j];
- break;
- }
+ if (vol && *vol > 0)
+ *vol -= 1;
}
void Control::renderVolumeDisc(int32 i, int32 j) {
diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 276731e075a..743ab2156a4 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -44,8 +44,9 @@ namespace Sword1 {
#define FADE_UP 1
#define FADE_DOWN -1
-Screen::Screen(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan) {
+Screen::Screen(OSystem *system, SwordEngine *vm, ResMan *pResMan, ObjectMan *pObjMan) {
_system = system;
+ _vm = vm;
_resMan = pResMan;
_objMan = pObjMan;
_screenBuf = _screenGrid = NULL;
@@ -349,7 +350,7 @@ void Screen::updateScreen() {
if (SwordEngine::isMac())
fnSetFadeTargetPalette(255, 1, 0, BORDER_BLACK);
- startFadePaletteUp(1);
+ _vm->startFadePaletteUp(1);
_updatePalette = false;
}
diff --git a/engines/sword1/screen.h b/engines/sword1/screen.h
index 2ca6ba05dca..cca6f57bde7 100644
--- a/engines/sword1/screen.h
+++ b/engines/sword1/screen.h
@@ -66,6 +66,7 @@ struct PSXDataCache { // Cache for PSX screen, to avoid decompressing background
#define BORDER_BLACK 5
#define TEXT_WHITE 6
+class SwordEngine;
class ResMan;
class ObjectMan;
class Text; // Text objects use sprites that are created internally at run-time
@@ -74,7 +75,7 @@ class Text; // Text objects use sprites that are created internally at run-time
class Screen {
friend class Text;
public:
- Screen(OSystem *system, ResMan *pResMan, ObjectMan *pObjMan);
+ Screen(OSystem *system, SwordEngine *vm, ResMan *pResMan, ObjectMan *pObjMan);
~Screen();
void clearScreen();
void useTextManager(Text *pTextMan);
@@ -158,6 +159,7 @@ private:
void flushPsxCache();
OSystem *_system;
+ SwordEngine *_vm;
ResMan *_resMan;
ObjectMan *_objMan;
Text *_textMan;
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 1d7d48eddba..644e9668cc9 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -52,7 +52,16 @@ Sound::Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan)
_cowHeader = NULL;
_endOfQueue = 0;
_currentCowFile = 0;
- _speechVolL = _speechVolR = _sfxVolL = _sfxVolR = 192;
+ _speechVolL = _speechVolR = 192;
+ //if (!GetVolumes()) {
+ volFX[0] = 8;
+ volFX[1] = 8;
+ volSpeech[0] = 8;
+ volSpeech[1] = 8;
+ volMusic[0] = 8;
+ volMusic[1] = 8;
+ // SetVolumes();
+ //}
}
Sound::~Sound() {
@@ -210,10 +219,10 @@ int Sound::addToQueue(uint32 fxNo) {
}
void Sound::removeFromQueue(uint32 fxNo) {
- uint32 i, j;
bool alreadyInQueue = false;
- uint8 cnt = 0;
- for (cnt = 0; cnt < _endOfQueue; j++) {
+ int cnt = 0;
+
+ for (cnt = 0; cnt < _endOfQueue; cnt++) {
if (_fxQueue[cnt].id == fxNo) {
alreadyInQueue = true;
break;
@@ -223,15 +232,16 @@ void Sound::removeFromQueue(uint32 fxNo) {
if (alreadyInQueue) {
_resMan->resClose(getSampleId(_fxQueue[cnt].id));
- for (uint8 j = 0; j < _endOfQueue; j++) { // scan fxq from start to last element stored
- if (_fxQueue[j].id == fxNo) { // if we've found the fxNo in question
- for (i = j; i < (_endOfQueue - 1); i++) { // move all the others down one to fill this space
+ for (int j = 0; j < _endOfQueue; j++) {
+ if (_fxQueue[j].id == fxNo) {
+ // Move all the others down one to fill this space...
+ for (int i = j; i < (_endOfQueue - 1); i++) {
_fxQueue[i].id = _fxQueue[i + 1].id;
_fxQueue[i].delay = _fxQueue[i + 1].delay;
}
- debug(5, "Sound::addToQueue(): Sound fxNo %d removed from _fxQueue[%d] (_endOfQueue = %d)\n", fxNo, j, _endOfQueue - 1);
- _endOfQueue--; // decrement the end of queue element-number
+ debug(5, "Sound::addToQueue(): Sound fxNo %d removed from _fxQueue[%d] (_endOfQueue = %d)", fxNo, j, _endOfQueue - 1);
+ _endOfQueue--;
break;
}
@@ -260,7 +270,7 @@ void Sound::engine() {
_fxQueue[cnt].delay--;
if (_fxQueue[cnt].delay == 0)
PlaySample(fxNo);
- } else if (CheckSampleStatus(fxNo) == 1) {
+ } else if (CheckSampleStatus(fxNo) == S_STATUS_FINISHED) {
// Delay countdown was already zero, so the sample has
// already been played, so check if it's finished...
removeFromQueue(fxNo);
@@ -288,10 +298,9 @@ bool Sound::amISpeaking(byte *buf) {
int32 readPos;
if (!speechSampleBusy)
- return (0);
-
- if (true /* AIL_sample_status(hSampleSpeech) != SMP_DONE*/) {
+ return false;
+ if (_mixer->isSoundHandleActive(hSampleSpeech)) {
speechCount += 1;
readPos = speechCount * 919 * 2;
@@ -313,9 +322,6 @@ bool Sound::amISpeaking(byte *buf) {
}
return false;
-
- //_waveVolPos++;
- //return _waveVolume[_waveVolPos - 1];
}
bool Sound::speechFinished() {
@@ -340,42 +346,6 @@ void Sound::newScreen(uint32 screen) {
}
}
-void Sound::playSample(QueueElement *elem) {
- uint8 *sampleData = (uint8 *)_resMan->fetchRes(getSampleId(elem->id));
- for (uint16 cnt = 0; cnt < MAX_ROOMS_PER_FX; cnt++) {
- if (_fxList[elem->id].roomVolList[cnt].roomNo) {
- if ((_fxList[elem->id].roomVolList[cnt].roomNo == (int)Logic::_scriptVars[SCREEN]) ||
- (_fxList[elem->id].roomVolList[cnt].roomNo == -1)) {
-
- uint8 volL = (_fxList[elem->id].roomVolList[cnt].leftVol * 10 * _sfxVolL) / 255;
- uint8 volR = (_fxList[elem->id].roomVolList[cnt].rightVol * 10 * _sfxVolR) / 255;
- int8 pan = (volR - volL) / 2;
- uint8 volume = (volR + volL) / 2;
-
- if (SwordEngine::isPsx()) {
- uint32 size = READ_LE_UINT32(sampleData);
- Audio::AudioStream *audStream = Audio::makeLoopingAudioStream(Audio::makeXAStream(new Common::MemoryReadStream(sampleData + 4, size - 4), 11025), (_fxList[elem->id].type == FX_LOOP) ? 0 : 1);
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &elem->handle, audStream, elem->id, volume, pan);
- } else {
- uint32 size = READ_LE_UINT32(sampleData + 0x28);
- uint8 flags;
- if (READ_LE_UINT16(sampleData + 0x22) == 16)
- flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
- else
- flags = Audio::FLAG_UNSIGNED;
- if (READ_LE_UINT16(sampleData + 0x16) == 2)
- flags |= Audio::FLAG_STEREO;
- Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
- Audio::makeRawStream(sampleData + 0x2C, size, 11025, flags, DisposeAfterUse::NO),
- (_fxList[elem->id].type == FX_LOOP) ? 0 : 1);
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &elem->handle, stream, elem->id, volume, pan);
- }
- }
- } else
- break;
- }
-}
-
bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
if (_cowHeader == NULL) {
warning("Sound::startSpeech: COW file isn't open");
@@ -768,60 +738,65 @@ void Sound::closeCowSystem() {
// playing yet. It returns 1 if finished, 0 if still playing
//
int32 Sound::CheckSampleStatus(int32 id) {
- uint32 i = 0;
Common::StackLock lock(_soundMutex);
- while (i < MAX_FX) {
+
+ for (int i = 0; i < MAX_FX; i++) {
if (fxSampleID[i] == id) {
- //if ((AIL_sample_status(hSampleFX[i]) == SMP_DONE) && (fxSampleBusy[i]) && (!fxPaused[i])) {
- fxSampleBusy[i] = 0;
- return (1);
- //} else {
- // return (0);
- //}
+ if (!_mixer->isSoundHandleActive(hSampleFX[i]) && (fxSampleBusy[i]) && (!fxPaused[i])) {
+ fxSampleBusy[i] = false;
+ return S_STATUS_FINISHED;
+ } else {
+ return S_STATUS_RUNNING;
+ }
}
- i += 1;
}
- return (0);
+ return S_STATUS_RUNNING;
}
int32 Sound::CheckSpeechStatus() {
+ Common::StackLock lock(_soundMutex);
+
if (!speechSampleBusy || speechSamplePaused)
- return (1);
+ return S_STATUS_FINISHED;
- //if (AIL_sample_status(hSampleSpeech) == SMP_DONE) {
+ if (!_mixer->isSoundHandleActive(hSampleSpeech)) {
speechSampleBusy = 0;
RestoreMusicVolume();
- return (1);
- //}
- //return (0);
+ return S_STATUS_FINISHED;
+ }
+
+ return S_STATUS_RUNNING;
}
int32 Sound::PlaySpeech(void *wavData, int32 size) {
+ Common::StackLock lock(_soundMutex);
+
speechSize = size;
speechCount = 0;
- // Check to see if the handle is free, else free it
+ // Check to see if the handle is free, else free it
if (speechSampleBusy)
StopSpeech();
- // Reset the sample parameters
+ // Reset the sample parameters
//AIL_init_sample(hSampleSpeech);
- speechSampleBusy = 1;
+ speechSampleBusy = true;
- // And point the sample to our new wav data
+ // And point the sample to our new wav data
if (true/* AIL_set_sample_file(hSampleSpeech, wavData, -1) == 0*/) {
- speechSampleBusy = 0;
- return (0);
+ speechSampleBusy = false;
+ return 0;
} else {
// We have found a free handle, and the wav file header
// has been successfully parsed.
//
// Modify the volume according to the master volume
- //AIL_set_sample_volume(hSampleSpeech, 4 * (volSpeech[0] + volSpeech[1]));
+ _mixer->setChannelVolume(hSampleSpeech, 2 * (4 * (volSpeech[0] + volSpeech[1])));
// Now set the pan position for the sample
- //AIL_set_sample_pan(hSampleSpeech, 64 + (4 * (volSpeech[1] - volSpeech[0])));
+ int pan = 64 + (4 * ((int32)volSpeech[1] - (int32)volSpeech[0]));
+ _mixer->setChannelBalance(hSampleSpeech, scalePan(pan));
// Start the sample
//AIL_start_sample(hSampleSpeech);
@@ -829,66 +804,31 @@ int32 Sound::PlaySpeech(void *wavData, int32 size) {
ReduceMusicVolume();
// and exit the function.
- return (1);
+ return 1;
}
}
int32 Sound::StopSpeech() {
- if (true/* AIL_sample_status(hSampleSpeech) != SMP_DONE*/) {
- //AIL_end_sample(hSampleSpeech);
- speechSampleBusy = 0;
+ Common::StackLock lock(_soundMutex);
+
+ if (_mixer->isSoundHandleActive(hSampleSpeech)) {
+ _mixer->stopHandle(hSampleSpeech);
+ speechSampleBusy = false;
RestoreMusicVolume();
- return (1);
+ return 1;
}
- return (0);
+
+ return 0;
}
static void soundCallback(void *refCon) {
Sound *snd = (Sound *)refCon;
Common::StackLock lock(snd->_soundMutex);
- if (snd->volumeFadingFlag) {
- snd->volumeCount += 1;
- if (snd->volumeCount > 128 / snd->volumeFadingRate) {
- snd->volumeFadingFlag = 0;
- } else {
- if (snd->volumeFadingFlag == 1) {
- //Fade the volume up
- snd->fadeVolume[0] = snd->masterVolume[0] * snd->volumeCount * snd->volumeFadingRate / 128;
- snd->fadeVolume[1] = snd->masterVolume[1] * snd->volumeCount * snd->volumeFadingRate / 128;
- } else {
- //Fade the volume down
- snd->fadeVolume[0] = snd->masterVolume[0] - (snd->masterVolume[0] * snd->volumeCount * snd->volumeFadingRate / 128);
- snd->fadeVolume[1] = snd->masterVolume[1] - (snd->masterVolume[1] * snd->volumeFadingRate * snd->volumeCount / 128);
- }
-
- //AIL_set_digital_master_volume(hDigiDriver, (snd->fadeVolume[0] + snd->fadeVolume[1]) / 2);
- }
- }
-
- if (snd->musicFadingFlag) {
- snd->musicCount += 1;
- if (snd->musicCount > 128 / snd->musicFadingRate) {
- snd->musicFadingFlag = 0;
- } else {
- if (snd->musicFadingFlag == 1) {
- //Fade the volume up
- snd->musicFadeVolume[0] = 8 * snd->volMusic[0] * snd->musicCount * snd->musicFadingRate / 128;
- snd->musicFadeVolume[1] = 8 * snd->volMusic[1] * snd->musicCount * snd->musicFadingRate / 128;
- } else {
- //Fade the volume down
- snd->musicFadeVolume[0] = 8 * snd->volMusic[0] - (8 * snd->volMusic[0] * snd->musicCount * snd->musicFadingRate / 128);
- snd->musicFadeVolume[1] = 8 * snd->volMusic[1] - (8 * snd->volMusic[1] * snd->musicFadingRate * snd->musicCount / 128);
- }
-
- for (int i = 0; i < MAX_MUSIC; i++) {
- if (snd->streamSamplePlaying[i])
- ;
- //AIL_set_sample_volume(snd->hStreamSample[i], (snd->musicFadeVolume[0] + snd->musicFadeVolume[1]) / 2);
- }
-
- }
- }
+ // Originally the code here had handling of fading flags for
+ // the master volume and the music volume (the latter only
+ // for fade-ups). They are omitted here as they are not used
+ // anywhere...
if (snd->fxFadingFlag) {
snd->fxCount += 1;
@@ -896,18 +836,21 @@ static void soundCallback(void *refCon) {
snd->fxFadingFlag = 0;
} else {
if (snd->fxFadingFlag == 1) {
- //Fade the volume up
+ // Fade the volume up...
snd->fxFadeVolume[0] = 8 * snd->volFX[0] * snd->fxCount * snd->fxFadingRate / 128;
snd->fxFadeVolume[1] = 8 * snd->volFX[1] * snd->fxCount * snd->fxFadingRate / 128;
} else {
- //Fade the volume down
+ // Fade the volume down...
snd->fxFadeVolume[0] = 8 * snd->volFX[0] - (8 * snd->volFX[0] * snd->fxCount * snd->fxFadingRate / 128);
snd->fxFadeVolume[1] = 8 * snd->volFX[1] - (8 * snd->volFX[1] * snd->fxFadingRate * snd->fxCount / 128);
}
for (int i = 0; i < MAX_FX; i++) {
- if (snd->fxSampleBusy[i])
- ;
- //AIL_set_sample_volume(hSampleFX[i], (fxFadeVolume[0] + fxFadeVolume[1]) / 2);
+ if (snd->fxSampleBusy[i]) {
+ int32 targetVolume = (snd->fxFadeVolume[0] + snd->fxFadeVolume[1]) / 2;
+
+ // Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
+ snd->_mixer->setChannelVolume(snd->hSampleFX[i], targetVolume * 2);
+ }
}
}
}
@@ -989,74 +932,89 @@ void Sound::UpdateSampleStreaming() {
}
}
-int32 Sound::PlayFX(int32 fxID, int32 type, void *wavData, uint32 vol[2]) {
- int32 i = 0;
- int32 v0, v1;
+int32 Sound::PlayFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]) {
Common::StackLock lock(_soundMutex);
+
+ int32 v0, v1;
// Search through the fx sample handles for a free slot
- while (i < MAX_FX) {
+ for (int i = 0; i < MAX_FX; i++) {
// Check to see if the handle is free
- if (fxSampleBusy[i] == 0) {
- // Reset the sample parameters
- //AIL_init_sample(hSampleFX[i]);
- fxSampleBusy[i] = 1;
+ if (!fxSampleBusy[i]) {
+ // Reset the sample parameters
+ fxSampleBusy[i] = true;
fxSampleID[i] = fxID;
- //if (type == FX_LOOP)
- // AIL_set_sample_loop_count(hSampleFX[i], 0);
+ Audio::AudioStream *stream = nullptr;
- // And point the sample to our new wav data
- if (true /* AIL_set_sample_file(hSampleFX[i], wavData, -1) == 0*/) {
- return (0);
+ if (SwordEngine::isPsx()) {
+ uint32 size = READ_LE_UINT32(wavData);
+ stream = Audio::makeLoopingAudioStream(
+ Audio::makeXAStream(new Common::MemoryReadStream(wavData + 4, size - 4), 11025),
+ (type == FX_LOOP) ? 0 : 1);
} else {
- // We have found a free handle, and the wav file header
- // has been successfully parsed.
+ uint32 size = READ_LE_UINT32(wavData + 0x28);
+ uint8 flags;
+ if (READ_LE_UINT16(wavData + 0x22) == 16)
+ flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
+ else
+ flags = Audio::FLAG_UNSIGNED;
+ if (READ_LE_UINT16(wavData + 0x16) == 2)
+ flags |= Audio::FLAG_STEREO;
+ stream = Audio::makeLoopingAudioStream(
+ Audio::makeRawStream(wavData + 0x2C, size, 11025, flags, DisposeAfterUse::NO),
+ (type == FX_LOOP) ? 0 : 1);
+ }
+
+ // And point the sample to our new wav data
+ if (!stream) {
+ return 0;
+ } else {
+ // We have found a free handle, and the wav file header
+ // has been successfully parsed.
//
- // Modify the volume according to the master volume
+ // Modify the volume according to the master volume
v0 = volFX[0] * vol[0];
v1 = volFX[1] * vol[1];
- //AIL_set_sample_volume(hSampleFX[i], (v0 + v1) / 8);
-
- // Now set the pan position for the sample
- //AIL_set_sample_pan(hSampleFX[i], 64 + ((v1 - v0) / 4));
-
- // Start the sample
- //AIL_start_sample(hSampleFX[i]);
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &hSampleFX[i], stream, -1, 0);
+ _mixer->setChannelVolume(hSampleFX[i], 2 * ((v0 + v1) / 8));
+ _mixer->setChannelBalance(hSampleFX[i], scalePan(64 + ((v1 - v0) / 4)));
- // and exit the function.
- return (1);
+ return 1;
}
}
- i += 1;
-
- } // while
+ }
- return (0);
+ return 0;
}
int32 Sound::StopFX(int32 fxID) {
Common::StackLock lock(_soundMutex);
- for (uint32 i = 0; i < MAX_FX; i++) {
+ for (int i = 0; i < MAX_FX; i++) {
if (fxSampleID[i] == fxID) {
- //if (AIL_sample_status(hSampleFX[i]) != SMP_DONE) {
- // AIL_end_sample(hSampleFX[i]);
- fxSampleBusy[i] = 0;
- return (1);
- //}
+ if (_mixer->isSoundHandleActive(hSampleFX[i])) {
+ _mixer->stopHandle(hSampleFX[i]);
+ fxSampleBusy[i] = false;
+ return 1;
+ }
}
}
- return (0);
+
+ return 0;
}
void Sound::clearAllFx() {
- for (int j = _endOfQueue - 1; j >= 0; j--) { // remove them from the end
- if (CheckSampleStatus(_fxQueue[j].id) == 0) // delay countdown was already zero, so the sample has already been played, so check if it's finished
+ // Remove them starting from the end...
+ for (int j = _endOfQueue - 1; j >= 0; j--) {
+ // Check if the sample has finished playing and
+ // if not, stop it manually...
+ if (CheckSampleStatus(_fxQueue[j].id) == S_STATUS_RUNNING)
StopFX(_fxQueue[j].id);
+
removeFromQueue(_fxQueue[j].id);
}
- _endOfQueue = 0; // just to be sure, like
+ _endOfQueue = 0;
}
void Sound::FadeVolumeDown(int32 rate) {
@@ -1100,30 +1058,25 @@ void Sound::FadeFxUp(int32 rate) {
}
int32 Sound::GetSpeechSize(void *compData) {
- typedef struct wavHeader {
- char riff[4];
- int fileLength;
- char wavID[4];
- char format[4];
- int formatLen;
- short int formatTag;
- short int channels;
- short int samplesPerSec;
- short int avgBytesPerSec;
- short int blockAlign;
- short int formatSpecific;
- short int unused[8];
- } wavHeader;
-
- wavHeader *head;
-
- head = (wavHeader *)compData;
-
- //Pdebug("Getting speech size : %d", head->fileLength + 8);
- //Pdebug("riff %c%c%c%c", head->riff[0], head->riff[1], head->riff[2], head->riff[3]);
- //Pdebug("file length %d\n", head->fileLength);
-
- return (head->fileLength + 8);
+ struct WaveHeader {
+ uint32 riffTag;
+ uint32 riffSize;
+ uint32 waveTag;
+ uint32 fmtTag;
+ uint32 fmtSize;
+
+ // Format subchunk
+ uint16 wFormatTag;
+ uint16 wChannels;
+ uint32 dwSamplesPerSec;
+ uint32 dwAvgBytesPerSec;
+ uint16 wBlockAlign;
+ uint16 wBitsPerSample;
+ };
+
+ WaveHeader *waveHeader = (WaveHeader *)compData;
+
+ return (waveHeader->riffSize + 8);
}
void Sound::ReduceMusicVolume() {
@@ -1131,12 +1084,15 @@ void Sound::ReduceMusicVolume() {
musicFadeVolume[0] = volMusic[0] * MUSIC_UNDERSCORE / 100;
musicFadeVolume[1] = volMusic[0] * MUSIC_UNDERSCORE / 100;
- //AIL_set_sample_volume(hStreamSample[0], (musicFadeVolume[0] + musicFadeVolume[1]) * 3);
+ // Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
+ _mixer->setChannelVolume(hStreamSample[0], 2 * ((musicFadeVolume[0] + musicFadeVolume[1]) * 3));
}
void Sound::RestoreMusicVolume() {
Common::StackLock lock(_soundMutex);
- //AIL_set_sample_volume(hStreamSample[0], (volMusic[0] + volMusic[1]) * 3);
+
+ // Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
+ _mixer->setChannelVolume(hStreamSample[0], 2 * ((volMusic[0] + volMusic[1]) * 3));
}
void Sound::SetCrossFadeIncrement() {
@@ -1146,32 +1102,32 @@ void Sound::SetCrossFadeIncrement() {
void Sound::PauseSpeech() {
if ((speechSampleBusy) && (!speechSamplePaused)) {
speechSamplePaused = true;
- //AIL_stop_sample(hSampleSpeech);
+ _mixer->pauseHandle(hSampleSpeech, true);
}
}
void Sound::UnpauseSpeech() {
if ((speechSampleBusy) && (speechSamplePaused)) {
speechSamplePaused = false;
- //AIL_resume_sample(hSampleSpeech);
+ _mixer->pauseHandle(hSampleSpeech, false);
}
}
void Sound::PauseMusic() {
Common::StackLock lock(_soundMutex);
- for (int32 i = 0; i < MAX_MUSIC; i++) {
+ for (int i = 0; i < MAX_MUSIC; i++) {
if (streamSamplePlaying[i]) {
musicPaused[i] = true;
- //AIL_stop_sample(hStreamSample[i]);
+ _mixer->pauseHandle(hSampleMusic[i], true);
}
}
}
void Sound::UnpauseMusic() {
Common::StackLock lock(_soundMutex);
- for (int32 i = 0; i < MAX_MUSIC; i++) {
+ for (int i = 0; i < MAX_MUSIC; i++) {
if (musicPaused[i]) {
- //AIL_resume_sample(hStreamSample[i]);
+ _mixer->pauseHandle(hSampleMusic[i], false);
musicPaused[i] = false;
}
}
@@ -1179,9 +1135,9 @@ void Sound::UnpauseMusic() {
void Sound::PauseFx() {
Common::StackLock lock(_soundMutex);
- for (uint32 i = 0; i < MAX_FX; i++) {
+ for (int i = 0; i < MAX_FX; i++) {
if (fxSampleBusy[i]) {
- //AIL_stop_sample(hSampleFX[i]);
+ _mixer->pauseHandle(hSampleFX[i], true);
fxPaused[i] = true;
}
}
@@ -1189,12 +1145,16 @@ void Sound::PauseFx() {
void Sound::UnpauseFx() {
Common::StackLock lock(_soundMutex);
- for (uint32 i = 0; i < MAX_FX; i++) {
+ for (int i = 0; i < MAX_FX; i++) {
if (fxPaused[i]) {
- //AIL_resume_sample(hSampleFX[i]);
+ _mixer->pauseHandle(hSampleFX[i], false);
fxPaused[i] = false;
}
}
}
+int8 Sound::scalePan(int pan) {
+ return (pan != 64) ? (int8)(2 * pan - 127) : 0;
+}
+
} // End of namespace Sword1
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index aedd491082c..27f62f65b66 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -78,6 +78,8 @@ class SwordEngine;
#define POS_MOUTH_THRESHOLD 750
#define MAX_FX 4
#define MAX_MUSIC 2
+#define S_STATUS_FINISHED 1
+#define S_STATUS_RUNNING 0
enum CowMode {
CowWave = 0,
@@ -95,9 +97,7 @@ public:
Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan);
~Sound();
void setSpeechVol(uint8 volL, uint8 volR) { _speechVolL = volL; _speechVolR = volR; }
- void setSfxVol(uint8 volL, uint8 volR) { _sfxVolL = volL; _sfxVolR = volR; }
void giveSpeechVol(uint8 *volL, uint8 *volR) { *volL = _speechVolL; *volR = _speechVolR; }
- void giveSfxVol(uint8 *volL, uint8 *volR) { *volL = _sfxVolL; *volR = _sfxVolR; }
void newScreen(uint32 screen);
void clearAllFx();
void closeCowSystem();
@@ -117,10 +117,10 @@ public:
double endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &maxSamples);
Common::Mutex _soundMutex;
+ Audio::Mixer *_mixer;
private:
- uint8 _sfxVolL, _sfxVolR, _speechVolL, _speechVolR;
- void playSample(QueueElement *elem);
+ uint8 _speechVolL, _speechVolR;
void initCowSystem();
uint32 getSampleId(int32 fxNo);
@@ -138,7 +138,6 @@ private:
QueueElement _fxQueue[MAX_FXQ_LENGTH];
uint8 _endOfQueue;
- Audio::Mixer *_mixer;
SwordEngine *_vm;
ResMan *_resMan;
@@ -156,7 +155,7 @@ public:
int32 StreamSample(char filename[], int32 looped);
void UpdateSampleStreaming();
- int32 PlayFX(int32 fxID, int32 type, void *wavData, uint32 vol[2]);
+ int32 PlayFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]);
int32 StopFX(int32 fxID);
int32 CheckSampleStatus(int32 id);
int32 CheckSpeechStatus();
@@ -177,14 +176,17 @@ public:
void PauseFx();
void UnpauseFx();
+ int8 scalePan(int pan); // From 0,127 to -127,127
+
void ReduceMusicVolume();
void RestoreMusicVolume();
+ // Handles for external volume changes (control panel)
uint32 volFX[2] = { 0, 0 };
uint32 volSpeech[2] = { 0, 0 };
uint32 volMusic[2] = { 0, 0 };
- // Volume variables
+ // Volume variables
int32 volumeFadingFlag = 0;
int32 volumeFadingRate = 0;
int32 musicFadingFlag = 0;
@@ -201,8 +203,7 @@ public:
int32 speechCount = 0;
int32 speechSize = 0;
-// Sample handles and information.
-
+ // Sample handles and information.
Audio::SoundHandle hSampleFX[MAX_FX];
Audio::SoundHandle hSampleSpeech;
Audio::SoundHandle hSampleMusic[MAX_MUSIC];
@@ -212,9 +213,9 @@ public:
Audio::SoundHandle hStreamSample[MAX_MUSIC];
int32 streamFile[MAX_MUSIC];
byte *streamBuffer[MAX_MUSIC][2];
- int32 fxSampleBusy[MAX_FX] = { 0, 0, 0, 0 };
+ bool fxSampleBusy[MAX_FX] = { false, false, false, false };
int32 fxSampleID[MAX_FX] = { 0, 0, 0, 0 };
- int32 speechSampleBusy;
+ bool speechSampleBusy = false;
uint32 musicSamples = 0;
bool crossFadeIncrement = false;
bool speechSamplePaused = false;
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 9826d3b5fdc..d77263c3b4f 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -100,7 +100,7 @@ Common::Error SwordEngine::init() {
debug(5, "Starting object manager");
_objectMan = new ObjectMan(_resMan);
_mouse = new Mouse(_system, _resMan, _objectMan);
- _screen = new Screen(_system, _resMan, _objectMan);
+ _screen = new Screen(_system, this, _resMan, _objectMan);
_music = new Music(_mixer);
_sound = new Sound(_mixer, this, _resMan);
_menu = new Menu(_screen, _mouse);
@@ -246,11 +246,9 @@ void SwordEngine::syncSoundSettings() {
if (mute) {
_music->setVolume(0, 0);
_sound->setSpeechVol(0, 0);
- _sound->setSfxVol(0, 0);
} else {
_music->setVolume(musicVolL, musicVolR);
_sound->setSpeechVol(speechVolL, speechVolR);
- _sound->setSfxVol(sfxVolL, sfxVolR);
}
}
@@ -972,7 +970,7 @@ void SwordEngine::askForCd() {
pollInput(0);
}
- _screen->startFadePaletteDown(1);
+ startFadePaletteDown(1);
startTime = _system->getMillis();
while (_screen->stillFading()) {
@@ -1092,7 +1090,7 @@ uint8 SwordEngine::mainLoop() {
(!shouldQuit()));
if ((Logic::_scriptVars[SCREEN] != 53) && !shouldQuit()) {
- _screen->startFadePaletteDown(1);
+ startFadePaletteDown(1);
}
_screen->quitScreen(); // Close graphic resources
@@ -1197,13 +1195,11 @@ void SwordEngine::fadePaletteStep() {
void SwordEngine::startFadePaletteDown(int speed) {
_screen->startFadePaletteDown(speed);
-
_sound->FadeFxDown(speed);
}
void SwordEngine::startFadePaletteUp(int speed) {
_screen->startFadePaletteUp(speed);
-
_sound->FadeFxUp(speed);
}
Commit: 4c0d127a62922b3ac2ca875d8dc1976a4cb1c31a
https://github.com/scummvm/scummvm/commit/4c0d127a62922b3ac2ca875d8dc1976a4cb1c31a
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Reimplement speech
Compressed speech files should work right out of
the box.
Changed paths:
engines/sword1/control.cpp
engines/sword1/logic.cpp
engines/sword1/logic.h
engines/sword1/sound.cpp
engines/sword1/sound.h
engines/sword1/sword1.cpp
engines/sword1/sword1.h
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index cab4aa0ec5d..73f1d52dee6 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -1041,7 +1041,7 @@ void Control::setVolumes() {
if (volBalance != ConfMan.getInt("music_balance"))
ConfMan.setInt("music_balance", volBalance);
- _sound->giveSpeechVol(&volL, &volR);
+ //_sound->giveSpeechVol(&volL, &volR);
vol = (int)((volR + volL) / 2);
volBalance = volToBalance(volL, volR);
if (vol != ConfMan.getInt("speech_volume"))
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 52c43fbf6fb..8bf1d1c0394 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -91,8 +91,10 @@ void Logic::initialize() {
_textMan = new Text(_vm, this, _objMan, _resMan, _screen,
(SwordEngine::_systemVars.language == BS1_CZECH) ? true : false);
_screen->useTextManager(_textMan);
- _textRunning = _speechRunning = false;
- _speechFinished = true;
+
+ SwordEngine::_systemVars.textRunning = false;
+ SwordEngine::_systemVars.speechRunning = 0;
+ SwordEngine::_systemVars.speechFinished = true;
}
void Logic::newScreen(uint32 screen) {
@@ -345,31 +347,41 @@ int Logic::logicArAnimate(Object *compact, uint32 id) {
int Logic::speechDriver(Object *compact) {
if ((!_speechClickDelay) &&
((_mouse->testEvent() & BS1L_BUTTON_DOWN) || (_mouse->testEvent() & BS1R_BUTTON_DOWN)))
- _speechFinished = true;
+ SwordEngine::_systemVars.speechFinished = true;
if (_speechClickDelay)
_speechClickDelay--;
- if (_speechRunning) {
- if (_sound->speechFinished())
- _speechFinished = true;
+ if (SwordEngine::_systemVars.speechRunning >= 2) {
+ SwordEngine::_systemVars.speechRunning--;
+ if (SwordEngine::_systemVars.speechRunning == 1)
+ _sound->PlaySpeech();
+ } else if (SwordEngine::_systemVars.speechRunning == 1) {
+ if (_sound->CheckSpeechStatus() == S_STATUS_FINISHED)
+ SwordEngine::_systemVars.speechFinished = true;
+
+ if (SwordEngine::_systemVars.speechFinished) {
+ _sound->StopSpeech();
+ free(_sound->speechSample);
+ _sound->speechSample = nullptr;
+ }
} else {
if (!compact->o_speech_time)
- _speechFinished = true;
+ SwordEngine::_systemVars.speechFinished = true;
else
compact->o_speech_time--;
}
- if (_speechFinished) {
- if (_speechRunning)
- _sound->stopSpeech();
+ if (SwordEngine::_systemVars.speechFinished) {
compact->o_logic = LOGIC_script;
- if (_textRunning) {
+ if (SwordEngine::_systemVars.textRunning) {
_textMan->releaseText(compact->o_text_id);
_objMan->fetchObject(compact->o_text_id)->o_status = 0; // kill compact linking text sprite
}
- _speechRunning = _textRunning = false;
- _speechFinished = true;
+
+ SwordEngine::_systemVars.speechRunning = 0;
+ SwordEngine::_systemVars.textRunning = false;
+ SwordEngine::_systemVars.speechFinished = true;
}
if (compact->o_anim_resource) {
@@ -378,8 +390,8 @@ int Logic::speechDriver(Object *compact) {
animData += 4;
compact->o_anim_pc++; // go to next frame of anim
- if (_speechFinished || (compact->o_anim_pc >= numFrames) ||
- (_speechRunning && (_sound->amISpeaking(nullptr) == 0)))
+ if (SwordEngine::_systemVars.speechFinished || (compact->o_anim_pc >= numFrames) ||
+ (SwordEngine::_systemVars.speechRunning != 0 && (_sound->amISpeaking() == 0)))
compact->o_anim_pc = 0; //set to frame 0, closed mouth
AnimUnit *animPtr = (AnimUnit *)(animData + sizeof(AnimUnit) * compact->o_anim_pc);
@@ -1180,13 +1192,14 @@ int Logic::fnISpeak(Object *cpt, int32 id, int32 cdt, int32 textNo, int32 spr, i
_resMan->resClose(cpt->o_resource);
}
+
+ SwordEngine::_systemVars.speechRunning = 0;
if (SwordEngine::_systemVars.playSpeech)
- _speechRunning = _sound->startSpeech(textNo >> 16, textNo & 0xFFFF);
- else
- _speechRunning = false;
- _speechFinished = false;
- if (SwordEngine::_systemVars.showText || (!_speechRunning)) {
- _textRunning = true;
+ _sound->startSpeech(textNo >> 16, textNo & 0xFFFF); // This will set speechRunning
+
+ SwordEngine::_systemVars.speechFinished = false;
+ if (SwordEngine::_systemVars.showText || (SwordEngine::_systemVars.speechRunning == 0)) {
+ SwordEngine::_systemVars.textRunning = true;
char *text = _objMan->lockText(textNo);
cpt->o_speech_time = strlen(text) + 5;
@@ -1234,6 +1247,16 @@ int Logic::fnISpeak(Object *cpt, int32 id, int32 cdt, int32 textNo, int32 spr, i
textCpt->o_anim_x = textCpt->o_xcoord = CLIP<uint16>(textX, textLeftMargin, textRightMargin);
textCpt->o_anim_y = textCpt->o_ycoord = CLIP<uint16>(textY, textTopMargin, textBottomMargin);
}
+
+ if (SwordEngine::_systemVars.speechRunning != 0) {
+ // This helps delaying the speech to make it play in sync with the text
+ if (SwordEngine::_systemVars.realLanguage == Common::EN_ANY) {
+ SwordEngine::_systemVars.speechRunning = 2; // Verified from disasm
+ } else {
+ SwordEngine::_systemVars.speechRunning = 3; // International versions
+ }
+ }
+
return SCRIPT_STOP;
}
@@ -1844,7 +1867,7 @@ void Logic::startPositions(uint32 pos) {
}
bool Logic::canShowDebugTextNumber() {
- return _speechRunning || _textRunning;
+ return SwordEngine::_systemVars.speechRunning || SwordEngine::_systemVars.textRunning;
}
void Logic::plotRouteGrid(Object *megaObject) {
diff --git a/engines/sword1/logic.h b/engines/sword1/logic.h
index 523fc13c7a3..d38a46c9811 100644
--- a/engines/sword1/logic.h
+++ b/engines/sword1/logic.h
@@ -84,7 +84,6 @@ private:
Menu *_menu;
Music *_music;
uint32 _newScript; // <= ugly, but I can't avoid it.
- bool _speechRunning, _speechFinished, _textRunning;
uint8 _speechClickDelay;
Common::RandomSource _rnd;
bool _psxFudgeRandom = false; // Used within fnIdle() and fnRandom() for the PSX version
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 644e9668cc9..f4c691180e7 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -52,7 +52,7 @@ Sound::Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan)
_cowHeader = NULL;
_endOfQueue = 0;
_currentCowFile = 0;
- _speechVolL = _speechVolR = 192;
+
//if (!GetVolumes()) {
volFX[0] = 8;
volFX[1] = 8;
@@ -135,15 +135,28 @@ void Sound::checkSpeechFileEndianness() {
uint32 size;
bool leOk = false, beOk = false;
// Compute average of difference between two consecutive samples for both BE and LE
+
_bigEndianSpeech = false;
- int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size, &leOk);
+ byte *compSample = (byte *)malloc(sampleSize);
+ _cowFile.seek(index + _cowHeaderSize, SEEK_SET);
+ _cowFile.read(compSample, sampleSize);
+ byte *data = (byte *)malloc(GetSpeechSize(compSample, sampleSize));
+ bool success = expandSpeech(compSample, data, sampleSize, &leOk, &size);
uint32 maxSamples = size > 2000 ? 2000 : size;
- double le_diff = endiannessHeuristicValue(data, size, maxSamples);
+ double le_diff = endiannessHeuristicValue((int16 *)data, size, maxSamples);
free(data);
+ data = nullptr;
+
_bigEndianSpeech = true;
- data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size, &beOk);
- double be_diff = endiannessHeuristicValue(data, size, maxSamples);
+ _cowFile.seek(index + _cowHeaderSize, SEEK_SET);
+ _cowFile.read(compSample, sampleSize);
+ data = (byte *)malloc(GetSpeechSize(compSample, sampleSize));
+ success = expandSpeech(compSample, data, sampleSize, &beOk, &size);
+ double be_diff = endiannessHeuristicValue((int16 *)data, size, maxSamples);
free(data);
+
+ free(compSample);
+
// Set the big endian flag
if (leOk && !beOk)
_bigEndianSpeech = false;
@@ -151,10 +164,12 @@ void Sound::checkSpeechFileEndianness() {
_bigEndianSpeech = true;
else
_bigEndianSpeech = (be_diff < le_diff);
+
if (_bigEndianSpeech)
debug(6, "Mac version: using big endian speech file");
else
debug(6, "Mac version: using little endian speech file");
+
debug(8, "Speech decompression memory check: big endian = %s, little endian = %s", beOk ? "good" : "bad", leOk ? "good" : "bad");
debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE (%d samples)", be_diff, le_diff, maxSamples);
}
@@ -278,21 +293,7 @@ void Sound::engine() {
}
}
-void Sound::fnStopFx(int32 fxNo) {
- _mixer->stopID(fxNo);
- for (uint8 cnt = 0; cnt < _endOfQueue; cnt++)
- if (_fxQueue[cnt].id == (uint32)fxNo) {
- if (!_fxQueue[cnt].delay) // sound was started
- _resMan->resClose(getSampleId(_fxQueue[cnt].id));
- if (cnt != _endOfQueue - 1)
- _fxQueue[cnt] = _fxQueue[_endOfQueue - 1];
- _endOfQueue--;
- return;
- }
- debug(8, "fnStopFx: id not found in queue");
-}
-
-bool Sound::amISpeaking(byte *buf) {
+bool Sound::amISpeaking() {
int16 *offset;
int16 count;
int32 readPos;
@@ -309,7 +310,7 @@ bool Sound::amISpeaking(byte *buf) {
if (readPos + 150 * sizeof(int16) > speechSize)
return false;
- offset = (int16 *)&buf[readPos];
+ offset = (int16 *)&speechSample[readPos];
count = 0;
for (int i = 0; i < 150; i++) {
if ((offset[i] < NEG_MOUTH_THRESHOLD) || (offset[i] > POS_MOUTH_THRESHOLD)) {
@@ -324,10 +325,6 @@ bool Sound::amISpeaking(byte *buf) {
return false;
}
-bool Sound::speechFinished() {
- return !_mixer->isSoundHandleActive(_speechHandle);
-}
-
void Sound::newScreen(uint32 screen) {
if (_currentCowFile != SwordEngine::_systemVars.currentCD) {
if (_cowFile.isOpen())
@@ -346,14 +343,14 @@ void Sound::newScreen(uint32 screen) {
}
}
-bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
+void Sound::startSpeech(uint16 roomNo, uint16 localNo) {
if (_cowHeader == NULL) {
warning("Sound::startSpeech: COW file isn't open");
- return false;
+ return;
}
uint32 locIndex = 0xFFFFFFFF;
- uint32 sampleSize = 0;
+ uint32 sampleFileSize = 0;
uint32 index = 0;
if (_cowMode == CowPSX) {
@@ -362,7 +359,7 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
if (!file.open("speech.lis")) {
warning("Could not open speech.lis");
- return false;
+ return;
}
for (i = 0; !file.eos() && !file.err(); i++)
@@ -374,12 +371,12 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
if (locIndex == 0xFFFFFFFF) {
warning("Could not find room %d in speech.lis", roomNo);
- return false;
+ return;
}
if (!file.open("speech.inf")) {
warning("Could not open speech.inf");
- return false;
+ return;
}
uint16 numRooms = file.readUint16LE(); // Read number of rooms referenced in this file
@@ -401,109 +398,88 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
if (locIndex == 0xFFFFFFFF) {
warning("Could not find local number %d in room %d in speech.inf", roomNo, localNo);
- return false;
+ return;
}
file.close();
index = _cowHeader[(roomOffset + locIndex) * 2];
- sampleSize = _cowHeader[(roomOffset + locIndex) * 2 + 1];
+ sampleFileSize = _cowHeader[(roomOffset + locIndex) * 2 + 1];
} else {
locIndex = _cowHeader[roomNo] >> 2;
- sampleSize = _cowHeader[locIndex + (localNo * 2)];
+ sampleFileSize = _cowHeader[locIndex + (localNo * 2)];
index = _cowHeader[locIndex + (localNo * 2) - 1];
}
- debug(6, "startSpeech(%d, %d): locIndex %d, sampleSize %d, index %d", roomNo, localNo, locIndex, sampleSize, index);
-
- Audio::AudioStream *stream = 0;
+ debug(6, "Sound::startSpeech(%d, %d): locIndex %d, sampleFileSize %d, index %d", roomNo, localNo, locIndex, sampleFileSize, index);
+
+ if (sampleFileSize) {
+ byte *compSample = (byte *)malloc(sampleFileSize);
+ if (compSample) {
+ if ((_cowMode == CowWave) || (_cowMode == CowDemo)) {
+ _cowFile.seek(index + _cowHeaderSize, SEEK_SET);
+ } else if (_cowMode == CowPSX && sampleFileSize != 0xffffffff) {
+ _cowFile.seek(index * 2048);
+ } else if (_cowMode == CowFLAC || _cowMode == CowVorbis || _cowMode == CowMP3) {
+ _cowFile.seek(index);
+ }
- if (sampleSize) {
- uint8 speechVol = (_speechVolR + _speechVolL) / 2;
- int8 speechPan = (_speechVolR - _speechVolL) / 2;
- if ((_cowMode == CowWave) || (_cowMode == CowDemo)) {
- uint32 size;
- int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
- if (data) {
- stream = Audio::makeRawStream((byte *)data, size, 11025, SPEECH_FLAGS);
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
+ _cowFile.read(compSample, sampleFileSize);
+ speechSize = GetSpeechSize(compSample, sampleFileSize);
+ speechSample = (byte *)malloc(speechSize);
+ if (speechSample) {
+ SwordEngine::_systemVars.speechRunning = expandSpeech(compSample, speechSample, sampleFileSize);
+ free(compSample);
}
- } else if (_cowMode == CowPSX && sampleSize != 0xffffffff) {
- _cowFile.seek(index * 2048);
- Common::SeekableReadStream *tmp = _cowFile.readStream(sampleSize);
- assert(tmp);
- stream = Audio::makeXAStream(tmp, 11025);
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
- // with compressed audio, we can't calculate the wave volume.
- // so default to talking.
- for (int cnt = 0; cnt < 480; cnt++)
- _waveVolume[cnt] = true;
- _waveVolPos = 0;
}
+ }
+}
+
+bool Sound::expandSpeech(byte *src, byte *dst, uint32 dstSize, bool *endiannessCheck, uint32 *sizeForEndiannessCheck) {
+
+ if (_cowMode == CowPSX) {
+ Audio::RewindableAudioStream *stream = Audio::makeXAStream(new Common::MemoryReadStream(src, dstSize), 11025);
+ stream->readBuffer((int16 *)speechSample, speechSize);
+ return true;
+ } else if (_cowMode != CowWave && _cowMode != CowDemo) {
+ Audio::RewindableAudioStream *stream = nullptr;
#ifdef USE_FLAC
- else if (_cowMode == CowFLAC) {
- _cowFile.seek(index);
- Common::SeekableReadStream *tmp = _cowFile.readStream(sampleSize);
- assert(tmp);
- stream = Audio::makeFLACStream(tmp, DisposeAfterUse::YES);
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
- // with compressed audio, we can't calculate the wave volume.
- // so default to talking.
- for (int cnt = 0; cnt < 480; cnt++)
- _waveVolume[cnt] = true;
- _waveVolPos = 0;
+ if (_cowMode == CowFLAC) {
+ stream = Audio::makeFLACStream(new Common::MemoryReadStream(src, dstSize), DisposeAfterUse::YES);
}
#endif
#ifdef USE_VORBIS
- else if (_cowMode == CowVorbis) {
- _cowFile.seek(index);
- Common::SeekableReadStream *tmp = _cowFile.readStream(sampleSize);
- assert(tmp);
- stream = Audio::makeVorbisStream(tmp, DisposeAfterUse::YES);
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
- // with compressed audio, we can't calculate the wave volume.
- // so default to talking.
- for (int cnt = 0; cnt < 480; cnt++)
- _waveVolume[cnt] = true;
- _waveVolPos = 0;
+ if (_cowMode == CowVorbis) {
+ stream = Audio::makeVorbisStream(new Common::MemoryReadStream(src, dstSize), DisposeAfterUse::YES);
}
#endif
#ifdef USE_MAD
- else if (_cowMode == CowMP3) {
- _cowFile.seek(index);
- Common::SeekableReadStream *tmp = _cowFile.readStream(sampleSize);
- assert(tmp);
- stream = Audio::makeMP3Stream(tmp, DisposeAfterUse::YES);
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
- // with compressed audio, we can't calculate the wave volume.
- // so default to talking.
- for (int cnt = 0; cnt < 480; cnt++)
- _waveVolume[cnt] = true;
- _waveVolPos = 0;
+ if (_cowMode == CowMP3) {
+ stream = Audio::makeMP3Stream(new Common::MemoryReadStream(src, dstSize), DisposeAfterUse::YES);
}
#endif
- return true;
- } else
- return false;
-}
+ if (stream) {
+ stream->readBuffer((int16 *)speechSample, speechSize);
+ return true;
+ } else {
+ return false;
+ }
+ }
-int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size, bool* ok) {
- uint8 *fBuf = (uint8 *)malloc(cSize);
- _cowFile.seek(index);
- _cowFile.read(fBuf, cSize);
+ uint8 *fBuf = src;
uint32 headerPos = 0;
while ((READ_BE_UINT32(fBuf + headerPos) != 'data') && (headerPos < 100))
headerPos++;
if (headerPos < 100) {
- if (ok != 0)
- *ok = true;
+ if (endiannessCheck)
+ *endiannessCheck = true;
int32 resSize;
int16 *srcData;
uint32 srcPos;
int16 length;
- cSize /= 2;
+ dstSize /= 2;
headerPos += 4; // skip 'data' tag
if (_cowMode != CowDemo) {
resSize = READ_LE_UINT32(fBuf + headerPos) >> 1;
@@ -527,7 +503,7 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size, bool* o
resSize = 0;
srcData = (int16 *)fBuf;
srcPos = headerPos >> 1;
- while (srcPos < cSize) {
+ while (srcPos < dstSize) {
length = (int16)READ_LE_UINT16(srcData + srcPos);
srcPos++;
if (length < 0) {
@@ -544,17 +520,18 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size, bool* o
srcData = (int16 *)fBuf;
srcPos = headerPos >> 1;
uint32 dstPos = 0;
- int16 *dstData = (int16 *)malloc(resSize * 2);
+ int16 *dstData = (int16 *)dst;
+
int32 samplesLeft = resSize;
- while (srcPos < cSize && samplesLeft > 0) {
+ while (srcPos < dstSize && samplesLeft > 0) {
length = (int16)(_bigEndianSpeech ? READ_BE_UINT16(srcData + srcPos) : READ_LE_UINT16(srcData + srcPos));
srcPos++;
if (length < 0) {
length = -length;
if (length > samplesLeft) {
length = samplesLeft;
- if (ok != 0)
- *ok = false;
+ if (endiannessCheck)
+ *endiannessCheck = false;
}
int16 value;
if (_bigEndianSpeech) {
@@ -568,8 +545,8 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size, bool* o
} else {
if (length > samplesLeft) {
length = samplesLeft;
- if (ok != 0)
- *ok = false;
+ if (endiannessCheck)
+ *endiannessCheck = false;
}
if (_bigEndianSpeech) {
for (uint16 cnt = 0; cnt < (uint16)length; cnt++)
@@ -584,55 +561,18 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size, bool* o
}
if (samplesLeft > 0) {
memset(dstData + dstPos, 0, samplesLeft * 2);
- if (ok != 0)
- *ok = false;
+ if (endiannessCheck)
+ *endiannessCheck = false;
}
if (_cowMode == CowDemo) // demo has wave output size embedded in the compressed data
*(uint32 *)dstData = 0;
- free(fBuf);
- *size = resSize * 2;
- calcWaveVolume(dstData, resSize);
- return dstData;
+ return true;
} else {
- if (ok != 0)
- *ok = false;
- free(fBuf);
- warning("Sound::uncompressSpeech(): DATA tag not found in wave header");
- *size = 0;
- return NULL;
- }
-}
-
-void Sound::calcWaveVolume(int16 *data, uint32 length) {
- int16 *blkPos = data + 918;
- uint32 cnt;
- for (cnt = 0; cnt < WAVE_VOL_TAB_LENGTH; cnt++)
- _waveVolume[cnt] = false;
- _waveVolPos = 0;
- for (uint32 blkCnt = 1; blkCnt < length / 918; blkCnt++) {
- if (blkCnt >= WAVE_VOL_TAB_LENGTH) {
- warning("Wave vol tab too small");
- return;
- }
- int32 average = 0;
- for (cnt = 0; cnt < 918; cnt++)
- average += blkPos[cnt];
- average /= 918;
- uint32 diff = 0;
- for (cnt = 0; cnt < 918; cnt++) {
- int16 smpDiff = *blkPos - average;
- diff += (uint32)ABS(smpDiff);
- blkPos++;
- }
- if (diff > WAVE_VOL_THRESHOLD)
- _waveVolume[blkCnt - 1] = true;
+ warning("Sound::expandSpeech(): DATA tag not found in wave header");
+ return false;
}
}
-void Sound::stopSpeech() {
- _mixer->stopID(SOUND_SPEECH_ID);
-}
-
void Sound::initCowSystem() {
if (SwordEngine::_systemVars.currentCD == 0)
return;
@@ -769,10 +709,9 @@ int32 Sound::CheckSpeechStatus() {
return S_STATUS_RUNNING;
}
-int32 Sound::PlaySpeech(void *wavData, int32 size) {
+int32 Sound::PlaySpeech() {
Common::StackLock lock(_soundMutex);
- speechSize = size;
speechCount = 0;
// Check to see if the handle is free, else free it
@@ -784,7 +723,7 @@ int32 Sound::PlaySpeech(void *wavData, int32 size) {
speechSampleBusy = true;
// And point the sample to our new wav data
- if (true/* AIL_set_sample_file(hSampleSpeech, wavData, -1) == 0*/) {
+ if (false/* AIL_set_sample_file(hSampleSpeech, wavData, -1) == 0*/) {
speechSampleBusy = false;
return 0;
} else {
@@ -792,6 +731,10 @@ int32 Sound::PlaySpeech(void *wavData, int32 size) {
// has been successfully parsed.
//
// Modify the volume according to the master volume
+ Audio::SeekableAudioStream *stream = Audio::makeRawStream(
+ (byte *)speechSample, speechSize, 11025, SPEECH_FLAGS, DisposeAfterUse::NO);
+ _mixer->playStream(Audio::Mixer::kSpeechSoundType, &hSampleSpeech, stream);
+
_mixer->setChannelVolume(hSampleSpeech, 2 * (4 * (volSpeech[0] + volSpeech[1])));
// Now set the pan position for the sample
@@ -958,17 +901,18 @@ int32 Sound::PlayFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]) {
flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
else
flags = Audio::FLAG_UNSIGNED;
- if (READ_LE_UINT16(wavData + 0x16) == 2)
- flags |= Audio::FLAG_STEREO;
- stream = Audio::makeLoopingAudioStream(
- Audio::makeRawStream(wavData + 0x2C, size, 11025, flags, DisposeAfterUse::NO),
- (type == FX_LOOP) ? 0 : 1);
+if (READ_LE_UINT16(wavData + 0x16) == 2)
+flags |= Audio::FLAG_STEREO;
+stream = Audio::makeLoopingAudioStream(
+ Audio::makeRawStream(wavData + 0x2C, size, 11025, flags, DisposeAfterUse::NO),
+ (type == FX_LOOP) ? 0 : 1);
}
// And point the sample to our new wav data
if (!stream) {
return 0;
- } else {
+ }
+ else {
// We have found a free handle, and the wav file header
// has been successfully parsed.
//
@@ -1057,32 +1001,69 @@ void Sound::FadeFxUp(int32 rate) {
fxCount = 0;
}
-int32 Sound::GetSpeechSize(void *compData) {
- struct WaveHeader {
- uint32 riffTag;
- uint32 riffSize;
- uint32 waveTag;
- uint32 fmtTag;
- uint32 fmtSize;
-
- // Format subchunk
- uint16 wFormatTag;
- uint16 wChannels;
- uint32 dwSamplesPerSec;
- uint32 dwAvgBytesPerSec;
- uint16 wBlockAlign;
- uint16 wBitsPerSample;
- };
-
- WaveHeader *waveHeader = (WaveHeader *)compData;
-
- return (waveHeader->riffSize + 8);
+int32 Sound::GetSpeechSize(byte *compData, uint32 compSize) {
+ if ((_cowMode == CowWave) || (_cowMode == CowDemo)) {
+ struct WaveHeader {
+ uint32 riffTag;
+ uint32 riffSize;
+ uint32 waveTag;
+ uint32 fmtTag;
+ uint32 fmtSize;
+
+ // Format subchunk
+ uint16 wFormatTag;
+ uint16 wChannels;
+ uint32 dwSamplesPerSec;
+ uint32 dwAvgBytesPerSec;
+ uint16 wBlockAlign;
+ uint16 wBitsPerSample;
+ uint32 dwDataTag;
+ uint32 dwDataSize;
+ };
+
+ WaveHeader *waveHeader = (WaveHeader *)compData;
+
+ return (waveHeader->riffSize + 8) - sizeof(WaveHeader);
+ } else {
+ Common::MemoryReadStream memStream(compData, compSize);
+ Audio::RewindableAudioStream *stream = nullptr;
+
+ if (_cowMode == CowPSX) {
+ stream = Audio::makeXAStream(&memStream, 11025);
+ }
+#ifdef USE_FLAC
+ else if (_cowMode == CowFLAC) {
+ stream = Audio::makeFLACStream(&memStream, DisposeAfterUse::YES);
+ }
+#endif
+#ifdef USE_VORBIS
+ else if (_cowMode == CowVorbis) {
+ stream = Audio::makeVorbisStream(&memStream, DisposeAfterUse::YES);
+ }
+#endif
+#ifdef USE_MAD
+ else if (_cowMode == CowMP3) {
+ stream = Audio::makeMP3Stream(&memStream, DisposeAfterUse::YES);
+ }
+#endif
+
+ if (stream) {
+ byte tmpBuffer[1000 * 2];
+ int32 finalSize = 0;
+ while (!stream->endOfData())
+ finalSize += stream->readBuffer((int16 *)tmpBuffer, 1000) * 2;
+
+ return finalSize;
+ }
+ }
+
+ return 0;
}
void Sound::ReduceMusicVolume() {
Common::StackLock lock(_soundMutex);
musicFadeVolume[0] = volMusic[0] * MUSIC_UNDERSCORE / 100;
- musicFadeVolume[1] = volMusic[0] * MUSIC_UNDERSCORE / 100;
+ musicFadeVolume[1] = volMusic[0] * MUSIC_UNDERSCORE / 100; // We are explicitly accessing volMusic[0] again
// Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
_mixer->setChannelVolume(hStreamSample[0], 2 * ((musicFadeVolume[0] + musicFadeVolume[1]) * 3));
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index 27f62f65b66..3600fd7d13a 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -96,18 +96,13 @@ class Sound {
public:
Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan);
~Sound();
- void setSpeechVol(uint8 volL, uint8 volR) { _speechVolL = volL; _speechVolR = volR; }
- void giveSpeechVol(uint8 *volL, uint8 *volR) { *volL = _speechVolL; *volR = _speechVolR; }
void newScreen(uint32 screen);
void clearAllFx();
void closeCowSystem();
- bool startSpeech(uint16 roomNo, uint16 localNo);
- bool speechFinished();
- void stopSpeech();
- bool amISpeaking(byte *buf);
+ void startSpeech(uint16 roomNo, uint16 localNo);
+ bool amISpeaking();
- void fnStopFx(int32 fxNo);
int addToQueue(uint32 fxNo);
void removeFromQueue(uint32 fxNo);
@@ -120,20 +115,17 @@ public:
Audio::Mixer *_mixer;
private:
- uint8 _speechVolL, _speechVolR;
void initCowSystem();
uint32 getSampleId(int32 fxNo);
- int16 *uncompressSpeech(uint32 index, uint32 cSize, uint32 *size, bool* ok = 0);
- void calcWaveVolume(int16 *data, uint32 length);
- bool _waveVolume[WAVE_VOL_TAB_LENGTH];
- uint16 _waveVolPos;
+ bool expandSpeech(byte *src, byte *dst, uint32 dstSize,
+ bool *endiannessCheck = nullptr, uint32 *sizeForEndiannessCheck = nullptr);
+
Common::File _cowFile;
uint32 *_cowHeader;
uint32 _cowHeaderSize;
uint8 _currentCowFile;
CowMode _cowMode;
- Audio::SoundHandle _speechHandle, _fxHandle;
Common::RandomSource _rnd;
QueueElement _fxQueue[MAX_FXQ_LENGTH];
@@ -150,24 +142,31 @@ private:
public:
void installFadeTimer();
void uninstallFadeTimer();
- void PlaySample(int32 fxNo);
- int32 StreamSample(char filename[], int32 looped);
- void UpdateSampleStreaming();
+ int8 scalePan(int pan); // From 0,127 to -127,127
+ void PlaySample(int32 fxNo);
int32 PlayFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]);
int32 StopFX(int32 fxID);
int32 CheckSampleStatus(int32 id);
+
+ void UpdateSampleStreaming();
int32 CheckSpeechStatus();
- int32 PlaySpeech(void *wavData, int32 size);
+ int32 PlaySpeech();
int32 StopSpeech();
+ int32 GetSpeechSize(byte *compData, uint32 compSize);
+
+ int32 StreamSample(char filename[], int32 looped);
+ void ReduceMusicVolume();
+ void RestoreMusicVolume();
+
void FadeVolumeDown(int32 rate);
void FadeVolumeUp(int32 rate);
void FadeMusicDown(int32 rate);
void FadeMusicUp(int32 rate);
void FadeFxDown(int32 rate);
void FadeFxUp(int32 rate);
- int32 GetSpeechSize(void *compData);
+
void SetCrossFadeIncrement();
void PauseSpeech();
void UnpauseSpeech();
@@ -176,11 +175,6 @@ public:
void PauseFx();
void UnpauseFx();
- int8 scalePan(int pan); // From 0,127 to -127,127
-
- void ReduceMusicVolume();
- void RestoreMusicVolume();
-
// Handles for external volume changes (control panel)
uint32 volFX[2] = { 0, 0 };
uint32 volSpeech[2] = { 0, 0 };
@@ -221,6 +215,7 @@ public:
bool speechSamplePaused = false;
bool fxPaused[MAX_FX] = { false, false, false, false };
bool musicPaused[MAX_MUSIC] = { false, false };
+ byte *speechSample = nullptr;
};
} // End of namespace Sword1
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index d77263c3b4f..173eb711f0e 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -245,10 +245,10 @@ void SwordEngine::syncSoundSettings() {
if (mute) {
_music->setVolume(0, 0);
- _sound->setSpeechVol(0, 0);
+ //_sound->setSpeechVol(0, 0);
} else {
_music->setVolume(musicVolL, musicVolR);
- _sound->setSpeechVol(speechVolL, speechVolR);
+ //_sound->setSpeechVol(speechVolL, speechVolR);
}
}
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index 448d098732b..4db2df23579 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -69,6 +69,9 @@ struct SystemVars {
int snrStatus;
bool wantFade; // when true => fade during scene change, else cut.
bool playSpeech;
+ bool textRunning;
+ uint32 speechRunning;
+ bool speechFinished;
bool showText;
int32 textNumber;
uint8 language;
Commit: bcff7980296ed220cf1b8910d6695b989beb6fc7
https://github.com/scummvm/scummvm/commit/bcff7980296ed220cf1b8910d6695b989beb6fc7
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Do a code clean-up pass
Changed paths:
engines/sword1/control.cpp
engines/sword1/logic.cpp
engines/sword1/sound.cpp
engines/sword1/sound.h
engines/sword1/sword1.cpp
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 73f1d52dee6..3cabae81317 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -255,10 +255,10 @@ void Control::getPlayerOptions() {
while (SwordEngine::_systemVars.snrStatus != SNR_BLANK && !Engine::shouldQuit()) {
delay(DEFAULT_FRAME_TIME / 2);
- _sound->SetCrossFadeIncrement();
+ _sound->setCrossFadeIncrement();
_mouse->animate();
- _sound->UpdateSampleStreaming(); // stream music
+ _sound->updateSampleStreaming(); // stream music
saveRestoreScreen();
}
@@ -288,7 +288,7 @@ void Control::getPlayerOptions() {
if (SwordEngine::_systemVars.saveGameFlag == SGF_SAVE) {
saveGame();
} else if (SwordEngine::_systemVars.saveGameFlag == SGF_QUIT) {
- _sound->FadeMusicDown(1);
+ _sound->fadeMusicDown(1);
Engine::quitGame();
}
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 8bf1d1c0394..5fea76143d2 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -355,13 +355,13 @@ int Logic::speechDriver(Object *compact) {
if (SwordEngine::_systemVars.speechRunning >= 2) {
SwordEngine::_systemVars.speechRunning--;
if (SwordEngine::_systemVars.speechRunning == 1)
- _sound->PlaySpeech();
+ _sound->playSpeech();
} else if (SwordEngine::_systemVars.speechRunning == 1) {
- if (_sound->CheckSpeechStatus() == S_STATUS_FINISHED)
+ if (_sound->checkSpeechStatus() == S_STATUS_FINISHED)
SwordEngine::_systemVars.speechFinished = true;
if (SwordEngine::_systemVars.speechFinished) {
- _sound->StopSpeech();
+ _sound->stopSpeech();
free(_sound->speechSample);
_sound->speechSample = nullptr;
}
@@ -1650,7 +1650,7 @@ int Logic::fnPlayFx(Object *cpt, int32 id, int32 fxNo, int32 b, int32 c, int32 d
}
int Logic::fnStopFx(Object *cpt, int32 id, int32 fxNo, int32 b, int32 c, int32 d, int32 z, int32 x) {
- _sound->StopFX(fxNo);
+ _sound->stopFX(fxNo);
_sound->removeFromQueue(fxNo);
return SCRIPT_CONT;
}
@@ -1663,14 +1663,14 @@ int Logic::fnPlayMusic(Object *cpt, int32 id, int32 tuneId, int32 loopFlag, int3
else
_scriptVars[CURRENT_MUSIC] = 0;
- //_sound->StreamSample(tuneId, loopFlag);
+ //_sound->streamSample(tuneId, loopFlag);
_music->startMusic(tuneId, loopFlag);
return SCRIPT_CONT;
}
int Logic::fnStopMusic(Object *cpt, int32 id, int32 a, int32 b, int32 c, int32 d, int32 z, int32 x) {
_scriptVars[CURRENT_MUSIC] = 0;
- _sound->FadeMusicDown(1);
+ _sound->fadeMusicDown(1);
return SCRIPT_CONT;
}
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index f4c691180e7..7a986fcdef7 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -140,7 +140,7 @@ void Sound::checkSpeechFileEndianness() {
byte *compSample = (byte *)malloc(sampleSize);
_cowFile.seek(index + _cowHeaderSize, SEEK_SET);
_cowFile.read(compSample, sampleSize);
- byte *data = (byte *)malloc(GetSpeechSize(compSample, sampleSize));
+ byte *data = (byte *)malloc(getSpeechSize(compSample, sampleSize));
bool success = expandSpeech(compSample, data, sampleSize, &leOk, &size);
uint32 maxSamples = size > 2000 ? 2000 : size;
double le_diff = endiannessHeuristicValue((int16 *)data, size, maxSamples);
@@ -150,7 +150,7 @@ void Sound::checkSpeechFileEndianness() {
_bigEndianSpeech = true;
_cowFile.seek(index + _cowHeaderSize, SEEK_SET);
_cowFile.read(compSample, sampleSize);
- data = (byte *)malloc(GetSpeechSize(compSample, sampleSize));
+ data = (byte *)malloc(getSpeechSize(compSample, sampleSize));
success = expandSpeech(compSample, data, sampleSize, &beOk, &size);
double be_diff = endiannessHeuristicValue((int16 *)data, size, maxSamples);
free(data);
@@ -284,8 +284,8 @@ void Sound::engine() {
if (_fxQueue[cnt].delay > 0) {
_fxQueue[cnt].delay--;
if (_fxQueue[cnt].delay == 0)
- PlaySample(fxNo);
- } else if (CheckSampleStatus(fxNo) == S_STATUS_FINISHED) {
+ playSample(fxNo);
+ } else if (checkSampleStatus(fxNo) == S_STATUS_FINISHED) {
// Delay countdown was already zero, so the sample has
// already been played, so check if it's finished...
removeFromQueue(fxNo);
@@ -302,9 +302,9 @@ bool Sound::amISpeaking() {
return false;
if (_mixer->isSoundHandleActive(hSampleSpeech)) {
- speechCount += 1;
+ speechLipsyncCounter += 1;
- readPos = speechCount * 919 * 2;
+ readPos = speechLipsyncCounter * 919 * 2;
// Ensure that we don't read beyond the buffer
if (readPos + 150 * sizeof(int16) > speechSize)
@@ -425,7 +425,7 @@ void Sound::startSpeech(uint16 roomNo, uint16 localNo) {
}
_cowFile.read(compSample, sampleFileSize);
- speechSize = GetSpeechSize(compSample, sampleFileSize);
+ speechSize = getSpeechSize(compSample, sampleFileSize);
speechSample = (byte *)malloc(speechSize);
if (speechSample) {
SwordEngine::_systemVars.speechRunning = expandSpeech(compSample, speechSample, sampleFileSize);
@@ -672,12 +672,7 @@ void Sound::closeCowSystem() {
_currentCowFile = 0;
}
-// New stuff
-
-// This function checks to see whether a specific sound effect has completed
-// playing yet. It returns 1 if finished, 0 if still playing
-//
-int32 Sound::CheckSampleStatus(int32 id) {
+int32 Sound::checkSampleStatus(int32 id) {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_FX; i++) {
@@ -694,7 +689,7 @@ int32 Sound::CheckSampleStatus(int32 id) {
return S_STATUS_RUNNING;
}
-int32 Sound::CheckSpeechStatus() {
+int32 Sound::checkSpeechStatus() {
Common::StackLock lock(_soundMutex);
if (!speechSampleBusy || speechSamplePaused)
@@ -702,66 +697,43 @@ int32 Sound::CheckSpeechStatus() {
if (!_mixer->isSoundHandleActive(hSampleSpeech)) {
speechSampleBusy = 0;
- RestoreMusicVolume();
+ restoreMusicVolume();
return S_STATUS_FINISHED;
}
return S_STATUS_RUNNING;
}
-int32 Sound::PlaySpeech() {
+void Sound::playSpeech() {
Common::StackLock lock(_soundMutex);
- speechCount = 0;
+ speechLipsyncCounter = 0;
- // Check to see if the handle is free, else free it
if (speechSampleBusy)
- StopSpeech();
+ stopSpeech();
- // Reset the sample parameters
- //AIL_init_sample(hSampleSpeech);
speechSampleBusy = true;
- // And point the sample to our new wav data
- if (false/* AIL_set_sample_file(hSampleSpeech, wavData, -1) == 0*/) {
- speechSampleBusy = false;
- return 0;
- } else {
- // We have found a free handle, and the wav file header
- // has been successfully parsed.
- //
- // Modify the volume according to the master volume
- Audio::SeekableAudioStream *stream = Audio::makeRawStream(
- (byte *)speechSample, speechSize, 11025, SPEECH_FLAGS, DisposeAfterUse::NO);
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, &hSampleSpeech, stream);
+ Audio::SeekableAudioStream *stream = Audio::makeRawStream(
+ (byte *)speechSample, speechSize, 11025, SPEECH_FLAGS, DisposeAfterUse::NO);
+ _mixer->playStream(Audio::Mixer::kSpeechSoundType, &hSampleSpeech, stream);
- _mixer->setChannelVolume(hSampleSpeech, 2 * (4 * (volSpeech[0] + volSpeech[1])));
+ _mixer->setChannelVolume(hSampleSpeech, 2 * (4 * (volSpeech[0] + volSpeech[1])));
- // Now set the pan position for the sample
- int pan = 64 + (4 * ((int32)volSpeech[1] - (int32)volSpeech[0]));
- _mixer->setChannelBalance(hSampleSpeech, scalePan(pan));
+ int pan = 64 + (4 * ((int32)volSpeech[1] - (int32)volSpeech[0]));
+ _mixer->setChannelBalance(hSampleSpeech, scalePan(pan));
- // Start the sample
- //AIL_start_sample(hSampleSpeech);
-
- ReduceMusicVolume();
-
- // and exit the function.
- return 1;
- }
+ reduceMusicVolume();
}
-int32 Sound::StopSpeech() {
+void Sound::stopSpeech() {
Common::StackLock lock(_soundMutex);
if (_mixer->isSoundHandleActive(hSampleSpeech)) {
_mixer->stopHandle(hSampleSpeech);
speechSampleBusy = false;
- RestoreMusicVolume();
- return 1;
+ restoreMusicVolume();
}
-
- return 0;
}
static void soundCallback(void *refCon) {
@@ -807,7 +779,7 @@ void Sound::uninstallFadeTimer() {
_vm->getTimerManager()->removeTimerProc(&soundCallback);
}
-void Sound::PlaySample(int32 fxNo) {
+void Sound::playSample(int32 fxNo) {
uint8 *samplePtr;
uint32 vol[2] = { 0, 0 };
int32 screen = Logic::_scriptVars[SCREEN];
@@ -821,8 +793,8 @@ void Sound::PlaySample(int32 fxNo) {
vol[0] = (_fxList[fxNo].roomVolList[i].leftVol);
vol[1] = (_fxList[fxNo].roomVolList[i].rightVol);
- debug(5, "Sound::PlaySample(): fxNo=%d, vol[0]=%d, vol[1]=%d)",fxNo,vol[0],vol[1]);
- PlayFX(fxNo, _fxList[fxNo].type, samplePtr, vol);
+ debug(5, "Sound::playSample(): fxNo=%d, vol[0]=%d, vol[1]=%d)",fxNo,vol[0],vol[1]);
+ playFX(fxNo, _fxList[fxNo].type, samplePtr, vol);
break;
}
} else {
@@ -831,11 +803,11 @@ void Sound::PlaySample(int32 fxNo) {
}
}
-int32 Sound::StreamSample(char filename[], int32 looped) {
+int32 Sound::streamSample(char filename[], int32 looped) {
return 0;
}
-void Sound::UpdateSampleStreaming() {
+void Sound::updateSampleStreaming() {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_MUSIC; i++) {
if ((streamSamplePlaying[i]) && (!musicPaused[i])) {
@@ -875,15 +847,14 @@ void Sound::UpdateSampleStreaming() {
}
}
-int32 Sound::PlayFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]) {
+void Sound::playFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]) {
Common::StackLock lock(_soundMutex);
int32 v0, v1;
- // Search through the fx sample handles for a free slot
+ // Search through the FX sample handles for a free slot...
for (int i = 0; i < MAX_FX; i++) {
- // Check to see if the handle is free
if (!fxSampleBusy[i]) {
- // Reset the sample parameters
+ // Found the handle! Now setup and play the sound...
fxSampleBusy[i] = true;
fxSampleID[i] = fxID;
@@ -901,50 +872,37 @@ int32 Sound::PlayFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]) {
flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
else
flags = Audio::FLAG_UNSIGNED;
-if (READ_LE_UINT16(wavData + 0x16) == 2)
-flags |= Audio::FLAG_STEREO;
-stream = Audio::makeLoopingAudioStream(
- Audio::makeRawStream(wavData + 0x2C, size, 11025, flags, DisposeAfterUse::NO),
- (type == FX_LOOP) ? 0 : 1);
+ if (READ_LE_UINT16(wavData + 0x16) == 2)
+ flags |= Audio::FLAG_STEREO;
+
+ stream = Audio::makeLoopingAudioStream(
+ Audio::makeRawStream(wavData + 0x2C, size, 11025, flags, DisposeAfterUse::NO),
+ (type == FX_LOOP) ? 0 : 1);
}
// And point the sample to our new wav data
- if (!stream) {
- return 0;
- }
- else {
- // We have found a free handle, and the wav file header
- // has been successfully parsed.
- //
- // Modify the volume according to the master volume
+ if (stream) {
v0 = volFX[0] * vol[0];
v1 = volFX[1] * vol[1];
_mixer->playStream(Audio::Mixer::kSFXSoundType, &hSampleFX[i], stream, -1, 0);
_mixer->setChannelVolume(hSampleFX[i], 2 * ((v0 + v1) / 8));
_mixer->setChannelBalance(hSampleFX[i], scalePan(64 + ((v1 - v0) / 4)));
-
- return 1;
}
}
}
-
- return 0;
}
-int32 Sound::StopFX(int32 fxID) {
+void Sound::stopFX(int32 fxID) {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_FX; i++) {
if (fxSampleID[i] == fxID) {
if (_mixer->isSoundHandleActive(hSampleFX[i])) {
_mixer->stopHandle(hSampleFX[i]);
fxSampleBusy[i] = false;
- return 1;
}
}
}
-
- return 0;
}
void Sound::clearAllFx() {
@@ -952,8 +910,8 @@ void Sound::clearAllFx() {
for (int j = _endOfQueue - 1; j >= 0; j--) {
// Check if the sample has finished playing and
// if not, stop it manually...
- if (CheckSampleStatus(_fxQueue[j].id) == S_STATUS_RUNNING)
- StopFX(_fxQueue[j].id);
+ if (checkSampleStatus(_fxQueue[j].id) == S_STATUS_RUNNING)
+ stopFX(_fxQueue[j].id);
removeFromQueue(_fxQueue[j].id);
}
@@ -961,47 +919,26 @@ void Sound::clearAllFx() {
_endOfQueue = 0;
}
-void Sound::FadeVolumeDown(int32 rate) {
- Common::StackLock lock(_soundMutex);
- volumeFadingFlag = -1;
- volumeFadingRate = 2 * rate;
- volumeCount = 0;
-}
-
-void Sound::FadeVolumeUp(int32 rate) {
- Common::StackLock lock(_soundMutex);
- volumeFadingFlag = 1;
- volumeFadingRate = 2 * rate;
- volumeCount = 0;
-}
-
-void Sound::FadeMusicDown(int32 rate) {
+void Sound::fadeMusicDown(int32 rate) {
Common::StackLock lock(_soundMutex);
streamSampleFading[1 - streamSamplePlaying[0]] = -12;
}
-void Sound::FadeMusicUp(int32 rate) {
- Common::StackLock lock(_soundMutex);
- musicFadingFlag = 1;
- musicFadingRate = 2 * rate;
- musicCount = 0;
-}
-
-void Sound::FadeFxDown(int32 rate) {
+void Sound::fadeFxDown(int32 rate) {
Common::StackLock lock(_soundMutex);
fxFadingFlag = -1;
fxFadingRate = 2 * rate;
fxCount = 0;
}
-void Sound::FadeFxUp(int32 rate) {
+void Sound::fadeFxUp(int32 rate) {
Common::StackLock lock(_soundMutex);
fxFadingFlag = 1;
fxFadingRate = 2 * rate;
fxCount = 0;
}
-int32 Sound::GetSpeechSize(byte *compData, uint32 compSize) {
+int32 Sound::getSpeechSize(byte *compData, uint32 compSize) {
if ((_cowMode == CowWave) || (_cowMode == CowDemo)) {
struct WaveHeader {
uint32 riffTag;
@@ -1060,7 +997,7 @@ int32 Sound::GetSpeechSize(byte *compData, uint32 compSize) {
return 0;
}
-void Sound::ReduceMusicVolume() {
+void Sound::reduceMusicVolume() {
Common::StackLock lock(_soundMutex);
musicFadeVolume[0] = volMusic[0] * MUSIC_UNDERSCORE / 100;
musicFadeVolume[1] = volMusic[0] * MUSIC_UNDERSCORE / 100; // We are explicitly accessing volMusic[0] again
@@ -1069,32 +1006,32 @@ void Sound::ReduceMusicVolume() {
_mixer->setChannelVolume(hStreamSample[0], 2 * ((musicFadeVolume[0] + musicFadeVolume[1]) * 3));
}
-void Sound::RestoreMusicVolume() {
+void Sound::restoreMusicVolume() {
Common::StackLock lock(_soundMutex);
// Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
_mixer->setChannelVolume(hStreamSample[0], 2 * ((volMusic[0] + volMusic[1]) * 3));
}
-void Sound::SetCrossFadeIncrement() {
+void Sound::setCrossFadeIncrement() {
crossFadeIncrement = true;
}
-void Sound::PauseSpeech() {
+void Sound::pauseSpeech() {
if ((speechSampleBusy) && (!speechSamplePaused)) {
speechSamplePaused = true;
_mixer->pauseHandle(hSampleSpeech, true);
}
}
-void Sound::UnpauseSpeech() {
+void Sound::unpauseSpeech() {
if ((speechSampleBusy) && (speechSamplePaused)) {
speechSamplePaused = false;
_mixer->pauseHandle(hSampleSpeech, false);
}
}
-void Sound::PauseMusic() {
+void Sound::pauseMusic() {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_MUSIC; i++) {
if (streamSamplePlaying[i]) {
@@ -1104,7 +1041,7 @@ void Sound::PauseMusic() {
}
}
-void Sound::UnpauseMusic() {
+void Sound::unpauseMusic() {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_MUSIC; i++) {
if (musicPaused[i]) {
@@ -1114,7 +1051,7 @@ void Sound::UnpauseMusic() {
}
}
-void Sound::PauseFx() {
+void Sound::pauseFx() {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_FX; i++) {
if (fxSampleBusy[i]) {
@@ -1124,7 +1061,7 @@ void Sound::PauseFx() {
}
}
-void Sound::UnpauseFx() {
+void Sound::unpauseFx() {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_FX; i++) {
if (fxPaused[i]) {
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index 3600fd7d13a..a99ca4e14ce 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -145,35 +145,32 @@ public:
int8 scalePan(int pan); // From 0,127 to -127,127
- void PlaySample(int32 fxNo);
- int32 PlayFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]);
- int32 StopFX(int32 fxID);
- int32 CheckSampleStatus(int32 id);
-
- void UpdateSampleStreaming();
- int32 CheckSpeechStatus();
- int32 PlaySpeech();
- int32 StopSpeech();
- int32 GetSpeechSize(byte *compData, uint32 compSize);
-
- int32 StreamSample(char filename[], int32 looped);
- void ReduceMusicVolume();
- void RestoreMusicVolume();
-
- void FadeVolumeDown(int32 rate);
- void FadeVolumeUp(int32 rate);
- void FadeMusicDown(int32 rate);
- void FadeMusicUp(int32 rate);
- void FadeFxDown(int32 rate);
- void FadeFxUp(int32 rate);
-
- void SetCrossFadeIncrement();
- void PauseSpeech();
- void UnpauseSpeech();
- void PauseMusic();
- void UnpauseMusic();
- void PauseFx();
- void UnpauseFx();
+ void playSample(int32 fxNo);
+ void playFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]);
+ void stopFX(int32 fxID);
+ int32 checkSampleStatus(int32 id);
+
+ void updateSampleStreaming();
+ int32 checkSpeechStatus();
+ void playSpeech();
+ void stopSpeech();
+ int32 getSpeechSize(byte *compData, uint32 compSize);
+
+ int32 streamSample(char filename[], int32 looped);
+ void reduceMusicVolume();
+ void restoreMusicVolume();
+
+ void fadeMusicDown(int32 rate);
+ void fadeFxDown(int32 rate);
+ void fadeFxUp(int32 rate);
+
+ void setCrossFadeIncrement();
+ void pauseSpeech();
+ void unpauseSpeech();
+ void pauseMusic();
+ void unpauseMusic();
+ void pauseFx();
+ void unpauseFx();
// Handles for external volume changes (control panel)
uint32 volFX[2] = { 0, 0 };
@@ -194,7 +191,7 @@ public:
int32 volumeCount = 0;
int32 musicCount = 0;
int32 fxCount = 0;
- int32 speechCount = 0;
+ int32 speechLipsyncCounter = 0;
int32 speechSize = 0;
// Sample handles and information.
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 173eb711f0e..14c41a1126b 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -265,18 +265,18 @@ void SwordEngine::flagsToBool(bool *dest, uint8 flags) {
void SwordEngine::checkKeys() {
if (_systemVars.gamePaused) {
- _sound->PauseSpeech();
- _sound->PauseMusic();
- _sound->PauseFx();
+ _sound->pauseSpeech();
+ _sound->pauseMusic();
+ _sound->pauseFx();
while (_keyPressed.keycode != Common::KEYCODE_p && !Engine::shouldQuit()) {
pollInput(0);
- _sound->UpdateSampleStreaming();
+ _sound->updateSampleStreaming();
}
- _sound->UnpauseSpeech();
- _sound->UnpauseMusic();
- _sound->UnpauseFx();
+ _sound->unpauseSpeech();
+ _sound->unpauseMusic();
+ _sound->unpauseFx();
_systemVars.gamePaused = false;
_keyPressed.reset();
@@ -1195,12 +1195,12 @@ void SwordEngine::fadePaletteStep() {
void SwordEngine::startFadePaletteDown(int speed) {
_screen->startFadePaletteDown(speed);
- _sound->FadeFxDown(speed);
+ _sound->fadeFxDown(speed);
}
void SwordEngine::startFadePaletteUp(int speed) {
_screen->startFadePaletteUp(speed);
- _sound->FadeFxUp(speed);
+ _sound->fadeFxUp(speed);
}
static void vblCallback(void *refCon) {
Commit: caaf249e09fcfec5984b106d091eb06094563439
https://github.com/scummvm/scummvm/commit/caaf249e09fcfec5984b106d091eb06094563439
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Implement music for DOS version
PSX and compressed versions will follow shortly after
Changed paths:
engines/sword1/animation.cpp
engines/sword1/animation.h
engines/sword1/logic.cpp
engines/sword1/music.h
engines/sword1/sound.cpp
engines/sword1/sound.h
engines/sword1/staticres.cpp
engines/sword1/sword1.cpp
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index dc15c888823..af03350dae5 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -101,8 +101,8 @@ static const char *const sequenceListPSX[20] = {
// Basic movie player
///////////////////////////////////////////////////////////////////////////////
-MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType)
- : _vm(vm), _textMan(textMan), _resMan(resMan), _system(system), _textX(0), _textY(0), _textWidth(0), _textHeight(0), _textColor(1) {
+MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Sound *sound, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType)
+ : _vm(vm), _textMan(textMan), _resMan(resMan), _sound(sound), _system(system), _textX(0), _textY(0), _textWidth(0), _textHeight(0), _textColor(1) {
_decoderType = decoderType;
_decoder = decoder;
@@ -318,6 +318,9 @@ bool MoviePlayer::playVideo() {
_vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h);
}
+ _sound->setCrossFadeIncrement();
+ _sound->updateSampleStreaming();
+
if (_decoder->hasDirtyPalette()) {
_vm->_system->getPaletteManager()->setPalette(_decoder->getPalette(), 0, 256);
@@ -512,7 +515,7 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
// Factory function for creating the appropriate cutscene player
///////////////////////////////////////////////////////////////////////////////
-MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system) {
+MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Sound *sound, OSystem *system) {
Common::String filename;
// For the PSX version, we'll try the PlayStation stream files
@@ -524,7 +527,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
#ifdef USE_RGB_COLOR
// All BS1 PSX videos run the videos at 2x speed
Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x);
- return new MoviePlayer(vm, textMan, resMan, system, psxDecoder, kVideoDecoderPSX);
+ return new MoviePlayer(vm, textMan, resMan, sound, system, psxDecoder, kVideoDecoderPSX);
#else
GUI::MessageDialog dialog(Common::U32String::format(_("PSX stream cutscene '%s' cannot be played in paletted mode"), filename.c_str()), _("OK"));
dialog.runModal();
@@ -537,14 +540,14 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
if (Common::File::exists(filename)) {
Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder();
- return new MoviePlayer(vm, textMan, resMan, system, smkDecoder, kVideoDecoderSMK);
+ return new MoviePlayer(vm, textMan, resMan, sound, system, smkDecoder, kVideoDecoderSMK);
}
filename = Common::String::format("%s.dxa", sequenceList[id]);
if (Common::File::exists(filename)) {
Video::VideoDecoder *dxaDecoder = new Video::DXADecoder();
- return new MoviePlayer(vm, textMan, resMan, system, dxaDecoder, kVideoDecoderDXA);
+ return new MoviePlayer(vm, textMan, resMan, sound, system, dxaDecoder, kVideoDecoderDXA);
}
// Old MPEG2 cutscenes
@@ -555,7 +558,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
// HACK: Old ScummVM builds ignored the AVI frame rate field and forced the video
// to be played back at 12fps.
Video::VideoDecoder *aviDecoder = new Video::AVIDecoder(12);
- return new MoviePlayer(vm, textMan, resMan, system, aviDecoder, kVideoDecoderMP2);
+ return new MoviePlayer(vm, textMan, resMan, sound, system, aviDecoder, kVideoDecoderMP2);
#else
GUI::MessageDialog dialog(_("MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"), _("OK"));
dialog.runModal();
diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h
index fbdf4dc2dbc..9ab1d765dab 100644
--- a/engines/sword1/animation.h
+++ b/engines/sword1/animation.h
@@ -60,7 +60,7 @@ public:
class MoviePlayer {
public:
- MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType);
+ MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Sound *sound, OSystem *system, Video::VideoDecoder *decoder, DecoderType decoderType);
virtual ~MoviePlayer();
bool load(uint32 id);
void play();
@@ -69,6 +69,7 @@ protected:
SwordEngine *_vm;
Text *_textMan;
ResMan *_resMan;
+ Sound *_sound;
OSystem *_system;
Common::List<MovieText> _movieTexts;
int _textX, _textY, _textWidth, _textHeight;
@@ -88,7 +89,7 @@ protected:
void convertColor(byte r, byte g, byte b, float &h, float &s, float &v);
};
-MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, OSystem *system);
+MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Sound *sound, OSystem *system);
} // End of namespace Sword1
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 5fea76143d2..62f1cc1fe47 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -129,7 +129,7 @@ void Logic::newScreen(uint32 screen) {
_scriptVars[GEORGE_WALKING] = 0;
}
SwordEngine::_systemVars.justRestoredGame = 0;
- _music->startMusic(_scriptVars[CURRENT_MUSIC], 1);
+ _sound->streamMusicFile(_scriptVars[CURRENT_MUSIC], 1);
} else { // if we haven't just restored a game, set George to stand, etc
compact->o_screen = _scriptVars[NEW_SCREEN]; //move the mega/player at this point between screens
fnStandAt(compact, PLAYER, _scriptVars[CHANGE_X], _scriptVars[CHANGE_Y], _scriptVars[CHANGE_DIR], _scriptVars[CHANGE_STANCE], 0, 0);
@@ -986,7 +986,7 @@ int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int3
// meantime, we don't want any looping sound effects still playing.
_sound->clearAllFx();
- MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _system);
+ MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _sound, _system);
if (player) {
_screen->clearScreen();
if (player->load(sequenceId))
@@ -1663,8 +1663,7 @@ int Logic::fnPlayMusic(Object *cpt, int32 id, int32 tuneId, int32 loopFlag, int3
else
_scriptVars[CURRENT_MUSIC] = 0;
- //_sound->streamSample(tuneId, loopFlag);
- _music->startMusic(tuneId, loopFlag);
+ _sound->streamMusicFile(tuneId, loopFlag);
return SCRIPT_CONT;
}
diff --git a/engines/sword1/music.h b/engines/sword1/music.h
index cfd432e6077..a8e86e20be2 100644
--- a/engines/sword1/music.h
+++ b/engines/sword1/music.h
@@ -85,7 +85,7 @@ private:
static void passMixerFunc(void *param, int16 *buf, uint len);
void mixer(int16 *buf, uint32 len);
- static const char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
+ char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
};
} // End of namespace Sword1
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 7a986fcdef7..0cda8f31faf 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -40,7 +40,6 @@
namespace Sword1 {
-#define SOUND_SPEECH_ID 1
#define SPEECH_FLAGS (Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN)
Sound::Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan)
@@ -53,6 +52,8 @@ Sound::Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan)
_endOfQueue = 0;
_currentCowFile = 0;
+ _stream[0] = Audio::makeQueuingAudioStream(11025, false);
+ _stream[1] = Audio::makeQueuingAudioStream(11025, false);
//if (!GetVolumes()) {
volFX[0] = 8;
volFX[1] = 8;
@@ -62,6 +63,8 @@ Sound::Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan)
volMusic[1] = 8;
// SetVolumes();
//}
+
+ memset(_fxQueue, 0, sizeof(_fxQueue));
}
Sound::~Sound() {
@@ -265,7 +268,10 @@ void Sound::removeFromQueue(uint32 fxNo) {
}
void Sound::engine() {
- // First of all, add any random sfx to the queue...
+ // Update music streaming...
+ updateSampleStreaming();
+
+ // Add any random sfx to the queue...
for (uint16 cnt = 0; cnt < TOTAL_FX_PER_ROOM; cnt++) {
uint16 fxNo = _roomsFixedFx[Logic::_scriptVars[SCREEN]][cnt];
if (fxNo) {
@@ -803,7 +809,132 @@ void Sound::playSample(int32 fxNo) {
}
}
-int32 Sound::streamSample(char filename[], int32 looped) {
+int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
+ int32 oldHandleId, newHandleId;
+
+ struct WaveHeader {
+ uint32 riffTag;
+ uint32 riffSize;
+ uint32 waveTag;
+ uint32 fmtTag;
+ uint32 fmtSize;
+
+ // Format subchunk
+ uint16 wFormatTag;
+ uint16 wChannels;
+ uint32 dwSamplesPerSec;
+ uint32 dwAvgBytesPerSec;
+ uint16 wBlockAlign;
+ uint16 wBitsPerSample;
+ uint32 dwDataTag;
+ uint32 dwDataSize;
+ };
+
+ WaveHeader wavHead;
+ Common::File tmp;
+ Common::String filename(_tuneList[tuneId]);
+
+ if (tmp.exists(filename + ".flac")) {
+ filename = filename + ".flac";
+ } else if (tmp.exists(filename + ".fla")) {
+ filename = filename + ".fla";
+ } else if (tmp.exists(filename + ".ogg")) {
+ filename = filename + ".ogg";
+ } else if (tmp.exists(filename + ".mp3")) {
+ filename = filename + ".mp3";
+ } else if (tmp.exists(filename + ".wav")) {
+ filename = filename + ".wav";
+ } else if (tmp.exists(filename + ".aif")) {
+ filename = filename + ".aif";
+ }
+
+ newHandleId = 0;
+ if ((streamSamplePlaying[0]) || (streamSamplePlaying[1])) {
+ if (streamSamplePlaying[0])
+ newHandleId = 1;
+ oldHandleId = 1 - newHandleId;
+
+ streamLoopingFlag[newHandleId] = looped;
+
+ streamSampleFading[oldHandleId] = -12;
+ streamSampleFading[newHandleId] = 1;
+
+ if (streamSamplePlaying[newHandleId]) {
+ _mixer->stopHandle(hStreamSample[newHandleId]);
+ _stream[newHandleId]->finish();
+ streamFile[newHandleId].close();
+
+ if (filename.empty())
+ return 1;
+
+ debug(5, "Sound::streamMusicFile(): interrupting sound in handle %d to play %s", newHandleId, filename.c_str());
+ _stream[newHandleId] = Audio::makeQueuingAudioStream(11025, false);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &hStreamSample[newHandleId], _stream[newHandleId]);
+
+ _mixer->setChannelRate(hStreamSample[newHandleId], 11025);
+ _mixer->setChannelVolume(hStreamSample[newHandleId], 2 * (2 * (volMusic[0] + volMusic[1])));
+ _mixer->setChannelBalance(hStreamSample[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
+
+ if (!streamFile[newHandleId].open(filename))
+ debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
+
+ if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
+ streamFile[newHandleId].close();
+ return 1;
+ }
+
+ streamSamplePlaying[newHandleId] = true;
+ return 2;
+ } else {
+ if (filename.empty())
+ return 1;
+
+ debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d with other handle busy", filename.c_str(), newHandleId);
+ _mixer->stopHandle(hStreamSample[newHandleId]);
+ _stream[newHandleId] = Audio::makeQueuingAudioStream(11025, false);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &hStreamSample[newHandleId], _stream[newHandleId]);
+
+ _mixer->setChannelRate(hStreamSample[newHandleId], 11025);
+ _mixer->setChannelVolume(hStreamSample[newHandleId], 0);
+ _mixer->setChannelBalance(hStreamSample[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
+
+ if (!streamFile[newHandleId].open(filename))
+ debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
+
+ if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
+ streamFile[newHandleId].close();
+ return 1;
+ }
+
+ streamSamplePlaying[newHandleId] = true;
+ }
+ } else {
+ if (filename.empty())
+ return 1;
+
+ debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d", filename.c_str(), newHandleId);
+
+ _mixer->stopHandle(hStreamSample[newHandleId]);
+ _stream[newHandleId] = Audio::makeQueuingAudioStream(11025, false);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &hStreamSample[newHandleId], _stream[newHandleId]);
+
+ _mixer->setChannelRate(hStreamSample[newHandleId], 11025);
+ _mixer->setChannelVolume(hStreamSample[newHandleId], 2 * (3 * (volMusic[0] + volMusic[1])));
+ _mixer->setChannelBalance(hStreamSample[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
+
+ if (!streamFile[newHandleId].open(filename))
+ debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
+
+ if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
+ streamFile[newHandleId].close();
+ return 4;
+ }
+
+ streamSamplePlaying[newHandleId] = true;
+ }
+
+ streamLoopingFlag[newHandleId] = looped;
+
return 0;
}
@@ -816,18 +947,23 @@ void Sound::updateSampleStreaming() {
crossFadeIncrement = false;
if (streamSampleFading[i] < 0) {
- //AIL_set_sample_volume(hStreamSample[i], ((0 - streamSampleFading[i]) * 3 * (volMusic[0] + volMusic[1])) / 16);
+ debug("Sound::updateSampleStreaming(): Fading %s to %d", streamFile[i].getName(),
+ 2 * (((0 - streamSampleFading[i]) * 3 * (volMusic[0] + volMusic[1])) / 16));
+ _mixer->setChannelVolume(hStreamSample[i],
+ 2 * (((0 - streamSampleFading[i]) * 3 * (volMusic[0] + volMusic[1])) / 16));
+
streamSampleFading[i] += 1;
if (streamSampleFading[i] == 0) {
- //AIL_stop_sample(hStreamSample[i]);
- //AIL_release_sample_handle(hStreamSample[i]);
- //close(streamFile[i]);
- streamSamplePlaying[i] = 0;
- //MEM_free_lock(streamBuffer[i][0], bufferSize);
- //MEM_free_lock(streamBuffer[i][1], bufferSize);
+ streamFile[i].close();
+
+ streamSamplePlaying[i] = false;
}
} else {
- //AIL_set_sample_volume(hStreamSample[i], (streamSampleFading[i] * 3 * (volMusic[0] + volMusic[1])) / 16);
+ debug("Sound::updateSampleStreaming(): Fading %s to %d", streamFile[i].getName(),
+ 2 * ((streamSampleFading[i] * 3 * (volMusic[0] + volMusic[1])) / 16));
+ _mixer->setChannelVolume(hStreamSample[i],
+ 2 * ((streamSampleFading[i] * 3 * (volMusic[0] + volMusic[1])) / 16));
+
streamSampleFading[i] += 1;
if (streamSampleFading[i] == 17) {
streamSampleFading[i] = 0;
@@ -835,14 +971,38 @@ void Sound::updateSampleStreaming() {
}
}
}
- //ServeSample(hStreamSample[i], streamBuffer[i], bufferSize, streamFile[i], i);
- //if (AIL_sample_status(hStreamSample[i]) != SMP_PLAYING) {
- // AIL_release_sample_handle(hStreamSample[i]);
- // streamSamplePlaying[i] = FALSE;
- // close(streamFile[i]);
- // MEM_free_lock(streamBuffer[i][0], bufferSize);
- // MEM_free_lock(streamBuffer[i][1], bufferSize);
- //}
+
+ if (streamFile[i].isOpen())
+ serveSample(&streamFile[i], i);
+
+ if (!_mixer->isSoundHandleActive(hStreamSample[i]) || _stream[i]->endOfData()) {
+ streamSamplePlaying[i] = false;
+ streamFile[i].close();
+ }
+ }
+ }
+}
+
+void Sound::serveSample(Common::File *file, int32 i) {
+ int32 len;
+ int32 nominalSize = MUSIC_BUFFER_SIZE;
+ byte *buf = (byte *)malloc(nominalSize);
+
+ if (!musicPaused[i]) {
+ if (_stream[i]->numQueuedStreams() < 4) {
+ len = file->read(buf, nominalSize);
+ if (len < nominalSize) {
+ if (streamLoopingFlag[i]) {
+ file->seek(44, SEEK_SET);
+ file->read(buf + len, nominalSize - len);
+ len = nominalSize;
+ debug(5, "Sound::serveSample(): Looping music file %s", file->getName());
+ } else {
+ debug(5, "Sound::serveSample(): Finished feeding music file %s", file->getName());
+ }
+ }
+
+ _stream[i]->queueBuffer(buf, len, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
}
}
}
@@ -889,6 +1049,8 @@ void Sound::playFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]) {
_mixer->setChannelVolume(hSampleFX[i], 2 * ((v0 + v1) / 8));
_mixer->setChannelBalance(hSampleFX[i], scalePan(64 + ((v1 - v0) / 4)));
}
+
+ return;
}
}
}
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index a99ca4e14ce..d32d1c0c350 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -32,6 +32,7 @@
#include "common/util.h"
#include "audio/mixer.h"
+#include "audio/audiostream.h"
namespace Audio {
class Mixer;
@@ -71,15 +72,15 @@ struct FxDef {
class ResMan;
class SwordEngine;
-#define WAVE_VOL_TAB_LENGTH 480
-#define WAVE_VOL_THRESHOLD 190000 //120000
-#define MUSIC_UNDERSCORE 50
-#define NEG_MOUTH_THRESHOLD (-750)
-#define POS_MOUTH_THRESHOLD 750
-#define MAX_FX 4
-#define MAX_MUSIC 2
-#define S_STATUS_FINISHED 1
-#define S_STATUS_RUNNING 0
+#define MUSIC_UNDERSCORE 50
+#define NEG_MOUTH_THRESHOLD -750
+#define POS_MOUTH_THRESHOLD 750
+#define MAX_FX 4
+#define MAX_MUSIC 2
+#define S_STATUS_FINISHED 1
+#define S_STATUS_RUNNING 0
+#define MUSIC_BUFFER_SIZE 0x4000
+#define TOTAL_TUNES 270
enum CowMode {
CowWave = 0,
@@ -137,6 +138,7 @@ private:
static const char _musicList[270];
static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
static const FxDef _fxList[312];
+ static const char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
// New stuff
public:
@@ -156,7 +158,8 @@ public:
void stopSpeech();
int32 getSpeechSize(byte *compData, uint32 compSize);
- int32 streamSample(char filename[], int32 looped);
+ int32 streamMusicFile(int32 tuneId, int32 looped);
+ void serveSample(Common::File *file, int32 i);
void reduceMusicVolume();
void restoreMusicVolume();
@@ -198,12 +201,14 @@ public:
Audio::SoundHandle hSampleFX[MAX_FX];
Audio::SoundHandle hSampleSpeech;
Audio::SoundHandle hSampleMusic[MAX_MUSIC];
- int32 streamSamplePlaying[MAX_MUSIC] = { 0, 0 };
+ bool streamSamplePlaying[MAX_MUSIC] = { false, false };
int32 streamSampleFading[MAX_MUSIC] = { 0, 0 };
- int32 streamLoopingFlag[MAX_MUSIC] = { 0, 0 };
+ bool streamLoopingFlag[MAX_MUSIC] = { false, false };
Audio::SoundHandle hStreamSample[MAX_MUSIC];
- int32 streamFile[MAX_MUSIC];
- byte *streamBuffer[MAX_MUSIC][2];
+ Audio::QueuingAudioStream *_stream[MAX_MUSIC];
+ int lastStreamBufferIdx[MAX_MUSIC] = { 0, 0 };
+
+ Common::File streamFile[MAX_MUSIC];
bool fxSampleBusy[MAX_FX] = { false, false, false, false };
int32 fxSampleID[MAX_FX] = { 0, 0, 0, 0 };
bool speechSampleBusy = false;
diff --git a/engines/sword1/staticres.cpp b/engines/sword1/staticres.cpp
index cef0fe83a43..9476ffcbced 100644
--- a/engines/sword1/staticres.cpp
+++ b/engines/sword1/staticres.cpp
@@ -2587,7 +2587,7 @@ RoomDef Screen::_roomDefTable[TOTAL_ROOMS] = { // these are NOT const
}
};
-const char Music::_tuneList[TOTAL_TUNES][8] = {
+const char Sound::_tuneList[TOTAL_TUNES][8] = {
"", // 0 SPARE
"1m2", // DONE 1 George picks up the newspaper
"1m3", // DONE 2 In the alley for the first time
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 14c41a1126b..26159d34ac6 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -1036,6 +1036,7 @@ uint8 SwordEngine::mainLoop() {
_systemVars.gameCycle++;
_logic->engine();
+ _sound->setCrossFadeIncrement();
_logic->updateScreenParams(); // sets scrolling
_screen->draw();
@@ -1154,6 +1155,8 @@ void SwordEngine::pollInput(uint32 delay) { //copied and mutilated from sky.cpp
}
}
+ _sound->updateSampleStreaming();
+
_screen->_screenAccessMutex.lock();
_system->updateScreen();
_screen->_screenAccessMutex.unlock();
Commit: 023426f90d253f7570c9caf5c3ca4d3abafa4e5a
https://github.com/scummvm/scummvm/commit/023426f90d253f7570c9caf5c3ca4d3abafa4e5a
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: Fix crashes and music pausing
Changed paths:
engines/sword1/sound.cpp
engines/sword1/sound.h
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 0cda8f31faf..a50cd13b140 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -860,8 +860,7 @@ int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
streamSampleFading[newHandleId] = 1;
if (streamSamplePlaying[newHandleId]) {
- _mixer->stopHandle(hStreamSample[newHandleId]);
- _stream[newHandleId]->finish();
+ _mixer->stopHandle(hSampleMusic[newHandleId]);
streamFile[newHandleId].close();
if (filename.empty())
@@ -869,11 +868,11 @@ int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
debug(5, "Sound::streamMusicFile(): interrupting sound in handle %d to play %s", newHandleId, filename.c_str());
_stream[newHandleId] = Audio::makeQueuingAudioStream(11025, false);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &hStreamSample[newHandleId], _stream[newHandleId]);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &hSampleMusic[newHandleId], _stream[newHandleId]);
- _mixer->setChannelRate(hStreamSample[newHandleId], 11025);
- _mixer->setChannelVolume(hStreamSample[newHandleId], 2 * (2 * (volMusic[0] + volMusic[1])));
- _mixer->setChannelBalance(hStreamSample[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
+ _mixer->setChannelRate(hSampleMusic[newHandleId], 11025);
+ _mixer->setChannelVolume(hSampleMusic[newHandleId], 2 * (2 * (volMusic[0] + volMusic[1])));
+ _mixer->setChannelBalance(hSampleMusic[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
if (!streamFile[newHandleId].open(filename))
debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
@@ -890,13 +889,13 @@ int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
return 1;
debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d with other handle busy", filename.c_str(), newHandleId);
- _mixer->stopHandle(hStreamSample[newHandleId]);
+ _mixer->stopHandle(hSampleMusic[newHandleId]);
_stream[newHandleId] = Audio::makeQueuingAudioStream(11025, false);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &hStreamSample[newHandleId], _stream[newHandleId]);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &hSampleMusic[newHandleId], _stream[newHandleId]);
- _mixer->setChannelRate(hStreamSample[newHandleId], 11025);
- _mixer->setChannelVolume(hStreamSample[newHandleId], 0);
- _mixer->setChannelBalance(hStreamSample[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
+ _mixer->setChannelRate(hSampleMusic[newHandleId], 11025);
+ _mixer->setChannelVolume(hSampleMusic[newHandleId], 0);
+ _mixer->setChannelBalance(hSampleMusic[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
if (!streamFile[newHandleId].open(filename))
debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
@@ -914,13 +913,13 @@ int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d", filename.c_str(), newHandleId);
- _mixer->stopHandle(hStreamSample[newHandleId]);
+ _mixer->stopHandle(hSampleMusic[newHandleId]);
_stream[newHandleId] = Audio::makeQueuingAudioStream(11025, false);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &hStreamSample[newHandleId], _stream[newHandleId]);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &hSampleMusic[newHandleId], _stream[newHandleId]);
- _mixer->setChannelRate(hStreamSample[newHandleId], 11025);
- _mixer->setChannelVolume(hStreamSample[newHandleId], 2 * (3 * (volMusic[0] + volMusic[1])));
- _mixer->setChannelBalance(hStreamSample[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
+ _mixer->setChannelRate(hSampleMusic[newHandleId], 11025);
+ _mixer->setChannelVolume(hSampleMusic[newHandleId], 2 * (3 * (volMusic[0] + volMusic[1])));
+ _mixer->setChannelBalance(hSampleMusic[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
if (!streamFile[newHandleId].open(filename))
debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
@@ -949,7 +948,7 @@ void Sound::updateSampleStreaming() {
if (streamSampleFading[i] < 0) {
debug("Sound::updateSampleStreaming(): Fading %s to %d", streamFile[i].getName(),
2 * (((0 - streamSampleFading[i]) * 3 * (volMusic[0] + volMusic[1])) / 16));
- _mixer->setChannelVolume(hStreamSample[i],
+ _mixer->setChannelVolume(hSampleMusic[i],
2 * (((0 - streamSampleFading[i]) * 3 * (volMusic[0] + volMusic[1])) / 16));
streamSampleFading[i] += 1;
@@ -961,7 +960,7 @@ void Sound::updateSampleStreaming() {
} else {
debug("Sound::updateSampleStreaming(): Fading %s to %d", streamFile[i].getName(),
2 * ((streamSampleFading[i] * 3 * (volMusic[0] + volMusic[1])) / 16));
- _mixer->setChannelVolume(hStreamSample[i],
+ _mixer->setChannelVolume(hSampleMusic[i],
2 * ((streamSampleFading[i] * 3 * (volMusic[0] + volMusic[1])) / 16));
streamSampleFading[i] += 1;
@@ -975,9 +974,11 @@ void Sound::updateSampleStreaming() {
if (streamFile[i].isOpen())
serveSample(&streamFile[i], i);
- if (!_mixer->isSoundHandleActive(hStreamSample[i]) || _stream[i]->endOfData()) {
+ if (!_mixer->isSoundHandleActive(hSampleMusic[i]) || _stream[i]->endOfData()) {
streamSamplePlaying[i] = false;
streamFile[i].close();
+ _stream[i]->finish();
+ _stream[i] = nullptr;
}
}
}
@@ -998,7 +999,9 @@ void Sound::serveSample(Common::File *file, int32 i) {
len = nominalSize;
debug(5, "Sound::serveSample(): Looping music file %s", file->getName());
} else {
- debug(5, "Sound::serveSample(): Finished feeding music file %s", file->getName());
+ Common::String fname(file->getName());
+ if (!fname.empty())
+ debug(5, "Sound::serveSample(): Finished feeding music file %s", file->getName());
}
}
@@ -1165,14 +1168,14 @@ void Sound::reduceMusicVolume() {
musicFadeVolume[1] = volMusic[0] * MUSIC_UNDERSCORE / 100; // We are explicitly accessing volMusic[0] again
// Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
- _mixer->setChannelVolume(hStreamSample[0], 2 * ((musicFadeVolume[0] + musicFadeVolume[1]) * 3));
+ _mixer->setChannelVolume(hSampleMusic[0], 2 * ((musicFadeVolume[0] + musicFadeVolume[1]) * 3));
}
void Sound::restoreMusicVolume() {
Common::StackLock lock(_soundMutex);
// Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
- _mixer->setChannelVolume(hStreamSample[0], 2 * ((volMusic[0] + volMusic[1]) * 3));
+ _mixer->setChannelVolume(hSampleMusic[0], 2 * ((volMusic[0] + volMusic[1]) * 3));
}
void Sound::setCrossFadeIncrement() {
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index d32d1c0c350..f23436fd5df 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -204,7 +204,7 @@ public:
bool streamSamplePlaying[MAX_MUSIC] = { false, false };
int32 streamSampleFading[MAX_MUSIC] = { 0, 0 };
bool streamLoopingFlag[MAX_MUSIC] = { false, false };
- Audio::SoundHandle hStreamSample[MAX_MUSIC];
+
Audio::QueuingAudioStream *_stream[MAX_MUSIC];
int lastStreamBufferIdx[MAX_MUSIC] = { 0, 0 };
Commit: 5fbb2a281eb5b38b6024e9b509bd8c8c4a1ae380
https://github.com/scummvm/scummvm/commit/5fbb2a281eb5b38b6024e9b509bd8c8c4a1ae380
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Clean-up and preparation for compressed music
Changed paths:
engines/sword1/logic.cpp
engines/sword1/sound.cpp
engines/sword1/sound.h
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 62f1cc1fe47..58c12a826aa 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -1650,7 +1650,7 @@ int Logic::fnPlayFx(Object *cpt, int32 id, int32 fxNo, int32 b, int32 c, int32 d
}
int Logic::fnStopFx(Object *cpt, int32 id, int32 fxNo, int32 b, int32 c, int32 d, int32 z, int32 x) {
- _sound->stopFX(fxNo);
+ _sound->stopSample(fxNo);
_sound->removeFromQueue(fxNo);
return SCRIPT_CONT;
}
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index a50cd13b140..7925c3bbd06 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -37,6 +37,7 @@
#include "audio/decoders/raw.h"
#include "audio/decoders/vorbis.h"
#include "audio/decoders/xa.h"
+#include "audio/decoders/aiff.h"
namespace Sword1 {
@@ -52,8 +53,8 @@ Sound::Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan)
_endOfQueue = 0;
_currentCowFile = 0;
- _stream[0] = Audio::makeQueuingAudioStream(11025, false);
- _stream[1] = Audio::makeQueuingAudioStream(11025, false);
+ _musicOutputStream[0] = Audio::makeQueuingAudioStream(DEFAULT_SAMPLE_RATE, false);
+ _musicOutputStream[1] = Audio::makeQueuingAudioStream(DEFAULT_SAMPLE_RATE, false);
//if (!GetVolumes()) {
volFX[0] = 8;
volFX[1] = 8;
@@ -698,7 +699,7 @@ int32 Sound::checkSampleStatus(int32 id) {
int32 Sound::checkSpeechStatus() {
Common::StackLock lock(_soundMutex);
- if (!speechSampleBusy || speechSamplePaused)
+ if (!speechSampleBusy || speechPaused)
return S_STATUS_FINISHED;
if (!_mixer->isSoundHandleActive(hSampleSpeech)) {
@@ -765,12 +766,13 @@ static void soundCallback(void *refCon) {
snd->fxFadeVolume[0] = 8 * snd->volFX[0] - (8 * snd->volFX[0] * snd->fxCount * snd->fxFadingRate / 128);
snd->fxFadeVolume[1] = 8 * snd->volFX[1] - (8 * snd->volFX[1] * snd->fxFadingRate * snd->fxCount / 128);
}
+
for (int i = 0; i < MAX_FX; i++) {
if (snd->fxSampleBusy[i]) {
int32 targetVolume = (snd->fxFadeVolume[0] + snd->fxFadeVolume[1]) / 2;
// Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
- snd->_mixer->setChannelVolume(snd->hSampleFX[i], targetVolume * 2);
+ snd->setFXVolume((byte)(targetVolume * 2), i);
}
}
}
@@ -785,6 +787,10 @@ void Sound::uninstallFadeTimer() {
_vm->getTimerManager()->removeTimerProc(&soundCallback);
}
+void Sound::setFXVolume(byte targetVolume, int handleIdx) {
+ _mixer->setChannelVolume(hSampleFX[handleIdx], targetVolume);
+}
+
void Sound::playSample(int32 fxNo) {
uint8 *samplePtr;
uint32 vol[2] = { 0, 0 };
@@ -809,43 +815,91 @@ void Sound::playSample(int32 fxNo) {
}
}
+void Sound::stopSample(int32 fxNo) {
+ stopFX(fxNo);
+}
+
+void Sound::prepareMusicStreaming(Common::String filename, int newHandleId, uint32 volume, int8 pan, MusCompMode assignedMode) {
+ int sampleRate = DEFAULT_SAMPLE_RATE;
+ WaveHeader wavHead;
+ Audio::RewindableAudioStream *compressedStream = nullptr;
+ bool isStereo = false;
+
+ if (filename.empty())
+ return;
+
+ if (!streamFile[newHandleId].open(filename))
+ debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
+
+ if (assignedMode == MusWav) {
+ if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
+ debug(5, "Sound::streamMusicFile(): couldn't read from file %s, bailing out...", filename.c_str());
+ streamFile[newHandleId].close();
+ return;
+ }
+
+ sampleRate = wavHead.dwSamplesPerSec;
+ } else if (assignedMode == MusFLAC) {
+ compressedStream = Audio::makeFLACStream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ sampleRate = compressedStream->getRate();
+ } else if (assignedMode == MusVorbis) {
+ compressedStream = Audio::makeVorbisStream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ sampleRate = compressedStream->getRate();
+ } else if (assignedMode == MusMP3) {
+ compressedStream = Audio::makeMP3Stream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ sampleRate = compressedStream->getRate();
+ } else if (assignedMode == MusAif) {
+ compressedStream = Audio::makeAIFFStream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ sampleRate = compressedStream->getRate();
+ }
+
+ if (assignedMode != MusWav && !compressedStream) {
+ debug(5, "Sound::streamMusicFile(): couldn't process compressed file %s, bailing out...", filename.c_str());
+ streamFile[newHandleId].close();
+ return;
+ }
+
+ _musicOutputStream[newHandleId] = Audio::makeQueuingAudioStream(sampleRate, isStereo);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &hSampleMusic[newHandleId], _musicOutputStream[newHandleId]);
+
+ if (assignedMode != MusWav) {
+ _musicOutputStream[newHandleId]->queueAudioStream(compressedStream);
+ }
+
+ _mixer->setChannelRate(hSampleMusic[newHandleId], sampleRate);
+ _mixer->setChannelVolume(hSampleMusic[newHandleId], volume);
+ _mixer->setChannelBalance(hSampleMusic[newHandleId], pan);
+
+ streamSamplePlaying[newHandleId] = true;
+ streamFormat[newHandleId] = assignedMode;
+}
+
int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
int32 oldHandleId, newHandleId;
- struct WaveHeader {
- uint32 riffTag;
- uint32 riffSize;
- uint32 waveTag;
- uint32 fmtTag;
- uint32 fmtSize;
-
- // Format subchunk
- uint16 wFormatTag;
- uint16 wChannels;
- uint32 dwSamplesPerSec;
- uint32 dwAvgBytesPerSec;
- uint16 wBlockAlign;
- uint16 wBitsPerSample;
- uint32 dwDataTag;
- uint32 dwDataSize;
- };
-
- WaveHeader wavHead;
Common::File tmp;
Common::String filename(_tuneList[tuneId]);
+ MusCompMode assignedMode = MusWav;
+
if (tmp.exists(filename + ".flac")) {
filename = filename + ".flac";
+ assignedMode = MusFLAC;
} else if (tmp.exists(filename + ".fla")) {
filename = filename + ".fla";
+ assignedMode = MusFLAC;
} else if (tmp.exists(filename + ".ogg")) {
filename = filename + ".ogg";
+ assignedMode = MusVorbis;
} else if (tmp.exists(filename + ".mp3")) {
filename = filename + ".mp3";
+ assignedMode = MusMP3;
} else if (tmp.exists(filename + ".wav")) {
filename = filename + ".wav";
+ assignedMode = MusWav;
} else if (tmp.exists(filename + ".aif")) {
filename = filename + ".aif";
+ assignedMode = MusAif;
}
newHandleId = 0;
@@ -863,73 +917,29 @@ int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
_mixer->stopHandle(hSampleMusic[newHandleId]);
streamFile[newHandleId].close();
- if (filename.empty())
- return 1;
+ prepareMusicStreaming(filename, newHandleId,
+ 2 * (2 * (volMusic[0] + volMusic[1])),
+ scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
+ assignedMode);
debug(5, "Sound::streamMusicFile(): interrupting sound in handle %d to play %s", newHandleId, filename.c_str());
- _stream[newHandleId] = Audio::makeQueuingAudioStream(11025, false);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &hSampleMusic[newHandleId], _stream[newHandleId]);
-
- _mixer->setChannelRate(hSampleMusic[newHandleId], 11025);
- _mixer->setChannelVolume(hSampleMusic[newHandleId], 2 * (2 * (volMusic[0] + volMusic[1])));
- _mixer->setChannelBalance(hSampleMusic[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
-
- if (!streamFile[newHandleId].open(filename))
- debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
- if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
- streamFile[newHandleId].close();
- return 1;
- }
-
- streamSamplePlaying[newHandleId] = true;
return 2;
} else {
- if (filename.empty())
- return 1;
+ prepareMusicStreaming(filename, newHandleId,
+ 0,
+ scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
+ assignedMode);
debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d with other handle busy", filename.c_str(), newHandleId);
- _mixer->stopHandle(hSampleMusic[newHandleId]);
- _stream[newHandleId] = Audio::makeQueuingAudioStream(11025, false);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &hSampleMusic[newHandleId], _stream[newHandleId]);
-
- _mixer->setChannelRate(hSampleMusic[newHandleId], 11025);
- _mixer->setChannelVolume(hSampleMusic[newHandleId], 0);
- _mixer->setChannelBalance(hSampleMusic[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
-
- if (!streamFile[newHandleId].open(filename))
- debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
-
- if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
- streamFile[newHandleId].close();
- return 1;
- }
-
- streamSamplePlaying[newHandleId] = true;
}
} else {
- if (filename.empty())
- return 1;
+ prepareMusicStreaming(filename, newHandleId,
+ 2 * (3 * (volMusic[0] + volMusic[1])),
+ scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
+ assignedMode);
debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d", filename.c_str(), newHandleId);
-
- _mixer->stopHandle(hSampleMusic[newHandleId]);
- _stream[newHandleId] = Audio::makeQueuingAudioStream(11025, false);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &hSampleMusic[newHandleId], _stream[newHandleId]);
-
- _mixer->setChannelRate(hSampleMusic[newHandleId], 11025);
- _mixer->setChannelVolume(hSampleMusic[newHandleId], 2 * (3 * (volMusic[0] + volMusic[1])));
- _mixer->setChannelBalance(hSampleMusic[newHandleId], scalePan(64 + (4 * (volMusic[1] - volMusic[0]))));
-
- if (!streamFile[newHandleId].open(filename))
- debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
-
- if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
- streamFile[newHandleId].close();
- return 4;
- }
-
- streamSamplePlaying[newHandleId] = true;
}
streamLoopingFlag[newHandleId] = looped;
@@ -956,6 +966,8 @@ void Sound::updateSampleStreaming() {
streamFile[i].close();
streamSamplePlaying[i] = false;
+ _musicOutputStream[i]->finish();
+ _musicOutputStream[i] = nullptr;
}
} else {
debug("Sound::updateSampleStreaming(): Fading %s to %d", streamFile[i].getName(),
@@ -974,11 +986,12 @@ void Sound::updateSampleStreaming() {
if (streamFile[i].isOpen())
serveSample(&streamFile[i], i);
- if (!_mixer->isSoundHandleActive(hSampleMusic[i]) || _stream[i]->endOfData()) {
+ if (!_mixer->isSoundHandleActive(hSampleMusic[i]) ||
+ (_musicOutputStream[i] && _musicOutputStream[i]->endOfData())) {
streamSamplePlaying[i] = false;
streamFile[i].close();
- _stream[i]->finish();
- _stream[i] = nullptr;
+ _musicOutputStream[i]->finish();
+ _musicOutputStream[i] = nullptr;
}
}
}
@@ -989,8 +1002,8 @@ void Sound::serveSample(Common::File *file, int32 i) {
int32 nominalSize = MUSIC_BUFFER_SIZE;
byte *buf = (byte *)malloc(nominalSize);
- if (!musicPaused[i]) {
- if (_stream[i]->numQueuedStreams() < 4) {
+ if (!musicPaused[i] && streamFormat[i] == MusWav) {
+ if (_musicOutputStream[i]->numQueuedStreams() < 4) {
len = file->read(buf, nominalSize);
if (len < nominalSize) {
if (streamLoopingFlag[i]) {
@@ -1005,8 +1018,10 @@ void Sound::serveSample(Common::File *file, int32 i) {
}
}
- _stream[i]->queueBuffer(buf, len, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
+ _musicOutputStream[i]->queueBuffer(buf, len, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
}
+ } else if (streamFormat[i] != MusWav && streamLoopingFlag[i]) {
+
}
}
@@ -1105,24 +1120,6 @@ void Sound::fadeFxUp(int32 rate) {
int32 Sound::getSpeechSize(byte *compData, uint32 compSize) {
if ((_cowMode == CowWave) || (_cowMode == CowDemo)) {
- struct WaveHeader {
- uint32 riffTag;
- uint32 riffSize;
- uint32 waveTag;
- uint32 fmtTag;
- uint32 fmtSize;
-
- // Format subchunk
- uint16 wFormatTag;
- uint16 wChannels;
- uint32 dwSamplesPerSec;
- uint32 dwAvgBytesPerSec;
- uint16 wBlockAlign;
- uint16 wBitsPerSample;
- uint32 dwDataTag;
- uint32 dwDataSize;
- };
-
WaveHeader *waveHeader = (WaveHeader *)compData;
return (waveHeader->riffSize + 8) - sizeof(WaveHeader);
@@ -1183,15 +1180,15 @@ void Sound::setCrossFadeIncrement() {
}
void Sound::pauseSpeech() {
- if ((speechSampleBusy) && (!speechSamplePaused)) {
- speechSamplePaused = true;
+ if ((speechSampleBusy) && (!speechPaused)) {
+ speechPaused = true;
_mixer->pauseHandle(hSampleSpeech, true);
}
}
void Sound::unpauseSpeech() {
- if ((speechSampleBusy) && (speechSamplePaused)) {
- speechSamplePaused = false;
+ if ((speechSampleBusy) && (speechPaused)) {
+ speechPaused = false;
_mixer->pauseHandle(hSampleSpeech, false);
}
}
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index f23436fd5df..f0510636f4b 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -81,6 +81,7 @@ class SwordEngine;
#define S_STATUS_RUNNING 0
#define MUSIC_BUFFER_SIZE 0x4000
#define TOTAL_TUNES 270
+#define DEFAULT_SAMPLE_RATE 11025
enum CowMode {
CowWave = 0,
@@ -91,6 +92,15 @@ enum CowMode {
CowPSX
};
+enum MusCompMode {
+ MusWav = 0,
+ MusAif,
+ MusFLAC,
+ MusVorbis,
+ MusMP3,
+ MusPSX
+};
+
class Sound {
friend class SwordConsole;
friend class Control;
@@ -112,56 +122,19 @@ public:
void checkSpeechFileEndianness();
double endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &maxSamples);
- Common::Mutex _soundMutex;
- Audio::Mixer *_mixer;
-
-private:
- void initCowSystem();
-
- uint32 getSampleId(int32 fxNo);
- bool expandSpeech(byte *src, byte *dst, uint32 dstSize,
- bool *endiannessCheck = nullptr, uint32 *sizeForEndiannessCheck = nullptr);
-
- Common::File _cowFile;
- uint32 *_cowHeader;
- uint32 _cowHeaderSize;
- uint8 _currentCowFile;
- CowMode _cowMode;
- Common::RandomSource _rnd;
-
- QueueElement _fxQueue[MAX_FXQ_LENGTH];
- uint8 _endOfQueue;
- SwordEngine *_vm;
- ResMan *_resMan;
-
- bool _bigEndianSpeech;
- static const char _musicList[270];
- static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
- static const FxDef _fxList[312];
- static const char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
-
- // New stuff
-public:
void installFadeTimer();
void uninstallFadeTimer();
-
- int8 scalePan(int pan); // From 0,127 to -127,127
+ void setFXVolume(byte targetVolume, int handleIdx);
void playSample(int32 fxNo);
- void playFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]);
- void stopFX(int32 fxID);
- int32 checkSampleStatus(int32 id);
+ void stopSample(int32 fxNo);
void updateSampleStreaming();
int32 checkSpeechStatus();
void playSpeech();
void stopSpeech();
- int32 getSpeechSize(byte *compData, uint32 compSize);
int32 streamMusicFile(int32 tuneId, int32 looped);
- void serveSample(Common::File *file, int32 i);
- void reduceMusicVolume();
- void restoreMusicVolume();
void fadeMusicDown(int32 rate);
void fadeFxDown(int32 rate);
@@ -175,49 +148,111 @@ public:
void pauseFx();
void unpauseFx();
+ Common::Mutex _soundMutex;
+ Audio::Mixer *_mixer;
+
// Handles for external volume changes (control panel)
- uint32 volFX[2] = { 0, 0 };
+ uint32 volFX[2] = { 0, 0 };
uint32 volSpeech[2] = { 0, 0 };
- uint32 volMusic[2] = { 0, 0 };
+ uint32 volMusic[2] = { 0, 0 };
- // Volume variables
- int32 volumeFadingFlag = 0;
- int32 volumeFadingRate = 0;
- int32 musicFadingFlag = 0;
- int32 musicFadingRate = 0;
+ // Volume fading variables
+ int32 fxCount = 0;
int32 fxFadingFlag = 0;
int32 fxFadingRate = 0;
- int32 masterVolume[2] = { 0, 0 };
- int32 fadeVolume[2] = { 0, 0 };
+ int32 fxFadeVolume[2] = { 0, 0 };
int32 musicFadeVolume[2] = { 0, 0 };
- int32 fxFadeVolume[2] = { 0, 0 };
- int32 volumeCount = 0;
- int32 musicCount = 0;
- int32 fxCount = 0;
+
+ // Sound FX information
+ bool fxSampleBusy[MAX_FX] = { false, false, false, false };
+
+ // Speech data
+ byte *speechSample = nullptr;
+
+private:
+ struct WaveHeader {
+ uint32 riffTag;
+ uint32 riffSize;
+ uint32 waveTag;
+ uint32 fmtTag;
+ uint32 fmtSize;
+
+ // Format subchunk
+ uint16 wFormatTag;
+ uint16 wChannels;
+ uint32 dwSamplesPerSec;
+ uint32 dwAvgBytesPerSec;
+ uint16 wBlockAlign;
+ uint16 wBitsPerSample;
+ uint32 dwDataTag;
+ uint32 dwDataSize;
+ };
+
+ void initCowSystem();
+
+ uint32 getSampleId(int32 fxNo);
+ void playFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]);
+ void stopFX(int32 fxID);
+ int32 checkSampleStatus(int32 id);
+
+ bool expandSpeech(byte *src, byte *dst, uint32 dstSize,
+ bool *endiannessCheck = nullptr, uint32 *sizeForEndiannessCheck = nullptr);
+ int32 getSpeechSize(byte *compData, uint32 compSize);
+
+ void prepareMusicStreaming(Common::String filename, int newHandleId,
+ uint32 volume, int8 pan, MusCompMode assignedMode);
+ void serveSample(Common::File *file, int32 i);
+ void reduceMusicVolume();
+ void restoreMusicVolume();
+
+ int8 scalePan(int pan); // From 0,127 to -127,127
+
+ Common::File _cowFile;
+ uint32 *_cowHeader;
+ uint32 _cowHeaderSize;
+ uint8 _currentCowFile;
+ CowMode _cowMode;
+ Common::RandomSource _rnd;
+
+ QueueElement _fxQueue[MAX_FXQ_LENGTH];
+ uint8 _endOfQueue;
+ SwordEngine *_vm;
+ ResMan *_resMan;
+
+ bool _bigEndianSpeech;
+ static const char _musicList[270];
+ static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
+ static const FxDef _fxList[312];
+ static const char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
+
+ // Volume fading variables
+ bool crossFadeIncrement = false;
+
+ // Speech variables
int32 speechLipsyncCounter = 0;
int32 speechSize = 0;
+ bool speechSampleBusy = false;
- // Sample handles and information.
+ // Sound handles
Audio::SoundHandle hSampleFX[MAX_FX];
Audio::SoundHandle hSampleSpeech;
Audio::SoundHandle hSampleMusic[MAX_MUSIC];
+
+ // Music stream information
bool streamSamplePlaying[MAX_MUSIC] = { false, false };
+ bool streamLoopingFlag[MAX_MUSIC] = { false, false };
int32 streamSampleFading[MAX_MUSIC] = { 0, 0 };
- bool streamLoopingFlag[MAX_MUSIC] = { false, false };
-
- Audio::QueuingAudioStream *_stream[MAX_MUSIC];
- int lastStreamBufferIdx[MAX_MUSIC] = { 0, 0 };
-
+ MusCompMode streamFormat[MAX_MUSIC] = { MusWav, MusWav };
+ Audio::QueuingAudioStream *_musicOutputStream[MAX_MUSIC];
Common::File streamFile[MAX_MUSIC];
- bool fxSampleBusy[MAX_FX] = { false, false, false, false };
+
+ // Sound FX information
int32 fxSampleID[MAX_FX] = { 0, 0, 0, 0 };
- bool speechSampleBusy = false;
- uint32 musicSamples = 0;
- bool crossFadeIncrement = false;
- bool speechSamplePaused = false;
+
+ // Pause variables
+ bool speechPaused = false;
bool fxPaused[MAX_FX] = { false, false, false, false };
bool musicPaused[MAX_MUSIC] = { false, false };
- byte *speechSample = nullptr;
};
} // End of namespace Sword1
Commit: 6ee4a692de67add38537ac1e7f866a2154048bcc
https://github.com/scummvm/scummvm/commit/6ee4a692de67add38537ac1e7f866a2154048bcc
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Finish implementing support for compressed music
Changed paths:
engines/sword1/sound.cpp
engines/sword1/sound.h
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 7925c3bbd06..2fbb9b84bab 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -822,7 +822,6 @@ void Sound::stopSample(int32 fxNo) {
void Sound::prepareMusicStreaming(Common::String filename, int newHandleId, uint32 volume, int8 pan, MusCompMode assignedMode) {
int sampleRate = DEFAULT_SAMPLE_RATE;
WaveHeader wavHead;
- Audio::RewindableAudioStream *compressedStream = nullptr;
bool isStereo = false;
if (filename.empty())
@@ -831,6 +830,8 @@ void Sound::prepareMusicStreaming(Common::String filename, int newHandleId, uint
if (!streamFile[newHandleId].open(filename))
debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
+ delete _compressedMusicStream[newHandleId];
+
if (assignedMode == MusWav) {
if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
debug(5, "Sound::streamMusicFile(): couldn't read from file %s, bailing out...", filename.c_str());
@@ -840,20 +841,20 @@ void Sound::prepareMusicStreaming(Common::String filename, int newHandleId, uint
sampleRate = wavHead.dwSamplesPerSec;
} else if (assignedMode == MusFLAC) {
- compressedStream = Audio::makeFLACStream(&streamFile[newHandleId], DisposeAfterUse::NO);
- sampleRate = compressedStream->getRate();
+ _compressedMusicStream[newHandleId] = Audio::makeFLACStream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ sampleRate = _compressedMusicStream[newHandleId]->getRate();
} else if (assignedMode == MusVorbis) {
- compressedStream = Audio::makeVorbisStream(&streamFile[newHandleId], DisposeAfterUse::NO);
- sampleRate = compressedStream->getRate();
+ _compressedMusicStream[newHandleId] = Audio::makeVorbisStream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ sampleRate = _compressedMusicStream[newHandleId]->getRate();
} else if (assignedMode == MusMP3) {
- compressedStream = Audio::makeMP3Stream(&streamFile[newHandleId], DisposeAfterUse::NO);
- sampleRate = compressedStream->getRate();
+ _compressedMusicStream[newHandleId] = Audio::makeMP3Stream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ sampleRate = _compressedMusicStream[newHandleId]->getRate();
} else if (assignedMode == MusAif) {
- compressedStream = Audio::makeAIFFStream(&streamFile[newHandleId], DisposeAfterUse::NO);
- sampleRate = compressedStream->getRate();
+ _compressedMusicStream[newHandleId] = Audio::makeAIFFStream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ sampleRate = _compressedMusicStream[newHandleId]->getRate();
}
- if (assignedMode != MusWav && !compressedStream) {
+ if (assignedMode != MusWav && !_compressedMusicStream[newHandleId]) {
debug(5, "Sound::streamMusicFile(): couldn't process compressed file %s, bailing out...", filename.c_str());
streamFile[newHandleId].close();
return;
@@ -862,10 +863,6 @@ void Sound::prepareMusicStreaming(Common::String filename, int newHandleId, uint
_musicOutputStream[newHandleId] = Audio::makeQueuingAudioStream(sampleRate, isStereo);
_mixer->playStream(Audio::Mixer::kMusicSoundType, &hSampleMusic[newHandleId], _musicOutputStream[newHandleId]);
- if (assignedMode != MusWav) {
- _musicOutputStream[newHandleId]->queueAudioStream(compressedStream);
- }
-
_mixer->setChannelRate(hSampleMusic[newHandleId], sampleRate);
_mixer->setChannelVolume(hSampleMusic[newHandleId], volume);
_mixer->setChannelBalance(hSampleMusic[newHandleId], pan);
@@ -1000,28 +997,57 @@ void Sound::updateSampleStreaming() {
void Sound::serveSample(Common::File *file, int32 i) {
int32 len;
int32 nominalSize = MUSIC_BUFFER_SIZE;
- byte *buf = (byte *)malloc(nominalSize);
+ byte *buf = nullptr;
- if (!musicPaused[i] && streamFormat[i] == MusWav) {
+ if (!musicPaused[i]) {
if (_musicOutputStream[i]->numQueuedStreams() < 4) {
- len = file->read(buf, nominalSize);
- if (len < nominalSize) {
- if (streamLoopingFlag[i]) {
- file->seek(44, SEEK_SET);
- file->read(buf + len, nominalSize - len);
- len = nominalSize;
- debug(5, "Sound::serveSample(): Looping music file %s", file->getName());
- } else {
- Common::String fname(file->getName());
- if (!fname.empty())
- debug(5, "Sound::serveSample(): Finished feeding music file %s", file->getName());
+ if (streamFormat[i] == MusWav) {
+ buf = (byte *)malloc(nominalSize);
+ if (!buf) {
+ warning("Sound::serveSample(): Couldn't allocate memory for streaming file %s", file->getName());
+ return;
+ }
+
+ len = file->read(buf, nominalSize);
+ if (len < nominalSize) {
+ if (streamLoopingFlag[i]) {
+ file->seek(44, SEEK_SET);
+ file->read(buf + len, nominalSize - len);
+ len = nominalSize;
+ debug(5, "Sound::serveSample(): Looping music file %s", file->getName());
+ } else {
+ Common::String fname(file->getName());
+ if (!fname.empty())
+ debug(5, "Sound::serveSample(): Finished feeding music file %s", file->getName());
+ }
+ }
+ } else {
+ buf = (byte *)malloc(nominalSize * 2);
+ if (!buf) {
+ warning("Sound::serveSample(): Couldn't allocate memory for streaming file %s", file->getName());
+ return;
+ }
+
+ len = _compressedMusicStream[i]->readBuffer((int16 *)buf, nominalSize);
+ if (len < nominalSize) {
+ if (streamLoopingFlag[i]) {
+ _compressedMusicStream[i]->rewind();
+ _compressedMusicStream[i]->readBuffer((int16 *)buf + len, nominalSize - len);
+ len = nominalSize;
+ debug(5, "Sound::serveSample(): Looping music file %s", file->getName());
+ } else {
+ Common::String fname(file->getName());
+ if (!fname.empty())
+ debug(5, "Sound::serveSample(): Finished feeding music file %s", file->getName());
+ }
}
}
+ if (streamFormat[i] != MusWav)
+ len *= 2;
+
_musicOutputStream[i]->queueBuffer(buf, len, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
}
- } else if (streamFormat[i] != MusWav && streamLoopingFlag[i]) {
-
}
}
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index f0510636f4b..43f9633d749 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -79,7 +79,7 @@ class SwordEngine;
#define MAX_MUSIC 2
#define S_STATUS_FINISHED 1
#define S_STATUS_RUNNING 0
-#define MUSIC_BUFFER_SIZE 0x4000
+#define MUSIC_BUFFER_SIZE 0x2000
#define TOTAL_TUNES 270
#define DEFAULT_SAMPLE_RATE 11025
@@ -107,16 +107,10 @@ class Sound {
public:
Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan);
~Sound();
+
void newScreen(uint32 screen);
- void clearAllFx();
void closeCowSystem();
- void startSpeech(uint16 roomNo, uint16 localNo);
- bool amISpeaking();
-
- int addToQueue(uint32 fxNo);
- void removeFromQueue(uint32 fxNo);
-
void engine();
void checkSpeechFileEndianness();
@@ -124,23 +118,29 @@ public:
void installFadeTimer();
void uninstallFadeTimer();
- void setFXVolume(byte targetVolume, int handleIdx);
void playSample(int32 fxNo);
void stopSample(int32 fxNo);
+ void setFXVolume(byte targetVolume, int handleIdx);
+ void clearAllFx();
+ int addToQueue(uint32 fxNo);
+ void removeFromQueue(uint32 fxNo);
- void updateSampleStreaming();
+ void startSpeech(uint16 roomNo, uint16 localNo);
+ bool amISpeaking();
int32 checkSpeechStatus();
void playSpeech();
void stopSpeech();
int32 streamMusicFile(int32 tuneId, int32 looped);
+ void updateSampleStreaming();
+ void setCrossFadeIncrement();
void fadeMusicDown(int32 rate);
void fadeFxDown(int32 rate);
void fadeFxUp(int32 rate);
- void setCrossFadeIncrement();
+
void pauseSpeech();
void unpauseSpeech();
void pauseMusic();
@@ -243,7 +243,8 @@ private:
bool streamLoopingFlag[MAX_MUSIC] = { false, false };
int32 streamSampleFading[MAX_MUSIC] = { 0, 0 };
MusCompMode streamFormat[MAX_MUSIC] = { MusWav, MusWav };
- Audio::QueuingAudioStream *_musicOutputStream[MAX_MUSIC];
+ Audio::QueuingAudioStream *_musicOutputStream[MAX_MUSIC] = { nullptr, nullptr };
+ Audio::RewindableAudioStream *_compressedMusicStream[MAX_MUSIC] = { nullptr, nullptr };
Common::File streamFile[MAX_MUSIC];
// Sound FX information
Commit: 1490905ea0e50ec78e2975f1af689825f2268560
https://github.com/scummvm/scummvm/commit/1490905ea0e50ec78e2975f1af689825f2268560
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Implement PSX music
Changed paths:
engines/sword1/sound.cpp
engines/sword1/sound.h
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 2fbb9b84bab..373c43070ef 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -819,16 +819,18 @@ void Sound::stopSample(int32 fxNo) {
stopFX(fxNo);
}
-void Sound::prepareMusicStreaming(Common::String filename, int newHandleId, uint32 volume, int8 pan, MusCompMode assignedMode) {
+bool Sound::prepareMusicStreaming(Common::String filename, int newHandleId, int32 tuneId, uint32 volume, int8 pan, MusCompMode assignedMode) {
int sampleRate = DEFAULT_SAMPLE_RATE;
WaveHeader wavHead;
bool isStereo = false;
if (filename.empty())
- return;
+ return false;
- if (!streamFile[newHandleId].open(filename))
+ if (!streamFile[newHandleId].open(filename)) {
debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
+ return false;
+ }
delete _compressedMusicStream[newHandleId];
@@ -836,7 +838,7 @@ void Sound::prepareMusicStreaming(Common::String filename, int newHandleId, uint
if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
debug(5, "Sound::streamMusicFile(): couldn't read from file %s, bailing out...", filename.c_str());
streamFile[newHandleId].close();
- return;
+ return false;
}
sampleRate = wavHead.dwSamplesPerSec;
@@ -852,12 +854,37 @@ void Sound::prepareMusicStreaming(Common::String filename, int newHandleId, uint
} else if (assignedMode == MusAif) {
_compressedMusicStream[newHandleId] = Audio::makeAIFFStream(&streamFile[newHandleId], DisposeAfterUse::NO);
sampleRate = _compressedMusicStream[newHandleId]->getRate();
+ } else if (assignedMode == MusPSX) {
+ Common::File tableFile;
+ if (!tableFile.open("tunes.tab")) {
+ debug(5, "Sound::streamMusicFile(): couldn't open the tunes.tab file, bailing out...");
+ return false;
+ }
+
+
+ // The PSX demo has a broken/truncated tunes.tab. So we check here that the offset is not
+ // beyond the end of the file.
+ int32 tableOffset = (tuneId - 1) * 8;
+ if (tableOffset >= tableFile.size())
+ return false;
+ tableFile.seek(tableOffset, SEEK_SET);
+ uint32 offset = tableFile.readUint32LE() * 0x800;
+ uint32 size = tableFile.readUint32LE();
+
+ tableFile.close();
+
+ // Because of broken tunes.dat/tab in psx demo, also check that tune offset is
+ // not over file size
+ if ((size != 0) && (size != 0xffffffff) && ((int32)(offset + size) <= streamFile[newHandleId].size())) {
+ streamFile[newHandleId].seek(offset, SEEK_SET);
+ _compressedMusicStream[newHandleId] = Audio::makeXAStream(streamFile[newHandleId].readStream(size), DEFAULT_SAMPLE_RATE);
+ }
}
if (assignedMode != MusWav && !_compressedMusicStream[newHandleId]) {
debug(5, "Sound::streamMusicFile(): couldn't process compressed file %s, bailing out...", filename.c_str());
streamFile[newHandleId].close();
- return;
+ return false;
}
_musicOutputStream[newHandleId] = Audio::makeQueuingAudioStream(sampleRate, isStereo);
@@ -869,6 +896,8 @@ void Sound::prepareMusicStreaming(Common::String filename, int newHandleId, uint
streamSamplePlaying[newHandleId] = true;
streamFormat[newHandleId] = assignedMode;
+
+ return true;
}
int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
@@ -878,10 +907,12 @@ int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
Common::String filename(_tuneList[tuneId]);
MusCompMode assignedMode = MusWav;
-
- if (tmp.exists(filename + ".flac")) {
- filename = filename + ".flac";
- assignedMode = MusFLAC;
+ if (tmp.exists(filename + ".wav")) {
+ filename = filename + ".wav";
+ assignedMode = MusWav;
+ } else if (SwordEngine::isPsx() && tmp.exists("tunes.dat") && tmp.exists("tunes.tab")) {
+ filename = "tunes.dat";
+ assignedMode = MusPSX;
} else if (tmp.exists(filename + ".fla")) {
filename = filename + ".fla";
assignedMode = MusFLAC;
@@ -891,12 +922,14 @@ int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
} else if (tmp.exists(filename + ".mp3")) {
filename = filename + ".mp3";
assignedMode = MusMP3;
- } else if (tmp.exists(filename + ".wav")) {
- filename = filename + ".wav";
- assignedMode = MusWav;
+ } else if (tmp.exists(filename + ".flac")) {
+ filename = filename + ".flac";
+ assignedMode = MusFLAC;
} else if (tmp.exists(filename + ".aif")) {
filename = filename + ".aif";
assignedMode = MusAif;
+ } else {
+ filename = "";
}
newHandleId = 0;
@@ -914,29 +947,32 @@ int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
_mixer->stopHandle(hSampleMusic[newHandleId]);
streamFile[newHandleId].close();
- prepareMusicStreaming(filename, newHandleId,
- 2 * (2 * (volMusic[0] + volMusic[1])),
- scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
- assignedMode);
+ bool success = prepareMusicStreaming(filename, newHandleId, tuneId,
+ 2 * (2 * (volMusic[0] + volMusic[1])),
+ scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
+ assignedMode);
- debug(5, "Sound::streamMusicFile(): interrupting sound in handle %d to play %s", newHandleId, filename.c_str());
+ if (success)
+ debug(5, "Sound::streamMusicFile(): interrupting sound in handle %d to play %s", newHandleId, filename.c_str());
return 2;
} else {
- prepareMusicStreaming(filename, newHandleId,
- 0,
- scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
- assignedMode);
+ bool success = prepareMusicStreaming(filename, newHandleId, tuneId,
+ 0,
+ scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
+ assignedMode);
- debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d with other handle busy", filename.c_str(), newHandleId);
+ if (success)
+ debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d with other handle busy", filename.c_str(), newHandleId);
}
} else {
- prepareMusicStreaming(filename, newHandleId,
- 2 * (3 * (volMusic[0] + volMusic[1])),
- scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
- assignedMode);
+ bool success = prepareMusicStreaming(filename, newHandleId, tuneId,
+ 2 * (3 * (volMusic[0] + volMusic[1])),
+ scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
+ assignedMode);
- debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d", filename.c_str(), newHandleId);
+ if (success)
+ debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d", filename.c_str(), newHandleId);
}
streamLoopingFlag[newHandleId] = looped;
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index 43f9633d749..cca0714d9b9 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -199,7 +199,7 @@ private:
bool *endiannessCheck = nullptr, uint32 *sizeForEndiannessCheck = nullptr);
int32 getSpeechSize(byte *compData, uint32 compSize);
- void prepareMusicStreaming(Common::String filename, int newHandleId,
+ bool prepareMusicStreaming(Common::String filename, int newHandleId, int32 tuneId,
uint32 volume, int8 pan, MusCompMode assignedMode);
void serveSample(Common::File *file, int32 i);
void reduceMusicVolume();
Commit: 0f02b66ebef602f048f2576b422dee25a51eb45b
https://github.com/scummvm/scummvm/commit/0f02b66ebef602f048f2576b422dee25a51eb45b
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Implement persistence of volume settings
Changed paths:
engines/sword1/control.cpp
engines/sword1/control.h
engines/sword1/sound.cpp
engines/sword1/sound.h
engines/sword1/sword1.cpp
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 3cabae81317..1a2d9b10906 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -176,14 +176,6 @@ const Button Control::volumeButtons[25] = {
};
-static int volToBalance(int volL, int volR) {
- if (volL + volR == 0) {
- return 50;
- } else {
- return (100 * volL / (volL + volR));
- }
-}
-
Control::Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen, Logic *pLogic) {
_vm = vm;
_saveFileMan = saveFileMan;
@@ -383,7 +375,7 @@ void Control::saveRestoreScreen() {
break;
case SNR_MAINPANEL:
removeControlPanel();
- setVolumes();
+ _sound->setVolumes();
break;
case SNR_SAVE:
removeSave();
@@ -400,7 +392,7 @@ void Control::saveRestoreScreen() {
break;
case SNR_VOLUME:
removeVolume();
- setVolumes();
+ _sound->setVolumes();
break;
case SNR_DRIVEFULL:
removeConfirmation();
@@ -417,7 +409,7 @@ void Control::saveRestoreScreen() {
initialiseResources();
}
- //GetVolumes();
+ _sound->getVolumes();
initialiseControlPanel();
break;
case SNR_SAVE:
@@ -442,7 +434,7 @@ void Control::saveRestoreScreen() {
initialiseSpeed();
break;
case SNR_VOLUME:
- //GetVolumes();
+ _sound->getVolumes();
initialiseVolume();
break;
case SNR_DRIVEFULL:
@@ -963,10 +955,6 @@ void Control::removeConfirmation() {
}
void Control::renderVolumeLight(int32 i) {
- // TODO: This function has been mangled to accomodate the current
- // audio engine, which will partly get rewritten in the immediate
- // future :)
-
uint8 *src, *dst;
uint8 vol[2] = { 0, 0 };
int32 x;
@@ -974,17 +962,17 @@ void Control::renderVolumeLight(int32 i) {
Sprite *srVlight;
switch (i) {
- case 0: //music
+ case 0:
vol[0] = _sound->volMusic[0];
vol[1] = _sound->volMusic[1];
x = 158;
break;
- case 1: //speech
+ case 1:
vol[0] = _sound->volSpeech[0];
vol[1] = _sound->volSpeech[1];
x = 291;
break;
- case 2: //fx
+ case 2:
vol[0] = _sound->volFX[0];
vol[1] = _sound->volFX[1];
x = 424;
@@ -997,7 +985,7 @@ void Control::renderVolumeLight(int32 i) {
srVlight = (Sprite *)_resMan->fetchRes(SR_VLIGHT);
// Render left light
- f = (FrameHeader *)((uint8 *)srVlight + _resMan->getUint32(srVlight->spriteOffset[vol[0] >> 4]));
+ f = (FrameHeader *)((uint8 *)srVlight + _resMan->getUint32(srVlight->spriteOffset[vol[0]]));
src = (uint8 *)f + sizeof(FrameHeader);
dst = _screenBuf + x + 211 * SCREEN_WIDTH;
@@ -1012,7 +1000,7 @@ void Control::renderVolumeLight(int32 i) {
}
// Render right light
- f = (FrameHeader *)((uint8 *)srVlight + _resMan->getUint32(srVlight->spriteOffset[vol[1] >> 4]));
+ f = (FrameHeader *)((uint8 *)srVlight + _resMan->getUint32(srVlight->spriteOffset[vol[1]]));
src = (uint8 *)f + sizeof(FrameHeader);
dst = _screenBuf + x + 32 + 211 * SCREEN_WIDTH;
@@ -1027,41 +1015,6 @@ void Control::renderVolumeLight(int32 i) {
}
}
-void Control::setVolumes() {
- // TODO: This function has been mangled to accomodate the current
- // audio engine, which will partly get rewritten in the immediate
- // future :)
-
- uint8 volL, volR;
- _music->giveVolume(&volL, &volR);
- int vol = (int)((volR + volL) / 2);
- int volBalance = volToBalance(volL, volR);
- if (vol != ConfMan.getInt("music_volume"))
- ConfMan.setInt("music_volume", vol);
- if (volBalance != ConfMan.getInt("music_balance"))
- ConfMan.setInt("music_balance", volBalance);
-
- //_sound->giveSpeechVol(&volL, &volR);
- vol = (int)((volR + volL) / 2);
- volBalance = volToBalance(volL, volR);
- if (vol != ConfMan.getInt("speech_volume"))
- ConfMan.setInt("speech_volume", vol);
- if (volBalance != ConfMan.getInt("speech_balance"))
- ConfMan.setInt("speech_balance", volBalance);
-
- //_sound->giveSfxVol(&volL, &volR);
- vol = (int)((volR + volL) / 2);
- volBalance = volToBalance(volL, volR);
- if (vol != ConfMan.getInt("sfx_volume"))
- ConfMan.setInt("sfx_volume", vol);
- if (volBalance != ConfMan.getInt("sfx_balance"))
- ConfMan.setInt("sfx_balance", volBalance);
-
- if (SwordEngine::_systemVars.showText != ConfMan.getBool("subtitles"))
- ConfMan.setBool("subtitles", SwordEngine::_systemVars.showText);
- ConfMan.flushToDisk();
-}
-
void Control::volUp(int32 i, int32 j) {
uint32 *vol = nullptr;
@@ -2023,7 +1976,7 @@ void Control::removeSave() {
_resMan->resClose(SR_REDFONT);
}
- setVolumes();
+ _sound->setVolumes();
}
bool Control::restoreGame() {
@@ -2434,7 +2387,7 @@ void Control::removeRestore() {
_resMan->resClose(SR_REDFONT);
}
- setVolumes();
+ _sound->setVolumes();
}
void Control::initialiseControlPanel() {
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index 003db627548..51f3317f51c 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -151,7 +151,6 @@ private:
int32 implementConfirmation();
void removeConfirmation();
- void setVolumes();
void volUp(int32 i, int32 j);
void volDown(int32 i, int32 j);
void renderVolumeLight(int32 i);
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 373c43070ef..13a38815a50 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -20,11 +20,11 @@
*/
+#include "common/config-manager.h"
#include "common/endian.h"
-
-#include "common/util.h"
#include "common/memstream.h"
#include "common/textconsole.h"
+#include "common/util.h"
#include "sword1/sound.h"
#include "sword1/resman.h"
@@ -55,15 +55,7 @@ Sound::Sound(Audio::Mixer *mixer, SwordEngine *vm, ResMan *pResMan)
_musicOutputStream[0] = Audio::makeQueuingAudioStream(DEFAULT_SAMPLE_RATE, false);
_musicOutputStream[1] = Audio::makeQueuingAudioStream(DEFAULT_SAMPLE_RATE, false);
- //if (!GetVolumes()) {
- volFX[0] = 8;
- volFX[1] = 8;
- volSpeech[0] = 8;
- volSpeech[1] = 8;
- volMusic[0] = 8;
- volMusic[1] = 8;
- // SetVolumes();
- //}
+ getVolumes();
memset(_fxQueue, 0, sizeof(_fxQueue));
}
@@ -1295,6 +1287,107 @@ void Sound::unpauseFx() {
}
}
+static void getConfigVolumes(uint32 volL, uint32 volR, int &balance, int &volume) {
+ // Calculate the balance
+ if (volL + volR == 0) {
+ balance = 50;
+ } else {
+ balance = (int)(100.0f * volL / (volL + volR) + 0.5f);
+ }
+
+ // Calculate and scale the volume to the 0-255 range
+ volume = (int)(((volL + volR) * 255.0f / 32) + 0.5f);
+ volume = CLIP<int>(((volL + volR) * 255 / 32), 0, 255);
+}
+
+static void getGameVolumes(int balance, int volume, uint32 &volL, uint32 &volR) {
+ volume = CLIP<int>(volume, 0, 255);
+
+ int totalVolume = (int)(volume * 32.0f / 255 + 0.5f);
+
+ if (balance == 50) {
+ volL = totalVolume / 2;
+ volR = volL;
+ return;
+ }
+
+ volL = (uint32)(totalVolume * (balance / 100.0f) + 0.5f);
+ volR = totalVolume - volL;
+}
+
+void Sound::getVolumes() {
+ int musicVol = ConfMan.getInt("music_volume");
+ int sfxVol = ConfMan.getInt("sfx_volume");
+ int speechVol = ConfMan.getInt("speech_volume");
+
+ int musicBal = 50;
+ if (ConfMan.hasKey("music_balance")) {
+ musicBal = CLIP(ConfMan.getInt("music_balance"), 0, 100);
+ }
+
+ int speechBal = 50;
+ if (ConfMan.hasKey("speech_balance")) {
+ speechBal = CLIP(ConfMan.getInt("speech_balance"), 0, 100);
+ }
+
+ int sfxBal = 50;
+ if (ConfMan.hasKey("sfx_balance")) {
+ sfxBal = CLIP(ConfMan.getInt("sfx_balance"), 0, 100);
+ }
+
+ getGameVolumes(musicBal, musicVol, volMusic[0], volMusic[1]);
+ getGameVolumes(speechBal, speechVol, volSpeech[0], volSpeech[1]);
+ getGameVolumes(sfxBal, sfxVol, volFX[0], volFX[1]);
+
+ if (ConfMan.getBool("mute")) {
+ volSpeech[0] = 0;
+ volSpeech[1] = 0;
+ }
+
+ SwordEngine::_systemVars.showText = ConfMan.getBool("subtitles");
+
+ if (volSpeech[0] + volSpeech[1] == 0) {
+ SwordEngine::_systemVars.showText = true;
+ SwordEngine::_systemVars.playSpeech = false;
+ } else {
+ SwordEngine::_systemVars.playSpeech = true;
+ }
+}
+
+void Sound::setVolumes() {
+ int volume = 0;
+ int balance = 0;
+
+ getConfigVolumes(volMusic[0], volMusic[1], balance, volume);
+ if (volume != ConfMan.getInt("music_volume"))
+ ConfMan.setInt("music_volume", volume);
+ if (balance != ConfMan.getInt("music_balance"))
+ ConfMan.setInt("music_balance", balance);
+
+ getConfigVolumes(volSpeech[0], volSpeech[1], balance, volume);
+ if (volume != ConfMan.getInt("speech_volume"))
+ ConfMan.setInt("speech_volume", volume);
+ if (balance != ConfMan.getInt("speech_balance"))
+ ConfMan.setInt("speech_balance", balance);
+
+ getConfigVolumes(volFX[0], volFX[1], balance, volume);
+ if (volume != ConfMan.getInt("sfx_volume"))
+ ConfMan.setInt("sfx_volume", volume);
+ if (balance != ConfMan.getInt("sfx_balance"))
+ ConfMan.setInt("sfx_balance", balance);
+
+ if (SwordEngine::_systemVars.showText != ConfMan.getBool("subtitles"))
+ ConfMan.setBool("subtitles", SwordEngine::_systemVars.showText);
+ ConfMan.flushToDisk();
+
+ if (volSpeech[0] + volSpeech[1] == 0) {
+ SwordEngine::_systemVars.showText = true;
+ SwordEngine::_systemVars.playSpeech = false;
+ } else {
+ SwordEngine::_systemVars.playSpeech = true;
+ }
+}
+
int8 Sound::scalePan(int pan) {
return (pan != 64) ? (int8)(2 * pan - 127) : 0;
}
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index cca0714d9b9..59fd2d4e409 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -140,7 +140,6 @@ public:
void fadeFxDown(int32 rate);
void fadeFxUp(int32 rate);
-
void pauseSpeech();
void unpauseSpeech();
void pauseMusic();
@@ -148,6 +147,9 @@ public:
void pauseFx();
void unpauseFx();
+ void getVolumes();
+ void setVolumes();
+
Common::Mutex _soundMutex;
Audio::Mixer *_mixer;
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 26159d34ac6..e44269d8900 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -194,62 +194,7 @@ void SwordEngine::reinitialize() {
void SwordEngine::syncSoundSettings() {
Engine::syncSoundSettings();
- uint musicVol = ConfMan.getInt("music_volume");
- uint sfxVol = ConfMan.getInt("sfx_volume");
- uint speechVol = ConfMan.getInt("speech_volume");
-
- uint musicBal = 50;
- if (ConfMan.hasKey("music_balance")) {
- musicBal = CLIP(ConfMan.getInt("music_balance"), 0, 100);
- }
-
- uint speechBal = 50;
- if (ConfMan.hasKey("speech_balance")) {
- speechBal = CLIP(ConfMan.getInt("speech_balance"), 0, 100);
- }
- uint sfxBal = 50;
- if (ConfMan.hasKey("sfx_balance")) {
- sfxBal = CLIP(ConfMan.getInt("sfx_balance"), 0, 100);
- }
-
- uint musicVolL = 2 * musicVol * musicBal / 100;
- uint musicVolR = 2 * musicVol - musicVolL;
-
- uint speechVolL = 2 * speechVol * speechBal / 100;
- uint speechVolR = 2 * speechVol - speechVolL;
-
- uint sfxVolL = 2 * sfxVol * sfxBal / 100;
- uint sfxVolR = 2 * sfxVol - sfxVolL;
-
- if (musicVolR > 255) {
- musicVolR = 255;
- }
- if (musicVolL > 255) {
- musicVolL = 255;
- }
-
- if (speechVolR > 255) {
- speechVolR = 255;
- }
- if (speechVolL > 255) {
- speechVolL = 255;
- }
- if (sfxVolR > 255) {
- sfxVolR = 255;
- }
- if (sfxVolL > 255) {
- sfxVolL = 255;
- }
-
- bool mute = ConfMan.getBool("mute");
-
- if (mute) {
- _music->setVolume(0, 0);
- //_sound->setSpeechVol(0, 0);
- } else {
- _music->setVolume(musicVolL, musicVolR);
- //_sound->setSpeechVol(speechVolL, speechVolR);
- }
+ _sound->setVolumes();
}
void SwordEngine::flagsToBool(bool *dest, uint8 flags) {
Commit: a4d08cfc4c9fcba6803b1c8d2aed0a009befd5ab
https://github.com/scummvm/scummvm/commit/a4d08cfc4c9fcba6803b1c8d2aed0a009befd5ab
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Final code clean-up pass
...hopefully :-)
Changed paths:
engines/sword1/animation.cpp
engines/sword1/control.cpp
engines/sword1/logic.cpp
engines/sword1/sound.cpp
engines/sword1/sound.h
engines/sword1/sword1.cpp
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index af03350dae5..dfaee05560a 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -319,7 +319,7 @@ bool MoviePlayer::playVideo() {
}
_sound->setCrossFadeIncrement();
- _sound->updateSampleStreaming();
+ _sound->updateMusicStreaming();
if (_decoder->hasDirtyPalette()) {
_vm->_system->getPaletteManager()->setPalette(_decoder->getPalette(), 0, 256);
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 1a2d9b10906..4c748dc1bcf 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -250,7 +250,7 @@ void Control::getPlayerOptions() {
_sound->setCrossFadeIncrement();
_mouse->animate();
- _sound->updateSampleStreaming(); // stream music
+ _sound->updateMusicStreaming();
saveRestoreScreen();
}
@@ -963,18 +963,18 @@ void Control::renderVolumeLight(int32 i) {
switch (i) {
case 0:
- vol[0] = _sound->volMusic[0];
- vol[1] = _sound->volMusic[1];
+ vol[0] = _sound->_volMusic[0];
+ vol[1] = _sound->_volMusic[1];
x = 158;
break;
case 1:
- vol[0] = _sound->volSpeech[0];
- vol[1] = _sound->volSpeech[1];
+ vol[0] = _sound->_volSpeech[0];
+ vol[1] = _sound->_volSpeech[1];
x = 291;
break;
case 2:
- vol[0] = _sound->volFX[0];
- vol[1] = _sound->volFX[1];
+ vol[0] = _sound->_volFX[0];
+ vol[1] = _sound->_volFX[1];
x = 424;
break;
default:
@@ -1020,13 +1020,13 @@ void Control::volUp(int32 i, int32 j) {
switch (i) {
case 0:
- vol = &_sound->volMusic[j];
+ vol = &_sound->_volMusic[j];
break;
case 1:
- vol = &_sound->volSpeech[j];
+ vol = &_sound->_volSpeech[j];
break;
case 2:
- vol = &_sound->volFX[j];
+ vol = &_sound->_volFX[j];
break;
}
@@ -1039,13 +1039,13 @@ void Control::volDown(int32 i, int32 j) {
switch (i) {
case 0:
- vol = &_sound->volMusic[j];
+ vol = &_sound->_volMusic[j];
break;
case 1:
- vol = &_sound->volSpeech[j];
+ vol = &_sound->_volSpeech[j];
break;
case 2:
- vol = &_sound->volFX[j];
+ vol = &_sound->_volFX[j];
break;
}
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 58c12a826aa..e70cf78e2a6 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -362,8 +362,8 @@ int Logic::speechDriver(Object *compact) {
if (SwordEngine::_systemVars.speechFinished) {
_sound->stopSpeech();
- free(_sound->speechSample);
- _sound->speechSample = nullptr;
+ free(_sound->_speechSample);
+ _sound->_speechSample = nullptr;
}
} else {
if (!compact->o_speech_time)
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 13a38815a50..5b70c415367 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -262,7 +262,7 @@ void Sound::removeFromQueue(uint32 fxNo) {
void Sound::engine() {
// Update music streaming...
- updateSampleStreaming();
+ updateMusicStreaming();
// Add any random sfx to the queue...
for (uint16 cnt = 0; cnt < TOTAL_FX_PER_ROOM; cnt++) {
@@ -297,19 +297,19 @@ bool Sound::amISpeaking() {
int16 count;
int32 readPos;
- if (!speechSampleBusy)
+ if (!_speechSampleBusy)
return false;
- if (_mixer->isSoundHandleActive(hSampleSpeech)) {
- speechLipsyncCounter += 1;
+ if (_mixer->isSoundHandleActive(_hSampleSpeech)) {
+ _speechLipsyncCounter += 1;
- readPos = speechLipsyncCounter * 919 * 2;
+ readPos = _speechLipsyncCounter * 919 * 2;
- // Ensure that we don't read beyond the buffer
- if (readPos + 150 * sizeof(int16) > speechSize)
+ // Ensure that we don't read beyond the buffer...
+ if (readPos + 150 * sizeof(int16) > _speechSize)
return false;
- offset = (int16 *)&speechSample[readPos];
+ offset = (int16 *)&_speechSample[readPos];
count = 0;
for (int i = 0; i < 150; i++) {
if ((offset[i] < NEG_MOUTH_THRESHOLD) || (offset[i] > POS_MOUTH_THRESHOLD)) {
@@ -378,14 +378,15 @@ void Sound::startSpeech(uint16 roomNo, uint16 localNo) {
return;
}
- uint16 numRooms = file.readUint16LE(); // Read number of rooms referenced in this file
+ uint16 numRooms = file.readUint16LE();
file.seek(locIndex * 4 + 2); // 4 bytes per room, skip first 2 bytes
uint16 numLines = file.readUint16LE();
uint16 roomOffset = file.readUint16LE();
- file.seek(2 + numRooms * 4 + roomOffset * 2); // The offset is in terms of uint16's, so multiply by 2. Skip the room indexes too.
+ // The offset is in terms of uint16's, so multiply by 2. Skip the room indexes too...
+ file.seek(2 + numRooms * 4 + roomOffset * 2);
locIndex = 0xFFFFFFFF;
@@ -424,10 +425,10 @@ void Sound::startSpeech(uint16 roomNo, uint16 localNo) {
}
_cowFile.read(compSample, sampleFileSize);
- speechSize = getSpeechSize(compSample, sampleFileSize);
- speechSample = (byte *)malloc(speechSize);
- if (speechSample) {
- SwordEngine::_systemVars.speechRunning = expandSpeech(compSample, speechSample, sampleFileSize);
+ _speechSize = getSpeechSize(compSample, sampleFileSize);
+ _speechSample = (byte *)malloc(_speechSize);
+ if (_speechSample) {
+ SwordEngine::_systemVars.speechRunning = expandSpeech(compSample, _speechSample, sampleFileSize);
free(compSample);
}
}
@@ -438,7 +439,7 @@ bool Sound::expandSpeech(byte *src, byte *dst, uint32 dstSize, bool *endiannessC
if (_cowMode == CowPSX) {
Audio::RewindableAudioStream *stream = Audio::makeXAStream(new Common::MemoryReadStream(src, dstSize), 11025);
- stream->readBuffer((int16 *)speechSample, speechSize);
+ stream->readBuffer((int16 *)_speechSample, _speechSize);
return true;
} else if (_cowMode != CowWave && _cowMode != CowDemo) {
Audio::RewindableAudioStream *stream = nullptr;
@@ -458,7 +459,7 @@ bool Sound::expandSpeech(byte *src, byte *dst, uint32 dstSize, bool *endiannessC
}
#endif
if (stream) {
- stream->readBuffer((int16 *)speechSample, speechSize);
+ stream->readBuffer((int16 *)_speechSample, _speechSize);
return true;
} else {
return false;
@@ -675,9 +676,9 @@ int32 Sound::checkSampleStatus(int32 id) {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_FX; i++) {
- if (fxSampleID[i] == id) {
- if (!_mixer->isSoundHandleActive(hSampleFX[i]) && (fxSampleBusy[i]) && (!fxPaused[i])) {
- fxSampleBusy[i] = false;
+ if (_fxSampleId[i] == id) {
+ if (!_mixer->isSoundHandleActive(_hSampleFX[i]) && (_fxSampleBusy[i]) && (!_fxPaused[i])) {
+ _fxSampleBusy[i] = false;
return S_STATUS_FINISHED;
} else {
return S_STATUS_RUNNING;
@@ -691,11 +692,11 @@ int32 Sound::checkSampleStatus(int32 id) {
int32 Sound::checkSpeechStatus() {
Common::StackLock lock(_soundMutex);
- if (!speechSampleBusy || speechPaused)
+ if (!_speechSampleBusy || _speechPaused)
return S_STATUS_FINISHED;
- if (!_mixer->isSoundHandleActive(hSampleSpeech)) {
- speechSampleBusy = 0;
+ if (!_mixer->isSoundHandleActive(_hSampleSpeech)) {
+ _speechSampleBusy = 0;
restoreMusicVolume();
return S_STATUS_FINISHED;
}
@@ -706,21 +707,21 @@ int32 Sound::checkSpeechStatus() {
void Sound::playSpeech() {
Common::StackLock lock(_soundMutex);
- speechLipsyncCounter = 0;
+ _speechLipsyncCounter = 0;
- if (speechSampleBusy)
+ if (_speechSampleBusy)
stopSpeech();
- speechSampleBusy = true;
+ _speechSampleBusy = true;
Audio::SeekableAudioStream *stream = Audio::makeRawStream(
- (byte *)speechSample, speechSize, 11025, SPEECH_FLAGS, DisposeAfterUse::NO);
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, &hSampleSpeech, stream);
+ (byte *)_speechSample, _speechSize, 11025, SPEECH_FLAGS, DisposeAfterUse::NO);
+ _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_hSampleSpeech, stream);
- _mixer->setChannelVolume(hSampleSpeech, 2 * (4 * (volSpeech[0] + volSpeech[1])));
+ _mixer->setChannelVolume(_hSampleSpeech, 2 * (4 * (_volSpeech[0] + _volSpeech[1])));
- int pan = 64 + (4 * ((int32)volSpeech[1] - (int32)volSpeech[0]));
- _mixer->setChannelBalance(hSampleSpeech, scalePan(pan));
+ int pan = 64 + (4 * ((int32)_volSpeech[1] - (int32)_volSpeech[0]));
+ _mixer->setChannelBalance(_hSampleSpeech, scalePan(pan));
reduceMusicVolume();
}
@@ -728,9 +729,9 @@ void Sound::playSpeech() {
void Sound::stopSpeech() {
Common::StackLock lock(_soundMutex);
- if (_mixer->isSoundHandleActive(hSampleSpeech)) {
- _mixer->stopHandle(hSampleSpeech);
- speechSampleBusy = false;
+ if (_mixer->isSoundHandleActive(_hSampleSpeech)) {
+ _mixer->stopHandle(_hSampleSpeech);
+ _speechSampleBusy = false;
restoreMusicVolume();
}
}
@@ -744,24 +745,24 @@ static void soundCallback(void *refCon) {
// for fade-ups). They are omitted here as they are not used
// anywhere...
- if (snd->fxFadingFlag) {
- snd->fxCount += 1;
- if (snd->fxCount > 128 / snd->fxFadingRate) {
- snd->fxFadingFlag = 0;
+ if (snd->_fxFadingFlag) {
+ snd->_fxCount += 1;
+ if (snd->_fxCount > 128 / snd->_fxFadingRate) {
+ snd->_fxFadingFlag = 0;
} else {
- if (snd->fxFadingFlag == 1) {
+ if (snd->_fxFadingFlag == 1) {
// Fade the volume up...
- snd->fxFadeVolume[0] = 8 * snd->volFX[0] * snd->fxCount * snd->fxFadingRate / 128;
- snd->fxFadeVolume[1] = 8 * snd->volFX[1] * snd->fxCount * snd->fxFadingRate / 128;
+ snd->_fxFadeVolume[0] = 8 * snd->_volFX[0] * snd->_fxCount * snd->_fxFadingRate / 128;
+ snd->_fxFadeVolume[1] = 8 * snd->_volFX[1] * snd->_fxCount * snd->_fxFadingRate / 128;
} else {
// Fade the volume down...
- snd->fxFadeVolume[0] = 8 * snd->volFX[0] - (8 * snd->volFX[0] * snd->fxCount * snd->fxFadingRate / 128);
- snd->fxFadeVolume[1] = 8 * snd->volFX[1] - (8 * snd->volFX[1] * snd->fxFadingRate * snd->fxCount / 128);
+ snd->_fxFadeVolume[0] = 8 * snd->_volFX[0] - (8 * snd->_volFX[0] * snd->_fxCount * snd->_fxFadingRate / 128);
+ snd->_fxFadeVolume[1] = 8 * snd->_volFX[1] - (8 * snd->_volFX[1] * snd->_fxFadingRate * snd->_fxCount / 128);
}
for (int i = 0; i < MAX_FX; i++) {
- if (snd->fxSampleBusy[i]) {
- int32 targetVolume = (snd->fxFadeVolume[0] + snd->fxFadeVolume[1]) / 2;
+ if (snd->_fxSampleBusy[i]) {
+ int32 targetVolume = (snd->_fxFadeVolume[0] + snd->_fxFadeVolume[1]) / 2;
// Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
snd->setFXVolume((byte)(targetVolume * 2), i);
@@ -780,7 +781,7 @@ void Sound::uninstallFadeTimer() {
}
void Sound::setFXVolume(byte targetVolume, int handleIdx) {
- _mixer->setChannelVolume(hSampleFX[handleIdx], targetVolume);
+ _mixer->setChannelVolume(_hSampleFX[handleIdx], targetVolume);
}
void Sound::playSample(int32 fxNo) {
@@ -819,7 +820,7 @@ bool Sound::prepareMusicStreaming(Common::String filename, int newHandleId, int3
if (filename.empty())
return false;
- if (!streamFile[newHandleId].open(filename)) {
+ if (!_musicFile[newHandleId].open(filename)) {
debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
return false;
}
@@ -827,24 +828,34 @@ bool Sound::prepareMusicStreaming(Common::String filename, int newHandleId, int3
delete _compressedMusicStream[newHandleId];
if (assignedMode == MusWav) {
- if (streamFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
+ if (_musicFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
debug(5, "Sound::streamMusicFile(): couldn't read from file %s, bailing out...", filename.c_str());
- streamFile[newHandleId].close();
+ _musicFile[newHandleId].close();
return false;
}
sampleRate = wavHead.dwSamplesPerSec;
- } else if (assignedMode == MusFLAC) {
- _compressedMusicStream[newHandleId] = Audio::makeFLACStream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ }
+#ifdef USE_FLAC
+ else if (assignedMode == MusFLAC) {
+ _compressedMusicStream[newHandleId] = Audio::makeFLACStream(&_musicFile[newHandleId], DisposeAfterUse::NO);
sampleRate = _compressedMusicStream[newHandleId]->getRate();
- } else if (assignedMode == MusVorbis) {
- _compressedMusicStream[newHandleId] = Audio::makeVorbisStream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ }
+#endif
+#ifdef USE_VORBIS
+ else if (assignedMode == MusVorbis) {
+ _compressedMusicStream[newHandleId] = Audio::makeVorbisStream(&_musicFile[newHandleId], DisposeAfterUse::NO);
sampleRate = _compressedMusicStream[newHandleId]->getRate();
- } else if (assignedMode == MusMP3) {
- _compressedMusicStream[newHandleId] = Audio::makeMP3Stream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ }
+#endif
+#ifdef USE_MAD
+ else if (assignedMode == MusMP3) {
+ _compressedMusicStream[newHandleId] = Audio::makeMP3Stream(&_musicFile[newHandleId], DisposeAfterUse::NO);
sampleRate = _compressedMusicStream[newHandleId]->getRate();
- } else if (assignedMode == MusAif) {
- _compressedMusicStream[newHandleId] = Audio::makeAIFFStream(&streamFile[newHandleId], DisposeAfterUse::NO);
+ }
+#endif
+ else if (assignedMode == MusAif) {
+ _compressedMusicStream[newHandleId] = Audio::makeAIFFStream(&_musicFile[newHandleId], DisposeAfterUse::NO);
sampleRate = _compressedMusicStream[newHandleId]->getRate();
} else if (assignedMode == MusPSX) {
Common::File tableFile;
@@ -853,9 +864,8 @@ bool Sound::prepareMusicStreaming(Common::String filename, int newHandleId, int3
return false;
}
-
- // The PSX demo has a broken/truncated tunes.tab. So we check here that the offset is not
- // beyond the end of the file.
+ // The PSX demo has a broken/truncated tunes.tab. So we check here
+ // that the offset is not beyond the end of the file.
int32 tableOffset = (tuneId - 1) * 8;
if (tableOffset >= tableFile.size())
return false;
@@ -865,34 +875,34 @@ bool Sound::prepareMusicStreaming(Common::String filename, int newHandleId, int3
tableFile.close();
- // Because of broken tunes.dat/tab in psx demo, also check that tune offset is
- // not over file size
- if ((size != 0) && (size != 0xffffffff) && ((int32)(offset + size) <= streamFile[newHandleId].size())) {
- streamFile[newHandleId].seek(offset, SEEK_SET);
- _compressedMusicStream[newHandleId] = Audio::makeXAStream(streamFile[newHandleId].readStream(size), DEFAULT_SAMPLE_RATE);
+ // Because of broken tunes.dat/tab in psx demo,
+ // also check that tune offset is not over file size
+ if ((size != 0) && (size != 0xffffffff) && ((int32)(offset + size) <= _musicFile[newHandleId].size())) {
+ _musicFile[newHandleId].seek(offset, SEEK_SET);
+ _compressedMusicStream[newHandleId] = Audio::makeXAStream(_musicFile[newHandleId].readStream(size), DEFAULT_SAMPLE_RATE);
}
}
if (assignedMode != MusWav && !_compressedMusicStream[newHandleId]) {
debug(5, "Sound::streamMusicFile(): couldn't process compressed file %s, bailing out...", filename.c_str());
- streamFile[newHandleId].close();
+ _musicFile[newHandleId].close();
return false;
}
_musicOutputStream[newHandleId] = Audio::makeQueuingAudioStream(sampleRate, isStereo);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &hSampleMusic[newHandleId], _musicOutputStream[newHandleId]);
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_hSampleMusic[newHandleId], _musicOutputStream[newHandleId]);
- _mixer->setChannelRate(hSampleMusic[newHandleId], sampleRate);
- _mixer->setChannelVolume(hSampleMusic[newHandleId], volume);
- _mixer->setChannelBalance(hSampleMusic[newHandleId], pan);
+ _mixer->setChannelRate(_hSampleMusic[newHandleId], sampleRate);
+ _mixer->setChannelVolume(_hSampleMusic[newHandleId], volume);
+ _mixer->setChannelBalance(_hSampleMusic[newHandleId], pan);
- streamSamplePlaying[newHandleId] = true;
- streamFormat[newHandleId] = assignedMode;
+ _musicStreamPlaying[newHandleId] = true;
+ _musicStreamFormat[newHandleId] = assignedMode;
return true;
}
-int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
+void Sound::streamMusicFile(int32 tuneId, int32 looped) {
int32 oldHandleId, newHandleId;
Common::File tmp;
@@ -925,96 +935,103 @@ int32 Sound::streamMusicFile(int32 tuneId, int32 looped) {
}
newHandleId = 0;
- if ((streamSamplePlaying[0]) || (streamSamplePlaying[1])) {
- if (streamSamplePlaying[0])
+
+ if ((_musicStreamPlaying[0]) || (_musicStreamPlaying[1])) {
+ // In this case at least one of the music streams is already
+ // busy so we still attempt to find a free one...
+ if (_musicStreamPlaying[0])
newHandleId = 1;
oldHandleId = 1 - newHandleId;
- streamLoopingFlag[newHandleId] = looped;
+ _streamLoopingFlag[newHandleId] = looped;
- streamSampleFading[oldHandleId] = -12;
- streamSampleFading[newHandleId] = 1;
+ _musicStreamFading[oldHandleId] = -12;
+ _musicStreamFading[newHandleId] = 1;
- if (streamSamplePlaying[newHandleId]) {
- _mixer->stopHandle(hSampleMusic[newHandleId]);
- streamFile[newHandleId].close();
+ if (_musicStreamPlaying[newHandleId]) {
+ // Whoops, they are BOTH busy! Let's kill the older one...
+ _mixer->stopHandle(_hSampleMusic[newHandleId]);
+ _musicFile[newHandleId].close();
bool success = prepareMusicStreaming(filename, newHandleId, tuneId,
- 2 * (2 * (volMusic[0] + volMusic[1])),
- scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
+ 2 * (2 * (_volMusic[0] + _volMusic[1])),
+ scalePan(64 + (4 * (_volMusic[1] - _volMusic[0]))),
assignedMode);
if (success)
debug(5, "Sound::streamMusicFile(): interrupting sound in handle %d to play %s", newHandleId, filename.c_str());
- return 2;
+ return;
} else {
+ // All good! We got the non-busy one :-)
bool success = prepareMusicStreaming(filename, newHandleId, tuneId,
0,
- scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
+ scalePan(64 + (4 * (_volMusic[1] - _volMusic[0]))),
assignedMode);
if (success)
debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d with other handle busy", filename.c_str(), newHandleId);
}
} else {
+ // No streams are busy, let's go!
bool success = prepareMusicStreaming(filename, newHandleId, tuneId,
- 2 * (3 * (volMusic[0] + volMusic[1])),
- scalePan(64 + (4 * (volMusic[1] - volMusic[0]))),
+ 2 * (3 * (_volMusic[0] + _volMusic[1])),
+ scalePan(64 + (4 * (_volMusic[1] - _volMusic[0]))),
assignedMode);
if (success)
debug(5, "Sound::streamMusicFile(): playing sound %s in handle %d", filename.c_str(), newHandleId);
}
- streamLoopingFlag[newHandleId] = looped;
-
- return 0;
+ _streamLoopingFlag[newHandleId] = looped;
}
-void Sound::updateSampleStreaming() {
+void Sound::updateMusicStreaming() {
Common::StackLock lock(_soundMutex);
+
+ // Within this function we make sure to fade music streams and
+ // stop them whenever they are either finished or at zero volume
for (int i = 0; i < MAX_MUSIC; i++) {
- if ((streamSamplePlaying[i]) && (!musicPaused[i])) {
- if (streamSampleFading[i]) {
- if (crossFadeIncrement) {
- crossFadeIncrement = false;
-
- if (streamSampleFading[i] < 0) {
- debug("Sound::updateSampleStreaming(): Fading %s to %d", streamFile[i].getName(),
- 2 * (((0 - streamSampleFading[i]) * 3 * (volMusic[0] + volMusic[1])) / 16));
- _mixer->setChannelVolume(hSampleMusic[i],
- 2 * (((0 - streamSampleFading[i]) * 3 * (volMusic[0] + volMusic[1])) / 16));
-
- streamSampleFading[i] += 1;
- if (streamSampleFading[i] == 0) {
- streamFile[i].close();
-
- streamSamplePlaying[i] = false;
+ if ((_musicStreamPlaying[i]) && (!_musicPaused[i])) {
+ if (_musicStreamFading[i]) {
+ if (_crossFadeIncrement) {
+ _crossFadeIncrement = false;
+
+ if (_musicStreamFading[i] < 0) {
+ debug("Sound::updateMusicStreaming(): Fading %s to %d", _musicFile[i].getName(),
+ 2 * (((0 - _musicStreamFading[i]) * 3 * (_volMusic[0] + _volMusic[1])) / 16));
+ _mixer->setChannelVolume(_hSampleMusic[i],
+ 2 * (((0 - _musicStreamFading[i]) * 3 * (_volMusic[0] + _volMusic[1])) / 16));
+
+ _musicStreamFading[i] += 1;
+ if (_musicStreamFading[i] == 0) {
+ _musicFile[i].close();
+
+ _musicStreamPlaying[i] = false;
_musicOutputStream[i]->finish();
_musicOutputStream[i] = nullptr;
}
} else {
- debug("Sound::updateSampleStreaming(): Fading %s to %d", streamFile[i].getName(),
- 2 * ((streamSampleFading[i] * 3 * (volMusic[0] + volMusic[1])) / 16));
- _mixer->setChannelVolume(hSampleMusic[i],
- 2 * ((streamSampleFading[i] * 3 * (volMusic[0] + volMusic[1])) / 16));
-
- streamSampleFading[i] += 1;
- if (streamSampleFading[i] == 17) {
- streamSampleFading[i] = 0;
+ debug("Sound::updateMusicStreaming(): Fading %s to %d", _musicFile[i].getName(),
+ 2 * ((_musicStreamFading[i] * 3 * (_volMusic[0] + _volMusic[1])) / 16));
+ _mixer->setChannelVolume(_hSampleMusic[i],
+ 2 * ((_musicStreamFading[i] * 3 * (_volMusic[0] + _volMusic[1])) / 16));
+
+ _musicStreamFading[i] += 1;
+ if (_musicStreamFading[i] == 17) {
+ _musicStreamFading[i] = 0;
}
}
}
}
- if (streamFile[i].isOpen())
- serveSample(&streamFile[i], i);
+ if (_musicFile[i].isOpen())
+ serveSample(&_musicFile[i], i);
- if (!_mixer->isSoundHandleActive(hSampleMusic[i]) ||
+ if (!_mixer->isSoundHandleActive(_hSampleMusic[i]) ||
(_musicOutputStream[i] && _musicOutputStream[i]->endOfData())) {
- streamSamplePlaying[i] = false;
- streamFile[i].close();
+ _musicStreamPlaying[i] = false;
+ _musicFile[i].close();
_musicOutputStream[i]->finish();
_musicOutputStream[i] = nullptr;
}
@@ -1027,9 +1044,9 @@ void Sound::serveSample(Common::File *file, int32 i) {
int32 nominalSize = MUSIC_BUFFER_SIZE;
byte *buf = nullptr;
- if (!musicPaused[i]) {
+ if (!_musicPaused[i]) {
if (_musicOutputStream[i]->numQueuedStreams() < 4) {
- if (streamFormat[i] == MusWav) {
+ if (_musicStreamFormat[i] == MusWav) {
buf = (byte *)malloc(nominalSize);
if (!buf) {
warning("Sound::serveSample(): Couldn't allocate memory for streaming file %s", file->getName());
@@ -1038,7 +1055,7 @@ void Sound::serveSample(Common::File *file, int32 i) {
len = file->read(buf, nominalSize);
if (len < nominalSize) {
- if (streamLoopingFlag[i]) {
+ if (_streamLoopingFlag[i]) {
file->seek(44, SEEK_SET);
file->read(buf + len, nominalSize - len);
len = nominalSize;
@@ -1058,7 +1075,7 @@ void Sound::serveSample(Common::File *file, int32 i) {
len = _compressedMusicStream[i]->readBuffer((int16 *)buf, nominalSize);
if (len < nominalSize) {
- if (streamLoopingFlag[i]) {
+ if (_streamLoopingFlag[i]) {
_compressedMusicStream[i]->rewind();
_compressedMusicStream[i]->readBuffer((int16 *)buf + len, nominalSize - len);
len = nominalSize;
@@ -1071,7 +1088,7 @@ void Sound::serveSample(Common::File *file, int32 i) {
}
}
- if (streamFormat[i] != MusWav)
+ if (_musicStreamFormat[i] != MusWav)
len *= 2;
_musicOutputStream[i]->queueBuffer(buf, len, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
@@ -1085,10 +1102,10 @@ void Sound::playFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]) {
int32 v0, v1;
// Search through the FX sample handles for a free slot...
for (int i = 0; i < MAX_FX; i++) {
- if (!fxSampleBusy[i]) {
+ if (!_fxSampleBusy[i]) {
// Found the handle! Now setup and play the sound...
- fxSampleBusy[i] = true;
- fxSampleID[i] = fxID;
+ _fxSampleBusy[i] = true;
+ _fxSampleId[i] = fxID;
Audio::AudioStream *stream = nullptr;
@@ -1112,14 +1129,13 @@ void Sound::playFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]) {
(type == FX_LOOP) ? 0 : 1);
}
- // And point the sample to our new wav data
if (stream) {
- v0 = volFX[0] * vol[0];
- v1 = volFX[1] * vol[1];
+ v0 = _volFX[0] * vol[0];
+ v1 = _volFX[1] * vol[1];
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &hSampleFX[i], stream, -1, 0);
- _mixer->setChannelVolume(hSampleFX[i], 2 * ((v0 + v1) / 8));
- _mixer->setChannelBalance(hSampleFX[i], scalePan(64 + ((v1 - v0) / 4)));
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_hSampleFX[i], stream, -1, 0);
+ _mixer->setChannelVolume(_hSampleFX[i], 2 * ((v0 + v1) / 8));
+ _mixer->setChannelBalance(_hSampleFX[i], scalePan(64 + ((v1 - v0) / 4)));
}
return;
@@ -1130,10 +1146,10 @@ void Sound::playFX(int32 fxID, int32 type, uint8 *wavData, uint32 vol[2]) {
void Sound::stopFX(int32 fxID) {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_FX; i++) {
- if (fxSampleID[i] == fxID) {
- if (_mixer->isSoundHandleActive(hSampleFX[i])) {
- _mixer->stopHandle(hSampleFX[i]);
- fxSampleBusy[i] = false;
+ if (_fxSampleId[i] == fxID) {
+ if (_mixer->isSoundHandleActive(_hSampleFX[i])) {
+ _mixer->stopHandle(_hSampleFX[i]);
+ _fxSampleBusy[i] = false;
}
}
}
@@ -1155,21 +1171,21 @@ void Sound::clearAllFx() {
void Sound::fadeMusicDown(int32 rate) {
Common::StackLock lock(_soundMutex);
- streamSampleFading[1 - streamSamplePlaying[0]] = -12;
+ _musicStreamFading[1 - _musicStreamPlaying[0]] = -12;
}
void Sound::fadeFxDown(int32 rate) {
Common::StackLock lock(_soundMutex);
- fxFadingFlag = -1;
- fxFadingRate = 2 * rate;
- fxCount = 0;
+ _fxFadingFlag = -1;
+ _fxFadingRate = 2 * rate;
+ _fxCount = 0;
}
void Sound::fadeFxUp(int32 rate) {
Common::StackLock lock(_soundMutex);
- fxFadingFlag = 1;
- fxFadingRate = 2 * rate;
- fxCount = 0;
+ _fxFadingFlag = 1;
+ _fxFadingRate = 2 * rate;
+ _fxCount = 0;
}
int32 Sound::getSpeechSize(byte *compData, uint32 compSize) {
@@ -1215,44 +1231,44 @@ int32 Sound::getSpeechSize(byte *compData, uint32 compSize) {
void Sound::reduceMusicVolume() {
Common::StackLock lock(_soundMutex);
- musicFadeVolume[0] = volMusic[0] * MUSIC_UNDERSCORE / 100;
- musicFadeVolume[1] = volMusic[0] * MUSIC_UNDERSCORE / 100; // We are explicitly accessing volMusic[0] again
+ _musicFadeVolume[0] = _volMusic[0] * MUSIC_UNDERSCORE / 100;
+ _musicFadeVolume[1] = _volMusic[0] * MUSIC_UNDERSCORE / 100; // We are explicitly accessing _volMusic[0] again
// Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
- _mixer->setChannelVolume(hSampleMusic[0], 2 * ((musicFadeVolume[0] + musicFadeVolume[1]) * 3));
+ _mixer->setChannelVolume(_hSampleMusic[0], 2 * ((_musicFadeVolume[0] + _musicFadeVolume[1]) * 3));
}
void Sound::restoreMusicVolume() {
Common::StackLock lock(_soundMutex);
// Multiplying by 2 because Miles Sound System uses 0-127 and we use 0-255
- _mixer->setChannelVolume(hSampleMusic[0], 2 * ((volMusic[0] + volMusic[1]) * 3));
+ _mixer->setChannelVolume(_hSampleMusic[0], 2 * ((_volMusic[0] + _volMusic[1]) * 3));
}
void Sound::setCrossFadeIncrement() {
- crossFadeIncrement = true;
+ _crossFadeIncrement = true;
}
void Sound::pauseSpeech() {
- if ((speechSampleBusy) && (!speechPaused)) {
- speechPaused = true;
- _mixer->pauseHandle(hSampleSpeech, true);
+ if ((_speechSampleBusy) && (!_speechPaused)) {
+ _speechPaused = true;
+ _mixer->pauseHandle(_hSampleSpeech, true);
}
}
void Sound::unpauseSpeech() {
- if ((speechSampleBusy) && (speechPaused)) {
- speechPaused = false;
- _mixer->pauseHandle(hSampleSpeech, false);
+ if ((_speechSampleBusy) && (_speechPaused)) {
+ _speechPaused = false;
+ _mixer->pauseHandle(_hSampleSpeech, false);
}
}
void Sound::pauseMusic() {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_MUSIC; i++) {
- if (streamSamplePlaying[i]) {
- musicPaused[i] = true;
- _mixer->pauseHandle(hSampleMusic[i], true);
+ if (_musicStreamPlaying[i]) {
+ _musicPaused[i] = true;
+ _mixer->pauseHandle(_hSampleMusic[i], true);
}
}
}
@@ -1260,9 +1276,9 @@ void Sound::pauseMusic() {
void Sound::unpauseMusic() {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_MUSIC; i++) {
- if (musicPaused[i]) {
- _mixer->pauseHandle(hSampleMusic[i], false);
- musicPaused[i] = false;
+ if (_musicPaused[i]) {
+ _mixer->pauseHandle(_hSampleMusic[i], false);
+ _musicPaused[i] = false;
}
}
}
@@ -1270,9 +1286,9 @@ void Sound::unpauseMusic() {
void Sound::pauseFx() {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_FX; i++) {
- if (fxSampleBusy[i]) {
- _mixer->pauseHandle(hSampleFX[i], true);
- fxPaused[i] = true;
+ if (_fxSampleBusy[i]) {
+ _mixer->pauseHandle(_hSampleFX[i], true);
+ _fxPaused[i] = true;
}
}
}
@@ -1280,9 +1296,9 @@ void Sound::pauseFx() {
void Sound::unpauseFx() {
Common::StackLock lock(_soundMutex);
for (int i = 0; i < MAX_FX; i++) {
- if (fxPaused[i]) {
- _mixer->pauseHandle(hSampleFX[i], false);
- fxPaused[i] = false;
+ if (_fxPaused[i]) {
+ _mixer->pauseHandle(_hSampleFX[i], false);
+ _fxPaused[i] = false;
}
}
}
@@ -1335,18 +1351,18 @@ void Sound::getVolumes() {
sfxBal = CLIP(ConfMan.getInt("sfx_balance"), 0, 100);
}
- getGameVolumes(musicBal, musicVol, volMusic[0], volMusic[1]);
- getGameVolumes(speechBal, speechVol, volSpeech[0], volSpeech[1]);
- getGameVolumes(sfxBal, sfxVol, volFX[0], volFX[1]);
+ getGameVolumes(musicBal, musicVol, _volMusic[0], _volMusic[1]);
+ getGameVolumes(speechBal, speechVol, _volSpeech[0], _volSpeech[1]);
+ getGameVolumes(sfxBal, sfxVol, _volFX[0], _volFX[1]);
if (ConfMan.getBool("mute")) {
- volSpeech[0] = 0;
- volSpeech[1] = 0;
+ _volSpeech[0] = 0;
+ _volSpeech[1] = 0;
}
SwordEngine::_systemVars.showText = ConfMan.getBool("subtitles");
- if (volSpeech[0] + volSpeech[1] == 0) {
+ if (_volSpeech[0] + _volSpeech[1] == 0) {
SwordEngine::_systemVars.showText = true;
SwordEngine::_systemVars.playSpeech = false;
} else {
@@ -1358,19 +1374,19 @@ void Sound::setVolumes() {
int volume = 0;
int balance = 0;
- getConfigVolumes(volMusic[0], volMusic[1], balance, volume);
+ getConfigVolumes(_volMusic[0], _volMusic[1], balance, volume);
if (volume != ConfMan.getInt("music_volume"))
ConfMan.setInt("music_volume", volume);
if (balance != ConfMan.getInt("music_balance"))
ConfMan.setInt("music_balance", balance);
- getConfigVolumes(volSpeech[0], volSpeech[1], balance, volume);
+ getConfigVolumes(_volSpeech[0], _volSpeech[1], balance, volume);
if (volume != ConfMan.getInt("speech_volume"))
ConfMan.setInt("speech_volume", volume);
if (balance != ConfMan.getInt("speech_balance"))
ConfMan.setInt("speech_balance", balance);
- getConfigVolumes(volFX[0], volFX[1], balance, volume);
+ getConfigVolumes(_volFX[0], _volFX[1], balance, volume);
if (volume != ConfMan.getInt("sfx_volume"))
ConfMan.setInt("sfx_volume", volume);
if (balance != ConfMan.getInt("sfx_balance"))
@@ -1380,7 +1396,7 @@ void Sound::setVolumes() {
ConfMan.setBool("subtitles", SwordEngine::_systemVars.showText);
ConfMan.flushToDisk();
- if (volSpeech[0] + volSpeech[1] == 0) {
+ if (_volSpeech[0] + _volSpeech[1] == 0) {
SwordEngine::_systemVars.showText = true;
SwordEngine::_systemVars.playSpeech = false;
} else {
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index 59fd2d4e409..4d1f4b27f78 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -132,8 +132,8 @@ public:
void playSpeech();
void stopSpeech();
- int32 streamMusicFile(int32 tuneId, int32 looped);
- void updateSampleStreaming();
+ void streamMusicFile(int32 tuneId, int32 looped);
+ void updateMusicStreaming();
void setCrossFadeIncrement();
void fadeMusicDown(int32 rate);
@@ -154,22 +154,22 @@ public:
Audio::Mixer *_mixer;
// Handles for external volume changes (control panel)
- uint32 volFX[2] = { 0, 0 };
- uint32 volSpeech[2] = { 0, 0 };
- uint32 volMusic[2] = { 0, 0 };
+ uint32 _volFX[2] = { 0, 0 };
+ uint32 _volSpeech[2] = { 0, 0 };
+ uint32 _volMusic[2] = { 0, 0 };
// Volume fading variables
- int32 fxCount = 0;
- int32 fxFadingFlag = 0;
- int32 fxFadingRate = 0;
- int32 fxFadeVolume[2] = { 0, 0 };
- int32 musicFadeVolume[2] = { 0, 0 };
+ int32 _fxCount = 0;
+ int32 _fxFadingFlag = 0;
+ int32 _fxFadingRate = 0;
+ int32 _fxFadeVolume[2] = { 0, 0 };
+ int32 _musicFadeVolume[2] = { 0, 0 };
// Sound FX information
- bool fxSampleBusy[MAX_FX] = { false, false, false, false };
+ bool _fxSampleBusy[MAX_FX] = { false, false, false, false };
// Speech data
- byte *speechSample = nullptr;
+ byte *_speechSample = nullptr;
private:
struct WaveHeader {
@@ -225,39 +225,39 @@ private:
static const char _musicList[270];
static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
static const FxDef _fxList[312];
- static const char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
+ static const char _tuneList[TOTAL_TUNES][8]; // In staticres.cpp
// Volume fading variables
- bool crossFadeIncrement = false;
+ bool _crossFadeIncrement = false;
// Speech variables
- int32 speechLipsyncCounter = 0;
- int32 speechSize = 0;
- bool speechSampleBusy = false;
+ int32 _speechLipsyncCounter = 0;
+ int32 _speechSize = 0;
+ bool _speechSampleBusy = false;
// Sound handles
- Audio::SoundHandle hSampleFX[MAX_FX];
- Audio::SoundHandle hSampleSpeech;
- Audio::SoundHandle hSampleMusic[MAX_MUSIC];
+ Audio::SoundHandle _hSampleFX[MAX_FX];
+ Audio::SoundHandle _hSampleSpeech;
+ Audio::SoundHandle _hSampleMusic[MAX_MUSIC];
// Music stream information
- bool streamSamplePlaying[MAX_MUSIC] = { false, false };
- bool streamLoopingFlag[MAX_MUSIC] = { false, false };
- int32 streamSampleFading[MAX_MUSIC] = { 0, 0 };
- MusCompMode streamFormat[MAX_MUSIC] = { MusWav, MusWav };
+ bool _musicStreamPlaying[MAX_MUSIC] = { false, false };
+ bool _streamLoopingFlag[MAX_MUSIC] = { false, false };
+ int32 _musicStreamFading[MAX_MUSIC] = { 0, 0 };
+ MusCompMode _musicStreamFormat[MAX_MUSIC] = { MusWav, MusWav };
Audio::QueuingAudioStream *_musicOutputStream[MAX_MUSIC] = { nullptr, nullptr };
Audio::RewindableAudioStream *_compressedMusicStream[MAX_MUSIC] = { nullptr, nullptr };
- Common::File streamFile[MAX_MUSIC];
+ Common::File _musicFile[MAX_MUSIC];
// Sound FX information
- int32 fxSampleID[MAX_FX] = { 0, 0, 0, 0 };
+ int32 _fxSampleId[MAX_FX] = { 0, 0, 0, 0 };
// Pause variables
- bool speechPaused = false;
- bool fxPaused[MAX_FX] = { false, false, false, false };
- bool musicPaused[MAX_MUSIC] = { false, false };
+ bool _speechPaused = false;
+ bool _fxPaused[MAX_FX] = { false, false, false, false };
+ bool _musicPaused[MAX_MUSIC] = { false, false };
};
} // End of namespace Sword1
-#endif //BSSOUND_H
+#endif // SOUND_H
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index e44269d8900..2a3eecdf7a6 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -216,7 +216,7 @@ void SwordEngine::checkKeys() {
while (_keyPressed.keycode != Common::KEYCODE_p && !Engine::shouldQuit()) {
pollInput(0);
- _sound->updateSampleStreaming();
+ _sound->updateMusicStreaming();
}
_sound->unpauseSpeech();
@@ -1100,7 +1100,7 @@ void SwordEngine::pollInput(uint32 delay) { //copied and mutilated from sky.cpp
}
}
- _sound->updateSampleStreaming();
+ _sound->updateMusicStreaming();
_screen->_screenAccessMutex.lock();
_system->updateScreen();
Commit: 5ecdcecf726dafe1293aa3ac0889bb04f1ffa585
https://github.com/scummvm/scummvm/commit/5ecdcecf726dafe1293aa3ac0889bb04f1ffa585
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Remove Music class and files
All sound is now handled by a single engine (Sound class)
Changed paths:
R engines/sword1/music.cpp
R engines/sword1/music.h
engines/sword1/control.cpp
engines/sword1/control.h
engines/sword1/logic.cpp
engines/sword1/logic.h
engines/sword1/module.mk
engines/sword1/staticres.cpp
engines/sword1/sword1.cpp
engines/sword1/sword1.h
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 4c748dc1bcf..0c3548f7786 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -36,7 +36,6 @@
#include "sword1/control.h"
#include "sword1/logic.h"
#include "sword1/mouse.h"
-#include "sword1/music.h"
#include "sword1/objectman.h"
#include "sword1/resman.h"
#include "sword1/sound.h"
@@ -176,14 +175,13 @@ const Button Control::volumeButtons[25] = {
};
-Control::Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen, Logic *pLogic) {
+Control::Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Screen *pScreen, Logic *pLogic) {
_vm = vm;
_saveFileMan = saveFileMan;
_resMan = pResMan;
_objMan = pObjMan;
_system = system;
_mouse = pMouse;
- _music = pMusic;
_sound = pSound;
_screen = pScreen;
_logic = pLogic;
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index 51f3317f51c..d0971d9ec3a 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -71,7 +71,6 @@ class SwordEngine;
class ObjectMan;
class ResMan;
class Mouse;
-class Music;
class Sound;
class Screen;
class Logic;
@@ -115,7 +114,7 @@ struct Button {
class Control {
public:
- Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic, Screen *pScreen, Logic *pLogic);
+ Control(SwordEngine *vm, Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Screen *pScreen, Logic *pLogic);
void getPlayerOptions();
void askForCdMessage(uint32 needCD, bool incorrectCDPhase);
@@ -211,7 +210,6 @@ private:
ResMan *_resMan;
OSystem *_system;
Mouse *_mouse;
- Music *_music;
Sound *_sound;
Screen *_screen;
Logic *_logic;
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index e70cf78e2a6..1419f52910f 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -33,7 +33,6 @@
#include "sword1/screen.h"
#include "sword1/mouse.h"
#include "sword1/sword1.h"
-#include "sword1/music.h"
#include "sword1/swordres.h"
#include "sword1/animation.h"
#include "sword1/control.h"
@@ -50,7 +49,7 @@ namespace Sword1 {
uint32 Logic::_scriptVars[NUM_SCRIPT_VARS];
-Logic::Logic(SwordEngine *vm, ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Music *pMusic, Menu *pMenu, OSystem *system, Audio::Mixer *mixer)
+Logic::Logic(SwordEngine *vm, ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Menu *pMenu, OSystem *system, Audio::Mixer *mixer)
: _rnd("sword1") {
_vm = vm;
@@ -58,7 +57,6 @@ Logic::Logic(SwordEngine *vm, ObjectMan *pObjMan, ResMan *resMan, Screen *pScree
_resMan = resMan;
_screen = pScreen;
_mouse = pMouse;
- _music = pMusic;
_sound = pSound;
_menu = pMenu;
_textMan = NULL;
diff --git a/engines/sword1/logic.h b/engines/sword1/logic.h
index d38a46c9811..af4bbd99169 100644
--- a/engines/sword1/logic.h
+++ b/engines/sword1/logic.h
@@ -47,7 +47,6 @@ class Menu;
class Router;
class Screen;
class Mouse;
-class Music;
class Logic;
typedef int (Logic::*BSMcodeTable)(Object *, int32, int32, int32, int32, int32, int32, int32);
@@ -55,7 +54,7 @@ typedef int (Logic::*BSMcodeTable)(Object *, int32, int32, int32, int32, int32,
class Logic {
friend class Control;
public:
- Logic(SwordEngine *vm, ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Music *pMusic, Menu *pMenu, OSystem *system, Audio::Mixer *mixer);
+ Logic(SwordEngine *vm, ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Menu *pMenu, OSystem *system, Audio::Mixer *mixer);
~Logic();
void initialize();
void newScreen(uint32 screen);
@@ -82,7 +81,6 @@ private:
Text *_textMan;
EventManager *_eventMan;
Menu *_menu;
- Music *_music;
uint32 _newScript; // <= ugly, but I can't avoid it.
uint8 _speechClickDelay;
Common::RandomSource _rnd;
diff --git a/engines/sword1/module.mk b/engines/sword1/module.mk
index a2b38fc75a1..0e548a7b964 100644
--- a/engines/sword1/module.mk
+++ b/engines/sword1/module.mk
@@ -11,7 +11,6 @@ MODULE_OBJS := \
menu.o \
metaengine.o \
mouse.o \
- music.o \
objectman.o \
resman.o \
router.o \
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp
deleted file mode 100644
index f0867e2a585..00000000000
--- a/engines/sword1/music.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-
-#include "common/file.h"
-#include "common/util.h"
-#include "common/textconsole.h"
-
-#include "sword1/sword1.h"
-#include "sword1/music.h"
-
-#include "audio/mixer.h"
-#include "audio/audiostream.h"
-#include "audio/decoders/aiff.h"
-#include "audio/decoders/flac.h"
-#include "audio/decoders/mp3.h"
-#include "audio/decoders/vorbis.h"
-#include "audio/decoders/wave.h"
-#include "audio/decoders/xa.h"
-
-#define SMP_BUFSIZE 8192
-
-namespace Sword1 {
-
-// This means fading takes 3 seconds.
-#define FADE_LENGTH 3
-
-// These functions are only called from Music, so I'm just going to
-// assume that if locking is needed it has already been taken care of.
-
-bool MusicHandle::play(const Common::String &filename, bool loop) {
- stop();
-
- // FIXME: How about using AudioStream::openStreamFile instead of the code below?
- // I.e.:
- //_audioSource = Audio::AudioStream::openStreamFile(fileBase, 0, 0, loop ? 0 : 1);
-
- Audio::RewindableAudioStream *stream = 0;
-
-#ifdef USE_FLAC
- if (!stream) {
- if (_file.open(filename + ".flac")) {
- stream = Audio::makeFLACStream(&_file, DisposeAfterUse::NO);
- if (!stream)
- _file.close();
- }
- }
-
- if (!stream) {
- if (_file.open(filename + ".fla")) {
- stream = Audio::makeFLACStream(&_file, DisposeAfterUse::NO);
- if (!stream)
- _file.close();
- }
- }
-#endif
-#ifdef USE_VORBIS
- if (!stream) {
- if (_file.open(filename + ".ogg")) {
- stream = Audio::makeVorbisStream(&_file, DisposeAfterUse::NO);
- if (!stream)
- _file.close();
- }
- }
-#endif
-#ifdef USE_MAD
- if (!stream) {
- if (_file.open(filename + ".mp3")) {
- stream = Audio::makeMP3Stream(&_file, DisposeAfterUse::NO);
- if (!stream)
- _file.close();
- }
- }
-#endif
- if (!stream) {
- if (_file.open(filename + ".wav"))
- stream = Audio::makeWAVStream(&_file, DisposeAfterUse::NO);
- }
-
- if (!stream) {
- if (_file.open(filename + ".aif"))
- stream = Audio::makeAIFFStream(&_file, DisposeAfterUse::NO);
- }
-
- if (!stream)
- return false;
-
- _audioSource = Audio::makeLoopingAudioStream(stream, loop ? 0 : 1);
-
- fadeUp();
- return true;
-}
-
-bool MusicHandle::playPSX(uint16 id, bool loop) {
- stop();
-
- if (!_file.isOpen())
- if (!_file.open("tunes.dat"))
- return false;
-
- Common::File tableFile;
- if (!tableFile.open("tunes.tab"))
- return false;
-
- // The PSX demo has a broken/truncated tunes.tab. So we check here that the offset is not
- // beyond the end of the file.
- int32 tableOffset = (id - 1) * 8;
- if (tableOffset >= tableFile.size())
- return false;
- tableFile.seek(tableOffset, SEEK_SET);
- uint32 offset = tableFile.readUint32LE() * 0x800;
- uint32 size = tableFile.readUint32LE();
-
- tableFile.close();
-
- // Because of broken tunes.dat/tab in psx demo, also check that tune offset is
- // not over file size
- if ((size != 0) && (size != 0xffffffff) && ((int32)(offset + size) <= _file.size())) {
- _file.seek(offset, SEEK_SET);
- _audioSource = Audio::makeLoopingAudioStream(Audio::makeXAStream(_file.readStream(size), 11025), loop ? 0 : 1);
- fadeUp();
- } else {
- _audioSource = NULL;
- return false;
- }
-
- return true;
-}
-
-void MusicHandle::fadeDown() {
- if (streaming()) {
- if (_fading < 0)
- _fading = -_fading;
- else if (_fading == 0)
- _fading = FADE_LENGTH * getRate();
- _fadeSamples = FADE_LENGTH * getRate();
- }
-}
-
-void MusicHandle::fadeUp() {
- if (streaming()) {
- if (_fading > 0)
- _fading = -_fading;
- else if (_fading == 0)
- _fading = -1;
- _fadeSamples = FADE_LENGTH * getRate();
- }
-}
-
-bool MusicHandle::endOfData() const {
- return !streaming();
-}
-
-// if we don't have an audiosource, return some dummy values.
-bool MusicHandle::streaming() const {
- return (_audioSource) ? (!_audioSource->endOfStream()) : false;
-}
-
-bool MusicHandle::isStereo() const {
- return (_audioSource) ? _audioSource->isStereo() : false;
-}
-
-int MusicHandle::getRate() const {
- return (_audioSource) ? _audioSource->getRate() : 11025;
-}
-
-int MusicHandle::readBuffer(int16 *buffer, const int numSamples) {
- int totalSamples = 0;
- int16 *bufStart = buffer;
- if (!_audioSource)
- return 0;
- int expectedSamples = numSamples;
- while ((expectedSamples > 0) && _audioSource) { // _audioSource becomes NULL if we reach EOF and aren't looping
- int samplesReturned = _audioSource->readBuffer(buffer, expectedSamples);
- buffer += samplesReturned;
- totalSamples += samplesReturned;
- expectedSamples -= samplesReturned;
- if ((expectedSamples > 0) && _audioSource->endOfData()) {
- debug(2, "Music reached EOF");
- stop();
- }
- }
- // buffer was filled, now do the fading (if necessary)
- int samplePos = 0;
- while ((_fading > 0) && (samplePos < totalSamples)) { // fade down
- --_fading;
- bufStart[samplePos] = (bufStart[samplePos] * _fading) / _fadeSamples;
- samplePos++;
- if (_fading == 0) {
- stop();
- // clear the rest of the buffer
- memset(bufStart + samplePos, 0, (totalSamples - samplePos) * 2);
- return samplePos;
- }
- }
- while ((_fading < 0) && (samplePos < totalSamples)) { // fade up
- bufStart[samplePos] = -(bufStart[samplePos] * --_fading) / _fadeSamples;
- if (_fading <= -_fadeSamples)
- _fading = 0;
- }
- return totalSamples;
-}
-
-void MusicHandle::stop() {
- delete _audioSource;
- _audioSource = NULL;
- _file.close();
- _fading = 0;
-}
-
-Music::Music(Audio::Mixer *pMixer) {
- _mixer = pMixer;
- _sampleRate = pMixer->getOutputRate();
- _converter[0] = NULL;
- _converter[1] = NULL;
- _volumeL = _volumeR = 192;
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-Music::~Music() {
- _mixer->stopHandle(_soundHandle);
- delete _converter[0];
- delete _converter[1];
-}
-
-void Music::mixer(int16 *buf, uint32 len) {
- Common::StackLock lock(_mutex);
- memset(buf, 0, 2 * len * sizeof(int16));
- for (int i = 0; i < ARRAYSIZE(_handles); i++)
- if (_handles[i].streaming() && _converter[i])
- _converter[i]->convert(_handles[i], buf, len, _volumeL, _volumeR);
-}
-
-void Music::setVolume(uint8 volL, uint8 volR) {
- _volumeL = (Audio::st_volume_t)volL;
- _volumeR = (Audio::st_volume_t)volR;
-}
-
-void Music::giveVolume(uint8 *volL, uint8 *volR) {
- *volL = (uint8)_volumeL;
- *volR = (uint8)_volumeR;
-}
-
-void Music::startMusic(int32 tuneId, int32 loopFlag) {
- if (strlen(_tuneList[tuneId]) > 0) {
- int newStream = 0;
- _mutex.lock();
- if (_handles[0].streaming() && _handles[1].streaming()) {
- int streamToStop;
- // Both streams playing - one must be forced to stop.
- if (!_handles[0].fading() && !_handles[1].fading()) {
- // None of them are fading. Shouldn't happen,
- // so it doesn't matter which one we pick.
- streamToStop = 0;
- } else if (_handles[0].fading() && !_handles[1].fading()) {
- // Stream 0 is fading, so pick that one.
- streamToStop = 0;
- } else if (!_handles[0].fading() && _handles[1].fading()) {
- // Stream 1 is fading, so pick that one.
- streamToStop = 1;
- } else {
- // Both streams are fading. Pick the one that
- // is closest to silent.
- if (ABS(_handles[0].fading()) < ABS(_handles[1].fading()))
- streamToStop = 0;
- else
- streamToStop = 1;
- }
- _handles[streamToStop].stop();
- }
- if (_handles[0].streaming()) {
- _handles[0].fadeDown();
- newStream = 1;
- } else if (_handles[1].streaming()) {
- _handles[1].fadeDown();
- newStream = 0;
- }
- delete _converter[newStream];
- _converter[newStream] = NULL;
- _mutex.unlock();
-
- /* The handle will load the music file now. It can take a while, so unlock
- the mutex before, to have the soundthread playing normally.
- As the corresponding _converter is NULL, the handle will be ignored by the playing thread */
- if (SwordEngine::isPsx()) {
- if (_handles[newStream].playPSX(tuneId, loopFlag != 0)) {
- _mutex.lock();
- // TODO: Avoid unnecessary channel conversion
- _converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), true, false);
- _mutex.unlock();
- }
- } else if (_handles[newStream].play(_tuneList[tuneId], loopFlag != 0)) {
- _mutex.lock();
- // TODO: Avoid unnecessary channel conversion
- _converter[newStream] = Audio::makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), true, false);
- _mutex.unlock();
- } else {
- if (tuneId != 81) // file 81 was apparently removed from BS.
- warning("Can't find music file %s", _tuneList[tuneId]);
- }
- } else {
- _mutex.lock();
- if (_handles[0].streaming())
- _handles[0].fadeDown();
- if (_handles[1].streaming())
- _handles[1].fadeDown();
- _mutex.unlock();
- }
-}
-
-void Music::fadeDown() {
- Common::StackLock lock(_mutex);
- for (int i = 0; i < ARRAYSIZE(_handles); i++)
- if (_handles[i].streaming())
- _handles[i].fadeDown();
-}
-
-} // End of namespace Sword1
diff --git a/engines/sword1/music.h b/engines/sword1/music.h
deleted file mode 100644
index a8e86e20be2..00000000000
--- a/engines/sword1/music.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef SWORD1_MUSIC_H
-#define SWORD1_MUSIC_H
-
-#include "common/scummsys.h"
-#include "common/mutex.h"
-#include "common/file.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "audio/rate.h"
-
-namespace Sword1 {
-
-#define TOTAL_TUNES 270
-
-class MusicHandle : public Audio::AudioStream {
-private:
- Common::File _file;
- int32 _fading;
- int32 _fadeSamples;
- Audio::AudioStream *_audioSource;
-public:
- MusicHandle() : _fading(0), _audioSource(NULL) {}
- int readBuffer(int16 *buffer, const int numSamples) override;
- bool play(const Common::String &filename, bool loop);
- bool playPSX(uint16 id, bool loop);
- void stop();
- void fadeUp();
- void fadeDown();
- bool streaming() const;
- int32 fading() { return _fading; }
- bool endOfData() const override;
- bool endOfStream() const override { return false; }
- bool isStereo() const override;
- int getRate() const override;
-};
-
-class Music : public Audio::AudioStream {
-public:
- Music(Audio::Mixer *pMixer);
- ~Music() override;
- void startMusic(int32 tuneId, int32 loopFlag);
- void fadeDown();
- void setVolume(uint8 volL, uint8 volR);
- void giveVolume(uint8 *volL, uint8 *volR);
-
- // AudioStream API
- int readBuffer(int16 *buffer, const int numSamples) override {
- mixer(buffer, numSamples / 2);
- return numSamples;
- }
- bool isStereo() const override { return true; }
- bool endOfData() const override { return false; }
- int getRate() const override { return _sampleRate; }
-
-private:
- Audio::st_volume_t _volumeL, _volumeR;
- MusicHandle _handles[2];
- Audio::RateConverter *_converter[2];
- Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
- uint32 _sampleRate;
- Common::Mutex _mutex;
-
- static void passMixerFunc(void *param, int16 *buf, uint len);
- void mixer(int16 *buf, uint32 len);
-
- char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
-};
-
-} // End of namespace Sword1
-
-#endif // BSMUSIC_H
diff --git a/engines/sword1/staticres.cpp b/engines/sword1/staticres.cpp
index 9476ffcbced..27181ab1eef 100644
--- a/engines/sword1/staticres.cpp
+++ b/engines/sword1/staticres.cpp
@@ -26,7 +26,6 @@
#include "sword1/resman.h"
#include "sword1/objectman.h"
#include "sword1/menu.h"
-#include "sword1/music.h"
#include "sword1/sound.h"
#include "sword1/sword1.h"
#include "sword1/logic.h"
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 2a3eecdf7a6..02e89fbb31a 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -29,7 +29,6 @@
#include "sword1/screen.h"
#include "sword1/swordres.h"
#include "sword1/menu.h"
-#include "sword1/music.h"
#include "sword1/control.h"
#include "common/config-manager.h"
@@ -73,7 +72,6 @@ SwordEngine::SwordEngine(OSystem *syst, const ADGameDescription *gameDesc)
_logic = 0;
_sound = 0;
_menu = 0;
- _music = 0;
_control = 0;
}
@@ -82,7 +80,6 @@ SwordEngine::~SwordEngine() {
delete _logic;
delete _menu;
delete _sound;
- delete _music;
delete _screen;
delete _mouse;
delete _objectMan;
@@ -101,10 +98,9 @@ Common::Error SwordEngine::init() {
_objectMan = new ObjectMan(_resMan);
_mouse = new Mouse(_system, _resMan, _objectMan);
_screen = new Screen(_system, this, _resMan, _objectMan);
- _music = new Music(_mixer);
_sound = new Sound(_mixer, this, _resMan);
_menu = new Menu(_screen, _mouse);
- _logic = new Logic(this, _objectMan, _resMan, _screen, _mouse, _sound, _music, _menu, _system, _mixer);
+ _logic = new Logic(this, _objectMan, _resMan, _screen, _mouse, _sound, _menu, _system, _mixer);
_mouse->useLogicAndMenu(_logic, _menu);
_mouse->useScreenMutex(&_screen->_screenAccessMutex);
@@ -175,7 +171,7 @@ Common::Error SwordEngine::init() {
_logic->initialize();
_objectMan->initialize();
_mouse->initialize();
- _control = new Control(this, _saveFileMan, _resMan, _objectMan, _system, _mouse, _sound, _music, _screen, _logic);
+ _control = new Control(this, _saveFileMan, _resMan, _objectMan, _system, _mouse, _sound, _screen, _logic);
return Common::kNoError;
}
@@ -874,7 +870,6 @@ void SwordEngine::checkCd() {
askForCd();
} // else: there is already a cd inserted and we don't care if it's cd1 or cd2.
} else if (needCd != _systemVars.currentCD) { // we need a different CD than the one in drive.
- _music->startMusic(0, 0); //
_sound->closeCowSystem(); // close music and sound files before changing CDs
_systemVars.currentCD = needCd; // askForCd will ask the player to insert _systemVars.currentCd,
askForCd(); // so it has to be updated before calling it.
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index 4db2df23579..105b9b46e32 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -57,7 +57,6 @@ class Mouse;
class ResMan;
class ObjectMan;
class Menu;
-class Music;
class Control;
struct SystemVars {
@@ -182,7 +181,6 @@ private:
Logic *_logic;
Sound *_sound;
Menu *_menu;
- Music *_music;
Control *_control;
static const uint8 _cdList[TOTAL_SECTIONS];
static const CdFile _pcCdFileList[];
Commit: 096da97262edbc88168df1898408e356041674ee
https://github.com/scummvm/scummvm/commit/096da97262edbc88168df1898408e356041674ee
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Fix warnings
Changed paths:
engines/sword1/sound.cpp
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 5b70c415367..6b7e5f8a98e 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -137,7 +137,7 @@ void Sound::checkSpeechFileEndianness() {
_cowFile.seek(index + _cowHeaderSize, SEEK_SET);
_cowFile.read(compSample, sampleSize);
byte *data = (byte *)malloc(getSpeechSize(compSample, sampleSize));
- bool success = expandSpeech(compSample, data, sampleSize, &leOk, &size);
+ expandSpeech(compSample, data, sampleSize, &leOk, &size);
uint32 maxSamples = size > 2000 ? 2000 : size;
double le_diff = endiannessHeuristicValue((int16 *)data, size, maxSamples);
free(data);
@@ -147,7 +147,7 @@ void Sound::checkSpeechFileEndianness() {
_cowFile.seek(index + _cowHeaderSize, SEEK_SET);
_cowFile.read(compSample, sampleSize);
data = (byte *)malloc(getSpeechSize(compSample, sampleSize));
- success = expandSpeech(compSample, data, sampleSize, &beOk, &size);
+ expandSpeech(compSample, data, sampleSize, &beOk, &size);
double be_diff = endiannessHeuristicValue((int16 *)data, size, maxSamples);
free(data);
@@ -306,7 +306,7 @@ bool Sound::amISpeaking() {
readPos = _speechLipsyncCounter * 919 * 2;
// Ensure that we don't read beyond the buffer...
- if (readPos + 150 * sizeof(int16) > _speechSize)
+ if (readPos + (int32)(150 * sizeof(int16)) > _speechSize)
return false;
offset = (int16 *)&_speechSample[readPos];
Commit: acba0e6a0bb7f6342a23a55ffa3f866fb88725a7
https://github.com/scummvm/scummvm/commit/acba0e6a0bb7f6342a23a55ffa3f866fb88725a7
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Fix typo which broke GMM interoperability
Changed paths:
engines/sword1/sword1.cpp
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 02e89fbb31a..53ecbb75524 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -190,7 +190,7 @@ void SwordEngine::reinitialize() {
void SwordEngine::syncSoundSettings() {
Engine::syncSoundSettings();
- _sound->setVolumes();
+ _sound->getVolumes();
}
void SwordEngine::flagsToBool(bool *dest, uint8 flags) {
Commit: d7dda29c5caa30963ae15b8af6125b811c9b5e50
https://github.com/scummvm/scummvm/commit/d7dda29c5caa30963ae15b8af6125b811c9b5e50
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Revert resource id hack (3451d1c)
The commit I'm reverting is a very old one and forces
stereo inversion in a couple of sound effects in Rue Jerry.
The wrong stereo direction is in the original as well;
this surely is fixable, but we shouldn't do things like
editing the resource identifiers anymore, instead we
should put up an enhancement system like the one in
the SCUMM engine, and force the samples swap at
runtime only during that particular screen.
Changed paths:
engines/sword1/swordres.h
diff --git a/engines/sword1/swordres.h b/engines/sword1/swordres.h
index eb2b4ab929c..038feddda57 100644
--- a/engines/sword1/swordres.h
+++ b/engines/sword1/swordres.h
@@ -1775,10 +1775,10 @@ namespace Sword1 {
#define FX_DOORTRY {0x07,0x04,0x04}
#define FX_FIESTA {0x07,0x05,0x05}
#define FX_FLATDOOR {0x07,0x06,0x06}
-#define FX_HVYVEHR {0x07,0x07,0xFF}
-#define FX_HVYVEHL {0x07,0x08,0xFF}
-#define FX_LITEVEHR {0x07,0x09,0xFF}
-#define FX_LITEVEHL {0x07,0x0A,0xFF}
+#define FX_HVYVEHL {0x07,0x07,0xFF}
+#define FX_HVYVEHR {0x07,0x08,0xFF}
+#define FX_LITEVEHL {0x07,0x09,0xFF}
+#define FX_LITEVEHR {0x07,0x0A,0xFF}
#define FX_FONEUP {0x07,0x0B,0x07}
#define FX_FONEDN {0x07,0x0C,0x08}
#define FX_GEOCCH {0x07,0x0D,0x09}
Commit: 598145cde02f62d9b9b65b8e80ed06f2f33c3443
https://github.com/scummvm/scummvm/commit/598145cde02f62d9b9b65b8e80ed06f2f33c3443
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Remove hack in fnPlayMusic()
We now handle missing files correctly.
Changed paths:
engines/sword1/logic.cpp
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 1419f52910f..1d2257f900c 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -1654,8 +1654,6 @@ int Logic::fnStopFx(Object *cpt, int32 id, int32 fxNo, int32 b, int32 c, int32 d
}
int Logic::fnPlayMusic(Object *cpt, int32 id, int32 tuneId, int32 loopFlag, int32 c, int32 d, int32 z, int32 x) {
- if (tuneId == 153)
- return SCRIPT_CONT;
if (loopFlag == LOOPED)
_scriptVars[CURRENT_MUSIC] = tuneId; // so it gets restarted when saving & reloading
else
Commit: 0d153d6e6229104e2042e098b7cff4613e8ae1e9
https://github.com/scummvm/scummvm/commit/0d153d6e6229104e2042e098b7cff4613e8ae1e9
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Zero out speech sample buffer before filling it
Changed paths:
engines/sword1/sound.cpp
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 6b7e5f8a98e..778d55e04f6 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -427,6 +427,12 @@ void Sound::startSpeech(uint16 roomNo, uint16 localNo) {
_cowFile.read(compSample, sampleFileSize);
_speechSize = getSpeechSize(compSample, sampleFileSize);
_speechSample = (byte *)malloc(_speechSize);
+
+ // Sometimes, the decompressed speech size is slightly longer than the actual
+ // decompressed sample data we are about to receive; this is normal, but to
+ // fully emulate what the original does, let's zero out the sample buffer.
+ memset(_speechSample, 0, _speechSize);
+
if (_speechSample) {
SwordEngine::_systemVars.speechRunning = expandSpeech(compSample, _speechSample, sampleFileSize);
free(compSample);
Commit: a68051b2f0092e1674d8096f0086fc541ece18c7
https://github.com/scummvm/scummvm/commit/a68051b2f0092e1674d8096f0086fc541ece18c7
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Move memset to after checking buffer availability
Changed paths:
engines/sword1/sound.cpp
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 778d55e04f6..1d46510066c 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -428,12 +428,12 @@ void Sound::startSpeech(uint16 roomNo, uint16 localNo) {
_speechSize = getSpeechSize(compSample, sampleFileSize);
_speechSample = (byte *)malloc(_speechSize);
- // Sometimes, the decompressed speech size is slightly longer than the actual
- // decompressed sample data we are about to receive; this is normal, but to
- // fully emulate what the original does, let's zero out the sample buffer.
- memset(_speechSample, 0, _speechSize);
-
if (_speechSample) {
+ // Sometimes, the decompressed speech size is slightly longer than the actual
+ // decompressed sample data we are about to receive; this is normal, but to
+ // fully emulate what the original does, let's zero out the sample buffer.
+ memset(_speechSample, 0, _speechSize);
+
SwordEngine::_systemVars.speechRunning = expandSpeech(compSample, _speechSample, sampleFileSize);
free(compSample);
}
Commit: dea30b96735e9745dc7d681423d2bfd343c734f0
https://github.com/scummvm/scummvm/commit/dea30b96735e9745dc7d681423d2bfd343c734f0
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Stop music handle at the end of fade-out
This emulates the AIL driver more closely, as the sample should
immediately stop. This also fixes Lady Piermont piano not fading out
properly whenever a conversation is started with her.
Changed paths:
engines/sword1/sound.cpp
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 1d46510066c..32f2cf79088 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -1011,11 +1011,14 @@ void Sound::updateMusicStreaming() {
_musicStreamFading[i] += 1;
if (_musicStreamFading[i] == 0) {
+ _mixer->setChannelVolume(_hSampleMusic[i], 0);
+ _musicOutputStream[i]->finish();
+ _musicOutputStream[i] = nullptr;
+
+ _mixer->stopHandle(_hSampleMusic[i]);
_musicFile[i].close();
_musicStreamPlaying[i] = false;
- _musicOutputStream[i]->finish();
- _musicOutputStream[i] = nullptr;
}
} else {
debug("Sound::updateMusicStreaming(): Fading %s to %d", _musicFile[i].getName(),
@@ -1037,9 +1040,14 @@ void Sound::updateMusicStreaming() {
if (!_mixer->isSoundHandleActive(_hSampleMusic[i]) ||
(_musicOutputStream[i] && _musicOutputStream[i]->endOfData())) {
_musicStreamPlaying[i] = false;
- _musicFile[i].close();
- _musicOutputStream[i]->finish();
- _musicOutputStream[i] = nullptr;
+
+ if (_musicFile[i].isOpen())
+ _musicFile[i].close();
+
+ if (_musicOutputStream[i]) {
+ _musicOutputStream[i]->finish();
+ _musicOutputStream[i] = nullptr;
+ }
}
}
}
Commit: 24828afcc4b7de0f24e1e091c1930d33402b4ee7
https://github.com/scummvm/scummvm/commit/24828afcc4b7de0f24e1e091c1930d33402b4ee7
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-12T23:54:24+02:00
Commit Message:
SWORD1: SOUND: Remove unnecessary debug print
Changed paths:
engines/sword1/sound.cpp
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 32f2cf79088..69748dd890f 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -1074,10 +1074,6 @@ void Sound::serveSample(Common::File *file, int32 i) {
file->read(buf + len, nominalSize - len);
len = nominalSize;
debug(5, "Sound::serveSample(): Looping music file %s", file->getName());
- } else {
- Common::String fname(file->getName());
- if (!fname.empty())
- debug(5, "Sound::serveSample(): Finished feeding music file %s", file->getName());
}
}
} else {
More information about the Scummvm-git-logs
mailing list