Beispiel #1
0
void Imuse::switchToNextRegion(Track *track) {
	assert(track);

	if (track->trackId >= MAX_IMUSE_TRACKS) {
		if (gDebugLevel == DEBUG_IMUSE || gDebugLevel == DEBUG_ALL)
			printf("Imuse::switchToNextRegion(): fadeTrack end: soundName:%s\n", track->soundName);
		flushTrack(track);
		return;
	}

	int numRegions = _sound->getNumRegions(track->soundDesc);

	if (++track->curRegion == numRegions) {
		if (gDebugLevel == DEBUG_IMUSE || gDebugLevel == DEBUG_ALL)
			printf("Imuse::switchToNextRegion(): end of tracks: soundName:%s\n", track->soundName);
		flushTrack(track);
		return;
	}

	ImuseSndMgr::SoundDesc *soundDesc = track->soundDesc;
	int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);
	if (jumpId == -1)
		jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, 0);
	if (jumpId != -1) {
		if (gDebugLevel == DEBUG_IMUSE || gDebugLevel == DEBUG_ALL)
			printf("Imuse::switchToNextRegion(): JUMP: soundName:%s\n", track->soundName);
		int region = _sound->getRegionIdByJumpId(soundDesc, jumpId);
		assert(region != -1);
		int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);
		assert(sampleHookId != -1);
		int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;
		if (fadeDelay) {
			Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
			if (fadeTrack) {
				fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
				fadeTrack->regionOffset = 0;
				fadeTrack->curHookId = 0;
			}
		}
		track->curRegion = region;
		if (track->curHookId == sampleHookId)
			track->curHookId = 0;
		else
			if (track->curHookId == 0x80)
				track->curHookId = 0;
	}

	if (gDebugLevel == DEBUG_IMUSE || gDebugLevel == DEBUG_ALL)
		printf("Imuse::switchToNextRegion(): REGION %d: soundName:%s\n", (int)track->curRegion, track->soundName);
	track->dataOffset = _sound->getRegionOffset(soundDesc, track->curRegion);
	track->regionOffset = 0;
}
Beispiel #2
0
void Imuse::switchToNextRegion(Track *track) {
	assert(track);

	if (track->trackId >= MAX_IMUSE_TRACKS) {
		Debug::debug(Debug::Imuse, "Imuse::switchToNextRegion(): fadeTrack end: soundName:%s", track->soundName);
		flushTrack(track);
		return;
	}

	int numRegions = _sound->getNumRegions(track->soundDesc);

	if (++track->curRegion == numRegions) {
		Debug::debug(Debug::Imuse, "Imuse::switchToNextRegion(): end of tracks: soundName:%s", track->soundName);
		flushTrack(track);
		return;
	}

	ImuseSndMgr::SoundDesc *soundDesc = track->soundDesc;
	int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);
	// It seems 128 is a special value meaning it should not force the 0 hookId,
	// otherwise the sound hkwine.imu when glottis drinks the wine in the barrel
	// in hk won't stop.
	if (jumpId == -1 && track->curHookId != 128)
		jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, 0);
	if (jumpId != -1) {
		Debug::debug(Debug::Imuse, "Imuse::switchToNextRegion(): JUMP: soundName:%s", track->soundName);
		int region = _sound->getRegionIdByJumpId(soundDesc, jumpId);
		assert(region != -1);
		int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);
		assert(sampleHookId != -1);
		int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;
		if (fadeDelay) {
			Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
			if (fadeTrack) {
				fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
				fadeTrack->regionOffset = 0;
				fadeTrack->curHookId = 0;
			}
		}
		track->curRegion = region;
		if (track->curHookId == sampleHookId)
			track->curHookId = 0;
		else
			if (track->curHookId == 0x80)
				track->curHookId = 0;
	}

	Debug::debug(Debug::Imuse, "Imuse::switchToNextRegion(): REGION %d: soundName:%s", (int)track->curRegion, track->soundName);
	track->dataOffset = _sound->getRegionOffset(soundDesc, track->curRegion);
	track->regionOffset = 0;
}
Beispiel #3
0
Track *Imuse::moveToFadeOutTrack(Track *track, int fadeDelay) {
	assert(track);
	Track *fadeTrack;

	if (track->toBeRemoved) {
		error("moveToFadeOutTrack: Tried to move a track to be removed, please bug report");
		return NULL;
	}

	// Clamp fade time to remaining time in the current region
	if (track->curRegion != -1) {
		int remainingLen = _sound->getRegionLength(track->soundDesc, track->curRegion) - track->regionOffset;
		int remainingTime = (remainingLen * 60) / track->feedSize;
		if (fadeDelay > remainingTime) {
			fadeDelay = remainingTime;
		}
	}

	if (fadeDelay <= 0) {
		flushTrack(track);
		return NULL;
	}

	assert(track->trackId < MAX_IMUSE_TRACKS);
	fadeTrack = _track[track->trackId + MAX_IMUSE_TRACKS];

	if (fadeTrack->used) {
		flushTrack(fadeTrack);
		g_system->getMixer()->stopHandle(fadeTrack->handle);
	}

	// Clone the settings of the given track
	memcpy(fadeTrack, track, sizeof(Track));
	fadeTrack->trackId = track->trackId + MAX_IMUSE_TRACKS;

	// Reset the track
	memset(track, 0, sizeof(Track));

	// Mark as used for now so the track won't be reused again this frame
	track->used = true;

	// Set the volume fading parameters to indicate a fade out
	fadeTrack->volFadeDelay = fadeDelay;
	fadeTrack->volFadeDest = 0;
	fadeTrack->volFadeStep = (fadeTrack->volFadeDest - fadeTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * fadeDelay);
	fadeTrack->volFadeUsed = true;

	fadeTrack->used = true;

	return fadeTrack;
}
Beispiel #4
0
void IMuseDigital::stopSound(int soundId) {
	Common::StackLock lock(_mutex, "IMuseDigital::stopSound()");
	debug(5, "IMuseDigital::stopSound(%d)", soundId);
	for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
		Track *track = _track[l];
		if (track->used && !track->toBeRemoved && (track->soundId == soundId)) {
			debug(5, "IMuseDigital::stopSound(%d) - stopping sound", soundId);
			flushTrack(track);
		}
	}
}
Beispiel #5
0
void IMuseDigital::fadeOutMusic(int fadeDelay) {
	Common::StackLock lock(_mutex, "IMuseDigital::fadeOutMusic()");
	debug(5, "IMuseDigital::fadeOutMusic(fade:%d)", fadeDelay);

	for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
		Track *track = _track[l];
		if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
			debug(5, "IMuseDigital::fadeOutMusic(fade:%d, sound:%d)", fadeDelay, track->soundId);
			cloneToFadeOutTrack(track, fadeDelay);
			flushTrack(track);
			break;
		}
	}
}
Beispiel #6
0
Track *IMuseDigital::cloneToFadeOutTrack(Track *track, int fadeDelay) {
	assert(track);
	Track *fadeTrack;

	debug(5, "cloneToFadeOutTrack(soundId:%d, fade:%d) - begin of func", track->trackId, fadeDelay);

	if (track->toBeRemoved) {
		error("cloneToFadeOutTrack: Tried to clone a track to be removed, please bug report");
		return NULL;
	}

	assert(track->trackId < MAX_DIGITAL_TRACKS);
	fadeTrack = _track[track->trackId + MAX_DIGITAL_TRACKS];

	if (fadeTrack->used) {
		debug(5, "cloneToFadeOutTrack: No free fade track, force flush fade soundId:%d", fadeTrack->soundId);
		flushTrack(fadeTrack);
		_mixer->stopHandle(fadeTrack->mixChanHandle);
	}

	// Clone the settings of the given track
	memcpy(fadeTrack, track, sizeof(Track));
	fadeTrack->trackId = track->trackId + MAX_DIGITAL_TRACKS;

	// Clone the sound.
	// leaving bug number for now #1635361
	ImuseDigiSndMgr::SoundDesc *soundDesc = _sound->cloneSound(track->soundDesc);
	if (!soundDesc) {
		// it fail load open old song after switch to diffrent CDs
		// so gave up
		error("Game not supported while playing on 2 diffrent CDs");
	}
	track->soundDesc = soundDesc;

	// Set the volume fading parameters to indicate a fade out
	fadeTrack->volFadeDelay = fadeDelay;
	fadeTrack->volFadeDest = 0;
	fadeTrack->volFadeStep = (fadeTrack->volFadeDest - fadeTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * fadeDelay);
	fadeTrack->volFadeUsed = true;

	// Create an appendable output buffer
	fadeTrack->stream = Audio::makeQueuingAudioStream(_sound->getFreq(fadeTrack->soundDesc), track->mixerFlags & kFlagStereo);
	_mixer->playStream(track->getType(), &fadeTrack->mixChanHandle, fadeTrack->stream, -1, fadeTrack->getVol(), fadeTrack->getPan());
	fadeTrack->used = true;

	debug(5, "cloneToFadeOutTrack() - end of func, soundId %d, fade soundId %d", track->soundId, fadeTrack->soundId);

	return fadeTrack;
}
Beispiel #7
0
void Imuse::stopSound(const char *soundName) {
    Common::StackLock lock(_mutex);
    if (gDebugLevel == DEBUG_IMUSE || gDebugLevel == DEBUG_ALL)
        printf("Imuse::stopSound(): SoundName %s\n", soundName);
    Track *removeTrack = NULL;

    removeTrack = findTrack(soundName);
    // Warn the user if the track was not found
    if (removeTrack == NULL) {
        if (gDebugLevel == DEBUG_IMUSE || gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL)
            warning("Sound track '%s' could not be found to stop", soundName);
        return;
    }
    flushTrack(removeTrack);
}
Beispiel #8
0
void IMuseDigital::fadeOutMusicAndStartNew(int fadeDelay, const char *filename, int soundId) {
	Common::StackLock lock(_mutex, "IMuseDigital::fadeOutMusicAndStartNew()");
	debug(5, "IMuseDigital::fadeOutMusicAndStartNew(fade:%d, file:%s, sound:%d)", fadeDelay, filename, soundId);

	for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
		Track *track = _track[l];
		if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
			debug(5, "IMuseDigital::fadeOutMusicAndStartNew(sound:%d) - starting", soundId);
			startMusicWithOtherPos(filename, soundId, 0, 127, track);
			cloneToFadeOutTrack(track, fadeDelay);
			flushTrack(track);
			break;
		}
	}
}
Beispiel #9
0
Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
	assert(track);
	Track *fadeTrack;

	if (track->toBeRemoved) {
		error("cloneToFadeOutTrack: Tried to clone a track to be removed, please bug report");
		return NULL;
	}

	assert(track->trackId < MAX_IMUSE_TRACKS);
	fadeTrack = _track[track->trackId + MAX_IMUSE_TRACKS];

	if (fadeTrack->used) {
		flushTrack(fadeTrack);
		g_system->getMixer()->stopHandle(fadeTrack->handle);
	}

	// Clone the settings of the given track
	memcpy(fadeTrack, track, sizeof(Track));
	fadeTrack->trackId = track->trackId + MAX_IMUSE_TRACKS;

	// Clone the sound.
	// leaving bug number for now #1635361
	ImuseSndMgr::SoundDesc *soundDesc = _sound->cloneSound(track->soundDesc);
	assert(soundDesc);
	track->soundDesc = soundDesc;

	// Set the volume fading parameters to indicate a fade out
	fadeTrack->volFadeDelay = fadeDelay;
	fadeTrack->volFadeDest = 0;
	fadeTrack->volFadeStep = (fadeTrack->volFadeDest - fadeTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * fadeDelay);
	fadeTrack->volFadeUsed = true;

	// Create an appendable output buffer
	fadeTrack->stream = Audio::makeQueuingAudioStream(_sound->getFreq(fadeTrack->soundDesc), track->mixerFlags & kFlagStereo);
	g_system->getMixer()->playStream(track->getType(), &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->getVol(),
											fadeTrack->getPan(), DisposeAfterUse::YES, false,
											(track->mixerFlags & kFlagReverseStereo) != 0);
	fadeTrack->used = true;

	return fadeTrack;
}
Beispiel #10
0
void IMuseDigital::switchToNextRegion(Track *track) {
	assert(track);

	if (track->trackId >= MAX_DIGITAL_TRACKS) {
		flushTrack(track);
		debug(5, "SwToNeReg(trackId:%d) - fadetrack can't go next region, exiting SwToNeReg", track->trackId);
		return;
	}

	int num_regions = _sound->getNumRegions(track->soundDesc);

	if (++track->curRegion == num_regions) {
		flushTrack(track);
		debug(5, "SwToNeReg(trackId:%d) - end of region, exiting SwToNeReg", track->trackId);
		return;
	}

	ImuseDigiSndMgr::SoundDesc *soundDesc = track->soundDesc;
	if (_triggerUsed && track->soundDesc->numMarkers) {
		if (_sound->checkForTriggerByRegionAndMarker(soundDesc, track->curRegion, _triggerParams.marker)) {
			debug(5, "SwToNeReg(trackId:%d) - trigger %s reached", track->trackId, _triggerParams.marker);
			debug(5, "SwToNeReg(trackId:%d) - exit current region %d", track->trackId, track->curRegion);
			debug(5, "SwToNeReg(trackId:%d) - call cloneToFadeOutTrack(delay:%d)", track->trackId, _triggerParams.fadeOutDelay);
			Track *fadeTrack = cloneToFadeOutTrack(track, _triggerParams.fadeOutDelay);
			if (fadeTrack) {
				fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
				fadeTrack->regionOffset = 0;
				debug(5, "SwToNeReg(trackId:%d)-sound(%d) select region %d, curHookId: %d", fadeTrack->trackId, fadeTrack->soundId, fadeTrack->curRegion, fadeTrack->curHookId);
				fadeTrack->curHookId = 0;
			}
			flushTrack(track);
			startMusic(_triggerParams.filename, _triggerParams.soundId, _triggerParams.hookId, _triggerParams.volume);
			_triggerUsed = false;
			return;
		}
	}

	int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);
	if (jumpId != -1) {
		int region = _sound->getRegionIdByJumpId(soundDesc, jumpId);
		assert(region != -1);
		int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);
		assert(sampleHookId != -1);
		debug(5, "SwToNeReg(trackId:%d) - JUMP found - sound:%d, track hookId:%d, data hookId:%d", track->trackId, track->soundId, track->curHookId, sampleHookId);
		if (track->curHookId == sampleHookId) {
			int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;
			debug(5, "SwToNeReg(trackId:%d) - sound(%d) match hookId", track->trackId, track->soundId);
			if (fadeDelay) {
				debug(5, "SwToNeReg(trackId:%d) - call cloneToFadeOutTrack(delay:%d)", track->trackId, fadeDelay);
				Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
				if (fadeTrack) {
					fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
					fadeTrack->regionOffset = 0;
					debug(5, "SwToNeReg(trackId:%d) - sound(%d) faded track, select region %d, curHookId: %d", fadeTrack->trackId, fadeTrack->soundId, fadeTrack->curRegion, fadeTrack->curHookId);
					fadeTrack->curHookId = 0;
				}
			}
			track->curRegion = region;
			debug(5, "SwToNeReg(trackId:%d) - sound(%d) jump to region %d, curHookId: %d", track->trackId, track->soundId, track->curRegion, track->curHookId);
			track->curHookId = 0;
		} else {
			debug(5, "SwToNeReg(trackId:%d) - Normal switch region, sound(%d), hookId(%d)", track->trackId, track->soundId, track->curHookId);
		}
	} else {
		debug(5, "SwToNeReg(trackId:%d) - Normal switch region, sound(%d), hookId(%d)", track->trackId, track->soundId, track->curHookId);
	}

	debug(5, "SwToNeReg(trackId:%d) - sound(%d), select region %d", track->trackId, track->soundId, track->curRegion);
	track->dataOffset = _sound->getRegionOffset(soundDesc, track->curRegion);
	track->regionOffset = 0;
	debug(5, "SwToNeReg(trackId:%d) - end of func", track->trackId);
}
Beispiel #11
0
void IMuseDigital::callback() {
	Common::StackLock lock(_mutex, "IMuseDigital::callback()");

	for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) {
		Track *track = _track[l];
		if (track->used) {
			// Ignore tracks which are about to finish. Also, if it did finish in the meantime,
			// mark it as unused.
			if (!track->stream) {
				if (!_mixer->isSoundHandleActive(track->mixChanHandle))
					memset(track, 0, sizeof(Track));
				continue;
			}

			if (_pause)
				return;

			if (track->volFadeUsed) {
				if (track->volFadeStep < 0) {
					if (track->vol > track->volFadeDest) {
						track->vol += track->volFadeStep;
						if (track->vol < track->volFadeDest) {
							track->vol = track->volFadeDest;
							track->volFadeUsed = false;
						}
						if (track->vol == 0) {
							// Fade out complete -> remove this track
							flushTrack(track);
							continue;
						}
					}
				} else if (track->volFadeStep > 0) {
					if (track->vol < track->volFadeDest) {
						track->vol += track->volFadeStep;
						if (track->vol > track->volFadeDest) {
							track->vol = track->volFadeDest;
							track->volFadeUsed = false;
						}
					}
				}
				debug(5, "Fade: sound(%d), Vol(%d)", track->soundId, track->vol / 1000);
			}

			if (!track->souStreamUsed) {
				assert(track->stream);
				byte *tmpSndBufferPtr = NULL;
				int32 curFeedSize = 0;

				if (track->curRegion == -1) {
					switchToNextRegion(track);
					if (!track->stream)	// Seems we reached the end of the stream
						continue;
				}

				int bits = _sound->getBits(track->soundDesc);
				int channels = _sound->getChannels(track->soundDesc);

				int32 feedSize = track->feedSize / _callbackFps;

				if (track->stream->endOfData()) {
					feedSize *= 2;
				}

				if ((bits == 12) || (bits == 16)) {
					if (channels == 1)
						feedSize &= ~1;
					if (channels == 2)
						feedSize &= ~3;
				} else if (bits == 8) {
					if (channels == 2)
						feedSize &= ~1;
				} else {
					warning("IMuseDigita::callback: Unexpected sample width, %d bits", bits);
					continue;
				}

				if (feedSize == 0)
					continue;

				do {
					if (bits == 12) {
						byte *tmpPtr = NULL;

						feedSize += track->dataMod12Bit;
						int tmpFeedSize12Bits = (feedSize * 3) / 4;
						int tmpLength12Bits = (tmpFeedSize12Bits / 3) * 4;
						track->dataMod12Bit = feedSize - tmpLength12Bits;

						int32 tmpOffset = (track->regionOffset * 3) / 4;
						int tmpFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpPtr, tmpOffset, tmpFeedSize12Bits);
						curFeedSize = BundleCodecs::decode12BitsSample(tmpPtr, &tmpSndBufferPtr, tmpFeedSize);

						free(tmpPtr);
					} else if (bits == 16) {
						curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize);
						if (channels == 1) {
							curFeedSize &= ~1;
						}
						if (channels == 2) {
							curFeedSize &= ~3;
						}
					} else if (bits == 8) {
						curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize);
						if (_radioChatterSFX && track->soundId == 10000) {
							if (curFeedSize > feedSize)
								curFeedSize = feedSize;
							byte *buf = (byte *)malloc(curFeedSize);
							int index = 0;
							int count = curFeedSize - 4;
							byte *ptr_1 = tmpSndBufferPtr;
							byte *ptr_2 = tmpSndBufferPtr + 4;
							int value = ptr_1[0] - 0x80;
							value += ptr_1[1] - 0x80;
							value += ptr_1[2] - 0x80;
							value += ptr_1[3] - 0x80;
							do {
								int t = *ptr_1++;
								int v = t - (value / 4);
								value = *ptr_2++ - 0x80 + (value - t + 0x80);
								buf[index++] = v * 2 + 0x80;
							} while (--count);
							buf[curFeedSize - 1] = 0x80;
							buf[curFeedSize - 2] = 0x80;
							buf[curFeedSize - 3] = 0x80;
							buf[curFeedSize - 4] = 0x80;
							free(tmpSndBufferPtr);
							tmpSndBufferPtr = buf;
						}
						if (channels == 2) {
							curFeedSize &= ~1;
						}
					}

					if (curFeedSize > feedSize)
						curFeedSize = feedSize;

					if (_mixer->isReady()) {
						track->stream->queueBuffer(tmpSndBufferPtr, curFeedSize, DisposeAfterUse::YES, makeMixerFlags(track));
						track->regionOffset += curFeedSize;
					} else
						free(tmpSndBufferPtr);

					if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) {
						switchToNextRegion(track);
						if (!track->stream)	// Seems we reached the end of the stream
							break;
					}
					feedSize -= curFeedSize;
					assert(feedSize >= 0);
				} while (feedSize != 0);
			}
			if (_mixer->isReady()) {
				_mixer->setChannelVolume(track->mixChanHandle, track->getVol());
				_mixer->setChannelBalance(track->mixChanHandle, track->getPan());
			}
		}
	}
}
Beispiel #12
0
void Imuse::callback() {
	Common::StackLock lock(_mutex);

	for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
		Track *track = _track[l];
		if (track->used) {
			// Ignore tracks which are about to finish. Also, if it did finish in the meantime,
			// mark it as unused.
			if (!track->stream) {
				if (!track->soundDesc || !g_system->getMixer()->isSoundHandleActive(track->handle))
					memset(track, 0, sizeof(Track));
				continue;
			}

			if (_pause)
				return;

			if (track->volFadeUsed) {
				if (track->volFadeStep < 0) {
					if (track->vol > track->volFadeDest) {
						track->vol += track->volFadeStep;
						//warning("fade: %d", track->vol);
						if (track->vol < track->volFadeDest) {
							track->vol = track->volFadeDest;
							track->volFadeUsed = false;
						}
						if (track->vol == 0) {
							// Fade out complete -> remove this track
							flushTrack(track);
							continue;
						}
					}
				} else if (track->volFadeStep > 0) {
					if (track->vol < track->volFadeDest) {
						track->vol += track->volFadeStep;
						//warning("fade: %d", track->vol);
						if (track->vol > track->volFadeDest) {
							track->vol = track->volFadeDest;
							track->volFadeUsed = false;
						}
					}
				}
			}

			if (track->panFadeUsed) {
				if (track->panFadeStep < 0) {
					if (track->pan > track->panFadeDest) {
						track->pan += track->panFadeStep;
						if (track->pan < track->panFadeDest) {
							track->pan = track->panFadeDest;
							track->panFadeUsed = false;
						}
					}
				} else if (track->panFadeStep > 0) {
					if (track->pan < track->panFadeDest) {
						track->pan += track->panFadeStep;
						if (track->pan > track->panFadeDest) {
							track->pan = track->panFadeDest;
							track->panFadeUsed = false;
						}
					}
				}
			}

			assert(track->stream);
			byte *data = NULL;
			int32 result = 0;

			if (track->curRegion == -1) {
				switchToNextRegion(track);
				if (!track->stream)	// Seems we reached the end of the stream
					continue;
			}

			int channels = _sound->getChannels(track->soundDesc);
			int32 mixer_size = track->feedSize / _callbackFps;

			if (track->stream->endOfData()) {
				mixer_size *= 2;
			}

			if (channels == 1)
				mixer_size &= ~1;
			if (channels == 2)
				mixer_size &= ~3;

			if (mixer_size == 0)
				continue;

			do {
				result = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &data, track->regionOffset, mixer_size);
				if (channels == 1) {
					result &= ~1;
				}
				if (channels == 2) {
					result &= ~3;
				}

				if (result > mixer_size)
					result = mixer_size;

				if (g_system->getMixer()->isReady()) {
					track->stream->queueBuffer(data, result, DisposeAfterUse::YES, makeMixerFlags(track->mixerFlags));
					track->regionOffset += result;
				} else
					delete[] data;

				if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) {
					switchToNextRegion(track);
					if (!track->stream)
						break;
				}
				mixer_size -= result;
				assert(mixer_size >= 0);
			} while (mixer_size);
			if (g_system->getMixer()->isReady()) {
				g_system->getMixer()->setChannelVolume(track->handle, track->getVol());
				g_system->getMixer()->setChannelBalance(track->handle, track->getPan());
			}
		}
	}
}
Beispiel #13
0
bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority, Track *otherTrack) {
	Common::StackLock lock(_mutex);
	Track *track = nullptr;
	int i;

	// If the track is fading out bring it back to the normal running tracks
	for (i = MAX_IMUSE_TRACKS; i < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; i++) {
		if (!scumm_stricmp(_track[i]->soundName, soundName) && !_track[i]->toBeRemoved) {

			Track *fadeTrack = _track[i];
			track = _track[i - MAX_IMUSE_TRACKS];

			if (track->used) {
				flushTrack(track);
				g_system->getMixer()->stopHandle(track->handle);
			}

			// Clone the settings of the given track
			memcpy(track, fadeTrack, sizeof(Track));
			track->trackId = i - MAX_IMUSE_TRACKS;
			// Reset the track
			memset(fadeTrack, 0, sizeof(Track));
			// Mark as used for now so the track won't be reused again this frame
			track->used = true;

			return true;
		}
	}

	// If the track is already playing then there is absolutely no
	// reason to start it again, the existing track should be modified
	// instead of starting a new copy of the track
	for (i = 0; i < MAX_IMUSE_TRACKS; i++) {
		// Filenames are case insensitive, see findTrack
		if (!scumm_stricmp(_track[i]->soundName, soundName)) {
			Debug::debug(Debug::Sound, "Imuse::startSound(): Track '%s' already playing.", soundName);
			return true;
		}
	}

	// Priority Level 127 appears to mean "load but don't play", so
	// within our paradigm this is a much lower priority than everything
	// else we're doing
	if (priority == 127)
		priority = -1;

	int l = allocSlot(priority);
	if (l == -1) {
		warning("Imuse::startSound() Can't start sound - no free slots");
		return false;
	}

	track = _track[l];
	// Reset the track
	memset(track, 0, sizeof(Track));

	track->pan = pan * 1000;
	track->vol = volume * 1000;
	track->volGroupId = volGroupId;
	track->curHookId = hookId;
	track->priority = priority;
	track->curRegion = -1;
	track->trackId = l;

	int bits = 0, freq = 0, channels = 0;

	strcpy(track->soundName, soundName);
	track->soundDesc = _sound->openSound(soundName, volGroupId);

	if (!track->soundDesc)
		return false;

	bits = _sound->getBits(track->soundDesc);
	channels = _sound->getChannels(track->soundDesc);
	freq = _sound->getFreq(track->soundDesc);

	assert(bits == 8 || bits == 12 || bits == 16);
	assert(channels == 1 || channels == 2);
	assert(0 < freq && freq <= 65535);

	track->feedSize = freq * channels * 2;
	track->mixerFlags = kFlag16Bits;
	if (channels == 2)
		track->mixerFlags |= kFlagStereo | kFlagReverseStereo;

	if (otherTrack && otherTrack->used && !otherTrack->toBeRemoved) {
		track->curRegion = otherTrack->curRegion;
		track->dataOffset = otherTrack->dataOffset;
		track->regionOffset = otherTrack->regionOffset;
	}

	track->stream = Audio::makeQueuingAudioStream(freq, track->mixerFlags & kFlagStereo);
	g_system->getMixer()->playStream(track->getType(), &track->handle, track->stream, -1,
											track->getVol(), track->getPan(), DisposeAfterUse::YES,
											false, (track->mixerFlags & kFlagReverseStereo) != 0);
	track->used = true;

	return true;
}