int32 Sound::playCompSpeech(uint32 speechId, uint8 vol, int8 pan) { if (_speechMuted) return RD_OK; if (getSpeechStatus() == RDERR_SPEECHPLAYING) return RDERR_SPEECHPLAYING; int cd = _vm->_resman->getCD(); SoundFileHandle *fh = (cd == 1) ? &_speechFile[0] : &_speechFile[1]; Audio::AudioStream *input = getAudioStream(fh, "speech", cd, speechId, NULL); if (!input) return RDERR_INVALIDID; // Modify the volume according to the master volume byte volume = _speechMuted ? 0 : vol * Audio::Mixer::kMaxChannelVolume / 16; int8 p = (pan * 127) / 16; if (isReverseStereo()) p = -p; // Start the speech playing _vm->_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandleSpeech, input, -1, volume, p); return RD_OK; }
void Sound::playMovieSound(int32 res, int type) { Audio::SoundHandle *handle; if (type == kLeadInSound) handle = &_leadInHandle; else handle = &_leadOutHandle; if (_vm->_mixer->isSoundHandleActive(*handle)) { _vm->_mixer->stopHandle(*handle); } byte *data = _vm->_resman->openResource(res); uint32 len = _vm->_resman->fetchLen(res); assert(_vm->_resman->fetchType(data) == WAV_FILE); // We want to close the resource right away, so to be safe we make a // private copy of the sound; byte *soundData = (byte *)malloc(len); if (soundData) { memcpy(soundData, data, len); Common::MemoryReadStream *stream = new Common::MemoryReadStream(soundData, len, DisposeAfterUse::YES); // In PSX version we have nothing to skip here, as data starts // right away. if (!Sword2Engine::isPsx()) { stream->seek(ResHeader::size()); } Audio::RewindableAudioStream *input = 0; if (Sword2Engine::isPsx()) { input = Audio::makeVagStream(stream); } else { input = Audio::makeWAVStream(stream, DisposeAfterUse::YES); } _vm->_mixer->playStream( Audio::Mixer::kMusicSoundType, handle, input, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES, false, isReverseStereo()); } else { warning("Sound::playMovieSound: Could not allocate %d bytes\n", len); } _vm->_resman->closeResource(res); }
int32 Sound::setFxIdVolumePan(int32 id, int vol, int pan) { if (!_fxQueue[id].resource) return RDERR_FXNOTOPEN; if (vol > 16) vol = 16; _fxQueue[id].volume = (vol * Audio::Mixer::kMaxChannelVolume) / 16; if (pan != 255) { if (isReverseStereo()) pan = -pan; _fxQueue[id].pan = (pan * 127) / 16; } if (!_fxMuted && _vm->_mixer->isSoundHandleActive(_fxQueue[id].handle)) { _vm->_mixer->setChannelVolume(_fxQueue[id].handle, _fxQueue[id].volume); if (pan != -1) _vm->_mixer->setChannelBalance(_fxQueue[id].handle, _fxQueue[id].pan); } return RD_OK; }
int32 Sound::playFx(Audio::SoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, Audio::Mixer::SoundType soundType) { if (_fxMuted) return RD_OK; if (_vm->_mixer->isSoundHandleActive(*handle)) return RDERR_FXALREADYOPEN; Common::MemoryReadStream *stream = new Common::MemoryReadStream(data, len); Audio::RewindableAudioStream *input = 0; if (Sword2Engine::isPsx()) input = Audio::makeVagStream(stream); else input = Audio::makeWAVStream(stream, DisposeAfterUse::YES); assert(input); _vm->_mixer->playStream(soundType, handle, Audio::makeLoopingAudioStream(input, loop ? 0 : 1), -1, vol, pan, DisposeAfterUse::YES, false, isReverseStereo()); return RD_OK; }
void Sound::queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan) { if (_vm->_wantSfxDebug) { const char *typeStr; switch (type) { case FX_SPOT: typeStr = "SPOT"; break; case FX_LOOP: typeStr = "LOOPED"; break; case FX_RANDOM: typeStr = "RANDOM"; break; default: typeStr = "INVALID"; break; } debug(0, "SFX (sample=\"%s\", vol=%d, pan=%d, delay=%d, type=%s)", _vm->_resman->fetchName(res), volume, pan, delay, typeStr); } for (int i = 0; i < FXQ_LENGTH; i++) { if (!_fxQueue[i].resource) { byte *data = _vm->_resman->openResource(res); // Check that we really have a WAV file here, alas this // check is useless with psx demo game, because psx audio files // are headerless and there is no way to check the type if (!(Sword2Engine::isPsx() && (_vm->_features & GF_DEMO))) assert(_vm->_resman->fetchType(data) == WAV_FILE); uint32 len = _vm->_resman->fetchLen(res); // Skip the header if using PC version if (!Sword2Engine::isPsx()) len -= ResHeader::size(); if (type == FX_RANDOM) { // For spot effects and loops the delay is the // number of frames to wait. For random // effects, however, it's the average number of // seconds between playing the sound, so we // have to multiply by the frame rate. delay *= FRAMES_PER_SECOND; } volume = (volume * Audio::Mixer::kMaxChannelVolume) / 16; pan = (pan * 127) / 16; if (isReverseStereo()) pan = -pan; _fxQueue[i].resource = res; if (Sword2Engine::isPsx()) _fxQueue[i].data = data; else _fxQueue[i].data = data + ResHeader::size(); _fxQueue[i].len = len; _fxQueue[i].delay = delay; _fxQueue[i].volume = volume; _fxQueue[i].pan = pan; _fxQueue[i].type = type; // Keep track of the index in the loop so that // fnStopFx() can be used later to kill this sound. // Mainly for FX_LOOP and FX_RANDOM. _vm->_logic->writeVar(RESULT, i); return; } } warning("No free slot in FX queue"); }