aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sandulenko2007-02-21 21:42:37 +0000
committerEugene Sandulenko2007-02-21 21:42:37 +0000
commitb825fb858f204bfd07eaff77dee3100eb1b893bf (patch)
tree275ecee2b1dfecb3628ea5c7127a3890ced46999
parentb2539cc19cf569bedc1521173943fe5693fad322 (diff)
downloadscummvm-rg350-b825fb858f204bfd07eaff77dee3100eb1b893bf.tar.gz
scummvm-rg350-b825fb858f204bfd07eaff77dee3100eb1b893bf.tar.bz2
scummvm-rg350-b825fb858f204bfd07eaff77dee3100eb1b893bf.zip
Add support for MIDI music. THough the music is not yet heard since
there are no instrument assignments yet. svn-id: r25774
-rw-r--r--engines/parallaction/callables.cpp4
-rw-r--r--engines/parallaction/intro.cpp4
-rw-r--r--engines/parallaction/location.cpp16
-rw-r--r--engines/parallaction/menu.cpp2
-rw-r--r--engines/parallaction/music.cpp195
-rw-r--r--engines/parallaction/music.h52
-rw-r--r--engines/parallaction/parallaction.cpp33
-rw-r--r--engines/parallaction/parallaction.h3
8 files changed, 207 insertions, 102 deletions
diff --git a/engines/parallaction/callables.cpp b/engines/parallaction/callables.cpp
index 15c8c2bd28..e6e10a02f2 100644
--- a/engines/parallaction/callables.cpp
+++ b/engines/parallaction/callables.cpp
@@ -51,9 +51,7 @@ void _c_play_boogie(void *parm) {
return;
flag = 0;
- stopMusic();
- loadMusic("boogie2");
- playMusic();
+ _vm->_midiPlayer->play("boogie2");
return;
}
diff --git a/engines/parallaction/intro.cpp b/engines/parallaction/intro.cpp
index d8c6ae8dfd..2338ced7a0 100644
--- a/engines/parallaction/intro.cpp
+++ b/engines/parallaction/intro.cpp
@@ -124,9 +124,7 @@ extern Credit _credits[];
void _c_startIntro(void *parm) {
_rightHandAnim = findAnimation("righthand");
- stopMusic();
- loadMusic("intro");
- playMusic();
+ _vm->_midiPlayer->play("intro");
_engineFlags |= kEngineMouse;
return;
diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp
index a27420f32c..ae2964f3a3 100644
--- a/engines/parallaction/location.cpp
+++ b/engines/parallaction/location.cpp
@@ -333,23 +333,19 @@ void Parallaction::changeLocation(char *location) {
// printf("changeLocation('%s')", location);
if (_musicData1 != 0) {
if (!scumm_stricmp(_characterName, "dino"))
- loadMusic("dino");
+ _vm->_midiPlayer->play("dino");
+ else if (!scumm_stricmp(_characterName, "donna"))
+ _vm->_midiPlayer->play("donna");
else
- if (!scumm_stricmp(_characterName, "donna"))
- loadMusic("donna");
- else
- loadMusic("nuts");
+ _vm->_midiPlayer->play("nuts");
- playMusic();
_musicData1 = 0;
debugC(2, kDebugLocation, "changeLocation: started character specific music");
}
if (!scumm_stricmp(location, "night") || !scumm_stricmp(location, "intsushi")) {
- stopMusic();
- loadMusic("soft");
- playMusic();
+ _vm->_midiPlayer->play("soft");
debugC(2, kDebugLocation, "changeLocation: started music 'soft'");
}
@@ -362,7 +358,7 @@ void Parallaction::changeLocation(char *location) {
!scumm_stricmp(location, "endtgz") ||
!scumm_stricmp(location, "common")) {
- stopMusic();
+ _vm->_midiPlayer->stop();
_musicData1 = 1;
debugC(2, kDebugLocation, "changeLocation: music stopped");
diff --git a/engines/parallaction/menu.cpp b/engines/parallaction/menu.cpp
index f9140590ff..9fd6db583a 100644
--- a/engines/parallaction/menu.cpp
+++ b/engines/parallaction/menu.cpp
@@ -313,7 +313,7 @@ void Menu::selectCharacter() {
v14._height = BLOCK_HEIGHT;
_engine->changeCursor(kCursorArrow);
- stopMusic();
+ _vm->_midiPlayer->stop();
_vm->_graphics->_proportionalFont = false;
_vm->_graphics->loadExternalCnv("slidecnv", &Graphics::_font);
diff --git a/engines/parallaction/music.cpp b/engines/parallaction/music.cpp
index 8b0aa35262..3cc3be5a3a 100644
--- a/engines/parallaction/music.cpp
+++ b/engines/parallaction/music.cpp
@@ -20,68 +20,34 @@
*
*/
+#include "common/stdafx.h"
#include "common/file.h"
#include "parallaction/parallaction.h"
-namespace Parallaction {
-
-// NOTE: these two guys are never changed.
-static int16 _musicFlag2 = 1;
-static int16 _musicFlag1 = 1;
-
-static bool _allocated = false;
-static bool _playing = false;
-// UNUSED
-// static char byte_14D22[10] = { 0 };
-static const char *_musicFilesNames[] = { "intro", "dino", "donna", "nuts", "soft", "boogie2" };
-static uint16 _musicFilesSizes[] = { 18805, 5486, 6195, 13006, 15818, 7507 };
-static byte *_musicBits = NULL;
-
-// TODO
-// move this into a proper midi driver and decode the numeric commands
-void _music_command(const void*, const void*, const void*, const void*) {
-
-}
+#include "common/stream.h"
-void stopMusic() {
+#include "sound/midiparser.h"
- if (_musicFlag1 == 0 && _musicFlag2 == 0) return;
- if (_playing == false) return;
- if (_allocated == false) return;
+#include "parallaction/music.h"
- _music_command((const void*)4, (const void*)0, (const void*)0, (const void*)0); // stop
- _music_command((const void*)5, (const void*)0, (const void*)0, (const void*)0); // reset timer
- memFree(_musicBits);
+namespace Parallaction {
- _allocated = false;
- _playing = false;
+MidiPlayer::MidiPlayer(MidiDriver *driver)
+ : _driver(driver), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _masterVolume(0) {
+ assert(_driver);
+ memset(_channelsTable, 0, sizeof(_channelsTable));
+ memset(_channelsVolume, 0, sizeof(_channelsVolume));
- return;
+ open();
}
-void playMusic() {
-
- if (_musicFlag1 == 0 && _musicFlag2 == 0) return;
- if (_playing == true) return;
- if (_allocated == false) return;
-
- _music_command(0, 0, 0, 0); // init driver
- _music_command((const void*)1, 0, 0, 0); // init timer
- _music_command((const void*)17, (const void*)1, 0, 0); // set source segment
- _music_command((const void*)7, (const void*)1, 0, 0); // set source offset and do SOMETHING
-
- // FIXME: casting pointer to uint32
- _music_command((const void*)2, (const void*)_musicBits, 0, 0); // play
-
- _playing = true;
-
- return;
+MidiPlayer::~MidiPlayer() {
+ close();
}
-void loadMusic(const char *filename) {
-
- uint16 _di = 0;
+void MidiPlayer::play(const char *filename) {
+ stop();
if (!scumm_strnicmp(_location, "museo", 5)) return;
if (!scumm_strnicmp(_location, "intgrottadopo", 13)) return;
@@ -90,20 +56,6 @@ void loadMusic(const char *filename) {
if (!scumm_strnicmp(_location, "plaza1", 6)) return;
if (!scumm_strnicmp(_location, "endtgz", 6)) return;
- if (_musicFlag1 == 0 && _musicFlag2 == 0) return;
- if (_allocated == true) return;
-
-// UNUSED
-// strcpy(byte_14D22, filename);
-
- for (uint16 _si = 0; _si < 6; _si++) {
- if (!strcmp(filename, _musicFilesNames[_si])) {
- _di = _musicFilesSizes[_si];
- }
- }
-
- if (_di == 0 ) return;
-
char path[PATH_LEN];
sprintf(path, "%s.mid", filename);
@@ -112,15 +64,120 @@ void loadMusic(const char *filename) {
if (!stream.open(path))
return;
- _musicBits = (byte*)memAlloc(_di);
- if (!_musicBits) return;
+ int size = stream.size();
+
+ _midiData = (uint8 *)malloc(size);
+ if (_midiData) {
+ stream.read(_midiData, size);
+ _mutex.lock();
+ _parser->loadMusic(_midiData, size);
+ _parser->setTrack(0);
+ _isLooping = true;
+ _isPlaying = true;
+ _mutex.unlock();
+ }
+}
+
+void MidiPlayer::stop() {
+ _mutex.lock();
+ if (_isPlaying) {
+ _isPlaying = false;
+ _parser->unloadMusic();
+ free(_midiData);
+ _midiData = 0;
+ }
+ _mutex.unlock();
+}
+
+void MidiPlayer::updateTimer() {
+ _mutex.lock();
+ if (_isPlaying) {
+ _parser->onTimer();
+ }
+ _mutex.unlock();
+}
+
+void MidiPlayer::adjustVolume(int diff) {
+ setVolume(_masterVolume + diff);
+}
+
+void MidiPlayer::setVolume(int volume) {
+ _masterVolume = CLIP(volume, 0, 255);
+ _mutex.lock();
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ if (_channelsTable[i]) {
+ _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
+ }
+ }
+ _mutex.unlock();
+}
+
+int MidiPlayer::open() {
+ int ret = _driver->open();
+ if (ret == 0) {
+ _parser = MidiParser::createParser_SMF();
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
+ _driver->setTimerCallback(this, &timerCallback);
+ }
+ return ret;
+}
+
+void MidiPlayer::close() {
+ stop();
+ _mutex.lock();
+ _driver->setTimerCallback(NULL, NULL);
+ _driver->close();
+ _driver = 0;
+ _parser->setMidiDriver(NULL);
+ delete _parser;
+ _mutex.unlock();
+}
+
+void MidiPlayer::send(uint32 b) {
+ byte volume, ch = (byte)(b & 0xF);
+ switch (b & 0xFFF0) {
+ case 0x07B0: // volume change
+ volume = (byte)((b >> 16) & 0x7F);
+ _channelsVolume[ch] = volume;
+ volume = volume * _masterVolume / 255;
+ b = (b & 0xFF00FFFF) | (volume << 16);
+ break;
+ case 0x7BB0: // all notes off
+ if (!_channelsTable[ch]) {
+ // channel not yet allocated, no need to send the event
+ return;
+ }
+ break;
+ }
+
+ if (!_channelsTable[ch]) {
+ _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ }
+ if (_channelsTable[ch]) {
+ _channelsTable[ch]->send(b);
+ }
+}
- stream.read(_musicBits, _di);
- stream.close();
+void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
+ switch (type) {
+ case 0x2F: // end of Track
+ if (_isLooping) {
+ _parser->jumpToTick(0);
+ } else {
+ stop();
+ }
+ break;
+ default:
+// warning("Unhandled meta event: %02x", type);
+ break;
+ }
+}
- _allocated = true;
+void MidiPlayer::timerCallback(void *p) {
+ MidiPlayer *player = (MidiPlayer *)p;
- return;
+ player->updateTimer();
}
} // namespace Parallaction
diff --git a/engines/parallaction/music.h b/engines/parallaction/music.h
index 4f3f211002..eef249a7d4 100644
--- a/engines/parallaction/music.h
+++ b/engines/parallaction/music.h
@@ -23,11 +23,57 @@
#ifndef PARALLACTION_MUSIC_H
#define PARALLACTION_MUSIC_H
+#include "common/util.h"
+#include "common/mutex.h"
+
+#include "sound/mididrv.h"
+
+class MidiParser;
+
namespace Parallaction {
-void stopMusic();
-void playMusic();
-void loadMusic(const char *filename);
+class MidiPlayer : public MidiDriver {
+public:
+
+ enum {
+ NUM_CHANNELS = 16
+ };
+
+ MidiPlayer(MidiDriver *driver);
+ ~MidiPlayer();
+
+ void play(const char *filename);
+ void stop();
+ void updateTimer();
+ void adjustVolume(int diff);
+ void setVolume(int volume);
+ int getVolume() const { return _masterVolume; }
+ void setLooping(bool loop) { _isLooping = loop; }
+
+ // MidiDriver interface
+ int open();
+ void close();
+ void send(uint32 b);
+ void metaEvent(byte type, byte *data, uint16 length);
+ void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
+ uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
+ MidiChannel *allocateChannel() { return 0; }
+ MidiChannel *getPercussionChannel() { return 0; }
+
+private:
+
+ static void timerCallback(void *p);
+
+ MidiDriver *_driver;
+ MidiParser *_parser;
+ uint8 *_midiData;
+ bool _isLooping;
+ bool _isPlaying;
+ int _masterVolume;
+ MidiChannel *_channelsTable[NUM_CHANNELS];
+ uint8 _channelsVolume[NUM_CHANNELS];
+ Common::Mutex _mutex;
+};
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index d7a023e97e..2f60f604c9 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -20,6 +20,15 @@
*
*/
+#include "common/stdafx.h"
+
+#include "common/util.h"
+#include "common/file.h"
+#include "common/config-manager.h"
+
+#include "sound/mididrv.h"
+#include "sound/mixer.h"
+
#include "parallaction/parallaction.h"
#include "parallaction/menu.h"
#include "parallaction/parser.h"
@@ -29,9 +38,6 @@
#include "parallaction/graphics.h"
#include "parallaction/zone.h"
-#include "common/util.h"
-#include "common/file.h"
-#include "common/config-manager.h"
namespace Parallaction {
@@ -170,6 +176,7 @@ Parallaction::Parallaction(OSystem *syst) :
_musicData1 = 0;
strcpy(_characterName1, "null");
+ _midiPlayer = 0;
_baseTime = 0;
@@ -195,7 +202,7 @@ Parallaction::Parallaction(OSystem *syst) :
Parallaction::~Parallaction() {
-
+ delete _midiPlayer;
}
@@ -270,6 +277,11 @@ int Parallaction::init() {
addNode(&_animations, &_yourself._zone._node);
_graphics = new Graphics(this);
+ int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
+ MidiDriver *driver = MidiDriver::createMidi(midiDriver);
+ _midiPlayer = new MidiPlayer(driver);
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
return 0;
}
@@ -856,19 +868,14 @@ void Parallaction::changeCharacter(const char *name) {
refreshInventory(name);
- stopMusic();
-
if (scumm_stricmp(name, "night") && scumm_stricmp(name, "intsushi")) {
if (!scumm_stricmp(name, "dino") || !scumm_stricmp(name, "minidino")) {
- loadMusic("dino");
- } else
- if (!scumm_stricmp(name, "donna") || !scumm_stricmp(name, "minidonna")) {
- loadMusic("donna");
+ _midiPlayer->play("dino");
+ } else if (!scumm_stricmp(name, "donna") || !scumm_stricmp(name, "minidonna")) {
+ _midiPlayer->play("donna");
} else {
- loadMusic("nuts");
+ _midiPlayer->play("nuts");
}
-
- playMusic();
}
}
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 67db74ee12..6ea8c56955 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -212,6 +212,7 @@ enum {
class Graphics;
class Menu;
+class MidiPlayer;
class Parallaction : public Engine {
@@ -256,6 +257,8 @@ private:
public:
+ MidiPlayer *_midiPlayer;
+
Graphics* _graphics;
Menu* _menu;
char _characterName[30];