SCI: Removed the FreeSCI music code

svn-id: r50532
This commit is contained in:
Filippos Karapetis 2010-06-30 13:49:05 +00:00
parent a14c6d7815
commit bff3e89e48
21 changed files with 4 additions and 4966 deletions

View file

@ -36,13 +36,8 @@
#include "sci/engine/savegame.h" #include "sci/engine/savegame.h"
#include "sci/engine/gc.h" #include "sci/engine/gc.h"
#include "sci/engine/features.h" #include "sci/engine/features.h"
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/songlib.h" // for SongLibrary
#include "sci/sound/iterator/iterator.h" // for SCI_SONG_ITERATOR_TYPE_SCI0
#else
#include "sci/sound/midiparser_sci.h" #include "sci/sound/midiparser_sci.h"
#include "sci/sound/music.h" #include "sci/sound/music.h"
#endif
#include "sci/sound/drivers/mididriver.h" #include "sci/sound/drivers/mididriver.h"
#include "sci/graphics/cursor.h" #include "sci/graphics/cursor.h"
#include "sci/graphics/screen.h" #include "sci/graphics/screen.h"
@ -215,19 +210,11 @@ Console::~Console() {
} }
void Console::preEnter() { void Console::preEnter() {
#ifdef USE_OLD_MUSIC_FUNCTIONS
if (_engine->_gamestate)
_engine->_gamestate->_sound.sfx_suspend(true);
#endif
if (g_sci && g_sci->_soundCmd) if (g_sci && g_sci->_soundCmd)
g_sci->_soundCmd->pauseAll(true); g_sci->_soundCmd->pauseAll(true);
} }
void Console::postEnter() { void Console::postEnter() {
#ifdef USE_OLD_MUSIC_FUNCTIONS
if (_engine->_gamestate)
_engine->_gamestate->_sound.sfx_suspend(false);
#endif
if (g_sci && g_sci->_soundCmd) if (g_sci && g_sci->_soundCmd)
g_sci->_soundCmd->pauseAll(false); g_sci->_soundCmd->pauseAll(false);
@ -846,7 +833,6 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
} }
bool Console::cmdShowInstruments(int argc, const char **argv) { bool Console::cmdShowInstruments(int argc, const char **argv) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
int songNumber = -1; int songNumber = -1;
if (argc == 2) if (argc == 2)
@ -1004,7 +990,6 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
DebugPrintf("\n\n"); DebugPrintf("\n\n");
} }
#endif
return true; return true;
} }
@ -1647,23 +1632,7 @@ bool Console::cmdShowMap(int argc, const char **argv) {
bool Console::cmdSongLib(int argc, const char **argv) { bool Console::cmdSongLib(int argc, const char **argv) {
DebugPrintf("Song library:\n"); DebugPrintf("Song library:\n");
#ifdef USE_OLD_MUSIC_FUNCTIONS
Song *seeker = _engine->_gamestate->_sound._songlib._lib;
do {
DebugPrintf(" %p", (void *)seeker);
if (seeker) {
DebugPrintf("[%04lx,p=%d,s=%d]->", seeker->_handle, seeker->_priority, seeker->_status);
seeker = seeker->_next;
}
DebugPrintf("\n");
} while (seeker);
DebugPrintf("\n");
#else
g_sci->_soundCmd->printPlayList(this); g_sci->_soundCmd->printPlayList(this);
#endif
return true; return true;
} }
@ -1726,19 +1695,6 @@ bool Console::cmdToggleSound(int argc, const char **argv) {
return true; return true;
} }
#ifdef USE_OLD_MUSIC_FUNCTIONS
int handle = id.segment << 16 | id.offset; // frobnicate handle
if (id.segment) {
SegManager *segMan = _engine->_gamestate->_segMan; // for writeSelectorValue
_engine->_gamestate->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
_engine->_gamestate->_sound.sfx_remove_song(handle);
writeSelectorValue(segMan, id, SELECTOR(signal), SIGNAL_OFFSET);
writeSelectorValue(segMan, id, SELECTOR(nodePtr), 0);
writeSelectorValue(segMan, id, SELECTOR(handle), 0);
}
#else
Common::String newState = argv[2]; Common::String newState = argv[2];
newState.toLowercase(); newState.toLowercase();
@ -1748,15 +1704,12 @@ bool Console::cmdToggleSound(int argc, const char **argv) {
g_sci->_soundCmd->stopSound(id); g_sci->_soundCmd->stopSound(id);
else else
DebugPrintf("New state can either be 'play' or 'stop'"); DebugPrintf("New state can either be 'play' or 'stop'");
#endif
return true; return true;
} }
bool Console::cmdStopAllSounds(int argc, const char **argv) { bool Console::cmdStopAllSounds(int argc, const char **argv) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
g_sci->_soundCmd->stopAllSounds(); g_sci->_soundCmd->stopAllSounds();
#endif
DebugPrintf("All sounds have been stopped\n"); DebugPrintf("All sounds have been stopped\n");
return true; return true;
@ -1770,36 +1723,6 @@ bool Console::cmdIsSample(int argc, const char **argv) {
return true; return true;
} }
#ifdef USE_OLD_MUSIC_FUNCTIONS
Resource *song = _engine->getResMan()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0);
SongIterator *songit;
Audio::AudioStream *data;
if (!song) {
DebugPrintf("Not a sound resource!\n");
return true;
}
songit = songit_new(song->data, song->size, SCI_SONG_ITERATOR_TYPE_SCI0, 0xcaffe /* What do I care about the ID? */);
if (!songit) {
DebugPrintf("Could not convert to song iterator!\n");
return true;
}
data = songit->getAudioStream();
if (data) {
// TODO
/*
DebugPrintf("\nIs sample (encoding %dHz/%s/%04x)", data->conf.rate, (data->conf.stereo) ?
((data->conf.stereo == SFX_PCM_STEREO_LR) ? "stereo-LR" : "stereo-RL") : "mono", data->conf.format);
*/
delete data;
} else
DebugPrintf("Valid song, but not a sample.\n");
delete songit;
#else
int16 number = atoi(argv[1]); int16 number = atoi(argv[1]);
if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) { if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) {
@ -1823,7 +1746,6 @@ bool Console::cmdIsSample(int argc, const char **argv) {
DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n",
track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr); track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr);
#endif
return true; return true;
} }

View file

@ -32,7 +32,6 @@
#include "common/str-array.h" #include "common/str-array.h"
#include "sci/engine/selector.h" #include "sci/engine/selector.h"
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#include "sci/engine/vm_types.h" // for reg_t #include "sci/engine/vm_types.h" // for reg_t
#include "sci/engine/vm.h" #include "sci/engine/vm.h"
@ -268,17 +267,6 @@ private:
const Common::String _invalid; const Common::String _invalid;
}; };
#ifdef USE_OLD_MUSIC_FUNCTIONS
/******************** Misc functions ********************/
/**
* Get all sound events, apply their changes to the heap.
*/
void process_sound_events(EngineState *s);
/******************** Constants ********************/
#endif
/* Maximum length of a savegame name (including terminator character). */ /* Maximum length of a savegame name (including terminator character). */
#define SCI_MAX_SAVENAME_LENGTH 0x24 #define SCI_MAX_SAVENAME_LENGTH 0x24

View file

@ -149,7 +149,6 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
con->onFrame(); con->onFrame();
} }
#ifndef USE_OLD_MUSIC_FUNCTIONS
if (g_sci->_features->detectDoSoundType() <= SCI_VERSION_0_LATE) { if (g_sci->_features->detectDoSoundType() <= SCI_VERSION_0_LATE) {
// If we're running a SCI0 game, update the sound cues, to compensate // If we're running a SCI0 game, update the sound cues, to compensate
// for the fact that SCI0 does not poll to update the sound cues itself, // for the fact that SCI0 does not poll to update the sound cues itself,
@ -158,7 +157,6 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// this call // this call
g_sci->_soundCmd->updateSci0Cues(); g_sci->_soundCmd->updateSci0Cues();
} }
#endif
return s->r_acc; return s->r_acc;
} }

View file

@ -1080,10 +1080,6 @@ reg_t kAnimate(EngineState *s, int argc, reg_t *argv) {
reg_t castListReference = (argc > 0) ? argv[0] : NULL_REG; reg_t castListReference = (argc > 0) ? argv[0] : NULL_REG;
bool cycle = (argc > 1) ? ((argv[1].toUint16()) ? true : false) : false; bool cycle = (argc > 1) ? ((argv[1].toUint16()) ? true : false) : false;
#ifdef USE_OLD_MUSIC_FUNCTIONS
// Take care of incoming events (kAnimate is called semi-regularly)
process_sound_events(s);
#endif
g_sci->_gfxAnimate->kernelAnimate(castListReference, cycle, argc, argv); g_sci->_gfxAnimate->kernelAnimate(castListReference, cycle, argc, argv);
return s->r_acc; return s->r_acc;

View file

@ -42,12 +42,7 @@
#include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS #include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS
#include "sci/graphics/ports.h" #include "sci/graphics/ports.h"
#include "sci/sound/audio.h" #include "sci/sound/audio.h"
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/core.h"
#include "sci/sound/iterator/iterator.h"
#else
#include "sci/sound/music.h" #include "sci/sound/music.h"
#endif
#include "gui/message.h" #include "gui/message.h"
@ -61,40 +56,11 @@ namespace Sci {
const uint32 INTMAPPER_MAGIC_KEY = 0xDEADBEEF; const uint32 INTMAPPER_MAGIC_KEY = 0xDEADBEEF;
#ifdef USE_OLD_MUSIC_FUNCTIONS
// from ksound.cpp:
SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorType type, songit_id_t id);
#endif
#pragma mark - #pragma mark -
// TODO: Many of the following sync_*() methods should be turned into member funcs // TODO: Many of the following sync_*() methods should be turned into member funcs
// of the classes they are syncing. // of the classes they are syncing.
#ifdef USE_OLD_MUSIC_FUNCTIONS
static void sync_songlib(Common::Serializer &s, SongLibrary &obj);
static void syncSong(Common::Serializer &s, Song &obj) {
s.syncAsSint32LE(obj._handle);
s.syncAsSint32LE(obj._resourceNum);
s.syncAsSint32LE(obj._priority);
s.syncAsSint32LE(obj._status);
s.syncAsSint32LE(obj._restoreBehavior);
s.syncAsSint32LE(obj._restoreTime);
s.syncAsSint32LE(obj._loops);
s.syncAsSint32LE(obj._hold);
if (s.isLoading()) {
obj._it = 0;
obj._delay = 0;
obj._next = 0;
obj._nextPlaying = 0;
obj._nextStopping = 0;
}
}
#else
#define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff)) #define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff))
void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) {
@ -148,7 +114,6 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) {
pStreamAud = 0; pStreamAud = 0;
} }
} }
#endif
// Experimental hack: Use syncWithSerializer to sync. By default, this assume // Experimental hack: Use syncWithSerializer to sync. By default, this assume
// the object to be synced is a subclass of Serializable and thus tries to invoke // the object to be synced is a subclass of Serializable and thus tries to invoke
@ -380,11 +345,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
syncArray<Class>(s, _segMan->_classTable); syncArray<Class>(s, _segMan->_classTable);
#ifdef USE_OLD_MUSIC_FUNCTIONS
sync_songlib(s, _sound._songlib);
#else
g_sci->_soundCmd->syncPlayList(s); g_sci->_soundCmd->syncPlayList(s);
#endif
} }
void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) { void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) {
@ -620,30 +581,6 @@ void DataStack::saveLoadWithSerializer(Common::Serializer &s) {
#pragma mark - #pragma mark -
#ifdef USE_OLD_MUSIC_FUNCTIONS
static void sync_songlib(Common::Serializer &s, SongLibrary &obj) {
int songcount = 0;
if (s.isSaving())
songcount = obj.countSongs();
s.syncAsUint32LE(songcount);
if (s.isLoading()) {
obj._lib = 0;
while (songcount--) {
Song *newsong = new Song;
syncSong(s, *newsong);
obj.addSong(newsong);
}
} else {
Song *seeker = obj._lib;
while (seeker) {
seeker->_restoreTime = seeker->_it->getTimepos();
syncSong(s, *seeker);
seeker = seeker->_next;
}
}
}
#else
void SciMusic::saveLoadWithSerializer(Common::Serializer &s) { void SciMusic::saveLoadWithSerializer(Common::Serializer &s) {
// Sync song lib data. When loading, the actual song lib will be initialized // Sync song lib data. When loading, the actual song lib will be initialized
// afterwards in gamestate_restore() // afterwards in gamestate_restore()
@ -692,16 +629,12 @@ void SciMusic::saveLoadWithSerializer(Common::Serializer &s) {
} }
} }
} }
#endif
void SoundCommandParser::syncPlayList(Common::Serializer &s) { void SoundCommandParser::syncPlayList(Common::Serializer &s) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->saveLoadWithSerializer(s); _music->saveLoadWithSerializer(s);
#endif
} }
void SoundCommandParser::reconstructPlayList(int savegame_version) { void SoundCommandParser::reconstructPlayList(int savegame_version) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
Common::StackLock lock(_music->_mutex); Common::StackLock lock(_music->_mutex);
const MusicList::iterator end = _music->getPlayListEnd(); const MusicList::iterator end = _music->getPlayListEnd();
@ -724,8 +657,6 @@ void SoundCommandParser::reconstructPlayList(int savegame_version) {
cmdPlaySound((*i)->soundObj, 0); cmdPlaySound((*i)->soundObj, 0);
} }
} }
#endif
} }
#ifdef ENABLE_SCI32 #ifdef ENABLE_SCI32
@ -819,42 +750,6 @@ void SegManager::reconstructClones() {
} // end for } // end for
} }
#ifdef USE_OLD_MUSIC_FUNCTIONS
static void reconstruct_sounds(EngineState *s) {
Song *seeker;
SongIteratorType it_type;
if (getSciVersion() > SCI_VERSION_01)
it_type = SCI_SONG_ITERATOR_TYPE_SCI1;
else
it_type = SCI_SONG_ITERATOR_TYPE_SCI0;
seeker = s->_sound._songlib._lib;
while (seeker) {
SongIterator *base, *ff = 0;
int oldstatus;
SongIterator::Message msg;
base = ff = build_iterator(g_sci->getResMan(), seeker->_resourceNum, it_type, seeker->_handle);
if (seeker->_restoreBehavior == RESTORE_BEHAVIOR_CONTINUE)
ff = new_fast_forward_iterator(base, seeker->_restoreTime);
ff->init();
msg = SongIterator::Message(seeker->_handle, SIMSG_SET_LOOPS(seeker->_loops));
songit_handle_message(&ff, msg);
msg = SongIterator::Message(seeker->_handle, SIMSG_SET_HOLD(seeker->_hold));
songit_handle_message(&ff, msg);
oldstatus = seeker->_status;
seeker->_status = SOUND_STATUS_STOPPED;
seeker->_it = ff;
s->_sound.sfx_song_set_status(seeker->_handle, oldstatus);
seeker = seeker->_next;
}
}
#endif
#pragma mark - #pragma mark -
@ -888,10 +783,6 @@ bool gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savenam
} }
void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
#ifdef USE_OLD_MUSIC_FUNCTIONS
SongLibrary temp;
#endif
SavegameMetadata meta; SavegameMetadata meta;
Common::Serializer ser(fh, 0); Common::Serializer ser(fh, 0);
@ -943,21 +834,8 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
s->reset(true); s->reset(true);
s->saveLoadWithSerializer(ser); // FIXME: Error handling? s->saveLoadWithSerializer(ser); // FIXME: Error handling?
#ifdef USE_OLD_MUSIC_FUNCTIONS
s->_sound.sfx_exit();
#endif
// Now copy all current state information // Now copy all current state information
#ifdef USE_OLD_MUSIC_FUNCTIONS
temp = s->_sound._songlib;
s->_sound.sfx_init(g_sci->getResMan(), s->sfx_init_flags, g_sci->_features->detectDoSoundType());
s->sfx_init_flags = s->sfx_init_flags;
s->_sound._songlib.freeSounds();
s->_sound._songlib = temp;
s->_soundCmd->updateSfxState(&s->_sound);
#endif
s->_segMan->reconstructStack(s); s->_segMan->reconstructStack(s);
s->_segMan->reconstructScripts(s); s->_segMan->reconstructScripts(s);
s->_segMan->reconstructClones(); s->_segMan->reconstructClones();
@ -969,15 +847,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
s->gameStartTime = g_system->getMillis(); s->gameStartTime = g_system->getMillis();
s->_screenUpdateTime = g_system->getMillis(); s->_screenUpdateTime = g_system->getMillis();
#ifdef USE_OLD_MUSIC_FUNCTIONS
s->_sound._it = NULL;
s->_sound._flags = s->_sound._flags;
s->_sound._song = NULL;
s->_sound._suspended = s->_sound._suspended;
reconstruct_sounds(s);
#else
g_sci->_soundCmd->reconstructPlayList(meta.savegame_version); g_sci->_soundCmd->reconstructPlayList(meta.savegame_version);
#endif
// Message state: // Message state:
s->_msgState = new MessageState(s->_segMan); s->_msgState = new MessageState(s->_segMan);

View file

@ -81,10 +81,6 @@ EngineState::~EngineState() {
} }
void EngineState::reset(bool isRestoring) { void EngineState::reset(bool isRestoring) {
#ifdef USE_OLD_MUSIC_FUNCTIONS
sfx_init_flags = 0;
#endif
if (!isRestoring) { if (!isRestoring) {
_memorySegmentSize = 0; _memorySegmentSize = 0;

View file

@ -41,9 +41,6 @@ namespace Common {
#include "sci/parser/vocabulary.h" #include "sci/parser/vocabulary.h"
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/core.h"
#endif
#include "sci/sound/soundcmd.h" #include "sci/sound/soundcmd.h"
namespace Sci { namespace Sci {
@ -105,11 +102,6 @@ public:
/* Non-VM information */ /* Non-VM information */
#ifdef USE_OLD_MUSIC_FUNCTIONS
SfxState _sound; /**< sound subsystem */
int sfx_init_flags; /**< flags the sfx subsystem was initialised with */
#endif
uint32 gameStartTime; /**< The time at which the interpreter was started */ uint32 gameStartTime; /**< The time at which the interpreter was started */
uint32 lastWaitTime; /**< The last time the game invoked Wait() */ uint32 lastWaitTime; /**< The last time the game invoked Wait() */
uint32 _screenUpdateTime; /**< The last time the game updated the screen */ uint32 _screenUpdateTime; /**< The last time the game updated the screen */

View file

@ -67,9 +67,6 @@ MODULE_OBJS := \
sound/drivers/fb01.o \ sound/drivers/fb01.o \
sound/drivers/midi.o \ sound/drivers/midi.o \
sound/drivers/pcjr.o \ sound/drivers/pcjr.o \
sound/iterator/core.o \
sound/iterator/iterator.o \
sound/iterator/songlib.o \
video/seq_decoder.o video/seq_decoder.o

View file

@ -222,10 +222,6 @@ Common::Error SciEngine::run() {
_kernel->loadKernelNames(_features); _kernel->loadKernelNames(_features);
_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, _features->detectDoSoundType()); _soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, _features->detectDoSoundType());
#ifdef USE_OLD_MUSIC_FUNCTIONS
initGameSound(0, _features->detectDoSoundType());
#endif
syncSoundSettings(); syncSoundSettings();
// Initialize all graphics related subsystems // Initialize all graphics related subsystems
@ -313,11 +309,6 @@ bool SciEngine::initGame() {
srand(g_system->getMillis()); // Initialize random number generator srand(g_system->getMillis()); // Initialize random number generator
#ifdef USE_OLD_MUSIC_FUNCTIONS
if (_gamestate->sfx_init_flags & SFX_STATE_FLAG_NOSOUND)
initGameSound(0, _features->detectDoSoundType());
#endif
// Load game language into printLang property of game object // Load game language into printLang property of game object
setSciLanguage(); setSciLanguage();
@ -399,18 +390,6 @@ void SciEngine::initGraphics() {
_gfxPalette->setDefault(); _gfxPalette->setDefault();
} }
#ifdef USE_OLD_MUSIC_FUNCTIONS
void SciEngine::initGameSound(int sound_flags, SciVersion soundVersion) {
if (getSciVersion() > SCI_VERSION_0_LATE)
sound_flags |= SFX_STATE_FLAG_MULTIPLAY;
_gamestate->sfx_init_flags = sound_flags;
_gamestate->_sound.sfx_init(_resMan, sound_flags, soundVersion);
}
#endif
void SciEngine::initStackBaseWithSelector(Selector selector) { void SciEngine::initStackBaseWithSelector(Selector selector) {
_gamestate->stack_base[0] = make_reg(0, (uint16)selector); _gamestate->stack_base[0] = make_reg(0, (uint16)selector);
_gamestate->stack_base[1] = NULL_REG; _gamestate->stack_base[1] = NULL_REG;
@ -438,9 +417,6 @@ void SciEngine::runGame() {
if (_gamestate->abortScriptProcessing == kAbortRestartGame) { if (_gamestate->abortScriptProcessing == kAbortRestartGame) {
_gamestate->_segMan->resetSegMan(); _gamestate->_segMan->resetSegMan();
initGame(); initGame();
#ifdef USE_OLD_MUSIC_FUNCTIONS
_gamestate->_sound.sfx_reset_player();
#endif
initStackBaseWithSelector(SELECTOR(play)); initStackBaseWithSelector(SELECTOR(play));
_gamestate->gameWasRestarted = true; _gamestate->gameWasRestarted = true;
} else if (_gamestate->abortScriptProcessing == kAbortLoadGame) { } else if (_gamestate->abortScriptProcessing == kAbortLoadGame) {
@ -455,14 +431,8 @@ void SciEngine::runGame() {
void SciEngine::exitGame() { void SciEngine::exitGame() {
if (_gamestate->abortScriptProcessing != kAbortLoadGame) { if (_gamestate->abortScriptProcessing != kAbortLoadGame) {
_gamestate->_executionStack.clear(); _gamestate->_executionStack.clear();
#ifdef USE_OLD_MUSIC_FUNCTIONS
_gamestate->_sound.sfx_exit();
// Reinit because some other code depends on having a valid state
initGameSound(SFX_STATE_FLAG_NOSOUND, _features->detectDoSoundType());
#else
_audio->stopAllAudio(); _audio->stopAllAudio();
g_sci->_soundCmd->clearPlayList(); g_sci->_soundCmd->clearPlayList();
#endif
} }
// TODO Free parser segment here // TODO Free parser segment here
@ -544,16 +514,12 @@ Common::String SciEngine::unwrapFilename(const Common::String &name) const {
} }
void SciEngine::pauseEngineIntern(bool pause) { void SciEngine::pauseEngineIntern(bool pause) {
#ifdef USE_OLD_MUSIC_FUNCTIONS
_gamestate->_sound.sfx_suspend(pause);
#endif
_mixer->pauseAll(pause); _mixer->pauseAll(pause);
} }
void SciEngine::syncSoundSettings() { void SciEngine::syncSoundSettings() {
Engine::syncSoundSettings(); Engine::syncSoundSettings();
#ifndef USE_OLD_MUSIC_FUNCTIONS
bool mute = false; bool mute = false;
if (ConfMan.hasKey("mute")) if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute"); mute = ConfMan.getBool("mute");
@ -564,7 +530,6 @@ void SciEngine::syncSoundSettings() {
int vol = (soundVolumeMusic + 1) * SoundCommandParser::kMaxSciVolume / Audio::Mixer::kMaxMixerVolume; int vol = (soundVolumeMusic + 1) * SoundCommandParser::kMaxSciVolume / Audio::Mixer::kMaxMixerVolume;
g_sci->_soundCmd->setMasterVolume(vol); g_sci->_soundCmd->setMasterVolume(vol);
} }
#endif
} }
} // End of namespace Sci } // End of namespace Sci

View file

@ -42,9 +42,6 @@ struct ADGameDescription;
*/ */
namespace Sci { namespace Sci {
// Uncomment this to use old music functions
//#define USE_OLD_MUSIC_FUNCTIONS
struct EngineState; struct EngineState;
class Vocabulary; class Vocabulary;
class ResourceManager; class ResourceManager;
@ -321,18 +318,6 @@ private:
*/ */
void exitGame(); void exitGame();
#ifdef USE_OLD_MUSIC_FUNCTIONS
/**
* Initializes the sound part of a SCI game
* This function may only be called if game_init() did not initialize
* the sound data.
* @param[in] s The state to initialize the sound in
* @param[in] sound_flags Flags to pass to the sound subsystem
* @param[in] soundVersion sound-version that got detected during game init
*/
void initGameSound(int sound_flags, SciVersion soundVersion);
#endif
void initStackBaseWithSelector(Selector selector); void initStackBaseWithSelector(Selector selector);
const ADGameDescription *_gameDescription; const ADGameDescription *_gameDescription;

View file

@ -1,969 +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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
/* Sound subsystem core: Event handler, sound player dispatching */
#include "sci/sci.h"
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/core.h"
#include "sci/sound/iterator/iterator.h"
#include "sci/sound/drivers/mididriver.h"
#include "common/system.h"
#include "common/timer.h"
#include "sound/mixer.h"
namespace Sci {
/* Plays a song iterator that found a PCM through a PCM device, if possible
** Parameters: (SongIterator *) it: The iterator to play
** (SongHandle) handle: Debug handle
** Returns : (int) 0 if the effect will not be played, nonzero if it will
** This assumes that the last call to 'it->next()' returned SI_PCM.
*/
static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle);
#pragma mark -
class SfxPlayer {
public:
/** Number of voices that can play simultaneously */
int _polyphony;
protected:
SciVersion _soundVersion;
MidiPlayer *_mididrv;
SongIterator *_iterator;
Audio::Timestamp _wakeupTime;
Audio::Timestamp _currentTime;
uint32 _pauseTimeDiff;
bool _paused;
bool _iteratorIsDone;
uint32 _tempo;
Common::Mutex _mutex;
int _volume;
void play_song(SongIterator *it);
static void player_timer_callback(void *refCon);
public:
SfxPlayer(SciVersion soundVersion);
~SfxPlayer();
/**
* Initializes the player.
* @param resMan a resource manager for driver initialization
* @param expected_latency expected delay in between calls to 'maintenance' (in microseconds)
* @return Common::kNoError on success, Common::kUnknownError on failure
*/
Common::Error init(ResourceManager *resMan, int expected_latency);
/**
* Adds an iterator to the song player
* @param it The iterator to play
* @param start_time The time to assume as the time the first MIDI command executes at
* @return Common::kNoError on success, Common::kUnknownError on failure
*
* The iterator should not be cloned (to avoid memory leaks) and
* may be modified according to the needs of the player.
* Implementors may use the 'sfx_iterator_combine()' function
* to add iterators onto their already existing iterators.
*/
Common::Error add_iterator(SongIterator *it, uint32 start_time);
/**
* Stops the currently playing song and deletes the associated iterator.
* @return Common::kNoError on success, Common::kUnknownError on failure
*/
Common::Error stop();
/**
* Transmits a song iterator message to the active song.
* @param msg the message to transmit
* @return Common::kNoError on success, Common::kUnknownError on failure
*/
Common::Error iterator_message(const SongIterator::Message &msg);
/**
* Pauses song playing.
* @return Common::kNoError on success, Common::kUnknownError on failure
*/
Common::Error pause();
/**
* Resumes song playing after a pause.
* @return Common::kNoError on success, Common::kUnknownError on failure
*/
Common::Error resume();
/**
* Pass a raw MIDI event to the synth.
* @param argc length of buffer holding the midi event
* @param argv the buffer itself
*/
void tell_synth(int buf_nr, byte *buf);
void setVolume(int vol);
int getVolume();
};
SfxPlayer::SfxPlayer(SciVersion soundVersion)
: _soundVersion(soundVersion), _wakeupTime(0, SFX_TICKS_PER_SEC), _currentTime(0, 1) {
_polyphony = 0;
_mididrv = 0;
_iterator = NULL;
_pauseTimeDiff = 0;
_paused = false;
_iteratorIsDone = false;
_tempo = 0;
_volume = 15;
}
SfxPlayer::~SfxPlayer() {
if (_mididrv) {
_mididrv->close();
delete _mididrv;
}
delete _iterator;
_iterator = NULL;
}
void SfxPlayer::play_song(SongIterator *it) {
while (_iterator && _wakeupTime.msecsDiff(_currentTime) <= 0) {
int delay;
byte buf[8];
int result;
switch ((delay = songit_next(&(_iterator),
buf, &result,
IT_READER_MASK_ALL
| IT_READER_MAY_FREE
| IT_READER_MAY_CLEAN))) {
case SI_FINISHED:
delete _iterator;
_iterator = NULL;
_iteratorIsDone = true;
return;
case SI_IGNORE:
case SI_LOOP:
case SI_RELATIVE_CUE:
case SI_ABSOLUTE_CUE:
break;
case SI_PCM:
sfx_play_iterator_pcm(_iterator, 0);
break;
case 0:
static_cast<MidiDriver *>(_mididrv)->send(buf[0], buf[1], buf[2]);
break;
default:
_wakeupTime = _wakeupTime.addFrames(delay);
}
}
}
void SfxPlayer::tell_synth(int buf_nr, byte *buf) {
byte op1 = (buf_nr < 2 ? 0 : buf[1]);
byte op2 = (buf_nr < 3 ? 0 : buf[2]);
static_cast<MidiDriver *>(_mididrv)->send(buf[0], op1, op2);
}
void SfxPlayer::player_timer_callback(void *refCon) {
SfxPlayer *thePlayer = (SfxPlayer *)refCon;
assert(refCon);
Common::StackLock lock(thePlayer->_mutex);
if (thePlayer->_iterator && !thePlayer->_iteratorIsDone && !thePlayer->_paused) {
thePlayer->play_song(thePlayer->_iterator);
}
thePlayer->_currentTime = thePlayer->_currentTime.addFrames(1);
}
/* API implementation */
Common::Error SfxPlayer::init(ResourceManager *resMan, int expected_latency) {
MidiDriverType musicDriver = MidiDriver::detectDevice(MDT_PCSPK | MDT_ADLIB);
switch (musicDriver) {
case MD_ADLIB:
// FIXME: There's no Amiga sound option, so we hook it up to AdLib
if (g_sci->getPlatform() == Common::kPlatformAmiga)
_mididrv = MidiPlayer_Amiga_create(_soundVersion);
else
_mididrv = MidiPlayer_AdLib_create(_soundVersion);
break;
case MD_PCJR:
_mididrv = MidiPlayer_PCJr_create(_soundVersion);
break;
case MD_PCSPK:
_mididrv = MidiPlayer_PCSpeaker_create(_soundVersion);
break;
default:
break;
}
assert(_mididrv);
_polyphony = _mididrv->getPolyphony();
_tempo = _mididrv->getBaseTempo();
uint32 time = g_system->getMillis();
_currentTime = Audio::Timestamp(time, 1000000 / _tempo);
_wakeupTime = Audio::Timestamp(time, SFX_TICKS_PER_SEC);
_mididrv->setTimerCallback(this, player_timer_callback);
_mididrv->open(resMan);
_mididrv->setVolume(_volume);
return Common::kNoError;
}
Common::Error SfxPlayer::add_iterator(SongIterator *it, uint32 start_time) {
Common::StackLock lock(_mutex);
SIMSG_SEND(it, SIMSG_SET_PLAYMASK(_mididrv->getPlayId()));
SIMSG_SEND(it, SIMSG_SET_RHYTHM(_mididrv->hasRhythmChannel()));
if (_iterator == NULL) {
// Resync with clock
_currentTime = Audio::Timestamp(g_system->getMillis(), 1000000 / _tempo);
_wakeupTime = Audio::Timestamp(start_time, SFX_TICKS_PER_SEC);
}
_iterator = sfx_iterator_combine(_iterator, it);
_iteratorIsDone = false;
return Common::kNoError;
}
Common::Error SfxPlayer::stop() {
debug(3, "Player: Stopping song iterator %p", (void *)_iterator);
Common::StackLock lock(_mutex);
delete _iterator;
_iterator = NULL;
for (int i = 0; i < MIDI_CHANNELS; i++)
static_cast<MidiDriver *>(_mididrv)->send(0xb0 + i, SCI_MIDI_CHANNEL_NOTES_OFF, 0);
return Common::kNoError;
}
Common::Error SfxPlayer::iterator_message(const SongIterator::Message &msg) {
Common::StackLock lock(_mutex);
if (!_iterator) {
return Common::kUnknownError;
}
songit_handle_message(&_iterator, msg);
return Common::kNoError;
}
Common::Error SfxPlayer::pause() {
Common::StackLock lock(_mutex);
_paused = true;
_pauseTimeDiff = _wakeupTime.msecsDiff(_currentTime);
_mididrv->playSwitch(false);
return Common::kNoError;
}
Common::Error SfxPlayer::resume() {
Common::StackLock lock(_mutex);
_wakeupTime = Audio::Timestamp(_currentTime.msecs() + _pauseTimeDiff, SFX_TICKS_PER_SEC);
_mididrv->playSwitch(true);
_paused = false;
return Common::kNoError;
}
void SfxPlayer::setVolume(int vol) {
_mididrv->setVolume(vol);
}
int SfxPlayer::getVolume() {
return _mididrv->getVolume();
}
#pragma mark -
void SfxState::sfx_reset_player() {
if (_player)
_player->stop();
}
void SfxState::sfx_player_tell_synth(int buf_nr, byte *buf) {
if (_player)
_player->tell_synth(buf_nr, buf);
}
int SfxState::sfx_get_player_polyphony() {
if (_player)
return _player->_polyphony;
else
return 0;
}
SfxState::SfxState() {
_player = NULL;
_it = NULL;
_flags = 0;
_song = NULL;
_suspended = 0;
}
SfxState::~SfxState() {
}
void SfxState::freezeTime() {
/* Freezes the top song delay time */
const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
Song *song = _song;
while (song) {
song->_delay = song->_wakeupTime.frameDiff(ctime);
if (song->_delay < 0)
song->_delay = 0;
song = song->_nextPlaying;
}
}
void SfxState::thawTime() {
/* inverse of freezeTime() */
const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
Song *song = _song;
while (song) {
song->_wakeupTime = ctime.addFrames(song->_delay);
song = song->_nextPlaying;
}
}
bool SfxState::isPlaying(Song *song) {
Song *playing_song = _song;
/* _dump_playing_list(this, "is-playing");*/
while (playing_song) {
if (playing_song == song)
return true;
playing_song = playing_song->_nextPlaying;
}
return false;
}
void SfxState::setSongStatus(Song *song, int status) {
const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
switch (status) {
case SOUND_STATUS_STOPPED:
// Reset
song->_it->init();
break;
case SOUND_STATUS_SUSPENDED:
case SOUND_STATUS_WAITING:
if (song->_status == SOUND_STATUS_PLAYING) {
// Update delay, set wakeup_time
song->_delay += song->_wakeupTime.frameDiff(ctime);
song->_wakeupTime = ctime;
}
if (status == SOUND_STATUS_SUSPENDED)
break;
/* otherwise... */
case SOUND_STATUS_PLAYING:
if (song->_status == SOUND_STATUS_STOPPED) {
// Starting anew
song->_wakeupTime = ctime;
}
if (isPlaying(song))
status = SOUND_STATUS_PLAYING;
else
status = SOUND_STATUS_WAITING;
break;
default:
fprintf(stderr, "%s L%d: Attempt to set invalid song"
" state %d!\n", __FILE__, __LINE__, status);
return;
}
song->_status = status;
}
/* Update internal state iff only one song may be played */
void SfxState::updateSingleSong() {
Song *newsong = _songlib.findFirstActive();
if (newsong != _song) {
freezeTime(); /* Store song delay time */
if (_player)
_player->stop();
if (newsong) {
if (!newsong->_it)
return; /* Restore in progress and not ready for this yet */
/* Change song */
if (newsong->_status == SOUND_STATUS_WAITING)
setSongStatus(newsong, SOUND_STATUS_PLAYING);
/* Change instrument mappings */
} else {
/* Turn off sound */
}
if (_song) {
if (_song->_status == SOUND_STATUS_PLAYING)
setSongStatus(newsong, SOUND_STATUS_WAITING);
}
Common::String debugMessage = "[SFX] Changing active song:";
if (!_song) {
debugMessage += " New song:";
} else {
char tmp[50];
sprintf(tmp, " pausing %08lx, now playing ", _song->_handle);
debugMessage += tmp;
}
if (newsong) {
char tmp[20];
sprintf(tmp, "%08lx\n", newsong->_handle);
debugMessage += tmp;
} else {
debugMessage += " none\n";
}
debugC(2, kDebugLevelSound, "%s", debugMessage.c_str());
_song = newsong;
thawTime(); /* Recover song delay time */
if (newsong && _player) {
SongIterator *clonesong = newsong->_it->clone(newsong->_delay);
_player->add_iterator(clonesong, newsong->_wakeupTime.msecs());
}
}
}
void SfxState::updateMultiSong() {
Song *oldfirst = _song;
Song *oldseeker;
Song *newsong = _songlib.findFirstActive();
Song *newseeker;
Song not_playing_anymore; /* Dummy object, referenced by
** songs which are no longer
** active. */
/* _dump_playing_list(this, "before");*/
freezeTime(); /* Store song delay time */
// WORKAROUND: sometimes, newsong can be NULL (e.g. in SQ4).
// Handle this here, so that we avoid a crash
if (!newsong) {
// Iterators should get freed when there's only one song left playing
if(oldfirst && oldfirst->_status == SOUND_STATUS_STOPPED) {
debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx", oldfirst->_handle);
if (_player && oldfirst->_it)
_player->iterator_message(SongIterator::Message(oldfirst->_it->ID, SIMSG_STOP));
}
return;
}
for (newseeker = newsong; newseeker;
newseeker = newseeker->_nextPlaying) {
if (!newseeker || !newseeker->_it)
return; /* Restore in progress and not ready for this yet */
}
/* First, put all old songs into the 'stopping' list and
** mark their 'next-playing' as not_playing_anymore. */
for (oldseeker = oldfirst; oldseeker;
oldseeker = oldseeker->_nextStopping) {
oldseeker->_nextStopping = oldseeker->_nextPlaying;
oldseeker->_nextPlaying = &not_playing_anymore;
if (oldseeker == oldseeker->_nextPlaying) {
error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__);
}
}
/* Second, re-generate the new song queue. */
for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) {
newseeker->_nextPlaying = _songlib.findNextActive(newseeker);
if (newseeker == newseeker->_nextPlaying) {
error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__);
}
}
/* We now need to update the currently playing song list, because we're
** going to use some functions that require this list to be in a sane
** state (particularly isPlaying(), indirectly */
_song = newsong;
/* Third, stop all old songs */
for (oldseeker = oldfirst; oldseeker;
oldseeker = oldseeker->_nextStopping)
if (oldseeker->_nextPlaying == &not_playing_anymore) {
setSongStatus(oldseeker, SOUND_STATUS_SUSPENDED);
debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx", oldseeker->_handle);
if (_player && oldseeker->_it)
_player->iterator_message(SongIterator::Message(oldseeker->_it->ID, SIMSG_STOP));
oldseeker->_nextPlaying = NULL; /* Clear this pointer; we don't need the tag anymore */
}
for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) {
if (newseeker->_status != SOUND_STATUS_PLAYING && _player) {
debugC(2, kDebugLevelSound, "[SFX] Adding song %lx", newseeker->_it->ID);
SongIterator *clonesong = newseeker->_it->clone(newseeker->_delay);
_player->add_iterator(clonesong, g_system->getMillis());
}
setSongStatus(newseeker, SOUND_STATUS_PLAYING);
}
_song = newsong;
thawTime();
/* _dump_playing_list(this, "after");*/
}
/* Update internal state */
void SfxState::update() {
if (_flags & SFX_STATE_FLAG_MULTIPLAY)
updateMultiSong();
else
updateSingleSong();
}
static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle) {
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Playing PCM: %08lx\n", handle);
#endif
if (g_system->getMixer()->isReady()) {
Audio::AudioStream *newfeed = it->getAudioStream();
if (newfeed) {
g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, 0, newfeed);
return 1;
}
}
return 0;
}
#define DELAY (1000000 / SFX_TICKS_PER_SEC)
void SfxState::sfx_init(ResourceManager *resMan, int flags, SciVersion soundVersion) {
_songlib._lib = 0;
_song = NULL;
_flags = flags;
_player = NULL;
if (flags & SFX_STATE_FLAG_NOSOUND) {
warning("[SFX] Sound disabled");
return;
}
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Initialising: flags=%x\n", flags);
#endif
/*-------------------*/
/* Initialise player */
/*-------------------*/
if (!resMan) {
warning("[SFX] Warning: No resource manager present, cannot initialise player");
return;
}
_player = new SfxPlayer(soundVersion);
if (!_player) {
warning("[SFX] No song player found");
return;
}
if (_player->init(resMan, DELAY / 1000)) {
warning("[SFX] Song player reported error, disabled");
delete _player;
_player = NULL;
}
_resMan = resMan;
}
void SfxState::sfx_exit() {
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Uninitialising\n");
#endif
delete _player;
_player = 0;
g_system->getMixer()->stopAll();
_songlib.freeSounds();
}
void SfxState::sfx_suspend(bool suspend) {
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Suspending? = %d\n", suspend);
#endif
if (suspend && (!_suspended)) {
/* suspend */
freezeTime();
if (_player)
_player->pause();
/* Suspend song player */
} else if (!suspend && (_suspended)) {
/* unsuspend */
thawTime();
if (_player)
_player->resume();
/* Unsuspend song player */
}
_suspended = suspend;
}
int SfxState::sfx_poll(SongHandle *handle, int *cue) {
if (!_song)
return 0; /* No milk today */
*handle = _song->_handle;
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Polling any (%08lx)\n", *handle);
#endif
return sfx_poll_specific(*handle, cue);
}
int SfxState::sfx_poll_specific(SongHandle handle, int *cue) {
const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
Song *song = _song;
while (song && song->_handle != handle)
song = song->_nextPlaying;
if (!song)
return 0; /* Song not playing */
debugC(2, kDebugLevelSound, "[SFX:CUE] Polled song %08lx ", handle);
while (1) {
if (song->_wakeupTime.frameDiff(ctime) > 0)
return 0; /* Patience, young hacker! */
byte buf[8];
int result = songit_next(&(song->_it), buf, cue, IT_READER_MASK_ALL);
switch (result) {
case SI_FINISHED:
setSongStatus(song, SOUND_STATUS_STOPPED);
update();
/* ...fall through... */
case SI_LOOP:
case SI_RELATIVE_CUE:
case SI_ABSOLUTE_CUE:
if (result == SI_FINISHED)
debugC(2, kDebugLevelSound, " => finished");
else {
if (result == SI_LOOP)
debugC(2, kDebugLevelSound, " => Loop: %d (0x%x)", *cue, *cue);
else
debugC(2, kDebugLevelSound, " => Cue: %d (0x%x)", *cue, *cue);
}
return result;
default:
if (result > 0)
song->_wakeupTime = song->_wakeupTime.addFrames(result);
/* Delay */
break;
}
}
}
/*****************/
/* Song basics */
/*****************/
void SfxState::sfx_add_song(SongIterator *it, int priority, SongHandle handle, int number) {
Song *song = _songlib.findSong(handle);
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Adding song: %08lx at %d, it=%p\n", handle, priority, it);
#endif
if (!it) {
error("[SFX] Attempt to add empty song with handle %08lx", handle);
return;
}
it->init();
/* If we're already playing this, stop it */
/* Tell player to shut up */
// _dump_songs(this);
if (_player)
_player->iterator_message(SongIterator::Message(handle, SIMSG_STOP));
if (song) {
setSongStatus( song, SOUND_STATUS_STOPPED);
fprintf(stderr, "Overwriting old song (%08lx) ...\n", handle);
if (song->_status == SOUND_STATUS_PLAYING || song->_status == SOUND_STATUS_SUSPENDED) {
delete it;
error("Unexpected (error): Song %ld still playing/suspended (%d)",
handle, song->_status);
return;
} else {
_songlib.removeSong(handle); /* No duplicates */
}
}
song = new Song(handle, it, priority);
song->_resourceNum = number;
song->_hold = 0;
song->_loops = 0;
song->_wakeupTime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
_songlib.addSong(song);
_song = NULL; /* As above */
update();
return;
}
void SfxState::sfx_remove_song(SongHandle handle) {
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Removing song: %08lx\n", handle);
#endif
if (_song && _song->_handle == handle)
_song = NULL;
_songlib.removeSong(handle);
update();
}
/**********************/
/* Song modifications */
/**********************/
#define ASSERT_SONG(s) if (!(s)) { warning("Looking up song handle %08lx failed in %s, L%d", handle, __FILE__, __LINE__); return; }
void SfxState::sfx_song_set_status(SongHandle handle, int status) {
Song *song = _songlib.findSong(handle);
ASSERT_SONG(song);
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Setting song status to %d"
" (0:stop, 1:play, 2:susp, 3:wait): %08lx\n", status, handle);
#endif
setSongStatus(song, status);
update();
}
void SfxState::sfx_song_set_fade(SongHandle handle, fade_params_t *params) {
#ifdef DEBUG_SONG_API
static const char *stopmsg[] = {"??? Should not happen", "Do not stop afterwards", "Stop afterwards"};
#endif
Song *song = _songlib.findSong(handle);
ASSERT_SONG(song);
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Setting fade params of %08lx to "
"final volume %d in steps of %d per %d ticks. %s.",
handle, fade->final_volume, fade->step_size, fade->ticks_per_step,
stopmsg[fade->action]);
#endif
SIMSG_SEND_FADE(song->_it, params);
update();
}
void SfxState::sfx_song_renice(SongHandle handle, int priority) {
Song *song = _songlib.findSong(handle);
ASSERT_SONG(song);
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Renicing song %08lx to %d\n",
handle, priority);
#endif
song->_priority = priority;
update();
}
void SfxState::sfx_song_set_loops(SongHandle handle, int loops) {
Song *song = _songlib.findSong(handle);
SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_LOOPS(loops));
ASSERT_SONG(song);
song->_loops = loops;
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Setting loops on %08lx to %d\n",
handle, loops);
#endif
songit_handle_message(&(song->_it), msg);
if (_player/* && _player->send_iterator_message*/)
/* FIXME: The above should be optional! */
_player->iterator_message(msg);
}
void SfxState::sfx_song_set_hold(SongHandle handle, int hold) {
Song *song = _songlib.findSong(handle);
SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_HOLD(hold));
ASSERT_SONG(song);
song->_hold = hold;
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] Setting hold on %08lx to %d\n",
handle, hold);
#endif
songit_handle_message(&(song->_it), msg);
if (_player/* && _player->send_iterator_message*/)
/* FIXME: The above should be optional! */
_player->iterator_message(msg);
}
/* Different from the one in iterator.c */
static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0,
3, 3, 0, 3, 2, 0, 3, 0
};
static const SongHandle midi_send_base = 0xffff0000;
Common::Error SfxState::sfx_send_midi(SongHandle handle, int channel,
int command, int arg1, int arg2) {
byte buffer[5];
/* Yes, in that order. SCI channel mutes are actually done via
a counting semaphore. 0 means to decrement the counter, 1
to increment it. */
static const char *channel_state[] = {"ON", "OFF"};
if (command == 0xb0 &&
arg1 == SCI_MIDI_CHANNEL_MUTE) {
warning("TODO: channel mute (channel %d %s)", channel, channel_state[arg2]);
/* We need to have a GET_PLAYMASK interface to use
here. SET_PLAYMASK we've got.
*/
return Common::kNoError;
}
buffer[0] = channel | command; /* No channel remapping yet */
switch (command) {
case 0x80 :
case 0x90 :
case 0xb0 :
buffer[1] = arg1 & 0xff;
buffer[2] = arg2 & 0xff;
break;
case 0xc0 :
buffer[1] = arg1 & 0xff;
break;
case 0xe0 :
buffer[1] = (arg1 & 0x7f) | 0x80;
buffer[2] = (arg1 & 0xff00) >> 7;
break;
default:
warning("Unexpected explicit MIDI command %02x", command);
return Common::kUnknownError;
}
if (_player)
_player->tell_synth(MIDI_cmdlen[command >> 4], buffer);
return Common::kNoError;
}
int SfxState::sfx_getVolume() {
return _player->getVolume();
}
void SfxState::sfx_setVolume(int volume) {
_player->setVolume(volume);
}
void SfxState::sfx_all_stop() {
#ifdef DEBUG_SONG_API
fprintf(stderr, "[sfx-core] All stop\n");
#endif
_songlib.freeSounds();
update();
}
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS

View file

@ -1,209 +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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
/* Sound engine */
#ifndef SCI_SFX_CORE_H
#define SCI_SFX_CORE_H
#include "common/error.h"
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/songlib.h"
#include "sci/resource.h"
namespace Sci {
class SfxPlayer;
class SongIterator;
struct fade_params_t;
#define SFX_TICKS_PER_SEC 60 /* MIDI ticks per second */
#define SFX_STATE_FLAG_MULTIPLAY (1 << 0) /* More than one song playable
** simultaneously ? */
#define SFX_STATE_FLAG_NOSOUND (1 << 1) /* Completely disable sound playing */
class SfxState {
private:
SfxPlayer *_player;
public: // FIXME, make private
SongIterator *_it; /**< The song iterator at the heart of things */
uint _flags; /**< SFX_STATE_FLAG_* */
SongLibrary _songlib; /**< Song library */
Song *_song; /**< Active song, or start of active song chain */
bool _suspended; /**< Whether we are suspended */
ResourceManager *_resMan;
public:
SfxState();
~SfxState();
/***********/
/* General */
/***********/
/* Initializes the sound engine
** Parameters: (ResourceManager *) resMan: Resource manager for initialization
** (int) flags: SFX_STATE_FLAG_*
*/
void sfx_init(ResourceManager *resMan, int flags, SciVersion soundVersion);
/** Deinitializes the sound subsystem. */
void sfx_exit();
/* Suspends/unsuspends the sound sybsystem
** Parameters: (int) suspend: Whether to suspend (non-null) or to unsuspend
*/
void sfx_suspend(bool suspend);
/* Polls the sound server for cues etc.
** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise
** (SongHandle) *handle: The affected handle
** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP)
*/
int sfx_poll(SongHandle *handle, int *cue);
/* Polls the sound server for cues etc.
** Parameters: (SongHandle) handle: The handle to poll
** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise
** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP)
*/
int sfx_poll_specific(SongHandle handle, int *cue);
/* Determines the current global volume settings
** Returns : (int) The global volume, between 0 (silent) and 127 (max. volume)
*/
int sfx_getVolume();
/* Determines the current global volume settings
** Parameters: (int) volume: The new global volume, between 0 and 127 (see above)
*/
void sfx_setVolume(int volume);
/* Stops all songs currently playing, purges song library
*/
void sfx_all_stop();
/*****************/
/* Song basics */
/*****************/
/* Adds a song to the internal sound library
** Parameters: (SongIterator *) it: The iterator describing the song
** (int) priority: Initial song priority (higher <-> more important)
** (SongHandle) handle: The handle to associate with the song
*/
void sfx_add_song(SongIterator *it, int priority, SongHandle handle, int resnum);
/* Deletes a song and its associated song iterator from the song queue
** Parameters: (SongHandle) handle: The song to remove
*/
void sfx_remove_song(SongHandle handle);
/**********************/
/* Song modifications */
/**********************/
/* Sets the song status, i.e. whether it is playing, suspended, or stopped.
** Parameters: (SongHandle) handle: Handle of the song to modify
** (int) status: The song status the song should assume
** WAITING and PLAYING are set implicitly and essentially describe the same state
** as far as this function is concerned.
*/
void sfx_song_set_status(SongHandle handle, int status);
/* Sets the new song priority
** Parameters: (SongHandle) handle: The handle to modify
** (int) priority: The priority to set
*/
void sfx_song_renice(SongHandle handle, int priority);
/* Sets the number of loops for the specified song
** Parameters: (SongHandle) handle: The song handle to reference
** (int) loops: Number of loops to set
*/
void sfx_song_set_loops(SongHandle handle, int loops);
/* Sets the number of loops for the specified song
** Parameters: (SongHandle) handle: The song handle to reference
** (int) hold: Number of loops to setn
*/
void sfx_song_set_hold(SongHandle handle, int hold);
/* Instructs a song to be faded out
** Parameters: (SongHandle) handle: The song handle to reference
** (fade_params_t *) fade_setup: The precise fade-out configuration to use
*/
void sfx_song_set_fade(SongHandle handle, fade_params_t *fade_setup);
// Previously undocumented:
Common::Error sfx_send_midi(SongHandle handle, int channel,
int command, int arg1, int arg2);
// misc
/**
* Determines the polyphony of the player in use.
* @return Number of voices the active player can emit
*/
int sfx_get_player_polyphony();
/**
* Tells the player to stop its internal iterator.
*/
void sfx_reset_player();
/**
* Pass a raw MIDI event to the synth of the player.
* @param argc Length of buffer holding the midi event
* @param argv The buffer itself
*/
void sfx_player_tell_synth(int buf_nr, byte *buf);
protected:
void freezeTime();
void thawTime();
bool isPlaying(Song *song);
void setSongStatus(Song *song, int status);
void updateSingleSong();
void updateMultiSong();
void update();
};
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS
#endif // SCI_SFX_CORE_H

File diff suppressed because it is too large Load diff

View file

@ -1,326 +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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
/* Song iterator declarations */
#ifndef SCI_SFX_SFX_ITERATOR_H
#define SCI_SFX_SFX_ITERATOR_H
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/drivers/mididriver.h"
namespace Audio {
class AudioStream;
}
namespace Sci {
enum SongIteratorStatus {
SI_FINISHED = -1, /**< Song finished playing */
SI_LOOP = -2, /**< Song just looped */
SI_ABSOLUTE_CUE = -3, /**< Found a song cue (absolute) */
SI_RELATIVE_CUE = -4, /**< Found a song cue (relative) */
SI_PCM = -5, /**< Found a PCM */
SI_IGNORE = -6, /**< This event got edited out by the remapper */
SI_MORPH = -255 /**< Song iterator requested self-morph. */
};
#define FADE_ACTION_NONE 0
#define FADE_ACTION_FADE_AND_STOP 1
#define FADE_ACTION_FADE_AND_CONT 2
struct fade_params_t {
int ticks_per_step;
int final_volume;
int step_size;
int action;
};
/* Helper defs for messages */
enum {
_SIMSG_BASE, /* Any base decoder */
_SIMSG_PLASTICWRAP /* Any "Plastic" (discardable) wrapper decoder */
};
/* Base messages */
enum {
_SIMSG_BASEMSG_SET_LOOPS, /* Set loops */
_SIMSG_BASEMSG_SET_PLAYMASK, /* Set the current playmask for filtering */
_SIMSG_BASEMSG_SET_RHYTHM, /* Activate/deactivate rhythm channel */
_SIMSG_BASEMSG_ACK_MORPH, /* Acknowledge self-morph */
_SIMSG_BASEMSG_STOP, /* Stop iterator */
_SIMSG_BASEMSG_PRINT, /* Print self to stderr, after printing param1 tabs */
_SIMSG_BASEMSG_SET_HOLD, /* Set value of hold parameter to expect */
_SIMSG_BASEMSG_SET_FADE /* Set fade parameters */
};
/* "Plastic" (discardable) wrapper messages */
enum {
_SIMSG_PLASTICWRAP_ACK_MORPH = _SIMSG_BASEMSG_ACK_MORPH /* Acknowledge self-morph */
};
/* Messages */
#define SIMSG_SET_LOOPS(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_LOOPS,(x)
#define SIMSG_SET_PLAYMASK(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_PLAYMASK,(x)
#define SIMSG_SET_RHYTHM(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_RHYTHM,(x)
#define SIMSG_ACK_MORPH _SIMSG_PLASTICWRAP,_SIMSG_PLASTICWRAP_ACK_MORPH,0
#define SIMSG_STOP _SIMSG_BASE,_SIMSG_BASEMSG_STOP,0
#define SIMSG_PRINT(indentation) _SIMSG_BASE,_SIMSG_BASEMSG_PRINT,(indentation)
#define SIMSG_SET_HOLD(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_HOLD,(x)
/* Message transmission macro: Takes song reference, message reference */
#define SIMSG_SEND(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, m))
#define SIMSG_SEND_FADE(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, _SIMSG_BASE, _SIMSG_BASEMSG_SET_FADE, m))
typedef unsigned long songit_id_t;
#define SONGIT_MAX_LISTENERS 2
class TeeSongIterator;
class SongIterator {
public:
struct Message {
songit_id_t ID;
uint _class; /* Type of iterator supposed to receive this */
uint _type;
union {
uint i;
void *p;
} _arg;
Message() : ID(0), _class(0xFFFF), _type(0xFFFF) {}
/**
* Create a song iterator message.
*
* @param id: song ID the message is targeted to
* @param recipient_class: Message recipient class
* @param type message type
* @param a argument
*
* @note You should only use this with the SIMSG_* macros
*/
Message(songit_id_t id, int recipient_class, int type, int a)
: ID(id), _class(recipient_class), _type(type) {
_arg.i = a;
}
/**
* Create a song iterator message, wherein the first parameter is a pointer.
*
* @param id: song ID the message is targeted to
* @param recipient_class: Message recipient class
* @param type message type
* @param a argument
*
* @note You should only use this with the SIMSG_* macros
*/
Message(songit_id_t id, int recipient_class, int type, void *a)
: ID(id), _class(recipient_class), _type(type) {
_arg.p = a;
}
};
public:
songit_id_t ID;
uint16 channel_mask; /* Bitmask of all channels this iterator will use */
fade_params_t fade;
int priority;
/* Death listeners */
/* These are not reset during initialisation */
TeeSongIterator *_deathListeners[SONGIT_MAX_LISTENERS];
/* See songit_* for the constructor and non-virtual member functions */
byte channel_remap[MIDI_CHANNELS]; ///< Remapping for channels
public:
SongIterator();
SongIterator(const SongIterator &);
virtual ~SongIterator();
/**
* Resets/initializes the sound iterator.
*/
virtual void init() {}
/**
* Reads the next MIDI operation _or_ delta time.
* @param buf The buffer to write to (needs to be able to store at least 4 bytes)
* @param result Number of bytes written to the buffer
* (equals the number of bytes that need to be passed
* to the lower layers) for 0, the cue value for SI_CUE,
* or the number of loops remaining for SI_LOOP.
* @return zero if a MIDI operation was written, SI_FINISHED
* if the song has finished playing, SI_LOOP if looping
* (after updating the loop variable), SI_CUE if we found
* a cue, SI_PCM if a PCM was found, or the number of ticks
* to wait before this function should be called next.
*
* @note If SI_PCM is returned, get_pcm() may be used to retrieve the associated
* PCM, but this must be done before any subsequent calls to next().
*
* @todo The actual buffer size should either be specified or passed in, so that
* we can detect buffer overruns.
*/
virtual int nextCommand(byte *buf, int *result) = 0;
/**
Checks for the presence of a pcm sample.
* @return NULL if no PCM data was found, an AudioStream otherwise.
*/
virtual Audio::AudioStream *getAudioStream() = 0;
/**
* Handles a message to the song iterator.
* @param msg the message to handle
* @return NULL if the message was not understood,
* this if the message could be handled, or a new song iterator
* if the current iterator had to be morphed (but the message could
* still be handled)
*
* @note This function is not supposed to be called directly; use
* songit_handle_message() instead. It should not recurse, since songit_handle_message()
* takes care of that and makes sure that its delegate received the message (and
* was morphed) before self.
*/
virtual SongIterator *handleMessage(Message msg) = 0;
/**
* Gets the song position to store in a savegame.
*/
virtual int getTimepos() = 0;
/**
* Clone this song iterator.
* @param delta number of ticks that still need to elapse until the
* next item should be read from the song iterator
*/
virtual SongIterator *clone(int delta) = 0;
private:
// Make the assignment operator unreachable, just in case...
SongIterator& operator=(const SongIterator&);
};
/********************************/
/*-- Song iterator operations --*/
/********************************/
enum SongIteratorType {
SCI_SONG_ITERATOR_TYPE_SCI0 = 0,
SCI_SONG_ITERATOR_TYPE_SCI1 = 1
};
#define IT_READER_MASK_MIDI (1 << 0)
#define IT_READER_MASK_DELAY (1 << 1)
#define IT_READER_MASK_LOOP (1 << 2)
#define IT_READER_MASK_CUE (1 << 3)
#define IT_READER_MASK_PCM (1 << 4)
#define IT_READER_MAY_FREE (1 << 10) /* Free SI_FINISHED iterators */
#define IT_READER_MAY_CLEAN (1 << 11)
/* MAY_CLEAN: May instantiate cleanup iterators
** (use for players; this closes open channels at the end of a song) */
#define IT_READER_MASK_ALL ( IT_READER_MASK_MIDI \
| IT_READER_MASK_DELAY \
| IT_READER_MASK_LOOP \
| IT_READER_MASK_CUE \
| IT_READER_MASK_PCM )
/* Convenience wrapper around it->next
** Parameters: (SongIterator **it) Reference to the iterator to access
** (byte *) buf: The buffer to write to (needs to be able to
** store at least 4 bytes)
** (int) mask: IT_READER_MASK options specifying the events to
** listen for
** Returns : (int) zero if a MIDI operation was written, SI_FINISHED
** if the song has finished playing, SI_LOOP if looping
** (after updating the loop variable), SI_CUE if we found
** a cue, SI_PCM if a PCM was found, or the number of ticks
** to wait before this function should be called next.
** (int) *result: Number of bytes written to the buffer
** (equals the number of bytes that need to be passed
** to the lower layers) for 0, the cue value for SI_CUE,
** or the number of loops remaining for SI_LOOP.
*/
int songit_next(SongIterator **it, byte *buf, int *result, int mask);
/* Constructs a new song iterator object
** Parameters: (byte *) data: The song data to iterate over
** (uint) size: Number of bytes in the song
** (int) type: One of the SCI_SONG_ITERATOR_TYPEs
** (songit_id_t) id: An ID for addressing the song iterator
** Returns : (SongIterator *) A newly allocated but uninitialized song
** iterator, or NULL if 'type' was invalid or unsupported
*/
SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id);
/* Constructs a new song timer iterator object
** Parameters: (int) delta: The delta after which to fire SI_FINISHED
** Returns : (SongIterator *) A newly allocated but uninitialized song
** iterator
*/
SongIterator *new_timer_iterator(int delta);
/* Handles a message to the song iterator
** Parameters: (SongIterator **): A reference to the variable storing the song iterator
** Returns : (int) Non-zero if the message was understood
** The song iterator may polymorph as result of msg, so a writeable reference is required.
*/
int songit_handle_message(SongIterator **it_reg, SongIterator::Message msg);
/* Creates a new song iterator which fast-forwards
** Parameters: (SongIterator *) it: The iterator to wrap
** (int) delta: The number of ticks to skip
** Returns : (SongIterator) A newly created song iterator
** which skips all delta times
** until 'delta' has been used up
*/
SongIterator *new_fast_forward_iterator(SongIterator *it, int delta);
/* Combines two song iterators into one
** Parameters: (sfx_iterator_t *) it1: One of the two iterators, or NULL
** (sfx_iterator_t *) it2: The other iterator, or NULL
** Returns : (sfx_iterator_t *) A combined iterator
** If a combined iterator is returned, it will be flagged to be allowed to
** dispose of 'it1' and 'it2', where applicable. This means that this
** call should be used by song players, but not by the core sound system
*/
SongIterator *sfx_iterator_combine(SongIterator *it1, SongIterator *it2);
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS
#endif // SCI_SFX_SFX_ITERATOR_H

View file

@ -1,276 +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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef SCI_SFX_SFX_ITERATOR_INTERNAL
#define SCI_SFX_SFX_ITERATOR_INTERNAL
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/iterator.h"
#include "sci/sound/drivers/mididriver.h"
#include "common/array.h"
#include "common/list.h"
namespace Sci {
/* Iterator types */
enum {
SI_STATE_UNINITIALISED = -1,
SI_STATE_DELTA_TIME = 0, ///< Now at a delta time
SI_STATE_COMMAND = 1, ///< Now at a MIDI operation
SI_STATE_PENDING = 2, ///< Pending for loop
SI_STATE_FINISHED = 3, ///< End of song
SI_STATE_PCM = 4, ///< Should report a PCM next (-> DELTA_TIME)
SI_STATE_PCM_MAGIC_DELTA = 5 ///< Should report a ``magic'' one tick delta time next (goes on to FINISHED)
};
struct SongIteratorChannel {
int state; ///< State of this song iterator channel
int offset; ///< Offset into the data chunk */
int end; ///< Last allowed byte in track */
int id; ///< Some channel ID */
/**
* Number of ticks before the specified channel is next used, or
* CHANNEL_DELAY_MISSING to indicate that the delay has not yet
* been read.
*/
int delay;
/* Two additional offsets for recovering: */
int loop_offset;
int initial_offset;
int playmask; ///< Active playmask (MIDI channels to play in here) */
int loop_timepos; ///< Total delay for this channel's loop marker */
int total_timepos; ///< Number of ticks since the beginning, ignoring loops */
int timepos_increment; ///< Number of ticks until the next command (to add) */
byte last_cmd; ///< Last operation executed, for running status */
public:
void init(int id, int offset, int end);
void resetSynthChannels();
};
class BaseSongIterator : public SongIterator {
public:
int _polyphony[MIDI_CHANNELS]; ///< # of simultaneous notes on each
int _ccc; ///< Cumulative cue counter, for those who need it
byte _resetflag; ///< for 0x4C -- on DoSound StopSound, do we return to start?
int _deviceId; ///< ID of the device we generating events for
int _numActiveChannels; ///< Number of active channels
Common::Array<byte> _data; ///< Song data
int _loops; ///< Number of loops remaining
public:
BaseSongIterator(byte *data, uint size, songit_id_t id);
protected:
int parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags);
int processMidi(byte *buf, int *result, SongIteratorChannel *channel, int flags);
};
/********************************/
/*--------- SCI 0 --------------*/
/********************************/
class Sci0SongIterator : public BaseSongIterator {
public:
SongIteratorChannel _channel;
public:
Sci0SongIterator(byte *data, uint size, songit_id_t id);
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream();
SongIterator *handleMessage(Message msg);
void init();
int getTimepos();
SongIterator *clone(int delta);
};
/********************************/
/*--------- SCI 1 --------------*/
/********************************/
struct Sci1Sample {
/**
* Time left-- initially, this is 'Sample point 1'.
* After initialisation, it is 'sample point 1 minus the sample
* point of the previous sample'
*/
int delta;
int size;
bool announced; /* Announced for download (SI_PCM) */
int rate;
byte *_data;
};
class Sci1SongIterator : public BaseSongIterator {
public:
SongIteratorChannel _channels[MIDI_CHANNELS];
/* Invariant: Whenever channels[i].delay == CHANNEL_DELAY_MISSING,
** channel_offset[i] points to a delta time object. */
bool _initialised; /**!< Whether the MIDI channel setup has been initialised */
int _numChannels; /**!< Number of channels actually used */
Common::List<Sci1Sample> _samples;
int _numLoopedChannels; /**!< Number of channels that are ready to loop */
int _delayRemaining; /**!< Number of ticks that haven't been polled yet */
int _hold;
public:
Sci1SongIterator(byte *data, uint size, songit_id_t id);
~Sci1SongIterator();
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream();
SongIterator *handleMessage(Message msg);
void init();
int getTimepos();
SongIterator *clone(int delta);
private:
int initSample(const int offset);
int initSong();
int getSmallestDelta() const;
void updateDelta(int delta);
/** Checks that none of the channels is waiting for its delta to be read */
bool noDeltaTime() const;
/** Determine the channel # of the next active event, or -1 */
int getCommandIndex() const;
};
#define PLAYMASK_NONE 0x0
/***************************/
/*--------- Timer ---------*/
/***************************/
/**
* A song iterator which waits a specified time and then fires
* SI_FINISHED. Used by DoSound, where audio resources are played (SCI1)
*/
class TimerSongIterator : public SongIterator {
protected:
int _delta; /**!< Remaining time */
public:
TimerSongIterator(int delta) : _delta(delta) {}
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream() { return NULL; }
SongIterator *handleMessage(Message msg) { return NULL; }
int getTimepos() { return 0; }
SongIterator *clone(int delta) { return new TimerSongIterator(*this); }
};
/**********************************/
/*--------- Fast Forward ---------*/
/**********************************/
/**
* A song iterator which fast-forwards another iterator.
* Skips all delta times until a specified 'delta' has been used up.
*/
class FastForwardSongIterator : public SongIterator {
protected:
SongIterator *_delegate;
int _delta; /**!< Remaining time */
public:
FastForwardSongIterator(SongIterator *capsit, int delta);
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream();
SongIterator *handleMessage(Message msg);
int getTimepos();
SongIterator *clone(int delta);
};
/**********************************/
/*--------- Tee iterator ---------*/
/**********************************/
enum {
TEE_LEFT = 0,
TEE_RIGHT = 1,
TEE_LEFT_ACTIVE = (1<<0),
TEE_RIGHT_ACTIVE = (1<<1),
TEE_LEFT_READY = (1<<2), /**!< left result is ready */
TEE_RIGHT_READY = (1<<3), /**!< right result is ready */
TEE_LEFT_PCM = (1<<4),
TEE_RIGHT_PCM = (1<<5)
};
/**
* This iterator combines two iterators, returns the next event available from either.
*/
class TeeSongIterator : public SongIterator {
public:
int _status;
bool _readyToMorph; /**!< One of TEE_MORPH_* above */
struct {
SongIterator *it;
byte buf[4];
int result;
int retval;
} _children[2];
public:
TeeSongIterator(SongIterator *left, SongIterator *right);
~TeeSongIterator();
int nextCommand(byte *buf, int *result);
Audio::AudioStream *getAudioStream();
SongIterator *handleMessage(Message msg);
void init();
int getTimepos() { return 0; }
SongIterator *clone(int delta);
};
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS
#endif // SCI_SFX_SFX_ITERATOR_INTERNAL

View file

@ -1,189 +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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/core.h"
#include "sci/sound/iterator/iterator.h"
namespace Sci {
#define debug_stream stderr
Song::Song() : _wakeupTime(0, SFX_TICKS_PER_SEC) {
_handle = 0;
_resourceNum = 0;
_priority = 0;
_status = SOUND_STATUS_STOPPED;
_restoreBehavior = RESTORE_BEHAVIOR_CONTINUE;
_restoreTime = 0;
_loops = 0;
_hold = 0;
_it = 0;
_delay = 0;
_next = NULL;
_nextPlaying = NULL;
_nextStopping = NULL;
}
Song::Song(SongHandle handle, SongIterator *it, int priority) : _wakeupTime(0, SFX_TICKS_PER_SEC) {
_handle = handle;
_resourceNum = 0;
_priority = priority;
_status = SOUND_STATUS_STOPPED;
_restoreBehavior = RESTORE_BEHAVIOR_CONTINUE;
_restoreTime = 0;
_loops = 0;
_hold = 0;
_it = it;
_delay = 0;
_next = NULL;
_nextPlaying = NULL;
_nextStopping = NULL;
}
void SongLibrary::addSong(Song *song) {
Song **seeker = NULL;
int pri = song->_priority;
if (NULL == song) {
warning("addSong(): NULL passed for song");
return;
}
seeker = &_lib;
while (*seeker && ((*seeker)->_priority > pri))
seeker = &((*seeker)->_next);
song->_next = *seeker;
*seeker = song;
}
void SongLibrary::freeSounds() {
Song *next = _lib;
while (next) {
Song *song = next;
delete song->_it;
song->_it = NULL;
next = song->_next;
delete song;
}
_lib = NULL;
}
Song *SongLibrary::findSong(SongHandle handle) {
Song *seeker = _lib;
while (seeker) {
if (seeker->_handle == handle)
break;
seeker = seeker->_next;
}
return seeker;
}
Song *SongLibrary::findNextActive(Song *other) {
Song *seeker = other ? other->_next : _lib;
while (seeker) {
if ((seeker->_status == SOUND_STATUS_WAITING) ||
(seeker->_status == SOUND_STATUS_PLAYING))
break;
seeker = seeker->_next;
}
/* Only return songs that have equal priority */
if (other && seeker && other->_priority > seeker->_priority)
return NULL;
return seeker;
}
Song *SongLibrary::findFirstActive() {
return findNextActive(NULL);
}
int SongLibrary::removeSong(SongHandle handle) {
int retval;
Song *goner = _lib;
if (!goner)
return -1;
if (goner->_handle == handle)
_lib = goner->_next;
else {
while ((goner->_next) && (goner->_next->_handle != handle))
goner = goner->_next;
if (goner->_next) { /* Found him? */
Song *oldnext = goner->_next;
goner->_next = goner->_next->_next;
goner = oldnext;
} else return -1; /* No. */
}
retval = goner->_status;
delete goner->_it;
delete goner;
return retval;
}
int SongLibrary::countSongs() {
Song *seeker = _lib;
int retval = 0;
while (seeker) {
retval++;
seeker = seeker->_next;
}
return retval;
}
void SongLibrary::setSongRestoreBehavior(SongHandle handle, RESTORE_BEHAVIOR action) {
Song *seeker = findSong(handle);
seeker->_restoreBehavior = action;
}
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS

View file

@ -1,171 +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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
/* Song library */
#ifndef SCI_SFX_SFX_SONGLIB_H
#define SCI_SFX_SFX_SONGLIB_H
#include "common/scummsys.h"
#include "sound/timestamp.h"
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
namespace Sci {
class SongIterator;
#define SOUND_STATUS_STOPPED 0
#define SOUND_STATUS_PLAYING 1
#define SOUND_STATUS_SUSPENDED 2
/* suspended: only if ordered from kernel space */
#define SOUND_STATUS_WAITING 3
/* "waiting" means "tagged for playing, but not active right now" */
typedef unsigned long SongHandle;
enum RESTORE_BEHAVIOR {
RESTORE_BEHAVIOR_CONTINUE, /* restart a song when restored from
a saved game */
RESTORE_BEHAVIOR_RESTART /* continue it from where it was */
};
class Song {
public:
SongHandle _handle;
int _resourceNum; /**<! Resource number */
int _priority; /**!< Song priority (more important if priority is higher) */
int _status; /* See above */
int _restoreBehavior;
int _restoreTime;
/* Grabbed from the sound iterator, for save/restore purposes */
int _loops;
int _hold;
SongIterator *_it;
int _delay; /**!< Delay before accessing the iterator, in ticks */
Audio::Timestamp _wakeupTime; /**!< Timestamp indicating the next MIDI event */
Song *_next; /**!< Next song or NULL if this is the last one */
/**
* Next playing song. Used by the core song system.
*/
Song *_nextPlaying;
/**
* Next song pending stopping. Used exclusively by the core song system's
* _update_multi_song()
*/
Song *_nextStopping;
public:
Song();
/**
* Initializes a new song.
* @param handle the sound handle
* @param it the song
* @param priority the song's priority
* @return a freshly allocated song
*/
Song(SongHandle handle, SongIterator *it, int priority);
};
class SongLibrary {
public:
Song *_lib;
public:
SongLibrary() : _lib(0) {}
/** Frees a song library. */
void freeSounds();
/**
* Adds a song to a song library.
* @param song song to add
*/
void addSong(Song *song);
/**
* Looks up the song with the specified handle.
* @param handle sound handle to look for
* @return the song or NULL if it wasn't found
*/
Song *findSong(SongHandle handle);
/**
* Finds the first song playing with the highest priority.
* @return the song that should be played next, or NULL if there is none
*/
Song *findFirstActive();
/**
* Finds the next song playing with the highest priority.
*
* The functions 'findFirstActive' and 'findNextActive'
* allow to iterate over all songs that satisfy the requirement of
* being 'playable'.
*
* @param song a song previously returned from the song library
* @return the next song to play relative to 'song', or NULL if none are left
*/
Song *findNextActive(Song *song);
/**
* Removes a song from the library.
* @param handle handle of the song to remove
* @return the status of the song that was removed
*/
int removeSong(SongHandle handle);
/**
* Counts the number of songs in a song library.
* @return the number of songs
*/
int countSongs();
/**
* Determines what should be done with the song "handle" when restoring
* it from a saved game.
* @param handle sound handle being restored
* @param action desired action
*/
void setSongRestoreBehavior(SongHandle handle,
RESTORE_BEHAVIOR action);
};
} // End of namespace Sci
#endif // USE_OLD_MUSIC_FUNCTIONS
#endif // SCI_SSFX_SFX_SONGLIB_H

View file

@ -1,423 +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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "iterator.h"
#include "iterator_internal.h"
#include <stdarg.h>
#include <stdio.h>
using namespace Sci;
#define ASSERT_S(x) if (!(x)) { error("Failed assertion in L%d: " #x, __LINE__); return; }
#define ASSERT(x) ASSERT_S(x)
/* Tests the song iterators */
int errors = 0;
void error(char *fmt, ...) {
va_list ap;
fprintf(stderr, "[ERROR] ");
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
++errors;
}
/* The simple iterator will finish after a fixed amount of time. Before that,
** it emits (absolute) cues in ascending order. */
struct simple_iterator : public SongIterator {
int lifetime_remaining;
char *cues;
int cue_counter;
int cue_progress;
int cues_nr;
};
int simple_it_next(SongIterator *_self, unsigned char *buf, int *result) {
simple_iterator *self = (simple_iterator *)_self;
if (self->lifetime_remaining == -1) {
error("Song iterator called post mortem");
return SI_FINISHED;
}
if (self->lifetime_remaining) {
if (self->cue_counter < self->cues_nr) {
int time_to_cue = self->cues[self->cue_counter];
if (self->cue_progress == time_to_cue) {
++self->cue_counter;
self->cue_progress = 0;
*result = self->cue_counter;
return SI_ABSOLUTE_CUE;
} else {
int retval = time_to_cue - self->cue_progress;
self->cue_progress = time_to_cue;
if (retval > self->lifetime_remaining) {
retval = self->lifetime_remaining;
self->lifetime_remaining = 0;
self->cue_progress = retval;
return retval;
}
self->lifetime_remaining -= retval;
return retval;
}
} else {
int retval = self->lifetime_remaining;
self->lifetime_remaining = 0;
return retval;
}
} else {
self->lifetime_remaining = -1;
return SI_FINISHED;
}
}
Audio::AudioStream *simple_it_pcm_feed(SongIterator *_self) {
error("No PCM feed");
return NULL;
}
void simple_it_init(SongIterator *_self) {
}
SongIterator *simple_it_handle_message(SongIterator *_self, SongIterator::Message msg) {
return NULL;
}
void simple_it_cleanup(SongIterator *_self) {
}
/* Initialises the simple iterator.
** Parameters: (int) delay: Number of ticks until the iterator finishes
** (int *) cues: An array of cue delays (cue values are [1,2...])
** (int) cues_nr: Number of cues in ``cues''
** The first cue is emitted after cues[0] ticks, and it is 1. After cues[1] additional ticks
** the next cue is emitted, and so on. */
SongIterator *setup_simple_iterator(int delay, char *cues, int cues_nr) {
simple_iterator.lifetime_remaining = delay;
simple_iterator.cues = cues;
simple_iterator.cue_counter = 0;
simple_iterator.cues_nr = cues_nr;
simple_iterator.cue_progress = 0;
simple_iterator.ID = 42;
simple_iterator.channel_mask = 0x004f;
simple_iterator.flags = 0;
simple_iterator.priority = 1;
simple_iterator.death_listeners_nr = 0;
simple_iterator.cleanup = simple_it_cleanup;
simple_iterator.init = simple_it_init;
simple_iterator.handle_message = simple_it_handle_message;
simple_iterator.get_pcm_feed = simple_it_pcm_feed;
simple_iterator.next = simple_it_next;
return (SongIterator *) &simple_iterator;
}
#define ASSERT_SIT ASSERT(it == simple_it)
#define ASSERT_FFIT ASSERT(it == ff_it)
#define ASSERT_NEXT(n) ASSERT(songit_next(&it, data, &result, IT_READER_MASK_ALL) == n)
#define ASSERT_RESULT(n) ASSERT(result == n)
#define ASSERT_CUE(n) ASSERT_NEXT(SI_ABSOLUTE_CUE); ASSERT_RESULT(n)
void test_simple_it() {
SongIterator *it;
SongIterator *simple_it = (SongIterator *) & simple_iterator;
unsigned char data[4];
int result;
puts("[TEST] simple iterator (test artifact)");
it = setup_simple_iterator(42, NULL, 0);
ASSERT_SIT;
ASSERT_NEXT(42);
ASSERT_SIT;
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, "\003\004", 2);
ASSERT_SIT;
ASSERT_NEXT(3);
ASSERT_CUE(1);
ASSERT_SIT;
ASSERT_NEXT(4);
ASSERT_CUE(2);
ASSERT_SIT;
// warning("XXX => %d", songit_next(&it, data, &result, IT_READER_MASK_ALL));
ASSERT_NEXT(35);
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
puts("[TEST] Test OK.");
}
void test_fastforward() {
SongIterator *it;
SongIterator *simple_it = (SongIterator *) & simple_iterator;
SongIterator *ff_it;
unsigned char data[4];
int result;
puts("[TEST] fast-forward iterator");
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 0);
ASSERT_FFIT;
ASSERT_NEXT(42);
ASSERT_SIT; /* Must have morphed back */
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 1);
ASSERT_FFIT;
ASSERT_NEXT(41);
/* May or may not have morphed back here */
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 41);
ASSERT_FFIT;
ASSERT_NEXT(1);
/* May or may not have morphed back here */
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 42);
ASSERT_NEXT(SI_FINISHED);
/* May or may not have morphed back here */
it = setup_simple_iterator(42, NULL, 0);
ff_it = it = new_fast_forward_iterator(it, 10000);
ASSERT_NEXT(SI_FINISHED);
/* May or may not have morphed back here */
it = setup_simple_iterator(42, "\003\004", 2);
ff_it = it = new_fast_forward_iterator(it, 2);
ASSERT_FFIT;
ASSERT_NEXT(1);
ASSERT_CUE(1);
ASSERT_SIT;
ASSERT_NEXT(4);
ASSERT_CUE(2);
ASSERT_SIT;
ASSERT_NEXT(35);
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, "\003\004", 2);
ff_it = it = new_fast_forward_iterator(it, 5);
ASSERT_FFIT;
ASSERT_CUE(1);
ASSERT_FFIT;
ASSERT_NEXT(2);
ASSERT_CUE(2);
ASSERT_SIT;
ASSERT_NEXT(35);
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
it = setup_simple_iterator(42, "\003\004", 2);
ff_it = it = new_fast_forward_iterator(it, 41);
ASSERT_FFIT;
ASSERT_CUE(1);
ASSERT_FFIT;
ASSERT_CUE(2);
ASSERT_FFIT;
ASSERT_NEXT(1);
ASSERT_NEXT(SI_FINISHED);
ASSERT_SIT;
puts("[TEST] Test OK.");
}
#define SIMPLE_SONG_SIZE 50
static unsigned char simple_song[SIMPLE_SONG_SIZE] = {
0x00, /* Regular song */
/* Only use channel 0 for all devices */
0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Song begins here */
42, 0x90, 60, 0x7f, /* Play C after 42 ticks */
02, 64, 0x42, /* Play E after 2 more ticks, using running status mode */
0xf8, 10, 0x80, 60, 0x02, /* Stop C after 250 ticks */
0, 64, 0x00, /* Stop E immediately */
00, 0xfc /* Stop song */
};
#define ASSERT_MIDI3(cmd, arg0, arg1) \
ASSERT(data[0] == cmd); \
ASSERT(data[1] == arg0); \
ASSERT(data[2] == arg1);
void test_iterator_sci0() {
SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l);
unsigned char data[4];
int result;
SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */
puts("[TEST] SCI0-style song");
ASSERT_NEXT(42);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 60, 0x7f);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(250);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 60, 0x02);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
ASSERT_NEXT(SI_FINISHED);
puts("[TEST] Test OK.");
}
void test_iterator_sci0_loop() {
SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l);
unsigned char data[4];
int result;
SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */
SIMSG_SEND(it, SIMSG_SET_LOOPS(2)); /* Loop one additional time */
puts("[TEST] SCI0-style song with looping");
ASSERT_NEXT(42);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 60, 0x7f);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(250);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 60, 0x02);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
ASSERT_NEXT(SI_LOOP);
ASSERT_NEXT(42);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 60, 0x7f);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(250);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 60, 0x02);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
ASSERT_NEXT(SI_FINISHED);
puts("[TEST] Test OK.");
}
#define LOOP_SONG_SIZE 54
unsigned char loop_song[LOOP_SONG_SIZE] = {
0x00, /* Regular song song */
/* Only use channel 0 for all devices */
0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Song begins here */
42, 0x90, 60, 0x7f, /* Play C after 42 ticks */
13, 0x80, 60, 0x00, /* Stop C after 13 ticks */
00, 0xCF, 0x7f, /* Set loop point */
02, 0x90, 64, 0x42, /* Play E after 2 more ticks, using running status mode */
03, 0x80, 64, 0x00, /* Stop E after 3 ticks */
00, 0xfc /* Stop song/loop */
};
void test_iterator_sci0_mark_loop() {
SongIterator *it = songit_new(loop_song, LOOP_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l);
unsigned char data[4];
int result;
SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */
SIMSG_SEND(it, SIMSG_SET_LOOPS(3)); /* Loop once more */
puts("[TEST] SCI0-style song with loop mark, looping");
ASSERT_NEXT(42);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 60, 0x7f);
ASSERT_NEXT(13);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 60, 0x00);
/* Loop point here: we don't observe that in the iterator interface yet, though */
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(3);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
/* Now we loop back to the loop pont */
ASSERT_NEXT(SI_LOOP);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(3);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
/* ...and one final time */
ASSERT_NEXT(SI_LOOP);
ASSERT_NEXT(2);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x90, 64, 0x42);
ASSERT_NEXT(3);
ASSERT_NEXT(0);
ASSERT_MIDI3(0x80, 64, 0x00);
ASSERT_NEXT(SI_FINISHED);
puts("[TEST] Test OK.");
}
int main(int argc, char **argv) {
test_simple_it();
test_fastforward();
test_iterator_sci0();
test_iterator_sci0_loop();
test_iterator_sci0_mark_loop();
if (errors != 0)
warning("[ERROR] %d errors total", errors);
return (errors != 0);
}

View file

@ -26,15 +26,11 @@
#ifndef SCI_MUSIC_H #ifndef SCI_MUSIC_H
#define SCI_MUSIC_H #define SCI_MUSIC_H
#ifndef USE_OLD_MUSIC_FUNCTIONS
#include "common/serializer.h" #include "common/serializer.h"
#endif
#include "common/mutex.h" #include "common/mutex.h"
#include "sound/mixer.h" #include "sound/mixer.h"
#include "sound/audiostream.h" #include "sound/audiostream.h"
//#include "sound/mididrv.h"
//#include "sound/midiparser.h"
#include "sci/sci.h" #include "sci/sci.h"
#include "sci/resource.h" #include "sci/resource.h"
@ -55,11 +51,7 @@ enum SoundStatus {
class MidiParser_SCI; class MidiParser_SCI;
class SegManager; class SegManager;
class MusicEntry class MusicEntry : public Common::Serializable {
#ifndef USE_OLD_MUSIC_FUNCTIONS
: public Common::Serializable
#endif
{
public: public:
// Do not get these directly for the sound objects! // Do not get these directly for the sound objects!
// It's a bad idea, as the sound code (i.e. the SciMusic // It's a bad idea, as the sound code (i.e. the SciMusic
@ -96,9 +88,6 @@ public:
Audio::Mixer::SoundType soundType; Audio::Mixer::SoundType soundType;
#ifndef USE_OLD_MUSIC_FUNCTIONS
//protected:
#endif
MidiParser_SCI *pMidiParser; MidiParser_SCI *pMidiParser;
// TODO: We need to revise how we store the different // TODO: We need to revise how we store the different
@ -114,19 +103,13 @@ public:
void doFade(); void doFade();
void onTimer(); void onTimer();
#ifndef USE_OLD_MUSIC_FUNCTIONS
virtual void saveLoadWithSerializer(Common::Serializer &ser); virtual void saveLoadWithSerializer(Common::Serializer &ser);
#endif
}; };
typedef Common::Array<MusicEntry *> MusicList; typedef Common::Array<MusicEntry *> MusicList;
typedef Common::Array<uint32> MidiCommandQueue; typedef Common::Array<uint32> MidiCommandQueue;
class SciMusic class SciMusic : public Common::Serializable {
#ifndef USE_OLD_MUSIC_FUNCTIONS
: public Common::Serializable
#endif
{
public: public:
SciMusic(SciVersion soundVersion); SciMusic(SciVersion soundVersion);
@ -193,9 +176,7 @@ public:
void setReverb(byte reverb); void setReverb(byte reverb);
#ifndef USE_OLD_MUSIC_FUNCTIONS
virtual void saveLoadWithSerializer(Common::Serializer &ser); virtual void saveLoadWithSerializer(Common::Serializer &ser);
#endif
// Mutex for music code. Used to guard access to the song playlist, to the // Mutex for music code. Used to guard access to the song playlist, to the
// MIDI parser and to the MIDI driver/player. Note that guarded code must NOT // MIDI parser and to the MIDI driver/player. Note that guarded code must NOT

View file

@ -23,12 +23,6 @@
* *
*/ */
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#ifdef USE_OLD_MUSIC_FUNCTIONS
#include "sci/sound/iterator/iterator.h" // for SongIteratorStatus
#endif
#include "common/config-manager.h" #include "common/config-manager.h"
#include "sci/sound/audio.h" #include "sci/sound/audio.h"
#include "sci/sound/music.h" #include "sci/sound/music.h"
@ -42,107 +36,13 @@ namespace Sci {
#define SCI1_SOUND_FLAG_MAY_PAUSE 1 /* Only here for completeness; The interpreter doesn't touch this bit */ #define SCI1_SOUND_FLAG_MAY_PAUSE 1 /* Only here for completeness; The interpreter doesn't touch this bit */
#define SCI1_SOUND_FLAG_SCRIPTED_PRI 2 /* but does touch this */ #define SCI1_SOUND_FLAG_SCRIPTED_PRI 2 /* but does touch this */
#ifdef USE_OLD_MUSIC_FUNCTIONS
#define FROBNICATE_HANDLE(reg) ((reg).segment << 16 | (reg).offset)
#define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff))
#endif
#define SOUNDCOMMAND(x) _soundCommands.push_back(new MusicEntryCommand(#x, &SoundCommandParser::x)) #define SOUNDCOMMAND(x) _soundCommands.push_back(new MusicEntryCommand(#x, &SoundCommandParser::x))
#ifdef USE_OLD_MUSIC_FUNCTIONS
static void script_set_priority(ResourceManager *resMan, SegManager *segMan, SfxState *state, reg_t obj, int priority) {
int song_nr = readSelectorValue(segMan, obj, SELECTOR(number));
Resource *song = resMan->findResource(ResourceId(kResourceTypeSound, song_nr), 0);
int flags = readSelectorValue(segMan, obj, SELECTOR(flags));
if (priority == -1) {
if (song->data[0] == 0xf0)
priority = song->data[1];
else
warning("Attempt to unset song priority when there is no built-in value");
flags &= ~SCI1_SOUND_FLAG_SCRIPTED_PRI;
} else flags |= SCI1_SOUND_FLAG_SCRIPTED_PRI;
state->sfx_song_renice(FROBNICATE_HANDLE(obj), priority);
writeSelectorValue(segMan, obj, SELECTOR(flags), flags);
}
SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorType type, songit_id_t id) {
Resource *song = resMan->findResource(ResourceId(kResourceTypeSound, song_nr), 0);
if (!song)
return NULL;
return songit_new(song->data, song->size, type, id);
}
void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */
int result;
SongHandle handle;
int cue;
SegManager *segMan = s->_segMan;
if (getSciVersion() > SCI_VERSION_01)
return;
// SCI1 and later explicitly poll for everything
while ((result = s->_sound.sfx_poll(&handle, &cue))) {
reg_t obj = DEFROBNICATE_HANDLE(handle);
if (!s->_segMan->isObject(obj)) {
warning("Non-object %04x:%04x received sound signal (%d/%d)", PRINT_REG(obj), result, cue);
return;
}
switch (result) {
case SI_LOOP:
debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x looped (to %d)",
PRINT_REG(obj), cue);
/* writeSelectorValue(segMan, obj, SELECTOR(loops), readSelectorValue(segMan, obj, SELECTOR(loop));; - 1);*/
writeSelectorValue(segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
break;
case SI_RELATIVE_CUE:
debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received relative cue %d",
PRINT_REG(obj), cue);
writeSelectorValue(segMan, obj, SELECTOR(signal), cue + 0x7f);
break;
case SI_ABSOLUTE_CUE:
debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received absolute cue %d",
PRINT_REG(obj), cue);
writeSelectorValue(segMan, obj, SELECTOR(signal), cue);
break;
case SI_FINISHED:
debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x finished",
PRINT_REG(obj));
writeSelectorValue(segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
writeSelectorValue(segMan, obj, SELECTOR(state), kSoundStopped);
break;
default:
warning("Unexpected result from sfx_poll: %d", result);
break;
}
}
}
#endif
SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, AudioPlayer *audio, SciVersion soundVersion) : SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, AudioPlayer *audio, SciVersion soundVersion) :
_resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) { _resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) {
#ifdef USE_OLD_MUSIC_FUNCTIONS _music = new SciMusic(_soundVersion);
// The following hack is needed to ease the change from old to new sound _music->init();
// code (because the new sound code does not use SfxState)
_state = &g_sci->getEngineState()->_sound; // HACK
#endif
#ifndef USE_OLD_MUSIC_FUNCTIONS
_music = new SciMusic(_soundVersion);
_music->init();
#endif
switch (_soundVersion) { switch (_soundVersion) {
case SCI_VERSION_0_EARLY: case SCI_VERSION_0_EARLY:
@ -215,9 +115,7 @@ SoundCommandParser::~SoundCommandParser() {
for (SoundCommandContainer::iterator i = _soundCommands.begin(); i != _soundCommands.end(); ++i) for (SoundCommandContainer::iterator i = _soundCommands.begin(); i != _soundCommands.end(); ++i)
delete *i; delete *i;
#ifndef USE_OLD_MUSIC_FUNCTIONS
delete _music; delete _music;
#endif
} }
reg_t SoundCommandParser::parseCommand(int argc, reg_t *argv, reg_t acc) { reg_t SoundCommandParser::parseCommand(int argc, reg_t *argv, reg_t acc) {
@ -261,40 +159,6 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) {
int resourceId = readSelectorValue(_segMan, obj, SELECTOR(number)); int resourceId = readSelectorValue(_segMan, obj, SELECTOR(number));
#ifdef USE_OLD_MUSIC_FUNCTIONS
SongHandle handle = FROBNICATE_HANDLE(obj);
if (_soundVersion != SCI_VERSION_1_LATE) {
if (!obj.segment)
return;
}
SongIteratorType type = (_soundVersion <= SCI_VERSION_0_LATE) ? SCI_SONG_ITERATOR_TYPE_SCI0 : SCI_SONG_ITERATOR_TYPE_SCI1;
if (_soundVersion <= SCI_VERSION_0_LATE) {
if (readSelectorValue(_segMan, obj, SELECTOR(nodePtr))) {
_state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
_state->sfx_remove_song(handle);
}
}
if (!obj.segment || !_resMan->testResource(ResourceId(kResourceTypeSound, resourceId)))
return;
_state->sfx_add_song(build_iterator(_resMan, resourceId, type, handle), 0, handle, resourceId);
// Notify the engine
if (_soundVersion <= SCI_VERSION_0_LATE)
writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundInitialized);
else
writeSelector(_segMan, obj, SELECTOR(nodePtr), obj);
writeSelector(_segMan, obj, SELECTOR(handle), obj);
#else
// Check if a track with the same sound object is already playing // Check if a track with the same sound object is already playing
MusicEntry *oldSound = _music->getSlot(obj); MusicEntry *oldSound = _music->getSlot(obj);
if (oldSound) if (oldSound)
@ -342,84 +206,12 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) {
writeSelector(_segMan, obj, SELECTOR(handle), obj); writeSelector(_segMan, obj, SELECTOR(handle), obj);
} }
#endif
} }
void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) {
if (!obj.segment) if (!obj.segment)
return; return;
#ifdef USE_OLD_MUSIC_FUNCTIONS
SongHandle handle = FROBNICATE_HANDLE(obj);
if (_soundVersion <= SCI_VERSION_0_LATE) {
_state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
_state->sfx_song_set_loops(handle, readSelectorValue(_segMan, obj, SELECTOR(loop)));
writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundPlaying);
} else if (_soundVersion == SCI_VERSION_1_EARLY) {
_state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
_state->sfx_song_set_loops(handle, readSelectorValue(_segMan, obj, SELECTOR(loop)));
_state->sfx_song_renice(handle, readSelectorValue(_segMan, obj, SELECTOR(pri)));
RESTORE_BEHAVIOR rb = (RESTORE_BEHAVIOR) value; /* Too lazy to look up a default value for this */
_state->_songlib.setSongRestoreBehavior(handle, rb);
writeSelectorValue(_segMan, obj, SELECTOR(signal), 0);
} else if (_soundVersion == SCI_VERSION_1_LATE) {
int looping = readSelectorValue(_segMan, obj, SELECTOR(loop));
//int vol = readSelectorValue(_segMan, obj, SELECTOR(vol));
int pri = readSelectorValue(_segMan, obj, SELECTOR(pri));
int sampleLen = 0;
Song *song = _state->_songlib.findSong(handle);
int songNumber = readSelectorValue(_segMan, obj, SELECTOR(number));
if (readSelectorValue(_segMan, obj, SELECTOR(nodePtr)) && (song && songNumber != song->_resourceNum)) {
_state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
_state->sfx_remove_song(handle);
writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG);
}
if (!readSelectorValue(_segMan, obj, SELECTOR(nodePtr)) && obj.segment) {
// In SCI1.1 games, sound effects are started from here. If we can
// find a relevant audio resource, play it, otherwise switch to
// synthesized effects. If the resource exists, play it using map
// 65535 (sound effects map).
if (_resMan->testResource(ResourceId(kResourceTypeAudio, songNumber)) &&
getSciVersion() >= SCI_VERSION_1_1) {
// Found a relevant audio resource, play it
_audio->stopAudio();
warning("Initializing audio resource instead of requested sound resource %d", songNumber);
sampleLen = _audio->startAudio(65535, songNumber);
// Also create iterator, that will fire SI_FINISHED event, when
// the sound is done playing.
_state->sfx_add_song(new_timer_iterator(sampleLen), 0, handle, songNumber);
} else {
if (!_resMan->testResource(ResourceId(kResourceTypeSound, songNumber))) {
warning("Could not open song number %d", songNumber);
// Send a "stop handle" event so that the engine won't wait
// forever here.
_state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
return;
}
debugC(2, kDebugLevelSound, "Initializing song number %d", songNumber);
_state->sfx_add_song(build_iterator(_resMan, songNumber, SCI_SONG_ITERATOR_TYPE_SCI1,
handle), 0, handle, songNumber);
}
writeSelector(_segMan, obj, SELECTOR(nodePtr), obj);
writeSelector(_segMan, obj, SELECTOR(handle), obj);
}
if (obj.segment) {
_state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING);
_state->sfx_song_set_loops(handle, looping);
_state->sfx_song_renice(handle, pri);
writeSelectorValue(_segMan, obj, SELECTOR(signal), 0);
}
}
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
warning("cmdPlaySound: Slot not found (%04x:%04x)", PRINT_REG(obj)); warning("cmdPlaySound: Slot not found (%04x:%04x)", PRINT_REG(obj));
@ -456,43 +248,16 @@ void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) {
musicSlot->loop, musicSlot->priority, musicSlot->volume); musicSlot->loop, musicSlot->priority, musicSlot->volume);
_music->soundPlay(musicSlot); _music->soundPlay(musicSlot);
#endif
} }
void SoundCommandParser::cmdDummy(reg_t obj, int16 value) { void SoundCommandParser::cmdDummy(reg_t obj, int16 value) {
warning("cmdDummy invoked"); // not supposed to occur warning("cmdDummy invoked"); // not supposed to occur
} }
#ifdef USE_OLD_MUSIC_FUNCTIONS
void SoundCommandParser::changeSoundStatus(reg_t obj, int newStatus) {
SongHandle handle = FROBNICATE_HANDLE(obj);
if (obj.segment) {
_state->sfx_song_set_status(handle, newStatus);
if (_soundVersion <= SCI_VERSION_0_LATE)
writeSelectorValue(_segMan, obj, SELECTOR(state), newStatus);
}
}
#endif
void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) { void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) {
if (!obj.segment) if (!obj.segment)
return; return;
#ifdef USE_OLD_MUSIC_FUNCTIONS
SongHandle handle = FROBNICATE_HANDLE(obj);
changeSoundStatus(obj, SOUND_STATUS_STOPPED);
if (obj.segment) {
_state->sfx_remove_song(handle);
if (_soundVersion <= SCI_VERSION_0_LATE)
writeSelectorValue(_segMan, obj, SELECTOR(handle), 0x0000);
}
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
warning("cmdDisposeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); warning("cmdDisposeSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
@ -507,7 +272,6 @@ void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) {
writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG); writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG);
else else
writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped); writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped);
#endif
} }
void SoundCommandParser::cmdStopSound(reg_t obj, int16 value) { void SoundCommandParser::cmdStopSound(reg_t obj, int16 value) {
@ -518,12 +282,6 @@ void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFin
if (!obj.segment) if (!obj.segment)
return; return;
#ifdef USE_OLD_MUSIC_FUNCTIONS
changeSoundStatus(obj, SOUND_STATUS_STOPPED);
if (_soundVersion >= SCI_VERSION_1_EARLY)
writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
warning("cmdStopSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); warning("cmdStopSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
@ -549,20 +307,9 @@ void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFin
musicSlot->dataInc = 0; musicSlot->dataInc = 0;
musicSlot->signal = 0; musicSlot->signal = 0;
_music->soundStop(musicSlot); _music->soundStop(musicSlot);
#endif
} }
void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) { void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) {
#ifdef USE_OLD_MUSIC_FUNCTIONS
if (!obj.segment)
return;
if (_soundVersion <= SCI_VERSION_0_LATE)
changeSoundStatus(obj, SOUND_STATUS_SUSPENDED);
else
changeSoundStatus(obj, value ? SOUND_STATUS_SUSPENDED : SOUND_STATUS_PLAYING);
#else
if (!obj.segment) { // pause the whole playlist if (!obj.segment) { // pause the whole playlist
// Pausing/Resuming the whole playlist was introduced in the SCI1 late // Pausing/Resuming the whole playlist was introduced in the SCI1 late
// sound scheme. // sound scheme.
@ -585,8 +332,6 @@ void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) {
_music->soundToggle(musicSlot, value); _music->soundToggle(musicSlot, value);
} }
} }
#endif
} }
void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) { void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) {
@ -595,9 +340,6 @@ void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) {
if (!obj.segment) if (!obj.segment)
return; return;
#ifdef USE_OLD_MUSIC_FUNCTIONS
changeSoundStatus(obj, SOUND_STATUS_PLAYING);
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
warning("cmdResumeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); warning("cmdResumeSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
@ -606,24 +348,15 @@ void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) {
writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying); writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying);
_music->soundResume(musicSlot); _music->soundResume(musicSlot);
#endif
} }
void SoundCommandParser::cmdMuteSound(reg_t obj, int16 value) { void SoundCommandParser::cmdMuteSound(reg_t obj, int16 value) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
if (_argc > 1) // the first parameter is the sound command if (_argc > 1) // the first parameter is the sound command
_music->soundSetSoundOn(obj.toUint16()); _music->soundSetSoundOn(obj.toUint16());
_acc = make_reg(0, _music->soundGetSoundOn()); _acc = make_reg(0, _music->soundGetSoundOn());
#endif
} }
void SoundCommandParser::cmdMasterVolume(reg_t obj, int16 value) { void SoundCommandParser::cmdMasterVolume(reg_t obj, int16 value) {
#ifdef USE_OLD_MUSIC_FUNCTIONS
_acc = make_reg(0, _state->sfx_getVolume());
if (obj != SIGNAL_REG)
_state->sfx_setVolume(obj.toSint16());
#else
debugC(2, kDebugLevelSound, "cmdMasterVolume: %d", value); debugC(2, kDebugLevelSound, "cmdMasterVolume: %d", value);
_acc = make_reg(0, _music->soundGetMasterVolume()); _acc = make_reg(0, _music->soundGetMasterVolume());
@ -634,44 +367,12 @@ void SoundCommandParser::cmdMasterVolume(reg_t obj, int16 value) {
ConfMan.setInt("sfx_volume", vol); ConfMan.setInt("sfx_volume", vol);
g_engine->syncSoundSettings(); g_engine->syncSoundSettings();
} }
#endif
} }
void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) {
if (!obj.segment) if (!obj.segment)
return; return;
#ifdef USE_OLD_MUSIC_FUNCTIONS
SongHandle handle = FROBNICATE_HANDLE(obj);
if (_soundVersion != SCI_VERSION_1_LATE) {
/* FIXME: The next couple of lines actually STOP the handle, rather
** than fading it! */
_state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
if (_soundVersion <= SCI_VERSION_0_LATE)
writeSelectorValue(_segMan, obj, SELECTOR(state), SOUND_STATUS_STOPPED);
writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
} else {
fade_params_t fade;
fade.final_volume = _argv[2].toUint16();
fade.ticks_per_step = _argv[3].toUint16();
fade.step_size = _argv[4].toUint16();
fade.action = _argv[5].toUint16() ?
FADE_ACTION_FADE_AND_STOP :
FADE_ACTION_FADE_AND_CONT;
_state->sfx_song_set_fade(handle, &fade);
/* FIXME: The next couple of lines actually STOP the handle, rather
** than fading it! */
if (_argv[5].toUint16()) {
writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
_state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
} else {
// FIXME: Support fade-and-continue. For now, send signal right away.
writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
}
}
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
warning("cmdFadeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); warning("cmdFadeSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
@ -711,28 +412,16 @@ void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) {
} }
debugC(2, kDebugLevelSound, "cmdFadeSound: to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); debugC(2, kDebugLevelSound, "cmdFadeSound: to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep);
#endif
} }
void SoundCommandParser::cmdGetPolyphony(reg_t obj, int16 value) { void SoundCommandParser::cmdGetPolyphony(reg_t obj, int16 value) {
#ifdef USE_OLD_MUSIC_FUNCTIONS
_acc = make_reg(0, _state->sfx_get_player_polyphony());
#else
_acc = make_reg(0, _music->soundGetVoices()); // Get the number of voices _acc = make_reg(0, _music->soundGetVoices()); // Get the number of voices
#endif
} }
void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) { void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) {
if (!obj.segment) if (!obj.segment)
return; return;
#ifdef USE_OLD_MUSIC_FUNCTIONS
SongHandle handle = FROBNICATE_HANDLE(obj);
if (_soundVersion <= SCI_VERSION_0_LATE && obj.segment) {
_state->sfx_song_set_loops(handle, readSelectorValue(_segMan, obj, SELECTOR(loop)));
script_set_priority(_resMan, _segMan, _state, obj, readSelectorValue(_segMan, obj, SELECTOR(pri)));
}
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
warning("cmdUpdateSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); warning("cmdUpdateSound: Slot not found (%04x:%04x)", PRINT_REG(obj));
@ -746,85 +435,12 @@ void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) {
uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(pri)); uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(pri));
if (objPrio != musicSlot->priority) if (objPrio != musicSlot->priority)
_music->soundSetPriority(musicSlot, objPrio); _music->soundSetPriority(musicSlot, objPrio);
#endif
} }
void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
if (!obj.segment) if (!obj.segment)
return; return;
#ifdef USE_OLD_MUSIC_FUNCTIONS
int signal = 0;
int min = 0;
int sec = 0;
int frame = 0;
int result = SI_LOOP; // small hack
SongHandle handle = FROBNICATE_HANDLE(obj);
while (result == SI_LOOP)
result = _state->sfx_poll_specific(handle, &signal);
switch (result) {
case SI_ABSOLUTE_CUE:
debugC(2, kDebugLevelSound, "--- [CUE] %04x:%04x Absolute Cue: %d",
PRINT_REG(obj), signal);
debugC(2, kDebugLevelSound, "abs-signal %04X", signal);
writeSelectorValue(_segMan, obj, SELECTOR(signal), signal);
break;
case SI_RELATIVE_CUE:
debugC(2, kDebugLevelSound, "--- [CUE] %04x:%04x Relative Cue: %d",
PRINT_REG(obj), signal);
/* FIXME to match commented-out semantics
* below, with proper storage of dataInc and
* signal in the iterator code. */
writeSelectorValue(_segMan, obj, SELECTOR(dataInc), signal);
debugC(2, kDebugLevelSound, "rel-signal %04X", signal);
if (_soundVersion == SCI_VERSION_1_EARLY)
writeSelectorValue(_segMan, obj, SELECTOR(signal), signal);
else
writeSelectorValue(_segMan, obj, SELECTOR(signal), signal + 127);
break;
case SI_FINISHED:
debugC(2, kDebugLevelSound, "--- [FINISHED] %04x:%04x", PRINT_REG(obj));
writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
break;
case SI_LOOP:
break; // Doesn't happen
}
//switch (signal) {
//case 0x00:
// if (dataInc != readSelectorValue(segMan, obj, SELECTOR(dataInc))) {
// writeSelectorValue(segMan, obj, SELECTOR(dataInc), dataInc);
// writeSelectorValue(segMan, obj, SELECTOR(signal), dataInc+0x7f);
// } else {
// writeSelectorValue(segMan, obj, SELECTOR(signal), signal);
// }
// break;
//case 0xFF: // May be unnecessary
// s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
// break;
//default :
// if (dataInc != readSelectorValue(segMan, obj, SELECTOR(dataInc))) {
// writeSelectorValue(segMan, obj, SELECTOR(dataInc), dataInc);
// writeSelectorValue(segMan, obj, SELECTOR(signal), dataInc + 0x7f);
// } else {
// writeSelectorValue(segMan, obj, SELECTOR(signal), signal);
// }
// break;
//}
if (_soundVersion == SCI_VERSION_1_EARLY) {
writeSelectorValue(_segMan, obj, SELECTOR(min), min);
writeSelectorValue(_segMan, obj, SELECTOR(sec), sec);
writeSelectorValue(_segMan, obj, SELECTOR(frame), frame);
}
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
warning("cmdUpdateCues: Slot not found (%04x:%04x)", PRINT_REG(obj)); warning("cmdUpdateCues: Slot not found (%04x:%04x)", PRINT_REG(obj));
@ -900,15 +516,9 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60); writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60);
writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker); writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker);
} }
#endif
} }
void SoundCommandParser::cmdSendMidi(reg_t obj, int16 value) { void SoundCommandParser::cmdSendMidi(reg_t obj, int16 value) {
#ifdef USE_OLD_MUSIC_FUNCTIONS
//SongHandle handle = FROBNICATE_HANDLE(obj);
//_state->sfx_send_midi(handle, value, _midiCmd, _controller, _param);
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
// TODO: maybe it's possible to call this with obj == 0:0 and send directly?! // TODO: maybe it's possible to call this with obj == 0:0 and send directly?!
@ -918,20 +528,13 @@ void SoundCommandParser::cmdSendMidi(reg_t obj, int16 value) {
return; return;
} }
_music->sendMidiCommand(musicSlot, _midiCommand); _music->sendMidiCommand(musicSlot, _midiCommand);
#endif
} }
void SoundCommandParser::cmdReverb(reg_t obj, int16 value) { void SoundCommandParser::cmdReverb(reg_t obj, int16 value) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->setReverb(obj.toUint16() & 0xF); _music->setReverb(obj.toUint16() & 0xF);
#endif
} }
void SoundCommandParser::cmdSetSoundHold(reg_t obj, int16 value) { void SoundCommandParser::cmdSetSoundHold(reg_t obj, int16 value) {
#ifdef USE_OLD_MUSIC_FUNCTIONS
SongHandle handle = FROBNICATE_HANDLE(obj);
_state->sfx_song_set_hold(handle, value);
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
warning("cmdSetSoundHold: Slot not found (%04x:%04x)", PRINT_REG(obj)); warning("cmdSetSoundHold: Slot not found (%04x:%04x)", PRINT_REG(obj));
@ -940,7 +543,6 @@ void SoundCommandParser::cmdSetSoundHold(reg_t obj, int16 value) {
// Set the special hold marker ID where the song should be looped at. // Set the special hold marker ID where the song should be looped at.
musicSlot->hold = value; musicSlot->hold = value;
#endif
} }
void SoundCommandParser::cmdGetAudioCapability(reg_t obj, int16 value) { void SoundCommandParser::cmdGetAudioCapability(reg_t obj, int16 value) {
@ -949,7 +551,6 @@ void SoundCommandParser::cmdGetAudioCapability(reg_t obj, int16 value) {
} }
void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) { void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
Common::StackLock(_music->_mutex); Common::StackLock(_music->_mutex);
const MusicList::iterator end = _music->getPlayListEnd(); const MusicList::iterator end = _music->getPlayListEnd();
@ -964,14 +565,12 @@ void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) {
(*i)->dataInc = 0; (*i)->dataInc = 0;
_music->soundStop(*i); _music->soundStop(*i);
} }
#endif
} }
void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) { void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) {
if (!obj.segment) if (!obj.segment)
return; return;
#ifndef USE_OLD_MUSIC_FUNCTIONS
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
// Do not throw a warning if the sound can't be found, as in some games // Do not throw a warning if the sound can't be found, as in some games
@ -991,16 +590,12 @@ void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) {
_music->soundSetVolume(musicSlot, value); _music->soundSetVolume(musicSlot, value);
writeSelectorValue(_segMan, obj, SELECTOR(vol), value); writeSelectorValue(_segMan, obj, SELECTOR(vol), value);
} }
#endif
} }
void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) { void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) {
if (!obj.segment) if (!obj.segment)
return; return;
#ifdef USE_OLD_MUSIC_FUNCTIONS
script_set_priority(_resMan, _segMan, _state, obj, value);
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
warning("cmdSetSoundPriority: Slot not found (%04x:%04x)", PRINT_REG(obj)); warning("cmdSetSoundPriority: Slot not found (%04x:%04x)", PRINT_REG(obj));
@ -1024,19 +619,12 @@ void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) {
writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2); writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2);
//DoSOund(0xF,hobj,w) //DoSOund(0xF,hobj,w)
} }
#endif
} }
void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) { void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) {
if (!obj.segment) if (!obj.segment)
return; return;
#ifdef USE_OLD_MUSIC_FUNCTIONS
if (!readSelector(_segMan, obj, SELECTOR(nodePtr)).isNull()) {
SongHandle handle = FROBNICATE_HANDLE(obj);
_state->sfx_song_set_loops(handle, value);
}
#else
MusicEntry *musicSlot = _music->getSlot(obj); MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) { if (!musicSlot) {
// Apparently, it's perfectly normal for a game to call cmdSetSoundLoop // Apparently, it's perfectly normal for a game to call cmdSetSoundLoop
@ -1058,7 +646,6 @@ void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) {
} }
writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop);
#endif
} }
void SoundCommandParser::cmdSuspendSound(reg_t obj, int16 value) { void SoundCommandParser::cmdSuspendSound(reg_t obj, int16 value) {
@ -1066,8 +653,6 @@ void SoundCommandParser::cmdSuspendSound(reg_t obj, int16 value) {
warning("STUB: cmdSuspendSound"); warning("STUB: cmdSuspendSound");
} }
#ifndef USE_OLD_MUSIC_FUNCTIONS
void SoundCommandParser::updateSci0Cues() { void SoundCommandParser::updateSci0Cues() {
bool noOnePlaying = true; bool noOnePlaying = true;
MusicEntry *pWaitingForPlay = NULL; MusicEntry *pWaitingForPlay = NULL;
@ -1101,34 +686,23 @@ void SoundCommandParser::updateSci0Cues() {
} }
} }
#endif
void SoundCommandParser::clearPlayList() { void SoundCommandParser::clearPlayList() {
#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->clearPlayList(); _music->clearPlayList();
#endif
} }
void SoundCommandParser::printPlayList(Console *con) { void SoundCommandParser::printPlayList(Console *con) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->printPlayList(con); _music->printPlayList(con);
#endif
} }
void SoundCommandParser::printSongInfo(reg_t obj, Console *con) { void SoundCommandParser::printSongInfo(reg_t obj, Console *con) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->printSongInfo(obj, con); _music->printSongInfo(obj, con);
#endif
} }
void SoundCommandParser::stopAllSounds() { void SoundCommandParser::stopAllSounds() {
#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->stopAll(); _music->stopAll();
#endif
} }
void SoundCommandParser::startNewSound(int number) { void SoundCommandParser::startNewSound(int number) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
Common::StackLock lock(_music->_mutex); Common::StackLock lock(_music->_mutex);
// Overwrite the first sound in the playlist // Overwrite the first sound in the playlist
@ -1138,19 +712,14 @@ void SoundCommandParser::startNewSound(int number) {
writeSelectorValue(_segMan, soundObj, SELECTOR(number), number); writeSelectorValue(_segMan, soundObj, SELECTOR(number), number);
cmdInitSound(soundObj, 0); cmdInitSound(soundObj, 0);
cmdPlaySound(soundObj, 0); cmdPlaySound(soundObj, 0);
#endif
} }
void SoundCommandParser::setMasterVolume(int vol) { void SoundCommandParser::setMasterVolume(int vol) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->soundSetMasterVolume(vol); _music->soundSetMasterVolume(vol);
#endif
} }
void SoundCommandParser::pauseAll(bool pause) { void SoundCommandParser::pauseAll(bool pause) {
#ifndef USE_OLD_MUSIC_FUNCTIONS
_music->pauseAll(pause); _music->pauseAll(pause);
#endif
} }
} // End of namespace Sci } // End of namespace Sci

View file

@ -26,8 +26,6 @@
#ifndef SCI_SOUNDCMD_H #ifndef SCI_SOUNDCMD_H
#define SCI_SOUNDCMD_H #define SCI_SOUNDCMD_H
#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
#include "common/list.h" #include "common/list.h"
#include "sci/engine/state.h" #include "sci/engine/state.h"
@ -53,10 +51,6 @@ public:
kMaxSciVolume = 15 kMaxSciVolume = 15
}; };
#ifdef USE_OLD_MUSIC_FUNCTIONS
void updateSfxState(SfxState *newState) { _state = newState; }
#endif
reg_t parseCommand(int argc, reg_t *argv, reg_t acc); reg_t parseCommand(int argc, reg_t *argv, reg_t acc);
// Functions used for game state loading // Functions used for game state loading
@ -76,7 +70,6 @@ public:
void printPlayList(Console *con); void printPlayList(Console *con);
void printSongInfo(reg_t obj, Console *con); void printSongInfo(reg_t obj, Console *con);
#ifndef USE_OLD_MUSIC_FUNCTIONS
/** /**
* Synchronizes the current state of the music list to the rest of the engine, so that * Synchronizes the current state of the music list to the rest of the engine, so that
* the changes that the sound thread makes to the music are registered with the engine * the changes that the sound thread makes to the music are registered with the engine
@ -85,7 +78,6 @@ public:
* by the engine scripts themselves, so the engine itself polls for changes to the music * by the engine scripts themselves, so the engine itself polls for changes to the music
*/ */
void updateSci0Cues(); void updateSci0Cues();
#endif
private: private:
typedef Common::Array<MusicEntryCommand *> SoundCommandContainer; typedef Common::Array<MusicEntryCommand *> SoundCommandContainer;
@ -93,12 +85,7 @@ private:
ResourceManager *_resMan; ResourceManager *_resMan;
SegManager *_segMan; SegManager *_segMan;
Kernel *_kernel; Kernel *_kernel;
#ifdef USE_OLD_MUSIC_FUNCTIONS
SfxState *_state;
int _midiCmd, _controller, _param;
#else
SciMusic *_music; SciMusic *_music;
#endif
AudioPlayer *_audio; AudioPlayer *_audio;
SciVersion _soundVersion; SciVersion _soundVersion;
int _argc; int _argc;
@ -131,10 +118,6 @@ private:
void cmdSuspendSound(reg_t obj, int16 value); void cmdSuspendSound(reg_t obj, int16 value);
void processStopSound(reg_t obj, int16 value, bool sampleFinishedPlaying); void processStopSound(reg_t obj, int16 value, bool sampleFinishedPlaying);
#ifdef USE_OLD_MUSIC_FUNCTIONS
void changeSoundStatus(reg_t obj, int newStatus);
#endif
}; };
} // End of namespace Sci } // End of namespace Sci