2007-05-30 21:56:52 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
2004-04-12 21:40:49 +00:00
|
|
|
*
|
2007-05-30 21:56:52 +00:00
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
2004-04-12 21:40:49 +00:00
|
|
|
*
|
|
|
|
* 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
|
2008-01-05 12:45:14 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2004-04-12 21:40:49 +00:00
|
|
|
* 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
|
2005-10-18 01:30:26 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2004-04-12 21:40:49 +00:00
|
|
|
*
|
2006-02-11 12:44:16 +00:00
|
|
|
* $URL$
|
|
|
|
* $Id$
|
2004-04-12 21:40:49 +00:00
|
|
|
*
|
|
|
|
*/
|
2007-07-31 18:08:40 +00:00
|
|
|
|
|
|
|
// MIDI and digital music class
|
|
|
|
|
2004-08-02 16:20:35 +00:00
|
|
|
#include "saga/saga.h"
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2008-12-22 14:13:15 +00:00
|
|
|
#include "saga/resource.h"
|
2004-08-02 16:20:35 +00:00
|
|
|
#include "saga/music.h"
|
2007-09-23 09:59:10 +00:00
|
|
|
|
2004-10-12 11:45:53 +00:00
|
|
|
#include "sound/audiostream.h"
|
2004-05-01 13:04:31 +00:00
|
|
|
#include "sound/mididrv.h"
|
2004-04-29 03:52:59 +00:00
|
|
|
#include "sound/midiparser.h"
|
2004-04-29 04:24:55 +00:00
|
|
|
#include "common/config-manager.h"
|
2004-04-30 07:13:26 +00:00
|
|
|
#include "common/file.h"
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
namespace Saga {
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-10-12 11:45:53 +00:00
|
|
|
#define BUFFER_SIZE 4096
|
2008-05-26 11:10:46 +00:00
|
|
|
#define MUSIC_SUNSPOT 26
|
2004-10-12 11:45:53 +00:00
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) {
|
2004-04-29 04:50:45 +00:00
|
|
|
memset(_channel, 0, sizeof(_channel));
|
2004-08-01 07:56:08 +00:00
|
|
|
_masterVolume = 0;
|
2004-04-29 03:52:59 +00:00
|
|
|
this->open();
|
|
|
|
}
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
MusicPlayer::~MusicPlayer() {
|
|
|
|
_driver->setTimerCallback(NULL, NULL);
|
2004-05-31 08:46:36 +00:00
|
|
|
stopMusic();
|
2004-04-29 03:52:59 +00:00
|
|
|
this->close();
|
2004-05-01 13:04:31 +00:00
|
|
|
}
|
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
void MusicPlayer::setVolume(int volume) {
|
2007-12-13 20:10:13 +00:00
|
|
|
volume = CLIP(volume, 0, 255);
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
if (_masterVolume == volume)
|
|
|
|
return;
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
_masterVolume = volume;
|
2004-04-29 04:24:55 +00:00
|
|
|
|
2008-08-20 09:12:11 +00:00
|
|
|
Common::StackLock lock(_mutex);
|
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
for (int i = 0; i < 16; ++i) {
|
2004-04-29 04:24:55 +00:00
|
|
|
if (_channel[i]) {
|
2004-04-29 03:52:59 +00:00
|
|
|
_channel[i]->volume(_channelVolume[i] * _masterVolume / 255);
|
2004-04-29 04:24:55 +00:00
|
|
|
}
|
2004-04-29 03:52:59 +00:00
|
|
|
}
|
|
|
|
}
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
int MusicPlayer::open() {
|
|
|
|
// Don't ever call open without first setting the output driver!
|
|
|
|
if (!_driver)
|
|
|
|
return 255;
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
int ret = _driver->open();
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2004-04-29 04:50:45 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
_driver->setTimerCallback(this, &onTimer);
|
|
|
|
return 0;
|
|
|
|
}
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
void MusicPlayer::close() {
|
|
|
|
stopMusic();
|
|
|
|
if (_driver)
|
|
|
|
_driver->close();
|
|
|
|
_driver = 0;
|
|
|
|
}
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
void MusicPlayer::send(uint32 b) {
|
2004-10-21 22:40:06 +00:00
|
|
|
if (_passThrough) {
|
|
|
|
_driver->send(b);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
byte channel = (byte)(b & 0x0F);
|
|
|
|
if ((b & 0xFFF0) == 0x07B0) {
|
|
|
|
// Adjust volume changes by master volume
|
|
|
|
byte volume = (byte)((b >> 16) & 0x7F);
|
|
|
|
_channelVolume[channel] = volume;
|
|
|
|
volume = volume * _masterVolume / 255;
|
|
|
|
b = (b & 0xFF00FFFF) | (volume << 16);
|
2004-04-30 07:13:26 +00:00
|
|
|
} else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
|
2005-04-03 22:01:38 +00:00
|
|
|
b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
|
2004-05-01 13:04:31 +00:00
|
|
|
}
|
2004-04-29 03:52:59 +00:00
|
|
|
else if ((b & 0xFFF0) == 0x007BB0) {
|
|
|
|
//Only respond to All Notes Off if this channel
|
|
|
|
//has currently been allocated
|
|
|
|
if (_channel[b & 0x0F])
|
|
|
|
return;
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
if (!_channel[channel])
|
|
|
|
_channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
if (_channel[channel])
|
|
|
|
_channel[channel]->send(b);
|
|
|
|
}
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
|
2004-10-12 11:45:53 +00:00
|
|
|
// FIXME: The "elkfanfare" is played much too quickly. There are some
|
|
|
|
// meta events that we don't handle. Perhaps there is a
|
|
|
|
// connection...?
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case 0x2F: // End of Track
|
|
|
|
if (_looping)
|
|
|
|
_parser->jumpToTick(0);
|
|
|
|
else
|
|
|
|
stopMusic();
|
|
|
|
break;
|
|
|
|
default:
|
2005-04-03 15:32:04 +00:00
|
|
|
//warning("Unhandled meta event: %02x", type);
|
2004-10-12 11:45:53 +00:00
|
|
|
break;
|
|
|
|
}
|
2004-04-29 03:52:59 +00:00
|
|
|
}
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
void MusicPlayer::onTimer(void *refCon) {
|
|
|
|
MusicPlayer *music = (MusicPlayer *)refCon;
|
2007-08-22 15:28:31 +00:00
|
|
|
Common::StackLock lock(music->_mutex);
|
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
if (music->_isPlaying)
|
|
|
|
music->_parser->onTimer();
|
|
|
|
}
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
void MusicPlayer::playMusic() {
|
|
|
|
_isPlaying = true;
|
|
|
|
}
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
void MusicPlayer::stopMusic() {
|
2007-08-22 15:28:31 +00:00
|
|
|
Common::StackLock lock(_mutex);
|
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
_isPlaying = false;
|
2004-05-31 08:46:36 +00:00
|
|
|
if (_parser) {
|
|
|
|
_parser->unloadMusic();
|
2004-05-31 08:59:11 +00:00
|
|
|
_parser = NULL;
|
2004-05-31 08:46:36 +00:00
|
|
|
}
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
2008-07-01 03:01:11 +00:00
|
|
|
Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver) : _vm(vm), _mixer(mixer), _adlib(false) {
|
2004-04-29 03:52:59 +00:00
|
|
|
_player = new MusicPlayer(driver);
|
2005-06-19 21:18:00 +00:00
|
|
|
_currentVolume = 0;
|
2004-10-12 11:45:53 +00:00
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
xmidiParser = MidiParser::createParser_XMIDI();
|
2008-01-27 19:47:41 +00:00
|
|
|
smfParser = MidiParser::createParser_SMF();
|
2005-07-19 19:05:52 +00:00
|
|
|
|
2009-03-08 15:39:19 +00:00
|
|
|
_digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE);
|
2005-08-30 11:16:11 +00:00
|
|
|
|
|
|
|
_songTableLen = 0;
|
|
|
|
_songTable = 0;
|
2005-09-20 18:04:26 +00:00
|
|
|
|
2006-03-02 18:25:56 +00:00
|
|
|
_midiMusicData = NULL;
|
2008-11-11 17:34:52 +00:00
|
|
|
_digitalMusic = false;
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
Music::~Music() {
|
2008-12-25 20:53:59 +00:00
|
|
|
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
|
2005-07-19 21:48:59 +00:00
|
|
|
_mixer->stopHandle(_musicHandle);
|
2004-04-29 03:52:59 +00:00
|
|
|
delete _player;
|
2005-07-19 19:44:20 +00:00
|
|
|
xmidiParser->setMidiDriver(NULL);
|
|
|
|
smfParser->setMidiDriver(NULL);
|
2005-07-19 19:05:52 +00:00
|
|
|
delete xmidiParser;
|
|
|
|
delete smfParser;
|
2005-08-30 11:16:11 +00:00
|
|
|
|
|
|
|
free(_songTable);
|
2006-03-02 18:25:56 +00:00
|
|
|
free(_midiMusicData);
|
2004-04-29 03:52:59 +00:00
|
|
|
}
|
|
|
|
|
2005-06-19 21:18:00 +00:00
|
|
|
void Music::musicVolumeGaugeCallback(void *refCon) {
|
|
|
|
((Music *)refCon)->musicVolumeGauge();
|
2005-07-29 17:58:00 +00:00
|
|
|
}
|
2005-06-19 21:18:00 +00:00
|
|
|
|
|
|
|
void Music::musicVolumeGauge() {
|
|
|
|
int volume;
|
|
|
|
|
|
|
|
_currentVolumePercent += 10;
|
|
|
|
|
|
|
|
if (_currentVolume - _targetVolume > 0) { // Volume decrease
|
|
|
|
volume = _targetVolume + (_currentVolume - _targetVolume) * (100 - _currentVolumePercent) / 100;
|
|
|
|
} else {
|
|
|
|
volume = _currentVolume + (_targetVolume - _currentVolume) * _currentVolumePercent / 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (volume < 0)
|
|
|
|
volume = 1;
|
|
|
|
|
2005-07-19 21:48:59 +00:00
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
|
2005-06-19 21:18:00 +00:00
|
|
|
_player->setVolume(volume);
|
|
|
|
|
|
|
|
if (_currentVolumePercent == 100) {
|
2008-12-25 20:53:59 +00:00
|
|
|
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
|
2005-06-19 21:18:00 +00:00
|
|
|
_currentVolume = _targetVolume;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Music::setVolume(int volume, int time) {
|
2008-09-05 13:02:03 +00:00
|
|
|
_targetVolume = volume;
|
2005-06-19 21:18:00 +00:00
|
|
|
_currentVolumePercent = 0;
|
|
|
|
|
|
|
|
if (volume == -1) // Set Full volume
|
2005-09-02 20:17:52 +00:00
|
|
|
volume = 255;
|
2005-06-19 21:18:00 +00:00
|
|
|
|
|
|
|
if (time == 1) {
|
2005-07-19 21:48:59 +00:00
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
|
2005-09-02 20:17:52 +00:00
|
|
|
_player->setVolume(volume);
|
2008-12-25 20:53:59 +00:00
|
|
|
_vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback);
|
2005-06-19 21:18:00 +00:00
|
|
|
_currentVolume = volume;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-12-25 20:53:59 +00:00
|
|
|
_vm->getTimerManager()->installTimerProc(&musicVolumeGaugeCallback, time * 100L, this);
|
2005-06-19 21:18:00 +00:00
|
|
|
}
|
|
|
|
|
2005-01-17 14:19:17 +00:00
|
|
|
bool Music::isPlaying() {
|
2005-03-12 18:56:09 +00:00
|
|
|
return _mixer->isSoundHandleActive(_musicHandle) || _player->isPlaying();
|
2005-01-17 14:19:17 +00:00
|
|
|
}
|
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
void Music::play(uint32 resourceId, MusicFlags flags) {
|
2010-01-06 00:00:50 +00:00
|
|
|
Audio::SeekableAudioStream *audioStream = NULL;
|
2005-07-19 19:05:52 +00:00
|
|
|
MidiParser *parser;
|
2007-06-26 23:40:22 +00:00
|
|
|
ResourceContext *context = NULL;
|
2005-07-19 19:05:52 +00:00
|
|
|
byte *resourceData;
|
2008-01-27 19:47:41 +00:00
|
|
|
size_t resourceSize;
|
2006-03-24 18:15:57 +00:00
|
|
|
uint32 loopStart;
|
2005-09-20 18:04:26 +00:00
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
debug(2, "Music::play %d, %d", resourceId, flags);
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
if (isPlaying() && _trackNumber == resourceId) {
|
|
|
|
return;
|
2005-01-17 14:19:17 +00:00
|
|
|
}
|
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
_trackNumber = resourceId;
|
2004-10-12 11:45:53 +00:00
|
|
|
_player->stopMusic();
|
2005-03-12 18:56:09 +00:00
|
|
|
_mixer->stopHandle(_musicHandle);
|
2009-01-01 15:06:43 +00:00
|
|
|
|
2005-09-21 10:46:20 +00:00
|
|
|
int realTrackNumber;
|
|
|
|
|
2008-12-21 15:59:05 +00:00
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
2005-09-21 10:46:20 +00:00
|
|
|
if (flags == MUSIC_DEFAULT) {
|
|
|
|
if (resourceId == 13 || resourceId == 19) {
|
|
|
|
flags = MUSIC_NORMAL;
|
|
|
|
} else {
|
|
|
|
flags = MUSIC_LOOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
realTrackNumber = resourceId - 8;
|
|
|
|
} else {
|
|
|
|
realTrackNumber = resourceId + 1;
|
|
|
|
}
|
|
|
|
|
2009-08-17 18:25:51 +00:00
|
|
|
// Try to open standalone digital track
|
|
|
|
char trackName[2][16];
|
|
|
|
sprintf(trackName[0], "track%d", realTrackNumber);
|
|
|
|
sprintf(trackName[1], "track%02d", realTrackNumber);
|
2010-01-06 00:00:50 +00:00
|
|
|
Audio::SeekableAudioStream *stream = 0;
|
2009-08-17 18:25:51 +00:00
|
|
|
for (int i = 0; i < 2; ++i) {
|
2010-01-06 15:23:33 +00:00
|
|
|
stream = Audio::SeekableAudioStream::openStreamFile(trackName[i]);
|
2009-08-17 18:25:51 +00:00
|
|
|
if (stream) {
|
2010-01-08 16:27:29 +00:00
|
|
|
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle,
|
|
|
|
Audio::makeLoopingAudioStream(stream, (flags == MUSIC_LOOP) ? 0 : 1));
|
2009-08-17 18:25:51 +00:00
|
|
|
_digitalMusic = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-21 15:59:05 +00:00
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
2005-07-19 19:05:52 +00:00
|
|
|
if (resourceId >= 9 && resourceId <= 34) {
|
2007-07-12 08:52:07 +00:00
|
|
|
if (_digitalMusicContext != NULL) {
|
2006-03-24 18:15:57 +00:00
|
|
|
loopStart = 0;
|
2009-08-17 18:25:51 +00:00
|
|
|
// Fix ITE sunstatm/sunspot score
|
2009-08-17 13:25:44 +00:00
|
|
|
if (resourceId == MUSIC_SUNSPOT)
|
2006-03-24 18:15:57 +00:00
|
|
|
loopStart = 4 * 18727;
|
|
|
|
|
2009-08-17 13:25:44 +00:00
|
|
|
// Digital music
|
|
|
|
ResourceData *resData = _digitalMusicContext->getResourceData(resourceId - 9);
|
|
|
|
Common::File *musicFile = _digitalMusicContext->getFile(resData);
|
2009-12-04 17:52:42 +00:00
|
|
|
int offs = (_digitalMusicContext->isCompressed()) ? 9 : 0;
|
2009-08-17 13:25:44 +00:00
|
|
|
|
|
|
|
Common::SeekableSubReadStream *musicStream = new Common::SeekableSubReadStream(musicFile,
|
|
|
|
(uint32)resData->offset + offs, (uint32)resData->offset + resData->size - offs);
|
|
|
|
|
2009-12-04 17:52:42 +00:00
|
|
|
if (!_digitalMusicContext->isCompressed()) {
|
2009-08-17 13:25:44 +00:00
|
|
|
byte musicFlags = Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_STEREO |
|
|
|
|
Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN;
|
|
|
|
if (flags == MUSIC_LOOP)
|
|
|
|
musicFlags |= Audio::Mixer::FLAG_LOOP;
|
|
|
|
|
|
|
|
Audio::LinearDiskStreamAudioBlock audioBlocks[1];
|
|
|
|
audioBlocks[0].pos = 0;
|
|
|
|
audioBlocks[0].len = resData->size / 2; // 16-bit sound
|
2009-08-17 13:49:56 +00:00
|
|
|
audioStream = Audio::makeLinearDiskStream(musicStream, audioBlocks, 1, 11025, musicFlags, false, loopStart, 0);
|
2009-08-17 13:25:44 +00:00
|
|
|
} else {
|
|
|
|
// Read compressed header to determine compression type
|
|
|
|
musicFile->seek((uint32)resData->offset, SEEK_SET);
|
|
|
|
byte identifier = musicFile->readByte();
|
|
|
|
|
|
|
|
if (identifier == 0) { // MP3
|
|
|
|
#ifdef USE_MAD
|
2010-01-06 00:00:50 +00:00
|
|
|
audioStream = Audio::makeMP3Stream(musicStream, false);
|
2009-08-17 13:25:44 +00:00
|
|
|
#endif
|
|
|
|
} else if (identifier == 1) { // OGG
|
|
|
|
#ifdef USE_VORBIS
|
2010-01-06 00:00:50 +00:00
|
|
|
audioStream = Audio::makeVorbisStream(musicStream, false);
|
2009-08-17 13:25:44 +00:00
|
|
|
#endif
|
|
|
|
} else if (identifier == 2) { // FLAC
|
|
|
|
#ifdef USE_FLAC
|
2010-01-06 00:00:50 +00:00
|
|
|
audioStream = Audio::makeFlacStream(musicStream, false);
|
2009-08-17 13:25:44 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2004-11-15 03:03:48 +00:00
|
|
|
}
|
2004-05-16 12:57:49 +00:00
|
|
|
}
|
2004-04-30 07:13:26 +00:00
|
|
|
}
|
|
|
|
|
2004-10-12 11:45:53 +00:00
|
|
|
if (audioStream) {
|
2005-06-05 09:28:40 +00:00
|
|
|
debug(2, "Playing digitized music");
|
2010-01-08 16:27:29 +00:00
|
|
|
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle,
|
|
|
|
Audio::makeLoopingAudioStream(audioStream, (flags == MUSIC_LOOP ? 0 : 1)));
|
2008-11-11 17:34:52 +00:00
|
|
|
_digitalMusic = true;
|
2005-07-19 19:05:52 +00:00
|
|
|
return;
|
2004-10-12 11:45:53 +00:00
|
|
|
}
|
2004-05-31 08:46:36 +00:00
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
if (flags == MUSIC_DEFAULT) {
|
|
|
|
flags = MUSIC_NORMAL;
|
|
|
|
}
|
2004-04-30 07:13:26 +00:00
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
// Load MIDI/XMI resource data
|
2004-04-30 07:13:26 +00:00
|
|
|
|
2008-12-21 15:59:05 +00:00
|
|
|
if (_vm->getGameId() == GID_ITE) {
|
2005-08-04 10:23:49 +00:00
|
|
|
context = _vm->_resource->getContext(GAME_MUSICFILE_GM);
|
|
|
|
if (context == NULL) {
|
|
|
|
context = _vm->_resource->getContext(GAME_RESOURCEFILE);
|
2008-01-27 19:47:41 +00:00
|
|
|
}
|
2008-12-21 15:59:05 +00:00
|
|
|
} else if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
|
2008-04-05 14:06:50 +00:00
|
|
|
// The music of the Mac version of IHNM is loaded from its
|
|
|
|
// associated external file later on
|
2004-04-30 07:13:26 +00:00
|
|
|
} else {
|
2005-07-19 19:05:52 +00:00
|
|
|
// I've listened to music from both the FM and the GM
|
|
|
|
// file, and I've tentatively reached the conclusion
|
|
|
|
// that they are both General MIDI. My guess is that
|
2005-07-29 17:58:00 +00:00
|
|
|
// the FM file has been reorchestrated to sound better
|
2005-07-19 19:05:52 +00:00
|
|
|
// on Adlib and other FM synths.
|
|
|
|
//
|
|
|
|
// Sev says the Adlib music does not sound like in the
|
|
|
|
// original, but I still think assuming General MIDI is
|
|
|
|
// the right thing to do. Some music, like the End
|
|
|
|
// Title (song 0) sound absolutely atrocious when piped
|
|
|
|
// through our MT-32 to GM mapping.
|
|
|
|
//
|
|
|
|
// It is, however, quite possible that the original
|
|
|
|
// used a different GM to FM mapping. If the original
|
|
|
|
// sounded markedly better, perhaps we should add some
|
|
|
|
// way of replacing our stock mapping in adlib.cpp?
|
|
|
|
//
|
|
|
|
// For the composer's own recording of the End Title,
|
|
|
|
// see http://www.johnottman.com/
|
2004-11-26 10:04:36 +00:00
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
// Oddly enough, the intro music (song 1) is very
|
|
|
|
// different in the two files. I have no idea why.
|
2007-07-30 18:26:56 +00:00
|
|
|
// Note that the IHNM demo has only got one music file
|
|
|
|
// (music.rsc). It is assumed that it contains FM music
|
2004-05-01 13:04:31 +00:00
|
|
|
|
2008-12-21 15:59:05 +00:00
|
|
|
if (hasAdlib() || _vm->getFeatures() & GF_IHNM_DEMO) {
|
2005-07-19 19:05:52 +00:00
|
|
|
context = _vm->_resource->getContext(GAME_MUSICFILE_FM);
|
|
|
|
} else {
|
|
|
|
context = _vm->_resource->getContext(GAME_MUSICFILE_GM);
|
2004-04-30 07:13:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
_player->setGM(true);
|
2004-11-15 03:03:48 +00:00
|
|
|
|
2008-12-21 15:59:05 +00:00
|
|
|
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
|
2008-04-05 14:06:50 +00:00
|
|
|
// Load the external music file for Mac IHNM
|
|
|
|
Common::File musicFile;
|
|
|
|
char musicFileName[40];
|
2008-04-05 14:18:32 +00:00
|
|
|
sprintf(musicFileName, "Music/Music%02x", resourceId);
|
2008-04-05 14:06:50 +00:00
|
|
|
musicFile.open(musicFileName);
|
|
|
|
resourceSize = musicFile.size();
|
|
|
|
resourceData = new byte[resourceSize];
|
|
|
|
musicFile.read(resourceData, resourceSize);
|
|
|
|
musicFile.close();
|
|
|
|
|
2008-05-26 11:10:46 +00:00
|
|
|
// TODO: The Mac music format is unsupported (QuickTime MIDI)
|
2008-04-05 14:06:50 +00:00
|
|
|
// so stop here
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
_vm->_resource->loadResource(context, resourceId, resourceData, resourceSize);
|
|
|
|
}
|
2005-07-29 17:58:00 +00:00
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
if (resourceSize < 4) {
|
|
|
|
error("Music::play() wrong music resource size");
|
2004-04-29 03:52:59 +00:00
|
|
|
}
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
if (xmidiParser->loadMusic(resourceData, resourceSize)) {
|
2008-12-21 15:59:05 +00:00
|
|
|
if (_vm->getGameId() == GID_ITE)
|
2006-02-09 04:58:21 +00:00
|
|
|
_player->setGM(false);
|
|
|
|
|
2005-07-19 19:05:52 +00:00
|
|
|
parser = xmidiParser;
|
|
|
|
} else {
|
|
|
|
if (smfParser->loadMusic(resourceData, resourceSize)) {
|
2005-07-29 17:58:00 +00:00
|
|
|
parser = smfParser;
|
2005-07-19 19:05:52 +00:00
|
|
|
} else {
|
|
|
|
error("Music::play() wrong music resource");
|
|
|
|
}
|
|
|
|
}
|
2004-04-12 21:40:49 +00:00
|
|
|
|
2004-04-29 12:27:17 +00:00
|
|
|
parser->setTrack(0);
|
2004-04-29 04:24:55 +00:00
|
|
|
parser->setMidiDriver(_player);
|
2004-04-29 13:45:10 +00:00
|
|
|
parser->setTimerRate(_player->getBaseTempo());
|
2005-10-12 06:57:25 +00:00
|
|
|
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
|
2004-04-29 12:27:17 +00:00
|
|
|
|
2004-04-29 03:52:59 +00:00
|
|
|
_player->_parser = parser;
|
2008-09-05 13:02:03 +00:00
|
|
|
setVolume(_vm->_musicVolume);
|
2005-07-19 19:05:52 +00:00
|
|
|
|
2004-10-27 21:32:28 +00:00
|
|
|
if (flags & MUSIC_LOOP)
|
2004-05-29 21:04:44 +00:00
|
|
|
_player->setLoop(true);
|
|
|
|
else
|
|
|
|
_player->setLoop(false);
|
|
|
|
|
2004-04-29 04:24:55 +00:00
|
|
|
_player->playMusic();
|
2006-03-02 18:25:56 +00:00
|
|
|
free(_midiMusicData);
|
|
|
|
_midiMusicData = resourceData;
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
2009-11-02 21:54:57 +00:00
|
|
|
void Music::pause() {
|
2007-08-22 16:00:45 +00:00
|
|
|
_player->setVolume(-1);
|
|
|
|
_player->setPlaying(false);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
2009-11-02 21:54:57 +00:00
|
|
|
void Music::resume() {
|
2008-09-05 13:02:03 +00:00
|
|
|
_player->setVolume(_vm->_musicVolume);
|
2007-08-22 16:00:45 +00:00
|
|
|
_player->setPlaying(true);
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
2009-11-02 21:54:57 +00:00
|
|
|
void Music::stop() {
|
2007-08-22 11:28:11 +00:00
|
|
|
_player->stopMusic();
|
2004-04-12 21:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // End of namespace Saga
|
|
|
|
|