mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-24 10:45:46 +00:00
8cdee5a931
svn-id: r21500
195 lines
4.7 KiB
C++
195 lines
4.7 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2006 The ScummVM project
|
|
*
|
|
* cinE Engine is (C) 2004-2005 by CinE Team
|
|
*
|
|
* 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 "common/stdafx.h"
|
|
#include "common/endian.h"
|
|
#include "common/system.h"
|
|
|
|
#include "cine/cine.h"
|
|
#include "cine/sfx_player.h"
|
|
#include "cine/sound_driver.h"
|
|
#include "cine/unpack.h"
|
|
#include "cine/various.h"
|
|
|
|
namespace Cine {
|
|
|
|
SfxPlayer::SfxPlayer(SoundDriver *driver)
|
|
: _playing(false), _driver(driver) {
|
|
memset(_instrumentsData, 0, sizeof(_instrumentsData));
|
|
_sfxData = NULL;
|
|
_fadeOutCounter = 0;
|
|
_driver->setUpdateCallback(updateCallback, this);
|
|
}
|
|
|
|
SfxPlayer::~SfxPlayer() {
|
|
_driver->setUpdateCallback(NULL, NULL);
|
|
if (_playing) {
|
|
stop();
|
|
}
|
|
}
|
|
|
|
bool SfxPlayer::load(const char *song) {
|
|
debug(9, "SfxPlayer::load('%s')", song);
|
|
|
|
/* stop (w/ fade out) the previous song */
|
|
while (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
|
|
g_system->delayMillis(50);
|
|
}
|
|
_fadeOutCounter = 0;
|
|
|
|
if (_playing) {
|
|
stop();
|
|
}
|
|
|
|
/* like the original PC version, skip introduction song (file doesn't exist) */
|
|
if (gameType == Cine::GID_OS && strncmp(song, "INTRO", 5) == 0) {
|
|
return 0;
|
|
}
|
|
|
|
_sfxData = snd_loadBasesonEntry(song);
|
|
if (!_sfxData) {
|
|
warning("Unable to load soundfx module '%s'", song);
|
|
return 0;
|
|
}
|
|
|
|
for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
|
|
_instrumentsData[i] = NULL;
|
|
|
|
char instrument[13];
|
|
memcpy(instrument, _sfxData + 20 + i * 30, 12);
|
|
instrument[12] = '\0';
|
|
|
|
if (strlen(instrument) != 0) {
|
|
char *dot = strrchr(instrument, '.');
|
|
if (dot) {
|
|
*dot = '\0';
|
|
}
|
|
strcat(instrument, _driver->getInstrumentExtension());
|
|
_instrumentsData[i] = snd_loadBasesonEntry(instrument);
|
|
if (!_instrumentsData[i]) {
|
|
warning("Unable to load soundfx instrument '%s'", instrument);
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void SfxPlayer::play() {
|
|
debug(9, "SfxPlayer::play()");
|
|
if (_sfxData) {
|
|
for (int i = 0; i < NUM_CHANNELS; ++i) {
|
|
_instrumentsChannelTable[i] = -1;
|
|
}
|
|
_currentPos = 0;
|
|
_currentOrder = 0;
|
|
_numOrders = _sfxData[470];
|
|
_eventsDelay = (252 - _sfxData[471]) * 50 / 1060;
|
|
_updateTicksCounter = 0;
|
|
_playing = true;
|
|
}
|
|
}
|
|
|
|
void SfxPlayer::stop() {
|
|
_fadeOutCounter = 0;
|
|
_playing = false;
|
|
for (int i = 0; i < NUM_CHANNELS; ++i) {
|
|
_driver->stopChannel(i);
|
|
}
|
|
_driver->stopSound();
|
|
unload();
|
|
}
|
|
|
|
void SfxPlayer::fadeOut() {
|
|
if (_playing) {
|
|
_fadeOutCounter = 1;
|
|
_playing = false;
|
|
}
|
|
}
|
|
|
|
void SfxPlayer::updateCallback(void *ref) {
|
|
((SfxPlayer *)ref)->update();
|
|
}
|
|
|
|
void SfxPlayer::update() {
|
|
if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) {
|
|
++_updateTicksCounter;
|
|
if (_updateTicksCounter > _eventsDelay) {
|
|
handleEvents();
|
|
_updateTicksCounter = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SfxPlayer::handleEvents() {
|
|
const byte *patternData = _sfxData + 600;
|
|
const byte *orderTable = _sfxData + 472;
|
|
uint16 patternNum = orderTable[_currentOrder] * 1024;
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
handlePattern(i, patternData + patternNum + _currentPos);
|
|
patternData += 4;
|
|
}
|
|
|
|
if (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
|
|
_fadeOutCounter += 2;
|
|
}
|
|
_currentPos += 16;
|
|
if (_currentPos >= 1024) {
|
|
_currentPos = 0;
|
|
++_currentOrder;
|
|
if (_currentOrder == _numOrders) {
|
|
_currentOrder = 0;
|
|
}
|
|
}
|
|
debug(7, "_currentOrder=%d/%d _currentPos=%d", _currentOrder, _numOrders, _currentPos);
|
|
}
|
|
|
|
void SfxPlayer::handlePattern(int channel, const byte *patternData) {
|
|
int instrument = patternData[2] >> 4;
|
|
if (instrument != 0) {
|
|
--instrument;
|
|
if (_instrumentsChannelTable[channel] != instrument || _fadeOutCounter != 0) {
|
|
_instrumentsChannelTable[channel] = instrument;
|
|
const int volume = _sfxData[instrument] - _fadeOutCounter;
|
|
_driver->setupChannel(channel, _instrumentsData[instrument], instrument, volume);
|
|
}
|
|
}
|
|
int16 freq = (int16)READ_BE_UINT16(patternData);
|
|
if (freq > 0) {
|
|
_driver->stopChannel(channel);
|
|
_driver->setChannelFrequency(channel, freq);
|
|
}
|
|
}
|
|
|
|
void SfxPlayer::unload() {
|
|
for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
|
|
free(_instrumentsData[i]);
|
|
_instrumentsData[i] = NULL;
|
|
}
|
|
free(_sfxData);
|
|
_sfxData = NULL;
|
|
}
|
|
|
|
} // End of namespace Cine
|