Example #1
0
/**
 * Handles the sciAudio calls in fanmade games.
 * sciAudio is an external .NET library for playing MP3 files in fanmade games.
 * It runs in the background, and obtains sound commands from the
 * currently running game via text files (called "conductor files").
 * For further info, check: http://sciprogramming.com/community/index.php?topic=634.0
 */
void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan) {
	// TODO: This is a bare bones implementation. Only the play/playx and stop commands
	// are handled for now - the other commands haven't been observed in any fanmade game
	// yet. All the volume related and fading functionality is currently missing.

	Kernel *kernel = g_sci->getKernel();

	reg_t commandReg = readSelector(segMan, sciAudioObject, kernel->findSelector("command"));
	Common::String command = segMan->getString(commandReg);

	if (command == "play" || command == "playx") {
#ifdef USE_MAD
		reg_t fileNameReg = readSelector(segMan, sciAudioObject, kernel->findSelector("fileName"));
		Common::String fileName = segMan->getString(fileNameReg);

		int16 loopCount = (int16)readSelectorValue(segMan, sciAudioObject, kernel->findSelector("loopCount"));
		// When loopCount is -1, we treat it as infinite looping, else no looping is done.
		// This is observed by game scripts, which can set loopCount to all sorts of random values.
		// Adjust loopCount for ScummVM's LoopingAudioStream semantics
		loopCount = (loopCount == -1) ? 0 : 1;

		// Determine sound type
		Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType;
		if (fileName.hasPrefix("music"))
			soundType = Audio::Mixer::kMusicSoundType;
		else if (fileName.hasPrefix("speech"))
			soundType = Audio::Mixer::kSpeechSoundType;

		Common::File *sciAudio = new Common::File();
		// Replace backwards slashes
		for (uint i = 0; i < fileName.size(); i++) {
			if (fileName[i] == '\\')
				fileName.setChar('/', i);
		}
		sciAudio->open("sciAudio/" + fileName);

		Audio::SeekableAudioStream *audioStream = Audio::makeMP3Stream(sciAudio, DisposeAfterUse::YES);

		// We only support one audio handle
		_mixer->playStream(soundType, &_audioHandle,
							Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audioStream, loopCount));
#endif
	} else if (command == "stop") {
		_mixer->stopHandle(_audioHandle);
	} else {
		warning("Unhandled sciAudio command: %s", command.c_str());
	}
}
Example #2
0
/**
 * Handles the sciAudio calls in fanmade games.
 * sciAudio is an external .NET library for playing MP3 files in fanmade games.
 * It runs in the background, and obtains sound commands from the
 * currently running game via text files (called "conductor files").
 * For further info, check: http://sciprogramming.com/community/index.php?topic=634.0
 */
void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan) {
	// TODO: This is a bare bones implementation. Only the play/playx and stop commands
	// are handled for now - the other commands haven't been observed in any fanmade game
	// yet. All the volume related and fading functionality is currently missing.

	Kernel *kernel = g_sci->getKernel();

	reg_t commandReg = readSelector(segMan, sciAudioObject, kernel->findSelector("command"));
	Common::String command = segMan->getString(commandReg);

	if (command == "play" || command == "playx") {
		reg_t fileNameReg = readSelector(segMan, sciAudioObject, kernel->findSelector("fileName"));
		Common::String fileName = segMan->getString(fileNameReg);

		reg_t loopCountReg = readSelector(segMan, sciAudioObject, kernel->findSelector("loopCount"));
		Common::String loopCountStr = segMan->getString(loopCountReg);
		int16 loopCount = atoi(loopCountStr.c_str());

		// Adjust loopCount for ScummVM's LoopingAudioStream semantics
		if (loopCount == -1) {
			loopCount = 0; // loop endlessly
		} else if (loopCount >= 0) {
			// sciAudio loopCount == 0 -> play 1 time  -> ScummVM's loopCount should be 1
			// sciAudio loopCount == 1 -> play 2 times -> ScummVM's loopCount should be 2
			loopCount++;
		} else {
			loopCount = 1; // play once in case the value makes no sense
		}

		// Determine sound type
		Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType;
		if (fileName.hasPrefix("music"))
			soundType = Audio::Mixer::kMusicSoundType;
		else if (fileName.hasPrefix("speech"))
			soundType = Audio::Mixer::kSpeechSoundType;

		// Determine compression
		uint32 audioCompressionType = 0;
		if ((fileName.hasSuffix(".mp3")) || (fileName.hasSuffix(".sciAudio")) || (fileName.hasSuffix(".sciaudio"))) {
			audioCompressionType = MKTAG('M','P','3',' ');
		} else if (fileName.hasSuffix(".wav")) {
			audioCompressionType = MKTAG('W','A','V',' ');
		} else if (fileName.hasSuffix(".aiff")) {
			audioCompressionType = MKTAG('A','I','F','F');
		} else {
			error("sciAudio: unsupported file type");
		}

		Common::File *sciAudioFile = new Common::File();
		// Replace backwards slashes
		for (uint i = 0; i < fileName.size(); i++) {
			if (fileName[i] == '\\')
				fileName.setChar('/', i);
		}
		sciAudioFile->open("sciAudio/" + fileName);

		Audio::RewindableAudioStream *audioStream = nullptr;

		switch (audioCompressionType) {
		case MKTAG('M','P','3',' '):
#ifdef USE_MAD
			audioStream = Audio::makeMP3Stream(sciAudioFile, DisposeAfterUse::YES);
#endif
			break;
		case MKTAG('W','A','V',' '):
			audioStream = Audio::makeWAVStream(sciAudioFile, DisposeAfterUse::YES);
			break;
		case MKTAG('A','I','F','F'):
			audioStream = Audio::makeAIFFStream(sciAudioFile, DisposeAfterUse::YES);
			break;
		default:
			break;
		}

		if (!audioStream) {
			error("sciAudio: requested compression not compiled into ScummVM");
		}

		// We only support one audio handle
		_mixer->playStream(soundType, &_audioHandle,
							Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audioStream, loopCount));
	} else if (command == "stop") {
		_mixer->stopHandle(_audioHandle);
	} else {
		warning("Unhandled sciAudio command: %s", command.c_str());
	}
}