SCI: Removed the FreeSCI music code
svn-id: r50532
This commit is contained in:
parent
a14c6d7815
commit
bff3e89e48
21 changed files with 4 additions and 4966 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 = ¬_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 == ¬_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
|
|
|
@ -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
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue