Moved the audio CD handling code inside the AudioPlayer class. Some cleanup

svn-id: r45656
This commit is contained in:
Filippos Karapetis 2009-11-04 11:22:46 +00:00
parent 2dbf6662fc
commit 7d00c4a7f1
5 changed files with 105 additions and 70 deletions

View File

@ -30,8 +30,6 @@
#include "sci/engine/kernel.h"
#include "sci/engine/vm.h" // for Object
#include "sound/audiocd.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
namespace Sci {
@ -1028,60 +1026,17 @@ reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) {
switch (argv[0].toUint16()) {
case kSciAudioWPlay:
case kSciAudioPlay: {
if (getSciVersion() == SCI_VERSION_1_1) {
// King's Quest VI CD Audio format
if (argc < 2)
return NULL_REG;
if (argc < 2)
return NULL_REG;
uint16 track = argv[1].toUint16() - 1;
uint32 startFrame = 0;
uint32 totalFrames = 0;
uint16 track = argv[1].toUint16() - 1;
uint32 startFrame = (argc > 2) ? argv[2].toUint16() * 75 : 0;
uint32 totalFrames = (argc > 3) ? argv[3].toUint16() * 75 : 0;
if (argc > 2)
startFrame = argv[2].toUint16() * 75;
if (argc > 3)
totalFrames = argv[3].toUint16() * 75;
AudioCD.play(track, 1, startFrame, totalFrames);
return make_reg(0, 1);
} else {
// Jones in the Fast Lane CD Audio format
if (argc != 2)
error("kDoCdAudio(%d) called with %d args", argv[0].toUint16(), argc);
AudioCD.stop();
Common::File audioMap;
if(!audioMap.open("cdaudio.map"))
error("Could not open cdaudio.map");
uint16 sample = argv[1].toUint16();
uint32 length = 0;
while (audioMap.pos() < audioMap.size()) {
uint16 res = audioMap.readUint16LE();
uint32 startFrame = audioMap.readUint16LE();
startFrame += audioMap.readByte() << 16;
audioMap.readByte(); // Unknown, always 0x20
length = audioMap.readUint16LE();
length += audioMap.readByte() << 16;
audioMap.readByte(); // Unknown, always 0x00
if (res == sample) {
AudioCD.play(1, 1, startFrame, length);
s->_audioCdStart = g_system->getMillis();
break;
}
}
audioMap.close();
return make_reg(0, length * 60 / 75); // return sample length in ticks
}
return make_reg(0, s->_audio->audioCdPlay(track, startFrame, totalFrames));
}
case kSciAudioStop:
AudioCD.stop();
s->_audio->audioCdStop();
if (getSciVersion() == SCI_VERSION_1_1)
return make_reg(0, 1);
@ -1093,15 +1048,10 @@ reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) {
case kSciAudioResume:
// This seems to be hacked up to update the CD instead of resuming
// audio like kDoAudio does.
AudioCD.updateCD();
s->_audio->audioCdUpdate();
break;
case kSciAudioPosition:
// Return -1 if the sample is done playing. Converting to frames to compare.
if (((g_system->getMillis() - s->_audioCdStart) * 75 / 1000) >= (uint32)AudioCD.getStatus().duration)
return SIGNAL_REG;
// Return the position otherwise (in ticks).
return make_reg(0, (g_system->getMillis() - s->_audioCdStart) * 60 / 1000);
return make_reg(0, s->_audio->audioCdPosition());
case kSciAudioRate: // No need to set the audio rate
case kSciAudioVolume: // The speech setting isn't used by CD Audio
case kSciAudioLanguage: // No need to set the language

View File

@ -110,7 +110,6 @@ EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc,
_gfxFunctionsType = SCI_VERSION_AUTODETECT;
_moveCountType = kMoveCountUninitialized;
_audioCdStart = 0;
_usesCdTrack = Common::File::exists("cdaudio.map");
}

View File

@ -286,8 +286,7 @@ public:
EngineState *successor; /**< Successor of this state: Used for restoring */
Common::String getLanguageString(const char *str, kLanguage lang) const;
uint32 _audioCdStart;
private:
SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType;
MoveCountType _moveCountType;

View File

@ -31,17 +31,26 @@
#include "common/system.h"
#include "sound/audiostream.h"
#include "sound/audiocd.h"
#include "sound/mixer.h"
namespace Sci {
AudioPlayer::AudioPlayer(ResourceManager *resMan) : _resMan(resMan), _audioRate(11025),
_syncResource(NULL), _syncOffset(0) {
_syncResource(NULL), _syncOffset(0), _audioCdStart(0) {
_mixer = g_system->getMixer();
}
AudioPlayer::~AudioPlayer() {
stopAllAudio();
}
void AudioPlayer::stopAllAudio() {
stopSoundSync();
stopAudio();
if (_audioCdStart > 0)
audioCdStop();
}
int AudioPlayer::startAudio(uint16 module, uint32 number) {
@ -49,16 +58,28 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) {
Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen);
if (audioStream) {
g_system->getMixer()->playInputStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream);
_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream);
return sampleLen;
}
return 0;
}
void AudioPlayer::stopAudio() {
_mixer->stopHandle(_audioHandle);
}
void AudioPlayer::pauseAudio() {
_mixer->pauseHandle(_audioHandle, true);
}
void AudioPlayer::resumeAudio() {
_mixer->pauseHandle(_audioHandle, false);
}
int AudioPlayer::getAudioPosition() {
if (g_system->getMixer()->isSoundHandleActive(_audioHandle))
return g_system->getMixer()->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks
if (_mixer->isSoundHandleActive(_audioHandle))
return _mixer->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks
else
return -1; // Sound finished
}
@ -261,4 +282,60 @@ void AudioPlayer::stopSoundSync() {
}
}
int AudioPlayer::audioCdPlay(int track, int start, int duration) {
if (getSciVersion() == SCI_VERSION_1_1) {
// King's Quest VI CD Audio format
_audioCdStart = g_system->getMillis();
AudioCD.play(track, 1, start, duration);
return 1;
} else {
// Jones in the Fast Lane CD Audio format
uint32 length = 0;
audioCdStop();
Common::File audioMap;
if(!audioMap.open("cdaudio.map"))
error("Could not open cdaudio.map");
while (audioMap.pos() < audioMap.size()) {
uint16 res = audioMap.readUint16LE();
uint32 startFrame = audioMap.readUint16LE();
startFrame += audioMap.readByte() << 16;
audioMap.readByte(); // Unknown, always 0x20
length = audioMap.readUint16LE();
length += audioMap.readByte() << 16;
audioMap.readByte(); // Unknown, always 0x00
if (res == track) {
AudioCD.play(1, 1, startFrame, length);
_audioCdStart = g_system->getMillis();
break;
}
}
audioMap.close();
return length * 60 / 75; // return sample length in ticks
}
}
void AudioPlayer::audioCdStop() {
_audioCdStart = 0;
AudioCD.stop();
}
void AudioPlayer::audioCdUpdate() {
AudioCD.updateCD();
}
int AudioPlayer::audioCdPosition() {
// Return -1 if the sample is done playing. Converting to frames to compare.
if (((g_system->getMillis() - _audioCdStart) * 75 / 1000) >= (uint32)AudioCD.getStatus().duration)
return -1;
// Return the position otherwise (in ticks).
return (g_system->getMillis() - _audioCdStart) * 60 / 1000;
}
} // End of namespace Sci

View File

@ -41,21 +41,31 @@ public:
Audio::SoundHandle* getAudioHandle() { return &_audioHandle; }
int getAudioPosition();
int startAudio(uint16 module, uint32 tuple);
void stopAudio() { g_system->getMixer()->stopHandle(_audioHandle); }
void pauseAudio() { g_system->getMixer()->pauseHandle(_audioHandle, true); }
void resumeAudio() { g_system->getMixer()->pauseHandle(_audioHandle, false); }
void stopAudio();
void pauseAudio();
void resumeAudio();
void setSoundSync(ResourceId id, reg_t syncObjAddr, SegManager *segMan);
void doSoundSync(reg_t syncObjAddr, SegManager *segMan);
void stopSoundSync();
int audioCdPlay(int track, int start, int duration);
void audioCdStop();
void audioCdUpdate();
int audioCdPosition();
void stopAllAudio();
private:
ResourceManager *_resMan;
uint16 _audioRate;
Audio::SoundHandle _audioHandle;
Audio::AudioStream* getAudioStream(uint32 number, uint32 volume, int *sampleLen);
Audio::Mixer* _mixer;
Resource *_syncResource; /**< Used by kDoSync for speech syncing in CD talkie games */
uint _syncOffset;
uint32 _audioCdStart;
Audio::AudioStream* getAudioStream(uint32 number, uint32 volume, int *sampleLen);
};
} // End of namespace Sci