aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dc/dcmain.cpp3
-rw-r--r--gameDetector.cpp17
-rw-r--r--gameDetector.h4
-rw-r--r--gfx.cpp2
-rw-r--r--gui.cpp9
-rw-r--r--mac/mac.cpp4
-rw-r--r--main.cpp3
-rw-r--r--morphos/morphos.cpp3
-rw-r--r--morphos/morphos_sound.cpp2
-rw-r--r--saveload.cpp7
-rw-r--r--scumm.h17
-rw-r--r--scummvm.cpp38
-rw-r--r--scummvm.dsp20
-rw-r--r--sdl.cpp75
-rw-r--r--simon/midi.cpp3
-rw-r--r--simon/simon.cpp45
-rw-r--r--simon/simon.h40
-rw-r--r--simon/simonsys.cpp1
-rw-r--r--sound.cpp392
-rw-r--r--sound.h645
-rw-r--r--sound/adlib.cpp989
-rw-r--r--sound/gmidi.cpp314
-rw-r--r--sound/imuse.cpp2083
-rw-r--r--sound/imuse.h46
-rw-r--r--sound/mididrv.cpp56
-rw-r--r--sound/mididrv.h (renamed from sound/gmidi.h)61
-rw-r--r--sound/mixer.cpp491
-rw-r--r--sound/mixer.h157
-rw-r--r--system.h27
-rw-r--r--wince/pocketpc.cpp6
-rw-r--r--windows.cpp3
-rw-r--r--x11.cpp3
32 files changed, 2911 insertions, 2655 deletions
diff --git a/dc/dcmain.cpp b/dc/dcmain.cpp
index bb1dc20521..e2ff7c5648 100644
--- a/dc/dcmain.cpp
+++ b/dc/dcmain.cpp
@@ -23,7 +23,6 @@
#include "stdafx.h"
#include "scumm.h"
#include "gui.h"
-#include "sound.h"
#include "dc.h"
#include "icon.h"
@@ -33,7 +32,7 @@ ScummDebugger debugger;
Gui gui;
Icon icon;
-SoundEngine sound;
+IMuse sound;
SOUND_DRIVER_TYPE snd_driv;
/* CD Audio stubs */
diff --git a/gameDetector.cpp b/gameDetector.cpp
index d74143ef86..e7a524e189 100644
--- a/gameDetector.cpp
+++ b/gameDetector.cpp
@@ -23,8 +23,9 @@
#include "stdafx.h"
#include "scumm.h"
+#include "mididrv.h"
#include "gameDetector.h"
-
+#include "imuse.h"
static const char USAGE_STRING[] =
@@ -104,17 +105,11 @@ void GameDetector::parseCommandLine(int argc, char **argv)
case 'm':{
if (*(s + 1) == '\0')
goto ShowHelpAndExit;
- SoundEngine *se = (SoundEngine *)_soundEngine;
-
- if (se)
- se->set_music_volume(atoi(s + 1));
+ _music_volume = atoi(s + 1);
goto NextArg;
}
case 'r':{
- SoundEngine *se = (SoundEngine *)_soundEngine;
-
- if (se)
- se->_mt32emulate = true;
+ _mt32emulate = true;
break;
}
case 'e':
@@ -208,8 +203,8 @@ bool GameDetector::parseMusicDriver(const char *s) {
for(i=0; i!=ARRAYSIZE(music_drivers); i++,md++) {
if (!scumm_stricmp(md->name, s)) {
/* FIXME: when adlib driver is in use, propagate that to
- * the Scumm class, and let it create an AdlibSoundDriver
- * instead of MidiSoundDriver */
+ * the IMuse class, and let it create an IMuseAdlib driver
+ * instead of IMuseGM driver */
if (md->id == -1) {
_use_adlib = true;
}
diff --git a/gameDetector.h b/gameDetector.h
index dc2d62b9f0..296ba6539d 100644
--- a/gameDetector.h
+++ b/gameDetector.h
@@ -34,6 +34,9 @@ public:
bool _use_adlib;
+ byte _music_volume;
+ bool _mt32emulate;
+
uint16 _debugMode;
uint16 _noSubtitles;
uint16 _bootParam;
@@ -41,7 +44,6 @@ public:
char *_gameDataPath;
int _gameTempo;
- void *_soundEngine;
int _midi_driver;
char *_exe_name;
const char *_gameText;
diff --git a/gfx.cpp b/gfx.cpp
index f9ba2248c3..708e9c8609 100644
--- a/gfx.cpp
+++ b/gfx.cpp
@@ -584,7 +584,7 @@ void Scumm::unkVirtScreen4(int a)
//setDirtyRange(0, 0, vs->height);
//updateDirtyScreen(0);
/* XXX: EGA_proc4(0); */
- warning("EGA_proc4"); /* FIXME */
+// warning("EGA_proc4"); /* FIXME */
break;
case 134:
unkScreenEffect5(0);
diff --git a/gui.cpp b/gui.cpp
index 76bd4a4dc9..93b93e3464 100644
--- a/gui.cpp
+++ b/gui.cpp
@@ -21,8 +21,10 @@
#include "stdafx.h"
#include "scumm.h"
+#include "mididrv.h"
#include "gui.h"
#include "guimaps.h"
+#include "imuse.h"
#ifdef _WIN32_WCE
// Additional variables for Win32 specific GUI
@@ -484,12 +486,13 @@ void Gui::handleSoundDialogCommand(int cmd)
{
if (cmd == 40 || cmd == 50) {
if (cmd == 40) {
- SoundEngine *se = (SoundEngine *)_s->_soundEngine;
_s->_sound_volume_master = _gui_variables[0]; // Master
_s->_sound_volume_music = _gui_variables[1]; // Music
_s->_sound_volume_sfx = _gui_variables[2]; // SFX
- se->set_music_volume(_s->_sound_volume_music);
- se->set_master_volume(_s->_sound_volume_master);
+
+ IMuse *imuse = _s->_imuse;
+ imuse->set_music_volume(_s->_sound_volume_music);
+ imuse->set_master_volume(_s->_sound_volume_master);
registry_save();
}
diff --git a/mac/mac.cpp b/mac/mac.cpp
index 0704eafbb2..c43cf5dae8 100644
--- a/mac/mac.cpp
+++ b/mac/mac.cpp
@@ -31,7 +31,6 @@
#include "stdafx.h"
#include "scumm.h"
#include "gui.h"
-#include "sound.h"
#include "cdmusic.h"
#include "mp3_cd.h"
#include "gameDetector.h"
@@ -138,7 +137,7 @@ int sel;
Scumm *scumm;
ScummDebugger debugger;
Gui gui;
-SoundEngine sound;
+IMuse sound;
SOUND_DRIVER_TYPE snd_driv;
OSystem _system;
GameDetector detector;
@@ -1025,7 +1024,6 @@ void InitScummStuff()
scumm->_scale = detector._scale;
scumm->_gameDataPath = detector._gameDataPath;
scumm->_gameTempo = detector._gameTempo;
- scumm->_soundEngine = detector._soundEngine;
scumm->_videoMode = detector._videoMode;
scumm->_exe_name = detector._exe_name;
scumm->_gameId = detector._gameId;
diff --git a/main.cpp b/main.cpp
index aafcf2f666..7176443fd1 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "scumm.h"
+#include "mididrv.h"
#include "gameDetector.h"
#include "gui.h"
#include "simon/simon.h"
@@ -57,7 +58,7 @@ int main(int argc, char *argv[])
{
char *s = detector.getGameName();
- system->set_param(OSystem::PARAM_WINDOW_CAPTION, (long)s);
+ system->property(OSystem::PROP_SET_WINDOW_CAPTION, (long)s);
free(s);
}
diff --git a/morphos/morphos.cpp b/morphos/morphos.cpp
index 7f45eaabb2..e8e30418a0 100644
--- a/morphos/morphos.cpp
+++ b/morphos/morphos.cpp
@@ -64,7 +64,7 @@ Gui gui;
OSystem _system;
GameDetector detector;
-SoundEngine sound;
+IMuse sound;
SOUND_DRIVER_TYPE snd_driv;
typedef void (*ScalerFunc)( uint32 src_x, uint32 src_y, uint32 dest_x, uint32 dest_y, uint32 width, uint32 height );
@@ -1879,7 +1879,6 @@ int main( int argc, char *argv[] )
scumm->_scale = detector._scale;
scumm->_gameDataPath = detector._gameDataPath;
scumm->_gameTempo = detector._gameTempo;
- scumm->_soundEngine = detector._soundEngine;
scumm->_videoMode = detector._videoMode;
scumm->_exe_name = detector._exe_name;
scumm->_gameId = detector._gameId;
diff --git a/morphos/morphos_sound.cpp b/morphos/morphos_sound.cpp
index 9abfb1c950..99f55807fe 100644
--- a/morphos/morphos_sound.cpp
+++ b/morphos/morphos_sound.cpp
@@ -40,7 +40,7 @@
extern int GetTicks();
extern Scumm scumm;
-extern SoundEngine sound;
+extern IMuse sound;
extern SOUND_DRIVER_TYPE snd_driv;
#define AHI_BUF_SIZE (8*1024)
diff --git a/saveload.cpp b/saveload.cpp
index 89a7a95539..f71774c899 100644
--- a/saveload.cpp
+++ b/saveload.cpp
@@ -22,6 +22,8 @@
#include "stdafx.h"
#include "scumm.h"
+#include "mididrv.h"
+#include "imuse.h"
#ifdef _WIN32_WCE
#define _MANAGE_OLD_SAVE
@@ -742,9 +744,8 @@ void Scumm::saveOrLoad(Serializer * s)
}
}
- if (_soundEngine)
- ((SoundEngine *)_soundEngine)->save_or_load(s);
-
+ if (_imuse)
+ _imuse->save_or_load(s, this);
}
void Scumm::saveLoadResource(Serializer * ser, int type, int idx)
diff --git a/scumm.h b/scumm.h
index 9debfb5763..277da70d0d 100644
--- a/scumm.h
+++ b/scumm.h
@@ -21,6 +21,7 @@
#include "scummsys.h"
#include "system.h"
+#include "mixer.h"
#ifdef COMPRESSED_SOUND_FILE
#include <mad.h>
@@ -35,6 +36,7 @@
class GameDetector;
class Gui;
class Scumm;
+class IMuse;
struct Actor;
struct ScummDebugger;
struct Serializer;
@@ -549,7 +551,6 @@ enum MouseButtonStatus {
#include "gfx.h"
#include "boxes.h"
-#include "sound.h"
#include "akos.h"
#include "smush.h"
@@ -559,7 +560,7 @@ public:
* That results in a shorter form of the opcode
* on some architectures. */
OSystem *_system;
- void *_soundEngine;
+ IMuse *_imuse;
Gui *_gui;
uint32 _features;
VerbSlot *_verbs;
@@ -939,10 +940,10 @@ public:
void runVerbCode(int script, int entry, int a, int b, int16 *vars);
void setVerbObject(uint room, uint object, uint verb);
-
/* Should be in Sound class */
- MixerChannel _mixer_channel[NUM_MIXER];
- int _gameTempo;
+ SoundMixer _mixer[1];
+
+// MixerChannel _mixer_channel[NUM_MIXER];
byte _sfxMode;
bool _use_adlib;
int16 _sound_volume_master, _sound_volume_music, _sound_volume_sfx;
@@ -982,13 +983,11 @@ public:
int num_sound_effects; // SO3 MP3 compressed audio
void pauseSounds(bool pause);
- MixerChannel *allocateMixer();
bool isSfxFinished();
void playBundleSound(char *sound);
void playSfxSound(void *sound, uint32 size, uint rate);
- void playSfxSound_MP3(void *sound, uint32 size);
+ void playSfxSound_MP3(void *sound, uint32 size);
void stopSfxSound();
- void mixWaves(int16 *sounds, int len);
bool _useTalkAnims;
uint16 _defaultTalkDelay;
@@ -1682,7 +1681,6 @@ public:
void updateCursor();
void animateCursor();
void updatePalette();
- static void on_generate_samples(void *s, int16 *samples, int len);
};
class Scumm_v3 : public Scumm
@@ -1798,6 +1796,7 @@ struct Serializer {
};
+
extern const uint32 IMxx_tags[];
extern const byte default_scale_table[768];
diff --git a/scummvm.cpp b/scummvm.cpp
index adc6640630..be83449eb6 100644
--- a/scummvm.cpp
+++ b/scummvm.cpp
@@ -22,6 +22,8 @@
#include "stdafx.h"
#include "scumm.h"
+#include "mididrv.h"
+#include "imuse.h"
#include "gui.h"
#include "string.h"
#include "gameDetector.h"
@@ -1259,10 +1261,6 @@ void Scumm::launch()
// _scummTimer = 0;
}
-void Scumm::on_generate_samples(void *s, int16 *samples, int len) {
- ((Scumm*)s)->mixWaves(samples, len);
-}
-
Scumm *Scumm::createFromDetector(GameDetector *detector, OSystem *syst)
{
Scumm *scumm;
@@ -1281,17 +1279,18 @@ Scumm *Scumm::createFromDetector(GameDetector *detector, OSystem *syst)
scumm->_system = syst;
/* This initializes SDL */
- syst->init_size(320,200, OSystem::SOUND_16BIT);
- syst->set_param(OSystem::PARAM_OPEN_CD, detector->_cdrom);
+ syst->init_size(320,200);
+ syst->property(OSystem::PROP_OPEN_CD, detector->_cdrom);
- syst->set_sound_proc(scumm, on_generate_samples);
+ /* bind the mixer to the system => mixer will be invoked
+ * automatically when samples need to be generated */
+ scumm->_mixer->bind_to_system(syst);
+ scumm->_mixer->set_volume(128);
scumm->_fullScreen = detector->_fullScreen;
scumm->_debugMode = detector->_debugMode;
scumm->_bootParam = detector->_bootParam;
scumm->_gameDataPath = detector->_gameDataPath;
- scumm->_gameTempo = detector->_gameTempo;
- scumm->_soundEngine = detector->_soundEngine;
scumm->_exe_name = detector->_exe_name;
scumm->_gameId = detector->_gameId;
scumm->_gameText = detector->_gameText;
@@ -1301,20 +1300,21 @@ Scumm *Scumm::createFromDetector(GameDetector *detector, OSystem *syst)
scumm->_cdrom = detector->_cdrom;
{
- SoundDriver *sdriv;
- SoundEngine *seng;
+ IMuse *imuse;
scumm->_use_adlib = detector->_use_adlib;
-
- if (!detector->_use_adlib) {
- MidiDriver *midi = detector->createMidi();
- sdriv = new MidiSoundDriver;
- ((MidiSoundDriver*)sdriv)->midiSetDriver(midi);
+
+ if (detector->_use_adlib) {
+ imuse = IMuse::create_adlib(syst, scumm->_mixer);
} else {
- sdriv = new AdlibSoundDriver;
+ imuse = IMuse::create_midi(syst, detector->createMidi());
}
- seng = new SoundEngine;
- seng->initialize(scumm, sdriv);
+
+ imuse->property(IMuse::PROP_MT32_EMULATE, detector->_mt32emulate);
+ if (detector->_gameTempo != 0)
+ imuse->property(IMuse::PROP_TEMPO_BASE, detector->_gameTempo);
+
+ scumm->_imuse = imuse;
}
scumm->delta = 6;
diff --git a/scummvm.dsp b/scummvm.dsp
index 42d7dba044..66bc3cc55f 100644
--- a/scummvm.dsp
+++ b/scummvm.dsp
@@ -121,27 +121,31 @@ LINK32=link.exe
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\sound\adlib.cpp
+SOURCE=.\sound\fmopl.cpp
# End Source File
# Begin Source File
-SOURCE=.\sound\fmopl.cpp
+SOURCE=.\sound\imuse.cpp
# End Source File
# Begin Source File
-SOURCE=.\sound\gmidi.cpp
+SOURCE=.\sound\imuse.h
# End Source File
# Begin Source File
-SOURCE=.\sound\gmidi.h
+SOURCE=.\sound\mididrv.cpp
# End Source File
# Begin Source File
-SOURCE=.\sound\imuse.cpp
+SOURCE=.\sound\mididrv.h
# End Source File
# Begin Source File
-SOURCE=.\sound\mididrv.cpp
+SOURCE=.\sound\mixer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sound\mixer.h
# End Source File
# End Group
# Begin Group "v3"
@@ -512,10 +516,6 @@ SOURCE=.\smush.h
# End Source File
# Begin Source File
-SOURCE=.\sound.h
-# End Source File
-# Begin Source File
-
SOURCE=.\StdAfx.h
# End Source File
# Begin Source File
diff --git a/sdl.cpp b/sdl.cpp
index eb4460c59e..af3997c37b 100644
--- a/sdl.cpp
+++ b/sdl.cpp
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "scumm.h"
+#include "mididrv.h"
#include "SDL_thread.h"
#include "gameDetector.h"
@@ -16,7 +17,7 @@ public:
// Set the size of the video bitmap.
// Typically, 320x200
- void init_size(uint w, uint h, byte sound);
+ void init_size(uint w, uint h);
// Draw a bitmap to screen.
// The screen will not be updated to reflect the new bitmap
@@ -51,13 +52,13 @@ public:
bool poll_event(Event *event);
// Set function that generates samples
- void set_sound_proc(void *param, SoundProc *proc);
+ void set_sound_proc(void *param, SoundProc *proc, byte sound);
// Quit
void quit();
// Set a parameter
- uint32 set_param(int param, uint32 value);
+ uint32 property(int param, uint32 value);
static OSystem *create(int gfx_mode, bool full_screen);
@@ -108,9 +109,6 @@ private:
int scaling;
- SoundProc *_sound_proc;
- void *_sound_param;
-
struct MousePos {
int16 x,y,w,h;
};
@@ -197,14 +195,6 @@ void OSystem_SDL::set_palette(const byte *colors, uint start, uint num) {
SDL_SetColors(sdl_screen, base, start, num);
}
-void OSystem_SDL::fill_sound(void *userdata, Uint8 * stream, int len) {
- OSystem_SDL *os = (OSystem_SDL*)userdata;
- if (os->_sound_proc)
- os->_sound_proc(os->_sound_param, (int16*)stream, len>>1);
- else
- memset(stream, 0x0, len);
-}
-
void OSystem_SDL::load_gfx_mode() {
force_full = true;
scaling = 1;
@@ -307,24 +297,10 @@ void OSystem_SDL::unload_gfx_mode() {
}
}
-void OSystem_SDL::init_size(uint w, uint h, byte sound) {
- SDL_AudioSpec desired;
-
+void OSystem_SDL::init_size(uint w, uint h) {
if (w != SCREEN_WIDTH && h != SCREEN_HEIGHT)
error("320x200 is the only game resolution supported");
- /* init sound */
- if (sound != SOUND_NONE) {
- desired.freq = SAMPLES_PER_SEC;
- desired.format = sound==SOUND_8BIT ? AUDIO_U8 : AUDIO_S16SYS;
- desired.channels = 1;
- desired.samples = 2048;
- desired.callback = fill_sound;
- desired.userdata = this;
- SDL_OpenAudio(&desired, NULL);
- SDL_PauseAudio(0);
- }
-
/* allocate palette, it needs to be persistent across
* driver changes, so i'll alloc it here */
_cur_pal = (SDL_Color*)calloc(sizeof(SDL_Color), 256);
@@ -668,7 +644,7 @@ bool OSystem_SDL::poll_event(Event *event) {
/* internal keypress? */
if (b == KBD_ALT && ev.key.keysym.sym==SDLK_RETURN) {
- set_param(PARAM_TOGGLE_FULLSCREEN, 0);
+ property(PROP_TOGGLE_FULLSCREEN, 0);
break;
}
@@ -679,7 +655,7 @@ bool OSystem_SDL::poll_event(Event *event) {
if (b == (KBD_CTRL|KBD_ALT) &&
ev.key.keysym.sym>='1' && ev.key.keysym.sym<='6') {
- set_param(PARAM_HOTSWAP_GFX_MODE, ev.key.keysym.sym - '1');
+ property(PROP_SET_GFX_MODE, ev.key.keysym.sym - '1');
break;
}
@@ -733,9 +709,19 @@ bool OSystem_SDL::poll_event(Event *event) {
}
}
-void OSystem_SDL::set_sound_proc(void *param, SoundProc *proc) {
- _sound_proc = proc;
- _sound_param = param;
+void OSystem_SDL::set_sound_proc(void *param, SoundProc *proc, byte format) {
+ SDL_AudioSpec desired;
+
+ /* only one format supported at the moment */
+
+ desired.freq = SAMPLES_PER_SEC;
+ desired.format = AUDIO_S16SYS;
+ desired.channels = 1;
+ desired.samples = 2048;
+ desired.callback = proc;
+ desired.userdata = param;
+ SDL_OpenAudio(&desired, NULL);
+ SDL_PauseAudio(0);
}
@@ -806,10 +792,10 @@ void OSystem_SDL::hotswap_gfx_mode() {
OSystem_SDL::update_screen();
}
-uint32 OSystem_SDL::set_param(int param, uint32 value) {
+uint32 OSystem_SDL::property(int param, uint32 value) {
switch(param) {
- case PARAM_TOGGLE_FULLSCREEN:
+ case PROP_TOGGLE_FULLSCREEN:
_full_screen ^= true;
if (!SDL_WM_ToggleFullScreen(sdl_hwscreen)) {
@@ -818,11 +804,11 @@ uint32 OSystem_SDL::set_param(int param, uint32 value) {
}
return 1;
- case PARAM_WINDOW_CAPTION:
+ case PROP_SET_WINDOW_CAPTION:
SDL_WM_SetCaption((char*)value, (char*)value);
return 1;
- case PARAM_OPEN_CD:
+ case PROP_OPEN_CD:
if (SDL_InitSubSystem(SDL_INIT_CDROM) == -1)
cdrom = NULL;
else {
@@ -834,7 +820,7 @@ uint32 OSystem_SDL::set_param(int param, uint32 value) {
}
break;
- case PARAM_HOTSWAP_GFX_MODE:
+ case PROP_SET_GFX_MODE:
if (value >= 6)
return 0;
@@ -843,9 +829,12 @@ uint32 OSystem_SDL::set_param(int param, uint32 value) {
return 1;
- case PARAM_SHOW_DEFAULT_CURSOR:
+ case PROP_SHOW_DEFAULT_CURSOR:
SDL_ShowCursor(value ? SDL_ENABLE : SDL_DISABLE);
break;
+
+ case PROP_GET_SAMPLE_RATE:
+ return SAMPLES_PER_SEC;
}
return 0;
@@ -1027,7 +1016,7 @@ void OSystem_SDL::undraw_mouse() {
class OSystem_NULL : public OSystem {
public:
void set_palette(const byte *colors, uint start, uint num) {}
- void init_size(uint w, uint h, byte sound);
+ void init_size(uint w, uint h);
void copy_rect(const byte *buf, int pitch, int x, int y, int w, int h) {}
void update_screen() {}
bool show_mouse(bool visible) { return false; }
@@ -1038,9 +1027,9 @@ public:
void delay_msecs(uint msecs);
void *create_thread(ThreadProc *proc, void *param) { return NULL; }
bool poll_event(Event *event) { return false; }
- void set_sound_proc(void *param, SoundProc *proc) {}
+ void set_sound_proc(void *param, SoundProc *proc, byte sound) {}
void quit() { exit(1); }
- uint32 set_param(int param, uint32 value) { return 0; }
+ uint32 property(int param, uint32 value) { return 0; }
static OSystem *create(int gfx_mode, bool full_screen);
private:
diff --git a/simon/midi.cpp b/simon/midi.cpp
index d48a03eb48..a83ed65707 100644
--- a/simon/midi.cpp
+++ b/simon/midi.cpp
@@ -23,7 +23,8 @@
#include "stdafx.h"
#include "scummsys.h"
#include "system.h"
-#include "gmidi.h"
+#include "mididrv.h"
+#include "mixer.h"
#include "simon.h"
void MidiPlayer::read_from_file(void *dst, uint size) {
diff --git a/simon/simon.cpp b/simon/simon.cpp
index ada5890267..f673a65e16 100644
--- a/simon/simon.cpp
+++ b/simon/simon.cpp
@@ -23,8 +23,10 @@
#include "stdafx.h"
#include "scummsys.h"
#include "system.h"
+#include "mixer.h"
#include "simon.h"
+
#include <errno.h>
#include <time.h>
#ifdef WIN32
@@ -5034,8 +5036,7 @@ void SimonState::vc_29_stop_all_sounds() {
/* XXX: implement */
// warning("vc_29_stop_all_sounds unimplemented");
- _voice_size = 0;
- _sound_size = 0;
+ _mixer->stop_all();
}
void SimonState::vc_30_set_base_delay() {
@@ -6518,7 +6519,7 @@ bool SimonState::vc_59_helper() {
#else
if (_voice_file==NULL)
return false;
- return _voice_size == 0;
+ return _voice_sound == 0;
#endif
}
@@ -6574,9 +6575,8 @@ void SimonState::readSfxFile(const char *filename) {
rewind(in);
- /* if a sound is playing, stop it */
- _sound_size = 0;
-
+ /* stop all sounds */
+ _mixer->stop_all();
if (_sfx_heap) free(_sfx_heap);
@@ -6595,10 +6595,6 @@ void SimonState::readSfxFile(const char *filename) {
vc_29_stop_all_sounds();
- /* if a sound is playing, stop it */
- _sound_size = 0;
-
-
if (_sfx_heap) free(_sfx_heap);
res = atoi(filename + 6) + gss->SOUND_INDEX_BASE - 1;
@@ -7386,7 +7382,7 @@ void SimonState::openGameFile() {
loadIconFile();
- _system->init_size(320,200,OSystem::SOUND_8BIT);
+ _system->init_size(320,200);
startUp(1);
}
@@ -7411,6 +7407,7 @@ void SimonState::runSubroutine101() {
startUp_helper_2();
}
+#if 0
void SimonState::generateSound(byte *ptr, int len) {
uint cur;
@@ -7438,10 +7435,11 @@ void SimonState::generateSound(byte *ptr, int len) {
_sound_ptr += cur;
}
}
+#endif
-static void fill_sound(void *userdata, int16 *stream, int len) {
- ((SimonState*)userdata)->generateSound((byte*)stream, len*2);
-}
+//static void fill_sound(void *userdata, int16 *stream, int len) {
+// ((SimonState*)userdata)->generateSound((byte*)stream, len*2);
+//}
void SimonState::dx_copy_rgn_from_3_to_2(uint b, uint r, uint y, uint x) {
byte *dst, *src;
@@ -7579,8 +7577,10 @@ void SimonState::go(OSystem *syst, MidiDriver *driver) {
_vga_base_delay = 1;
_vk_t_toggle = true;
- _system->set_param(OSystem::PARAM_SHOW_DEFAULT_CURSOR, 1);
- _system->set_sound_proc(this, fill_sound);
+ _system->property(OSystem::PROP_SHOW_DEFAULT_CURSOR, 1);
+
+ _mixer->bind_to_system(_system);
+ _mixer->set_volume(256);
while(1) {
hitarea_stuff();
@@ -7915,11 +7915,11 @@ void SimonState::playVoice(uint voice) {
// assert(voice < 14496/4);
- _voice_size = 0;
-
if (_voice_offsets == NULL)
return;
+ _mixer->stop(_voice_sound);
+
fseek(_voice_file, _voice_offsets[voice], SEEK_SET);
if (fread(&wave_hdr, sizeof(wave_hdr), 1, _voice_file)!=1 ||
@@ -7937,7 +7937,8 @@ void SimonState::playVoice(uint voice) {
return;
}
- _voice_size = data[1];
+ _mixer->play_raw(&_voice_sound, _voice_file, data[1], wave_hdr.samples_per_sec,
+ SoundMixer::FLAG_FILE|SoundMixer::FLAG_UNSIGNED);
}
@@ -7945,8 +7946,7 @@ void SimonState::playSound(uint sound) {
if (_game & GAME_WIN) {
byte *p;
- /* stop any currently playing sound */
- _sound_size = 0;
+ _mixer->stop(_playing_sound);
/* Check if _sfx_heap is NULL */
if (_sfx_heap == NULL) {
@@ -7968,8 +7968,7 @@ void SimonState::playSound(uint sound) {
p++;
}
- _sound_ptr = p + 8;
- _sound_size = ((uint32*)p)[1];
+ _mixer->play_raw(&_playing_sound, p+8,*(uint32*)(p+4),22050,SoundMixer::FLAG_UNSIGNED);
} else {
warning("playSound(%d)", sound);
}
diff --git a/simon/simon.h b/simon/simon.h
index a4067dad26..a4391e482f 100644
--- a/simon/simon.h
+++ b/simon/simon.h
@@ -1,12 +1,22 @@
-/* Copyright ©2002, The ScummVM Team.
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
*
- * Current status:
- * Save/Load dialog doesn't work. You can still save, but only to ONE slot.
- * There is possibly one or two problems that makes it impossible to finish SIMON1WIN.
- * Sound & Music only works with SIMON1WIN.
- * SIMON1DOS works, but without sound & music.
- * Simon 2 works a little.
- * The code only compiles in win32. It's currently not alignment safe and not endian safe.
*/
/* GFX Settings. Sound & Music only works properly with SIMON1WIN */
@@ -504,10 +514,10 @@ public:
uint _invoke_timer_callback;
- uint32 _voice_size;
+// uint32 _voice_size;
- uint32 _sound_size;
- byte *_sound_ptr;
+// uint32 _sound_size;
+// byte *_sound_ptr;
uint _vga_sprite_changed;
@@ -542,6 +552,8 @@ public:
byte _fcs_data_1[8];
bool _fcs_data_2[8];
+ SoundMixer _mixer[1];
+
ThreeValues _threevalues_1, _threevalues_2, _threevalues_3, _threevalues_4;
int _free_string_slot;
@@ -574,6 +586,9 @@ public:
int _num_screen_updates;
int _vga_tick_counter;
+ PlayingSoundHandle _playing_sound;
+ PlayingSoundHandle _voice_sound;
+
int _timer_id;
FILE *_dump_file;
@@ -994,7 +1009,8 @@ public:
void playVoice(uint voice);
void playSound(uint sound);
- void generateSound(byte *ptr, int len);
+
+// void generateSound(byte *ptr, int len);
void playMusic(uint music);
diff --git a/simon/simonsys.cpp b/simon/simonsys.cpp
index 047a672f71..7d6d54b6c5 100644
--- a/simon/simonsys.cpp
+++ b/simon/simonsys.cpp
@@ -23,6 +23,7 @@
#include "stdafx.h"
#include "scummsys.h"
#include "system.h"
+#include "mixer.h"
#include "simon.h"
#include <stdarg.h>
diff --git a/sound.cpp b/sound.cpp
index 22c14dbad2..1085088abf 100644
--- a/sound.cpp
+++ b/sound.cpp
@@ -22,6 +22,8 @@
#include "stdafx.h"
#include "scumm.h"
+#include "mididrv.h"
+#include "imuse.h"
#include "cdmusic.h"
#ifdef _WIN32_WCE
@@ -54,7 +56,7 @@ void Scumm::processSoundQues()
int i, j;
int num;
int16 data[16];
- SoundEngine *se;
+ IMuse *se;
processSfxQueues();
@@ -77,7 +79,7 @@ void Scumm::processSoundQues()
data[j] = _soundQue[i + j];
i += num;
- se = (SoundEngine *)_soundEngine;
+ se = _imuse;
#if 0
debug(1, "processSoundQues(%d,%d,%d,%d,%d,%d,%d,%d,%d)",
data[0] >> 8,
@@ -100,7 +102,7 @@ void Scumm::processSoundQues()
void Scumm::playSound(int sound)
{
byte *ptr;
- SoundEngine *se = (SoundEngine *)_soundEngine;
+ IMuse *se = _imuse;
ptr = getResourceAddress(rtSound, sound);
if (ptr != NULL && READ_UINT32_UNALIGNED(ptr) == MKID('SOUN')) {
@@ -253,7 +255,7 @@ bool Scumm::isMouthSyncOff(uint pos)
int Scumm::isSoundRunning(int sound)
{
- SoundEngine *se;
+ IMuse *se;
int i;
if (sound == current_cd_sound)
@@ -271,7 +273,7 @@ int Scumm::isSoundRunning(int sound)
if (!isResourceLoaded(rtSound, sound))
return 0;
- se = (SoundEngine *)_soundEngine;
+ se = _imuse;
if (!se)
return 0;
return se->get_sound_status(sound);
@@ -300,7 +302,7 @@ bool Scumm::isSoundInQueue(int sound)
void Scumm::stopSound(int a)
{
- SoundEngine *se;
+ IMuse *se;
int i;
if (a == current_cd_sound) {
@@ -308,7 +310,7 @@ void Scumm::stopSound(int a)
cd_stop();
}
- se = (SoundEngine *)_soundEngine;
+ se = _imuse;
if (se)
se->stop_sound(a);
@@ -319,7 +321,7 @@ void Scumm::stopSound(int a)
void Scumm::stopAllSounds()
{
- SoundEngine *se = (SoundEngine *)_soundEngine;
+ IMuse *se = _imuse;
if (current_cd_sound != 0) {
current_cd_sound = 0;
@@ -376,7 +378,7 @@ void Scumm::talkSound(uint32 a, uint32 b, int mode)
void Scumm::setupSound()
{
- SoundEngine *se = (SoundEngine *)_soundEngine;
+ IMuse *se = _imuse;
if (se) {
se->setBase(res.address[rtSound]);
if (se->get_music_volume() == 0)
@@ -392,7 +394,7 @@ void Scumm::setupSound()
void Scumm::pauseSounds(bool pause)
{
- SoundEngine *se = (SoundEngine *)_soundEngine;
+ IMuse *se = _imuse;
if (se)
se->pause(pause);
_soundsPaused = pause;
@@ -562,84 +564,16 @@ void *Scumm::openSfxFile()
return file;
}
-MixerChannel *Scumm::allocateMixer()
-{
- int i;
- MixerChannel *mc = _mixer_channel;
- for (i = 0; i < NUM_MIXER; i++, mc++) {
- if (!mc->_sfx_sound)
- return mc;
- }
- return NULL;
-}
-
void Scumm::stopSfxSound()
{
- MixerChannel *mc = _mixer_channel;
- int i;
- for (i = 0; i < NUM_MIXER; i++, mc++) {
- if (mc->_sfx_sound)
- mc->clear();
- }
+ _mixer->stop_all();
}
bool Scumm::isSfxFinished()
{
- int i;
- for (i = 0; i < NUM_MIXER; i++)
- if (_mixer_channel[i]._sfx_sound)
- return false;
- return true;
-}
-
-#ifdef COMPRESSED_SOUND_FILE
-void Scumm::playSfxSound_MP3(void *sound, uint32 size)
-{
- MixerChannel *mc = allocateMixer();
-
- if (!mc) {
- warning("No mixer channel available");
- return;
- }
-
- mc->type = MIXER_MP3;
- mc->_sfx_sound = sound;
-
- mad_stream_init(&mc->sound_data.mp3.stream);
-
-
-
-#ifdef _WIN32_WCE
-
- // 11 kHz on WinCE
-
- mad_stream_options((mad_stream *) & mc->sound_data.mp3.stream,
- MAD_OPTION_HALFSAMPLERATE);
-
-#endif
-
-
- mad_frame_init(&mc->sound_data.mp3.frame);
- mad_synth_init(&mc->sound_data.mp3.synth);
- mc->sound_data.mp3.position = 0;
- mc->sound_data.mp3.pos_in_frame = 0xFFFFFFFF;
- mc->sound_data.mp3.size = size;
- /* This variable is the number of samples to cut at the start of the MP3
- file. This is needed to have lip-sync as the MP3 file have some miliseconds
- of blank at the start (as, I suppose, the MP3 compression algorithm need to
- have some silence at the start to really be efficient and to not distort
- too much the start of the sample).
-
- This value was found by experimenting out. If you recompress differently your
- .SO3 file, you may have to change this value.
-
- When using Lame, it seems that the sound starts to have some volume about 50 ms
- from the start of the sound => we skip about 1024 samples.
- */
- mc->sound_data.mp3.silence_cut = 1024;
+ return !_mixer->has_active_channel();
}
-#endif
void Scumm::playBundleSound(char *sound)
{
@@ -648,304 +582,8 @@ void Scumm::playBundleSound(char *sound)
void Scumm::playSfxSound(void *sound, uint32 size, uint rate)
{
- MixerChannel *mc = allocateMixer();
-
- if (!mc) {
- warning("No mixer channel available");
- return;
- }
-
- mc->type = MIXER_STANDARD;
- mc->_sfx_sound = sound;
- mc->sound_data.standard._sfx_pos = 0;
- mc->sound_data.standard._sfx_fp_pos = 0;
-
-#ifdef _WIN32_WCE
- mc->sound_data.standard._sfx_fp_speed = (1 << 16) * rate / 11025;
-#else
- mc->sound_data.standard._sfx_fp_speed = (1 << 16) * rate / 22050;
-#endif
- while (size & 0xFFFF0000)
- size >>= 1, rate >>= 1;
-
-
-#ifdef _WIN32_WCE
- mc->sound_data.standard._sfx_size = size * 11025 / rate;
-#else
- mc->sound_data.standard._sfx_size = size * 22050 / rate;
-#endif
+ _mixer->play_raw(NULL, sound, size, rate, SoundMixer::FLAG_AUTOFREE);
}
-#ifdef COMPRESSED_SOUND_FILE
-static inline int scale_sample(mad_fixed_t sample)
-{
- /* round */
- sample += (1L << (MAD_F_FRACBITS - 16));
- /* clip */
- if (sample >= MAD_F_ONE)
- sample = MAD_F_ONE - 1;
- else if (sample < -MAD_F_ONE)
- sample = -MAD_F_ONE;
- /* quantize and scale to not saturate when mixing a lot of channels */
- return sample >> (MAD_F_FRACBITS + 2 - 16);
-}
-#endif
-
-void MixerChannel::mix(int16 * data, uint32 len)
-{
- if (!_sfx_sound)
- return;
-
-#ifdef COMPRESSED_SOUND_FILE
- if (type == MIXER_STANDARD) {
-#endif
- int8 *s;
- uint32 fp_pos, fp_speed;
-
- if (len > sound_data.standard._sfx_size)
- len = sound_data.standard._sfx_size;
- sound_data.standard._sfx_size -= len;
-
- s = (int8 *) _sfx_sound + sound_data.standard._sfx_pos;
- fp_pos = sound_data.standard._sfx_fp_pos;
- fp_speed = sound_data.standard._sfx_fp_speed;
-
- do {
- fp_pos += fp_speed;
- *data++ += (*s << 6);
- s += fp_pos >> 16;
- fp_pos &= 0x0000FFFF;
- } while (--len);
-
- sound_data.standard._sfx_pos = s - (int8 *) _sfx_sound;
- sound_data.standard._sfx_fp_speed = fp_speed;
- sound_data.standard._sfx_fp_pos = fp_pos;
-
- if (!sound_data.standard._sfx_size)
- clear();
-#ifdef COMPRESSED_SOUND_FILE
- } else {
- if (type == MIXER_MP3) {
- mad_fixed_t const *ch;
- while (1) {
- ch =
- sound_data.mp3.synth.pcm.samples[0] + sound_data.mp3.pos_in_frame;
- while ((sound_data.mp3.pos_in_frame < sound_data.mp3.synth.pcm.length)
- && (len > 0)) {
- if (sound_data.mp3.silence_cut > 0) {
- sound_data.mp3.silence_cut--;
- } else {
- *data++ += scale_sample(*ch++);
- len--;
- }
- sound_data.mp3.pos_in_frame++;
- }
- if (len == 0)
- return;
-
- if (sound_data.mp3.position >= sound_data.mp3.size) {
- clear();
- return;
- }
-
- mad_stream_buffer(&sound_data.mp3.stream,
- ((unsigned char *)_sfx_sound) +
- sound_data.mp3.position,
- sound_data.mp3.size + MAD_BUFFER_GUARD -
- sound_data.mp3.position);
-
- if (mad_frame_decode(&sound_data.mp3.frame, &sound_data.mp3.stream) ==
- -1) {
- /* End of audio... */
- if (sound_data.mp3.stream.error == MAD_ERROR_BUFLEN) {
- clear();
- return;
- } else if (!MAD_RECOVERABLE(sound_data.mp3.stream.error)) {
- error("MAD frame decode error !");
- }
- }
- mad_synth_frame(&sound_data.mp3.synth, &sound_data.mp3.frame);
- sound_data.mp3.pos_in_frame = 0;
- sound_data.mp3.position =
- (unsigned char *)sound_data.mp3.stream.next_frame -
- (unsigned char *)_sfx_sound;
- }
- } else if (type == MIXER_MP3_CDMUSIC) {
- mad_fixed_t const *ch;
- mad_timer_t frame_duration;
- static long last_pos = 0;
-
- if (!sound_data.mp3_cdmusic.playing)
- return;
-
- while (1) {
-
- // See if we just skipped
- if (ftell(sound_data.mp3_cdmusic.file) != last_pos) {
- int skip_loop;
-
- // Read the new data
- memset(_sfx_sound, 0,
- sound_data.mp3_cdmusic.buffer_size + MAD_BUFFER_GUARD);
- sound_data.mp3_cdmusic.size =
- fread(_sfx_sound, 1, sound_data.mp3_cdmusic.buffer_size,
- sound_data.mp3_cdmusic.file);
- if (!sound_data.mp3_cdmusic.size) {
- sound_data.mp3_cdmusic.playing = false;
- return;
- }
- last_pos = ftell(sound_data.mp3_cdmusic.file);
- // Resync
- mad_stream_buffer(&sound_data.mp3_cdmusic.stream,
- (unsigned char *)_sfx_sound,
- sound_data.mp3_cdmusic.size);
- skip_loop = 2;
- while (skip_loop != 0) {
- if (mad_frame_decode(&sound_data.mp3_cdmusic.frame,
- &sound_data.mp3_cdmusic.stream) == 0) {
- /* Do not decrease duration - see if it's a problem */
- skip_loop--;
- if (skip_loop == 0) {
- mad_synth_frame(&sound_data.mp3_cdmusic.synth,
- &sound_data.mp3_cdmusic.frame);
- }
- } else {
- if (!MAD_RECOVERABLE(sound_data.mp3_cdmusic.stream.error)) {
- debug(1, "Unrecoverable error while skipping !");
- sound_data.mp3_cdmusic.playing = false;
- return;
- }
- }
- }
- // We are supposed to be in synch
- mad_frame_mute(&sound_data.mp3_cdmusic.frame);
- mad_synth_mute(&sound_data.mp3_cdmusic.synth);
- // Resume decoding
- if (mad_frame_decode(&sound_data.mp3_cdmusic.frame,
- &sound_data.mp3_cdmusic.stream) == 0) {
- sound_data.mp3_cdmusic.position =
- (unsigned char *)sound_data.mp3_cdmusic.stream.next_frame -
- (unsigned char *)_sfx_sound;
- sound_data.mp3_cdmusic.pos_in_frame = 0;
- } else {
- sound_data.mp3_cdmusic.playing = false;
- return;
- }
- }
- // Get samples, play samples ...
-
- ch = sound_data.mp3_cdmusic.synth.pcm.samples[0] +
- sound_data.mp3_cdmusic.pos_in_frame;
- while ((sound_data.mp3_cdmusic.pos_in_frame <
- sound_data.mp3_cdmusic.synth.pcm.length) && (len > 0)) {
- *data++ += scale_sample(*ch++);
- len--;
- sound_data.mp3_cdmusic.pos_in_frame++;
- }
- if (len == 0) {
- return;
- }
- // See if we have finished
- // May be incorrect to check the size at the end of a frame but I suppose
- // they are short enough :)
-
- frame_duration = sound_data.mp3_cdmusic.frame.header.duration;
-
- mad_timer_negate(&frame_duration);
- mad_timer_add(&sound_data.mp3_cdmusic.duration, frame_duration);
- if (mad_timer_compare(sound_data.mp3_cdmusic.duration, mad_timer_zero)
- < 0) {
- sound_data.mp3_cdmusic.playing = false;
- }
-
- if (mad_frame_decode(&sound_data.mp3_cdmusic.frame,
- &sound_data.mp3_cdmusic.stream) == -1) {
-
- if (sound_data.mp3_cdmusic.stream.error == MAD_ERROR_BUFLEN) {
- int not_decoded;
-
- if (!sound_data.mp3_cdmusic.stream.next_frame) {
- memset(_sfx_sound, 0,
- sound_data.mp3_cdmusic.buffer_size + MAD_BUFFER_GUARD);
- sound_data.mp3_cdmusic.size =
- fread(_sfx_sound, 1, sound_data.mp3_cdmusic.buffer_size,
- sound_data.mp3_cdmusic.file);
- sound_data.mp3_cdmusic.position = 0;
- not_decoded = 0;
- } else {
- not_decoded = sound_data.mp3_cdmusic.stream.bufend -
- sound_data.mp3_cdmusic.stream.next_frame;
- memcpy(_sfx_sound, sound_data.mp3_cdmusic.stream.next_frame,
- not_decoded);
-
- sound_data.mp3_cdmusic.size =
- fread((unsigned char *)_sfx_sound + not_decoded, 1,
- sound_data.mp3_cdmusic.buffer_size - not_decoded,
- sound_data.mp3_cdmusic.file);
- }
- last_pos = ftell(sound_data.mp3_cdmusic.file);
- sound_data.mp3_cdmusic.stream.error = MAD_ERROR_NONE;
- // Restream
- mad_stream_buffer(&sound_data.mp3_cdmusic.stream,
- (unsigned char *)_sfx_sound,
- sound_data.mp3_cdmusic.size + not_decoded);
- if (mad_frame_decode
- (&sound_data.mp3_cdmusic.frame,
- &sound_data.mp3_cdmusic.stream) == -1) {
- debug(1, "Error decoding after restream %d !",
- sound_data.mp3.stream.error);
- }
- } else if (!MAD_RECOVERABLE(sound_data.mp3.stream.error)) {
- error("MAD frame decode error in MP3 CDMUSIC !");
- }
- }
-
- mad_synth_frame(&sound_data.mp3_cdmusic.synth,
- &sound_data.mp3_cdmusic.frame);
- sound_data.mp3_cdmusic.pos_in_frame = 0;
- sound_data.mp3_cdmusic.position =
- (unsigned char *)sound_data.mp3_cdmusic.stream.next_frame -
- (unsigned char *)_sfx_sound;
- }
- }
- }
-#endif
-}
-
-void MixerChannel::clear()
-{
- free(_sfx_sound);
- _sfx_sound = NULL;
-
-#ifdef COMPRESSED_SOUND_FILE
- if (type == MIXER_MP3) {
- mad_synth_finish(&sound_data.mp3.synth);
- mad_frame_finish(&sound_data.mp3.frame);
- mad_stream_finish(&sound_data.mp3.stream);
- }
-#endif
-}
-
-void Scumm::mixWaves(int16 * sounds, int len)
-{
- int i;
-
- memset(sounds, 0, len * sizeof(int16));
-
- if (_soundsPaused)
- return;
-
- SoundEngine *se = (SoundEngine *)_soundEngine;
- if (se) {
- se->driver()->generate_samples(sounds, len);
- }
-
- for (i = NUM_MIXER - 1; i >= 0; i--) {
- _mixer_channel[i].mix(sounds, len);
- }
-
- if (_soundsPaused2)
- memset(sounds, 0x0, len * sizeof(int16));
-}
diff --git a/sound.h b/sound.h
deleted file mode 100644
index 2d4ba7b7e8..0000000000
--- a/sound.h
+++ /dev/null
@@ -1,645 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2001 The ScummVM project
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
- #ifndef SOUND_H
- #define SOUND_H
-
-#include "gmidi.h" /* General Midi */
-
-struct MP3OffsetTable { /* Compressed Sound (.SO3) */
- int org_offset;
- int new_offset;
- int num_tags;
- int compressed_size;
-};
-
-typedef enum { /* Mixer types */
- MIXER_STANDARD,
- MIXER_MP3,
- MIXER_MP3_CDMUSIC
-} MixerType;
-
-struct MixerChannel { /* Mixer Channel */
- void *_sfx_sound;
- MixerType type;
- union {
- struct {
- uint32 _sfx_pos;
- uint32 _sfx_size;
- uint32 _sfx_fp_speed;
- uint32 _sfx_fp_pos;
- } standard;
-#ifdef COMPRESSED_SOUND_FILE
- struct {
- struct mad_stream stream;
- struct mad_frame frame;
- struct mad_synth synth;
- uint32 silence_cut;
- uint32 pos_in_frame;
- uint32 position;
- uint32 size;
- } mp3;
- struct {
- struct mad_stream stream;
- struct mad_frame frame;
- struct mad_synth synth;
- uint32 pos_in_frame;
- uint32 position;
- uint32 size;
- uint32 buffer_size;
- mad_timer_t duration;
- bool playing;
- FILE *file;
- } mp3_cdmusic;
-#endif
- } sound_data;
- void mix(int16 *data, uint32 len);
- void clear();
-};
-
-int clamp(int val, int min, int max);
-
-
-
-struct FM_OPL;
-struct Part;
-struct MidiChannel;
-struct MidiChannelAdl;
-struct MidiChannelGM;
-struct VolumeFader;
-struct Player;
-struct HookDatas;
-struct SoundEngine;
-struct SoundDriver;
-struct Instrument;
-struct AdlibSoundDriver;
-struct MidiSoundDriver;
-
-struct Struct10 {
- byte active;
- int16 cur_val;
- int16 count;
- uint16 param;
- int16 start_value;
- byte loop;
- byte table_a[4];
- byte table_b[4];
- int8 unk3;
- int8 modwheel;
- int8 modwheel_last;
- uint16 speed_lo_max;
- uint16 num_steps;
- int16 speed_hi;
- int8 direction;
- uint16 speed_lo;
- uint16 speed_lo_counter;
-};
-
-struct Struct11 {
- int16 modify_val;
- byte param,flag0x40,flag0x10;
- Struct10 *s10;
-};
-
-struct InstrumentExtra {
- byte a,b,c,d,e,f,g,h;
-};
-
-struct Instrument {
- byte flags_1;
- byte oplvl_1;
- byte atdec_1;
- byte sustrel_1;
- byte waveform_1;
- byte flags_2;
- byte oplvl_2;
- byte atdec_2;
- byte sustrel_2;
- byte waveform_2;
- byte feedback;
- byte flags_a;
- InstrumentExtra extra_a;
- byte flags_b;
- InstrumentExtra extra_b;
- byte duration;
-};
-
-struct Part {
- int _slot;
- SoundDriver *_drv;
- Part *_next, *_prev;
- MidiChannel *_mc;
- Player *_player;
- int16 _pitchbend;
- byte _pitchbend_factor;
- int8 _transpose,_transpose_eff;
- byte _vol,_vol_eff;
- int8 _detune,_detune_eff;
- int8 _pan,_pan_eff;
- bool _on;
- byte _modwheel;
- bool _pedal;
- byte _program;
- int8 _pri;
- byte _pri_eff;
- byte _chan;
- byte _effect_level;
- byte _chorus;
- byte _percussion;
- byte _bank;
-
- void key_on(byte note, byte velocity);
- void key_off(byte note);
- void set_param(byte param, int value);
- void init(SoundDriver *_driver);
- void setup(Player *player);
- void uninit();
- void off();
- void silence();
- void set_instrument(uint b);
- void set_instrument(Instrument *data);
-
- void set_transpose(int8 transpose);
- void set_vol(uint8 volume);
- void set_detune(int8 detune);
- void set_pri(int8 pri);
- void set_pan(int8 pan);
- void set_modwheel(uint value);
- void set_pedal(bool value);
- void set_pitchbend(int value);
- void release_pedal();
- void set_program(byte program);
- void set_chorus(uint chorus);
- void set_effect_level(uint level);
-
- int update_actives(uint16 *active);
- void set_pitchbend_factor(uint8 value);
- void set_onoff(bool on);
- void fix_after_load();
-
- void update_pris();
-
- void changed(byte what);
-};
-
-
-struct MidiChannel {
- Part *_part;
- MidiChannelAdl *adl() { return (MidiChannelAdl*)this; }
- MidiChannelGM *gm() { return (MidiChannelGM*)this; }
-};
-
-struct MidiChannelAdl : MidiChannel {
- MidiChannelAdl *_next,*_prev;
- byte _waitforpedal;
- byte _note;
- byte _channel;
- byte _twochan;
- byte _vol_1,_vol_2;
- int16 _duration;
-
- Struct10 _s10a;
- Struct11 _s11a;
- Struct10 _s10b;
- Struct11 _s11b;
-};
-
-struct MidiChannelGM : MidiChannel {
- byte _chan;
- uint16 _actives[8];
-};
-
-struct VolumeFader {
- Player *player;
- bool active;
- byte curvol;
- uint16 speed_lo_max,num_steps;
- int8 speed_hi;
- int8 direction;
- int8 speed_lo;
- uint16 speed_lo_counter;
-
- void initialize() { active = false; }
- void on_timer();
-};
-
-struct HookDatas {
- byte _jump,_transpose;
- byte _part_onoff[16];
- byte _part_volume[16];
- byte _part_program[16];
- byte _part_transpose[16];
-
- int query_param(int param, byte chan);
- int set(byte cls, byte value, byte chan);
-};
-
-struct Player {
- SoundEngine *_se;
-
- Part *_parts;
- bool _active;
- bool _scanning;
- int _id;
- byte _priority;
- byte _volume;
- int8 _pan;
- int8 _transpose;
- int8 _detune;
- uint _vol_chan;
- byte _vol_eff;
-
- uint _song_index;
- uint _track_index;
- uint _timer_counter;
- uint _loop_to_beat;
- uint _loop_from_beat;
- uint _loop_counter;
- uint _loop_to_tick;
- uint _loop_from_tick;
- uint32 _tempo;
- uint32 _tempo_eff; /* NoSave */
- uint32 _cur_pos;
- uint32 _next_pos;
- uint32 _song_offset;
- uint32 _timer_speed; /* NoSave */
- uint _tick_index;
- uint _beat_index;
- uint _ticks_per_beat;
- byte _speed; /* NoSave */
- bool _abort;
-
- HookDatas _hook;
-
- /* Player part */
- void hook_clear();
- void clear();
- bool start_sound(int sound);
- void uninit_parts();
- byte *parse_midi(byte *s);
- void key_off(uint8 chan, byte data);
- void key_on(uint8 chan, byte data, byte velocity);
- void part_set_transpose(uint8 chan, byte relative, int8 b);
- void parse_sysex(byte *p, uint len);
- void maybe_jump(byte *data);
- void maybe_set_transpose(byte *data);
- void maybe_part_onoff(byte *data);
- void maybe_set_volume(byte *data);
- void maybe_set_program(byte *data);
- void maybe_set_transpose_part(byte *data);
- uint update_actives();
- Part *get_part(uint8 part);
- void turn_off_pedals();
- int set_vol(byte vol);
- int get_param(int param, byte chan);
- int query_part_param(int param, byte chan);
- int set_transpose(byte relative, int b);
- void set_priority(int pri);
- void set_pan(int pan);
- void set_detune(int detune);
- void turn_off_parts();
- void play_active_notes();
- void cancel_volume_fade();
-
- static void decode_sysex_bytes(byte *src, byte *dst, int len);
-
- void clear_active_note(int chan, byte note);
- void set_active_note(int chan, byte note);
- void clear_active_notes();
-
- /* Sequencer part */
- bool set_loop(uint count, uint tobeat, uint totick, uint frombeat, uint fromtick);
- void clear_loop();
- void set_speed(byte speed);
- bool jump(uint track, uint beat, uint tick);
- void uninit_seq();
- void set_tempo(uint32 data);
- int start_seq_sound(int sound);
- void find_sustaining_notes(byte *a, byte *b, uint32 l);
- int scan(uint totrack, uint tobeat, uint totick);
- int query_param(int param);
-
- int fade_vol(byte vol, int time);
- void sequencer_timer();
-};
-
-
-struct SustainingNotes {
- SustainingNotes *next;
- SustainingNotes *prev;
- Player *player;
- byte note,chan;
- uint32 off_pos;
- uint32 pos;
- uint16 counter;
-};
-
-struct CommandQueue {
- uint16 array[8];
-};
-
-struct IsNoteCmdData {
- byte chan;
- byte note;
- byte vel;
-};
-
-struct SoundDriver {
- enum {
- pcMod = 1,
- pcVolume = 2,
- pcPedal = 4,
- pcModwheel = 8,
- pcPan = 16,
- pcEffectLevel = 32,
- pcProgram = 64,
- pcChorus = 128,
- pcAll = 255,
- };
-
- virtual void on_timer() = 0;
- virtual uint32 get_base_tempo() = 0;
- virtual byte get_hardware_type() = 0;
- virtual void init(SoundEngine *eng, OSystem *syst) = 0;
- virtual void update_pris() = 0;
- virtual void set_instrument(uint slot, byte *instr) = 0;
- virtual void part_set_instrument(Part *part, Instrument *instr) = 0;
- virtual void part_key_on(Part *part, byte note, byte velocity) = 0;
- virtual void part_key_off(Part *part, byte note) = 0;
- virtual void part_off(Part *part) = 0;
- virtual void part_changed(Part *part,byte what) = 0;
- virtual void part_set_param(Part *part, byte param, int value) = 0;
- virtual int part_update_active(Part *part,uint16 *active) = 0;
- virtual void generate_samples(int16 *buf, int len) = 0;
-};
-
-struct AdlibSoundDriver : SoundDriver {
-private:
- FM_OPL *_opl;
- byte *_adlib_reg_cache;
- SoundEngine *_se;
-
- int _adlib_timer_counter;
-
- uint16 channel_table_2[9];
- int _midichan_index;
- int _next_tick;
- uint16 curnote_table[9];
- MidiChannelAdl _midi_channels[9];
-
- Instrument _part_instr[32];
- Instrument _glob_instr[32];
-
- void adlib_key_off(int chan);
- void adlib_note_on(int chan, byte note, int mod);
- void adlib_note_on_ex(int chan, byte note, int mod);
- int adlib_read_param(int chan, byte data);
- void adlib_setup_channel(int chan, Instrument *instr, byte vol_1, byte vol_2);
- byte adlib_read(byte port) { return _adlib_reg_cache[port]; }
- void adlib_set_param(int channel, byte param, int value);
- void adlib_key_onoff(int channel);
- void adlib_write(byte port, byte value);
- void adlib_playnote(int channel, int note);
-
- MidiChannelAdl *allocate_midichan(byte pri);
-
- void reset_tick();
- void mc_off(MidiChannel *mc);
-
- static void link_mc(Part *part, MidiChannelAdl *mc);
- static void mc_inc_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11 *s11);
- static void mc_init_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11 *s11, byte flags, InstrumentExtra *ie);
- static void struct10_init(Struct10 *s10, InstrumentExtra *ie);
- static byte struct10_ontimer(Struct10 *s10, Struct11 *s11);
- static void struct10_setup(Struct10 *s10);
- static int random_nr(int a);
- void mc_key_on(MidiChannel *mc, byte note, byte velocity);
-
-public:
- void uninit();
- void init(SoundEngine *eng, OSystem *syst);
- void update_pris() { }
- void generate_samples(int16 *buf, int len);
- void on_timer();
- void set_instrument(uint slot, byte *instr);
- void part_set_instrument(Part *part, Instrument *instr);
- void part_key_on(Part *part, byte note, byte velocity);
- void part_key_off(Part *part, byte note);
- void part_set_param(Part *part, byte param, int value);
- void part_changed(Part *part,byte what);
- void part_off(Part *part);
- int part_update_active(Part *part,uint16 *active);
- void adjust_priorities() {}
-
- uint32 get_base_tempo() {
-#ifdef _WIN32_WCE
- return 0x1F0000 * 2; // Sampled down to 11 kHz
-#else //_WIN32_WCE
- return 0x1924E0;
-#endif //_WIN32_WCE
- }
-
- byte get_hardware_type() { return 1; }
-};
-
-#if 0
-struct MidiDriver {
- bool MidiInitialized;
- int DeviceType;
- int SeqDevice;
- void *_mo; /* midi out */
-
- void midiInit();
- void midiInitTimidity();
- void midiInitSeq();
- void midiInitWindows();
- void midiInitNull();
- void midiInitQuicktime();
-
- void MidiOut(int b);
- void MidiOutSeq(void *a, int b);
- void MidiOutWindows(void *a, int b);
- void MidiOutQuicktime(void *a, int b);
- void MidiOutMorphOS(void *a, int b);
-
- int connect_to_timidity(int port);
- int open_sequencer_device();
-};
-#endif
-
-struct MidiSoundDriver : SoundDriver {
- SoundEngine *_se;
- OSystem *_system;
-
- MidiChannelGM _midi_channels[9];
-
- int16 _midi_pitchbend_last[16];
- uint8 _midi_volume_last[16];
- bool _midi_pedal_last[16];
- byte _midi_modwheel_last[16];
- byte _midi_effectlevel_last[16];
- byte _midi_chorus_last[16];
- int8 _midi_pan_last[16];
-
- MidiDriver *_md;
- void midiPitchBend(byte chan, int16 pitchbend);
- void midiVolume(byte chan, byte volume);
- void midiPedal(byte chan, bool pedal);
- void midiModWheel(byte chan, byte modwheel);
- void midiEffectLevel(byte chan, byte level);
- void midiChorus(byte chan, byte chorus);
- void midiControl0(byte chan, byte value);
- void midiProgram(byte chan, byte program);
- void midiPan(byte chan, int8 pan);
- void midiNoteOn(byte chan, byte note, byte velocity);
- void midiNoteOff(byte chan, byte note);
- void midiSilence(byte chan);
- void midiInit();
-
-public:
- void uninit();
- void init(SoundEngine *eng, OSystem *os);
- void update_pris();
- void part_off(Part *part);
- int part_update_active(Part *part,uint16 *active);
-
- void generate_samples(int16 *buf, int len) {}
- void on_timer() {}
- void set_instrument(uint slot, byte *instr) {}
- void part_set_instrument(Part *part, Instrument *instr) {}
- void part_set_param(Part *part, byte param, int value) {}
- void part_key_on(Part *part, byte note, byte velocity);
- void part_key_off(Part *part, byte note);
- void part_changed(Part *part,byte what);
- void midiSetDriver(MidiDriver *driver);
-
- static int midi_driver_thread(void *param);
-
- uint32 get_base_tempo() { return 0x400000; }
- byte get_hardware_type() { return 5; }
-};
-
-struct SoundEngine {
-friend struct Player;
-private:
- SoundDriver *_driver;
-
- byte **_base_sounds;
-
- Scumm *_s;
-
- byte _locked;
- byte _hardware_type;
-
- bool _paused;
- bool _active_volume_faders;
- bool _initialized;
- byte _volume_fader_counter;
-
- uint _queue_end, _queue_pos, _queue_sound;
- byte _queue_adding;
-
- SustainingNotes *_sustain_notes_used;
- SustainingNotes *_sustain_notes_free;
- SustainingNotes *_sustain_notes_head;
-
- byte _queue_marker;
- byte _queue_cleared;
- byte _master_volume;
- byte _music_volume; /* Global music volume. Percantage */
-
- uint16 _trigger_count;
-
- uint16 _channel_volume[8];
- uint16 _channel_volume_eff[8]; /* NoSave */
- uint16 _volchan_table[8];
-
- Player _players[8];
- SustainingNotes _sustaining_notes[24];
- VolumeFader _volume_fader[8];
- Part _parts[32];
-
- uint16 _active_notes[128];
- CommandQueue _cmd_queue[64];
-
- byte *findTag(int sound, char *tag, int index);
- int get_queue_sound_status(int sound);
- Player *allocate_player(byte priority);
- void handle_marker(uint id, byte data);
- int get_channel_volume(uint a);
- void init_players();
- void init_parts();
- void init_volume_fader();
- void init_sustaining_notes();
- void init_queue();
-
- void sequencer_timers();
- void expire_sustain_notes();
- void expire_volume_faders();
-
- Part *allocate_part(byte pri);
-
- int enqueue_command(int a, int b, int c, int d, int e, int f, int g);
- int enqueue_trigger(int sound, int marker);
- int query_queue(int param);
- Player *get_player_byid(int id);
-
- int get_volchan_entry(uint a);
- int set_volchan_entry(uint a, uint b);
- int set_channel_volume(uint chan, uint vol);
- void update_volumes();
- void reset_tick();
- VolumeFader *allocate_volume_fader();
-
- int set_volchan(int sound, int volchan);
-
- void fix_parts_after_load();
- void fix_players_after_load();
-
- static int saveReference(SoundEngine *me, byte type, void *ref);
- static void *loadReference(SoundEngine *me, byte type, int ref);
-
- void lock();
- void unlock();
-
-public:
- void on_timer();
- Part *parts_ptr() { return _parts; }
- void pause(bool paused);
- int initialize(Scumm *scumm, SoundDriver *driver);
- int terminate();
- int save_or_load(Serializer *ser);
- int set_music_volume(uint vol);
- int get_music_volume();
- int set_master_volume(uint vol);
- int get_master_volume();
- bool start_sound(int sound);
- int stop_sound(int sound);
- int stop_all_sounds();
- int get_sound_status(int sound);
- int32 do_command(int a, int b, int c, int d, int e, int f, int g, int h);
- int clear_queue();
- void setBase(byte **base) { _base_sounds = base; }
-
- SoundDriver *driver() { return _driver; }
- bool _mt32emulate;
-};
-
-
-#endif \ No newline at end of file
diff --git a/sound/adlib.cpp b/sound/adlib.cpp
deleted file mode 100644
index 9700d99255..0000000000
--- a/sound/adlib.cpp
+++ /dev/null
@@ -1,989 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2001 Ludvig Strigeus
- * Copyright (C) 2001/2002 The ScummVM project
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * $Header$
- */
-
-#include "stdafx.h"
-#include "scumm.h"
-#include "fmopl.h"
-
-
-static byte lookup_table[64][32];
-const byte volume_table[] = {
- 0, 4, 7, 11,
- 13, 16, 18, 20,
- 22, 24, 26, 27,
- 29, 30, 31, 33,
- 34, 35, 36, 37,
- 38, 39, 40, 41,
- 42, 43, 44, 44,
- 45, 46, 47, 47,
- 48, 49, 49, 50,
- 51, 51, 52, 53,
- 53, 54, 54, 55,
- 55, 56, 56, 57,
- 57, 58, 58, 59,
- 59, 60, 60, 60,
- 61, 61, 62, 62,
- 62, 63, 63, 63
-};
-
-int lookup_volume(int a, int b)
-{
- if (b == 0)
- return 0;
-
- if (b == 31)
- return a;
-
- if (a < -63 || a > 63) {
- return b * (a + 1) >> 5;
- }
-
- if (b < 0) {
- if (a < 0) {
- return lookup_table[-a][-b];
- } else {
- return -lookup_table[a][-b];
- }
- } else {
- if (a < 0) {
- return -lookup_table[-a][b];
- } else {
- return lookup_table[a][b];
- }
- }
-}
-
-void create_lookup_table()
-{
- int i, j;
- int sum;
-
- for (i = 0; i < 64; i++) {
- sum = i;
- for (j = 0; j < 32; j++) {
- lookup_table[i][j] = sum >> 5;
- sum += i;
- }
- }
- for (i = 0; i < 64; i++)
- lookup_table[i][0] = 0;
-}
-
-MidiChannelAdl *AdlibSoundDriver::allocate_midichan(byte pri)
-{
- MidiChannelAdl *ac, *best = NULL;
- int i;
-
- for (i = 0; i < 9; i++) {
- if (++_midichan_index >= 9)
- _midichan_index = 0;
- ac = &_midi_channels[_midichan_index];
- if (!ac->_part)
- return ac;
- if (!ac->_next) {
- if (ac->_part->_pri_eff <= pri) {
- pri = ac->_part->_pri_eff;
- best = ac;
- }
- }
- }
-
- if (best)
- mc_off(best);
- else; //debug(1, "Denying adlib channel request");
- return best;
-}
-
-void AdlibSoundDriver::init(SoundEngine *eng, OSystem *syst)
-{
- int i;
- MidiChannelAdl *mc;
-
- _se = eng;
-
- for (i = 0, mc = _midi_channels; i != ARRAYSIZE(_midi_channels); i++, mc++) {
- mc->_channel = i;
- mc->_s11a.s10 = &mc->_s10b;
- mc->_s11b.s10 = &mc->_s10a;
- }
-
- _adlib_reg_cache = (byte *)calloc(256, 1);
-
-#ifdef _WIN32_WCE // Poor WIN32 won't handle 22050 well !
- _opl = OPLCreate(OPL_TYPE_YM3812, 3579545, 11025);
-#else
- _opl = OPLCreate(OPL_TYPE_YM3812, 3579545, 22050);
-#endif
- adlib_write(1, 0x20);
- adlib_write(8, 0x40);
- adlib_write(0xBD, 0x00);
- create_lookup_table();
-}
-
-void AdlibSoundDriver::adlib_write(byte port, byte value)
-{
- if (_adlib_reg_cache[port] == value)
- return;
- _adlib_reg_cache[port] = value;
-
- OPLWriteReg(_opl, port, value);
-}
-
-void AdlibSoundDriver::adlib_key_off(int chan)
-{
- byte port = chan + 0xB0;
- adlib_write(port, adlib_read(port) & ~0x20);
-}
-
-struct AdlibSetParams {
- byte a, b, c, d;
-};
-
-static const byte channel_mappings[9] = {
- 0, 1, 2, 8,
- 9, 10, 16, 17,
- 18
-};
-
-static const byte channel_mappings_2[9] = {
- 3, 4, 5, 11,
- 12, 13, 19, 20,
- 21
-};
-
-static const AdlibSetParams adlib_setparam_table[] = {
- {0x40, 0, 63, 63}, /* level */
- {0xE0, 2, 0, 0}, /* unused */
- {0x40, 6, 192, 0}, /* level key scaling */
- {0x20, 0, 15, 0}, /* modulator frequency multiple */
- {0x60, 4, 240, 15}, /* attack rate */
- {0x60, 0, 15, 15}, /* decay rate */
- {0x80, 4, 240, 15}, /* sustain level */
- {0x80, 0, 15, 15}, /* release rate */
- {0xE0, 0, 3, 0}, /* waveform select */
- {0x20, 7, 128, 0}, /* amp mod */
- {0x20, 6, 64, 0}, /* vib */
- {0x20, 5, 32, 0}, /* eg typ */
- {0x20, 4, 16, 0}, /* ksr */
- {0xC0, 0, 1, 0}, /* decay alg */
- {0xC0, 1, 14, 0} /* feedback */
-};
-
-void AdlibSoundDriver::adlib_set_param(int channel, byte param, int value)
-{
- const AdlibSetParams *as;
- byte port;
-
- assert(channel >= 0 && channel < 9);
-
- if (param <= 12) {
- port = channel_mappings_2[channel];
- } else if (param <= 25) {
- param -= 13;
- port = channel_mappings[channel];
- } else if (param <= 27) {
- param -= 13;
- port = channel;
- } else if (param == 28 || param == 29) {
- if (param == 28)
- value -= 15;
- else
- value -= 383;
- value <<= 4;
- channel_table_2[channel] = value;
- adlib_playnote(channel, curnote_table[channel] + value);
- return;
- } else {
- return;
- }
-
- as = &adlib_setparam_table[param];
- if (as->d)
- value = as->d - value;
- port += as->a;
- adlib_write(port, (adlib_read(port) & ~as->c) | (((byte)value) << as->b));
-}
-
-static const byte octave_numbers[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7
-};
-
-static const byte note_numbers[] = {
- 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14,
- 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14,
- 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14,
- 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14,
- 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14,
- 3, 4, 5, 6, 7, 8, 9, 10
-};
-
-static const byte note_to_f_num[] = {
- 90, 91, 92, 92, 93, 94, 94, 95,
- 96, 96, 97, 98, 98, 99, 100, 101,
- 101, 102, 103, 104, 104, 105, 106, 107,
- 107, 108, 109, 110, 111, 111, 112, 113,
- 114, 115, 115, 116, 117, 118, 119, 120,
- 121, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 132, 133, 134,
- 135, 136, 137, 138, 139, 140, 141, 142,
- 143, 145, 146, 147, 148, 149, 150, 151,
- 152, 153, 154, 155, 157, 158, 159, 160,
- 161, 162, 163, 165, 166, 167, 168, 169,
- 171, 172, 173, 174, 176, 177, 178, 180,
- 181, 182, 184, 185, 186, 188, 189, 190,
- 192, 193, 194, 196, 197, 199, 200, 202,
- 203, 205, 206, 208, 209, 211, 212, 214,
- 215, 217, 218, 220, 222, 223, 225, 226,
- 228, 230, 231, 233, 235, 236, 238, 240,
- 242, 243, 245, 247, 249, 251, 252, 254,
-};
-
-void AdlibSoundDriver::adlib_playnote(int channel, int note)
-{
- byte old, oct, notex;
- int note2;
- int i;
-
- note2 = (note >> 7) - 4;
-
- oct = octave_numbers[note2] << 2;
- notex = note_numbers[note2];
-
- old = adlib_read(channel + 0xB0);
- if (old & 0x20) {
- old &= ~0x20;
- if (oct > old) {
- if (notex < 6) {
- notex += 12;
- oct -= 4;
- }
- } else if (oct < old) {
- if (notex > 11) {
- notex -= 12;
- oct += 4;
- }
- }
- }
-
- i = (notex << 3) + ((note >> 4) & 0x7);
- adlib_write(channel + 0xA0, note_to_f_num[i]);
- adlib_write(channel + 0xB0, oct | 0x20);
-}
-
-void AdlibSoundDriver::adlib_note_on(int chan, byte note, int mod)
-{
- int code;
- assert(chan >= 0 && chan < 9);
- code = (note << 7) + mod;
- curnote_table[chan] = code;
- adlib_playnote(chan, channel_table_2[chan] + code);
-}
-
-void AdlibSoundDriver::adlib_note_on_ex(int chan, byte note, int mod)
-{
- int code;
- assert(chan >= 0 && chan < 9);
- code = (note << 7) + mod;
- curnote_table[chan] = code;
- channel_table_2[chan] = 0;
- adlib_playnote(chan, code);
-}
-
-void AdlibSoundDriver::adlib_key_onoff(int channel)
-{
- byte val;
- byte port = channel + 0xB0;
- assert(channel >= 0 && channel < 9);
-
- val = adlib_read(port);
- adlib_write(port, val & ~0x20);
- adlib_write(port, val | 0x20);
-}
-
-void AdlibSoundDriver::adlib_setup_channel(int chan, Instrument * instr,
- byte vol_1, byte vol_2)
-{
- byte port;
-
- assert(chan >= 0 && chan < 9);
-
- port = channel_mappings[chan];
- adlib_write(port + 0x20, instr->flags_1);
- adlib_write(port + 0x40, (instr->oplvl_1 | 0x3F) - vol_1);
- adlib_write(port + 0x60, ~instr->atdec_1);
- adlib_write(port + 0x80, ~instr->sustrel_1);
- adlib_write(port + 0xE0, instr->waveform_1);
-
- port = channel_mappings_2[chan];
- adlib_write(port + 0x20, instr->flags_2);
- adlib_write(port + 0x40, (instr->oplvl_2 | 0x3F) - vol_2);
- adlib_write(port + 0x60, ~instr->atdec_2);
- adlib_write(port + 0x80, ~instr->sustrel_2);
- adlib_write(port + 0xE0, instr->waveform_2);
-
- adlib_write((byte)chan + 0xC0, instr->feedback);
-}
-
-int AdlibSoundDriver::adlib_read_param(int chan, byte param)
-{
- const AdlibSetParams *as;
- byte val;
- byte port;
-
- assert(chan >= 0 && chan < 9);
-
- if (param <= 12) {
- port = channel_mappings_2[chan];
- } else if (param <= 25) {
- param -= 13;
- port = channel_mappings[chan];
- } else if (param <= 27) {
- param -= 13;
- port = chan;
- } else if (param == 28) {
- return 0xF;
- } else if (param == 29) {
- return 0x17F;
- } else {
- return 0;
- }
-
- as = &adlib_setparam_table[param];
- val = adlib_read(port + as->a);
- val &= as->c;
- val >>= as->b;
- if (as->d)
- val = as->d - val;
-
- return val;
-}
-
-void AdlibSoundDriver::generate_samples(int16 * data, int len)
-{
- int step;
-
- if (!_opl) {
- memset(data, 0, len * sizeof(int16));
- return;
- }
-
- do {
- step = len;
- if (step > _next_tick)
- step = _next_tick;
- YM3812UpdateOne(_opl, data, step);
-
- if (!(_next_tick -= step)) {
- _se->on_timer();
- reset_tick();
- }
- data += step;
- } while (len -= step);
-}
-
-void AdlibSoundDriver::reset_tick()
-{
- _next_tick = 88;
-}
-
-void AdlibSoundDriver::on_timer()
-{
- MidiChannelAdl *mc;
- int i;
-
- _adlib_timer_counter += 0xD69;
- while (_adlib_timer_counter >= 0x411B) {
- _adlib_timer_counter -= 0x411B;
- mc = _midi_channels;
- for (i = 0; i != ARRAYSIZE(_midi_channels); i++, mc++) {
- if (!mc->_part)
- continue;
- if (mc->_duration && (mc->_duration -= 0x11) <= 0) {
- mc_off(mc);
- return;
- }
- if (mc->_s10a.active) {
- mc_inc_stuff(mc, &mc->_s10a, &mc->_s11a);
- }
- if (mc->_s10b.active) {
- mc_inc_stuff(mc, &mc->_s10b, &mc->_s11b);
- }
- }
- }
-}
-
-const byte param_table_1[16] = {
- 29, 28, 27, 0,
- 3, 4, 7, 8,
- 13, 16, 17, 20,
- 21, 30, 31, 0
-};
-
-const uint16 param_table_2[16] = {
- 0x2FF, 0x1F, 0x7, 0x3F,
- 0x0F, 0x0F, 0x0F, 0x3,
- 0x3F, 0x0F, 0x0F, 0x0F,
- 0x3, 0x3E, 0x1F, 0
-};
-
-static const uint16 num_steps_table[] = {
- 1, 2, 4, 5,
- 6, 7, 8, 9,
- 10, 12, 14, 16,
- 18, 21, 24, 30,
- 36, 50, 64, 82,
- 100, 136, 160, 192,
- 240, 276, 340, 460,
- 600, 860, 1200, 1600
-};
-
-int AdlibSoundDriver::random_nr(int a)
-{
- static byte _rand_seed = 1;
- if (_rand_seed & 1) {
- _rand_seed >>= 1;
- _rand_seed ^= 0xB8;
- } else {
- _rand_seed >>= 1;
- }
- return _rand_seed * a >> 8;
-}
-
-void AdlibSoundDriver::struct10_setup(Struct10 * s10)
-{
- int b, c, d, e, f, g, h;
- byte t;
-
- b = s10->unk3;
- f = s10->active - 1;
-
- t = s10->table_a[f];
- e = num_steps_table[lookup_table[t & 0x7F][b]];
- if (t & 0x80) {
- e = random_nr(e);
- }
- if (e == 0)
- e++;
-
- s10->num_steps = s10->speed_lo_max = e;
-
- if (f != 2) {
- c = s10->param;
- g = s10->start_value;
- t = s10->table_b[f];
- d = lookup_volume(c, (t & 0x7F) - 31);
- if (t & 0x80) {
- d = random_nr(d);
- }
- if (d + g > c) {
- h = c - g;
- } else {
- h = d;
- if (d + g < 0)
- h = -g;
- }
- h -= s10->cur_val;
- } else {
- h = 0;
- }
-
- s10->speed_hi = h / e;
- if (h < 0) {
- h = -h;
- s10->direction = -1;
- } else {
- s10->direction = 1;
- }
-
- s10->speed_lo = h % e;
- s10->speed_lo_counter = 0;
-}
-
-byte AdlibSoundDriver::struct10_ontimer(Struct10 * s10, Struct11 * s11)
-{
- byte result = 0;
- int i;
-
- if (s10->count && (s10->count -= 17) <= 0) {
- s10->active = 0;
- return 0;
- }
-
- i = s10->cur_val + s10->speed_hi;
- s10->speed_lo_counter += s10->speed_lo;
- if (s10->speed_lo_counter >= s10->speed_lo_max) {
- s10->speed_lo_counter -= s10->speed_lo_max;
- i += s10->direction;
- }
- if (s10->cur_val != i || s10->modwheel != s10->modwheel_last) {
- s10->cur_val = i;
- s10->modwheel_last = s10->modwheel;
- i = lookup_volume(i, s10->modwheel_last);
- if (i != s11->modify_val) {
- s11->modify_val = i;
- result = 1;
- }
- }
-
- if (!--s10->num_steps) {
- s10->active++;
- if (s10->active > 4) {
- if (s10->loop) {
- s10->active = 1;
- result |= 2;
- struct10_setup(s10);
- } else {
- s10->active = 0;
- }
- } else {
- struct10_setup(s10);
- }
- }
-
- return result;
-}
-
-void AdlibSoundDriver::struct10_init(Struct10 * s10, InstrumentExtra * ie)
-{
- s10->active = 1;
- s10->cur_val = 0;
- s10->modwheel_last = 31;
- s10->count = ie->a;
- if (s10->count)
- s10->count *= 63;
- s10->table_a[0] = ie->b;
- s10->table_a[1] = ie->d;
- s10->table_a[2] = ie->f;
- s10->table_a[3] = ie->g;
-
- s10->table_b[0] = ie->c;
- s10->table_b[1] = ie->e;
- s10->table_b[2] = 0;
- s10->table_b[3] = ie->h;
-
- struct10_setup(s10);
-}
-
-void AdlibSoundDriver::mc_init_stuff(MidiChannelAdl *mc, Struct10 * s10,
- Struct11 * s11, byte flags,
- InstrumentExtra * ie)
-{
- Part *part = mc->_part;
-
- s11->modify_val = 0;
- s11->flag0x40 = flags & 0x40;
- s10->loop = flags & 0x20;
- s11->flag0x10 = flags & 0x10;
- s11->param = param_table_1[flags & 0xF];
- s10->param = param_table_2[flags & 0xF];
- s10->unk3 = 31;
- if (s11->flag0x40) {
- s10->modwheel = part->_modwheel >> 2;
- } else {
- s10->modwheel = 31;
- }
-
- switch (s11->param) {
- case 0:
- s10->start_value = mc->_vol_2;
- break;
- case 13:
- s10->start_value = mc->_vol_1;
- break;
- case 30:
- s10->start_value = 31;
- s11->s10->modwheel = 0;
- break;
- case 31:
- s10->start_value = 0;
- s11->s10->unk3 = 0;
- break;
- default:
- s10->start_value = ((AdlibSoundDriver*)part->_drv)->adlib_read_param(mc->_channel, s11->param);
- }
-
- struct10_init(s10, ie);
-}
-
-void AdlibSoundDriver::mc_inc_stuff(MidiChannelAdl *mc, Struct10 * s10,
- Struct11 * s11)
-{
- byte code;
- Part *part = mc->_part;
-
- code = struct10_ontimer(s10, s11);
-
- if (code & 1) {
- switch (s11->param) {
- case 0:
- mc->_vol_2 = s10->start_value + s11->modify_val;
- ((AdlibSoundDriver*)part->_drv)->adlib_set_param(mc->_channel, 0,
- volume_table[lookup_table[mc->_vol_2]
- [part->_vol_eff >> 2]]);
- break;
- case 13:
- mc->_vol_1 = s10->start_value + s11->modify_val;
- if (mc->_twochan) {
- ((AdlibSoundDriver*)part->_drv)->adlib_set_param(mc->_channel, 13,
- volume_table[lookup_table[mc->_vol_1]
- [part->_vol_eff >> 2]]);
- } else {
- ((AdlibSoundDriver*)part->_drv)->adlib_set_param(mc->_channel, 13, mc->_vol_1);
- }
- break;
- case 30:
- s11->s10->modwheel = (char)s11->modify_val;
- break;
- case 31:
- s11->s10->unk3 = (char)s11->modify_val;
- break;
- default:
- ((AdlibSoundDriver*)part->_drv)->adlib_set_param(mc->_channel, s11->param,
- s10->start_value + s11->modify_val);
- break;
- }
- }
-
- if (code & 2 && s11->flag0x10)
- ((AdlibSoundDriver*)part->_drv)->adlib_key_onoff(mc->_channel);
-}
-
-void AdlibSoundDriver::part_changed(Part *part, byte what)
-{
- MidiChannelAdl *mc;
-
- if (what & pcProgram) {
- if (part->_program < 32) {
- part_set_instrument(part, &_glob_instr[part->_program]);
- }
- }
-
- if (what & pcMod) {
- for (mc = part->_mc->adl(); mc; mc = mc->_next) {
- adlib_note_on(mc->_channel, mc->_note + part->_transpose_eff,
- part->_pitchbend + part->_detune_eff);
- }
- }
-
- if (what & pcVolume) {
- for (mc = part->_mc->adl(); mc; mc = mc->_next) {
- adlib_set_param(mc->_channel, 0, volume_table[lookup_table[mc->_vol_2]
- [part->_vol_eff >> 2]]);
- if (mc->_twochan) {
- adlib_set_param(mc->_channel, 13,
- volume_table[lookup_table[mc->_vol_1]
- [part->_vol_eff >> 2]]);
- }
- }
- }
-
- if (what & pcPedal) {
- if (!part->_pedal) {
- for (mc = (MidiChannelAdl *)part->_mc; mc; mc = mc->_next) {
- if (mc->_waitforpedal)
- mc_off(mc);
- }
- }
- }
-
- if (what & pcModwheel) {
- for (mc = (MidiChannelAdl *)part->_mc; mc; mc = mc->_next) {
- if (mc->_s10a.active && mc->_s11a.flag0x40)
- mc->_s10a.modwheel = part->_modwheel >> 2;
- if (mc->_s10b.active && mc->_s11b.flag0x40)
- mc->_s10b.modwheel = part->_modwheel >> 2;
- }
- }
-}
-
-void AdlibSoundDriver::mc_key_on(MidiChannel * mc2, byte note, byte velocity)
-{
- MidiChannelAdl *mc = (MidiChannelAdl *)mc2;
- Part *part = mc->_part;
- Instrument *instr = &_part_instr[part->_slot];
- int c;
- byte vol_1, vol_2;
-
- mc->_twochan = instr->feedback & 1;
- mc->_note = note;
- mc->_waitforpedal = false;
- mc->_duration = instr->duration;
- if (mc->_duration != 0)
- mc->_duration *= 63;
-
- vol_1 =
- (instr->oplvl_1 & 0x3F) +
- lookup_table[velocity >> 1][instr->waveform_1 >> 2];
- if (vol_1 > 0x3F)
- vol_1 = 0x3F;
- mc->_vol_1 = vol_1;
-
- vol_2 =
- (instr->oplvl_2 & 0x3F) +
- lookup_table[velocity >> 1][instr->waveform_2 >> 2];
- if (vol_2 > 0x3F)
- vol_2 = 0x3F;
- mc->_vol_2 = vol_2;
-
- c = part->_vol_eff >> 2;
-
- vol_2 = volume_table[lookup_table[vol_2][c]];
- if (mc->_twochan)
- vol_1 = volume_table[lookup_table[vol_1][c]];
-
- adlib_setup_channel(mc->_channel, instr, vol_1, vol_2);
- adlib_note_on_ex(mc->_channel, part->_transpose_eff + note,
- part->_detune_eff + part->_pitchbend);
-
- if (instr->flags_a & 0x80) {
- mc_init_stuff(mc, &mc->_s10a, &mc->_s11a, instr->flags_a,
- &instr->extra_a);
- } else {
- mc->_s10a.active = 0;
- }
-
- if (instr->flags_b & 0x80) {
- mc_init_stuff(mc, &mc->_s10b, &mc->_s11b, instr->flags_b,
- &instr->extra_b);
- } else {
- mc->_s10b.active = 0;
- }
-}
-
-void AdlibSoundDriver::set_instrument(uint slot, byte *data)
-{
- if (slot < 32) {
- memcpy(&_glob_instr[slot], data, sizeof(Instrument));
- }
-}
-
-
-void AdlibSoundDriver::link_mc(Part *part, MidiChannelAdl *mc)
-{
- mc->_part = part;
- mc->_next = (MidiChannelAdl *)part->_mc;
- part->_mc = mc;
- mc->_prev = NULL;
-
- if (mc->_next)
- mc->_next->_prev = mc;
-}
-
-void AdlibSoundDriver::part_key_on(Part *part, byte note, byte velocity)
-{
- MidiChannelAdl *mc;
-
- mc = allocate_midichan(part->_pri_eff);
- if (!mc)
- return;
-
- link_mc(part, mc);
- mc_key_on(mc, note, velocity);
-}
-
-void AdlibSoundDriver::part_key_off(Part *part, byte note)
-{
- MidiChannelAdl *mc;
-
- for (mc = (MidiChannelAdl *)part->_mc; mc; mc = mc->_next) {
- if (mc->_note == note) {
- if (part->_pedal)
- mc->_waitforpedal = true;
- else
- mc_off(mc);
- }
- }
-}
-
-struct AdlibInstrSetParams {
- byte param;
- byte shl;
- byte mask;
-};
-
-#define MKLINE(_a_,_b_,_c_) { (int)&((Instrument*)0)->_a_, _b_, ((1<<(_c_))-1)<<(_b_) }
-static const AdlibInstrSetParams adlib_instr_params[69] = {
- MKLINE(oplvl_2, 0, 6),
- MKLINE(waveform_2, 2, 5),
- MKLINE(oplvl_2, 6, 2),
- MKLINE(flags_2, 0, 4),
- MKLINE(atdec_2, 4, 4),
- MKLINE(atdec_2, 0, 4),
- MKLINE(sustrel_2, 4, 4),
- MKLINE(sustrel_2, 0, 4),
- MKLINE(waveform_2, 0, 2),
- MKLINE(flags_2, 7, 1),
- MKLINE(flags_2, 6, 1),
- MKLINE(flags_2, 5, 1),
- MKLINE(flags_2, 4, 1),
-
- MKLINE(oplvl_1, 0, 6),
- MKLINE(waveform_1, 2, 5),
- MKLINE(oplvl_1, 6, 2),
- MKLINE(flags_1, 0, 4),
- MKLINE(atdec_1, 4, 4),
- MKLINE(atdec_1, 0, 4),
- MKLINE(sustrel_1, 4, 4),
- MKLINE(sustrel_1, 0, 4),
- MKLINE(waveform_1, 0, 2),
- MKLINE(flags_1, 7, 1),
- MKLINE(flags_1, 6, 1),
- MKLINE(flags_1, 5, 1),
- MKLINE(flags_1, 4, 1),
-
- MKLINE(feedback, 0, 1),
- MKLINE(feedback, 1, 3),
-
- MKLINE(flags_a, 7, 1),
- MKLINE(flags_a, 6, 1),
- MKLINE(flags_a, 5, 1),
- MKLINE(flags_a, 4, 1),
- MKLINE(flags_a, 0, 4),
- MKLINE(extra_a.a, 0, 8),
- MKLINE(extra_a.b, 0, 7),
- MKLINE(extra_a.c, 0, 7),
- MKLINE(extra_a.d, 0, 7),
- MKLINE(extra_a.e, 0, 7),
- MKLINE(extra_a.f, 0, 7),
- MKLINE(extra_a.g, 0, 7),
- MKLINE(extra_a.h, 0, 7),
- MKLINE(extra_a.b, 7, 1),
- MKLINE(extra_a.c, 7, 1),
- MKLINE(extra_a.d, 7, 1),
- MKLINE(extra_a.e, 7, 1),
- MKLINE(extra_a.f, 7, 1),
- MKLINE(extra_a.g, 7, 1),
- MKLINE(extra_a.h, 7, 1),
-
- MKLINE(flags_b, 7, 1),
- MKLINE(flags_b, 6, 1),
- MKLINE(flags_b, 5, 1),
- MKLINE(flags_b, 4, 1),
- MKLINE(flags_b, 0, 4),
- MKLINE(extra_b.a, 0, 8),
- MKLINE(extra_b.b, 0, 7),
- MKLINE(extra_b.c, 0, 7),
- MKLINE(extra_b.d, 0, 7),
- MKLINE(extra_b.e, 0, 7),
- MKLINE(extra_b.f, 0, 7),
- MKLINE(extra_b.g, 0, 7),
- MKLINE(extra_b.h, 0, 7),
- MKLINE(extra_b.b, 7, 1),
- MKLINE(extra_b.c, 7, 1),
- MKLINE(extra_b.d, 7, 1),
- MKLINE(extra_b.e, 7, 1),
- MKLINE(extra_b.f, 7, 1),
- MKLINE(extra_b.g, 7, 1),
- MKLINE(extra_b.h, 7, 1),
-
- MKLINE(duration, 0, 8),
-};
-#undef MKLINE
-
-void AdlibSoundDriver::part_set_param(Part *part, byte param, int value)
-{
- const AdlibInstrSetParams *sp = &adlib_instr_params[param];
- byte *p = (byte *)&_part_instr[part->_slot] + sp->param;
- *p = (*p & ~sp->mask) | (value << sp->shl);
-
- if (param < 28) {
- MidiChannelAdl *mc;
-
- for (mc = (MidiChannelAdl *)part->_mc; mc; mc = mc->_next) {
- adlib_set_param(mc->_channel, param, value);
- }
- }
-}
-
-void AdlibSoundDriver::part_off(Part *part)
-{
- MidiChannelAdl *mc = (MidiChannelAdl *)part->_mc;
- part->_mc = NULL;
- for (; mc; mc = mc->_next) {
- mc_off(mc);
- }
-}
-
-void AdlibSoundDriver::mc_off(MidiChannel * mc2)
-{
- MidiChannelAdl *mc = (MidiChannelAdl *)mc2, *tmp;
-
- adlib_key_off(mc->_channel);
-
- tmp = mc->_prev;
-
- if (mc->_next)
- mc->_next->_prev = tmp;
- if (tmp)
- tmp->_next = mc->_next;
- else
- mc->_part->_mc = mc->_next;
- mc->_part = NULL;
-}
-
-void AdlibSoundDriver::part_set_instrument(Part *part, Instrument * instr)
-{
- Instrument *i = &_part_instr[part->_slot];
- memcpy(i, instr, sizeof(Instrument));
-}
-
-int AdlibSoundDriver::part_update_active(Part *part, uint16 *active)
-{
- uint16 bits;
- int count = 0;
- MidiChannelAdl *mc;
-
- bits = 1 << part->_chan;
-
- for (mc = part->_mc->adl(); mc; mc = mc->_next) {
- if (!(active[mc->_note] & bits)) {
- active[mc->_note] |= bits;
- count++;
- }
- }
- return count;
-}
-
diff --git a/sound/gmidi.cpp b/sound/gmidi.cpp
deleted file mode 100644
index ecd4e560c1..0000000000
--- a/sound/gmidi.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2001 Ludvig Strigeus
- * Copyright (C) 2001/2002 The ScummVM project
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * $Header$
- */
-
-#include "stdafx.h"
-#include "scumm.h"
-#include "gmidi.h"
-
-void MidiSoundDriver::midiSetDriver(MidiDriver *driver)
-{
- _md = driver;
-
- int result = _md->open(MidiDriver::MO_SIMPLE);
- if (result)
- error("MidiSoundDriver::error = %s", MidiDriver::get_error_name(result));
-}
-
-/****************** Common midi code (SCUMM specific) *****************/
-void MidiSoundDriver::midiPitchBend(byte chan, int16 pitchbend)
-{
- uint16 tmp;
-
- if (_midi_pitchbend_last[chan] != pitchbend) {
- _midi_pitchbend_last[chan] = pitchbend;
- tmp = (pitchbend << 2) + 0x2000;
- _md->send(((tmp >> 7) & 0x7F) << 16 | (tmp & 0x7F) << 8 | 0xE0 | chan);
- }
-}
-
-void MidiSoundDriver::midiVolume(byte chan, byte volume)
-{
- if (_midi_volume_last[chan] != volume) {
- _midi_volume_last[chan] = volume;
- _md->send(volume << 16 | 7 << 8 | 0xB0 | chan);
- }
-}
-void MidiSoundDriver::midiPedal(byte chan, bool pedal)
-{
- if (_midi_pedal_last[chan] != pedal) {
- _midi_pedal_last[chan] = pedal;
- _md->send(pedal << 16 | 64 << 8 | 0xB0 | chan);
- }
-}
-
-void MidiSoundDriver::midiModWheel(byte chan, byte modwheel)
-{
- if (_midi_modwheel_last[chan] != modwheel) {
- _midi_modwheel_last[chan] = modwheel;
- _md->send(modwheel << 16 | 1 << 8 | 0xB0 | chan);
- }
-}
-
-void MidiSoundDriver::midiEffectLevel(byte chan, byte level)
-{
- if (_midi_effectlevel_last[chan] != level) {
- _midi_effectlevel_last[chan] = level;
- _md->send(level << 16 | 91 << 8 | 0xB0 | chan);
- }
-}
-
-void MidiSoundDriver::midiChorus(byte chan, byte chorus)
-{
- if (_midi_chorus_last[chan] != chorus) {
- _midi_chorus_last[chan] = chorus;
- _md->send(chorus << 16 | 93 << 8 | 0xB0 | chan);
- }
-}
-
-void MidiSoundDriver::midiControl0(byte chan, byte value)
-{
- _md->send(value << 16 | 0 << 8 | 0xB0 | chan);
-}
-
-void MidiSoundDriver::midiProgram(byte chan, byte program)
-{
- if ((chan + 1) != 10) { /* Ignore percussion prededed by patch change */
- if (_se->_mt32emulate)
- program = mt32_to_gmidi[program];
-
- _md->send(program << 8 | 0xC0 | chan);
- }
-}
-
-void MidiSoundDriver::midiPan(byte chan, int8 pan)
-{
- if (_midi_pan_last[chan] != pan) {
- _midi_pan_last[chan] = pan;
- _md->send(((pan - 64) & 0x7F) << 16 | 10 << 8 | 0xB0 | chan);
- }
-}
-
-void MidiSoundDriver::midiNoteOn(byte chan, byte note, byte velocity)
-{
- _md->send(velocity << 16 | note << 8 | 0x90 | chan);
-}
-
-void MidiSoundDriver::midiNoteOff(byte chan, byte note)
-{
- _md->send(note << 8 | 0x80 | chan);
-}
-
-void MidiSoundDriver::midiSilence(byte chan)
-{
- _md->send((64 << 8) | 0xB0 | chan);
- _md->send((123 << 8) | 0xB0 | chan);
-}
-
-
-void MidiSoundDriver::part_key_on(Part *part, byte note, byte velocity)
-{
- MidiChannelGM *mc = part->_mc->gm();
-
- if (mc) {
- mc->_actives[note >> 4] |= (1 << (note & 0xF));
- midiNoteOn(mc->_chan, note, velocity);
- } else if (part->_percussion) {
- midiVolume(SPECIAL_CHANNEL, part->_vol_eff);
- midiProgram(SPECIAL_CHANNEL, part->_bank);
- midiNoteOn(SPECIAL_CHANNEL, note, velocity);
- }
-}
-
-void MidiSoundDriver::part_key_off(Part *part, byte note)
-{
- MidiChannelGM *mc = part->_mc->gm();
-
- if (mc) {
- mc->_actives[note >> 4] &= ~(1 << (note & 0xF));
- midiNoteOff(mc->_chan, note);
- } else if (part->_percussion) {
- midiNoteOff(SPECIAL_CHANNEL, note);
- }
-}
-
-int MidiSoundDriver::midi_driver_thread(void *param) {
- MidiSoundDriver *mid = (MidiSoundDriver*) param;
- int old_time, cur_time;
-
- old_time = mid->_system->get_msecs();
-
- for(;;) {
- mid->_system->delay_msecs(10);
-
- cur_time = mid->_system->get_msecs();
- while (old_time < cur_time) {
- old_time += 10;
- mid->_se->on_timer();
- }
- }
-}
-
-void MidiSoundDriver::init(SoundEngine *eng, OSystem *syst)
-{
- int i;
- MidiChannelGM *mc;
-
- _system = syst;
-
- /* Install the on_timer thread */
- syst->create_thread(midi_driver_thread, this);
- _se = eng;
-
- for (i = 0, mc = _midi_channels; i != ARRAYSIZE(_midi_channels); i++, mc++)
- mc->_chan = i;
-}
-
-void MidiSoundDriver::update_pris()
-{
- Part *part, *hipart;
- int i;
- byte hipri, lopri;
- MidiChannelGM *mc, *lomc;
-
- while (true) {
- hipri = 0;
- hipart = NULL;
- for (i = 32, part = _se->parts_ptr(); i; i--, part++) {
- if (part->_player && !part->_percussion && part->_on && !part->_mc
- && part->_pri_eff >= hipri) {
- hipri = part->_pri_eff;
- hipart = part;
- }
- }
-
- if (!hipart)
- return;
-
- lopri = 255;
- lomc = NULL;
- for (i = ARRAYSIZE(_midi_channels), mc = _midi_channels;; mc++) {
- if (!mc->_part) {
- lomc = mc;
- break;
- }
- if (mc->_part->_pri_eff <= lopri) {
- lopri = mc->_part->_pri_eff;
- lomc = mc;
- }
-
- if (!--i) {
- if (lopri >= hipri)
- return;
- lomc->_part->off();
- break;
- }
- }
-
- hipart->_mc = lomc;
- lomc->_part = hipart;
- hipart->changed(pcAll);
- }
-}
-
-int MidiSoundDriver::part_update_active(Part *part, uint16 *active)
-{
- int i, j;
- uint16 *act, mask, bits;
- int count = 0;
-
- bits = 1 << part->_chan;
-
- act = part->_mc->gm()->_actives;
-
- for (i = 8; i; i--) {
- mask = *act++;
- if (mask) {
- for (j = 16; j; j--, mask >>= 1, active++) {
- if (mask & 1 && !(*active & bits)) {
- *active |= bits;
- count++;
- }
- }
- } else {
- active += 16;
- }
- }
- return count;
-}
-
-void MidiSoundDriver::part_changed(Part *part, byte what)
-{
- MidiChannelGM *mc;
-
- /* Mark for re-schedule if program changed when in pre-state */
- if (what & pcProgram && part->_percussion) {
- part->_percussion = false;
- update_pris();
- }
-
- if (!(mc = part->_mc->gm()))
- return;
-
- if (what & pcMod)
- midiPitchBend(mc->_chan,
- clamp(part->_pitchbend + part->_detune_eff +
- (part->_transpose_eff << 7), -2048, 2047));
-
- if (what & pcVolume)
- midiVolume(mc->_chan, part->_vol_eff);
-
- if (what & pcPedal)
- midiPedal(mc->_chan, part->_pedal);
-
- if (what & pcModwheel)
- midiModWheel(mc->_chan, part->_modwheel);
-
- if (what & pcPan)
- midiPan(mc->_chan, part->_pan_eff);
-
- if (what & pcEffectLevel)
- midiEffectLevel(mc->_chan, part->_effect_level);
-
- if (what & pcProgram) {
- if (part->_bank) {
- midiControl0(mc->_chan, part->_bank);
- midiProgram(mc->_chan, part->_program);
- midiControl0(mc->_chan, 0);
- } else {
- midiProgram(mc->_chan, part->_program);
- }
- }
-
- if (what & pcChorus)
- midiChorus(mc->_chan, part->_effect_level);
-}
-
-
-void MidiSoundDriver::part_off(Part *part)
-{
- MidiChannelGM *mc = part->_mc->gm();
- if (mc) {
- part->_mc = NULL;
- mc->_part = NULL;
- memset(mc->_actives, 0, sizeof(mc->_actives));
- midiSilence(mc->_chan);
- }
-}
diff --git a/sound/imuse.cpp b/sound/imuse.cpp
index b91b8a845c..5f621466fe 100644
--- a/sound/imuse.cpp
+++ b/sound/imuse.cpp
@@ -20,8 +20,9 @@
*/
#include "stdafx.h"
-
#include "scumm.h"
+#include "fmopl.h"
+#include "mididrv.h"
int num_mix;
@@ -36,7 +37,603 @@ int num_mix;
#define MDPG_TAG "MDpg"
#define MDHD_TAG "MDhd"
-int clamp(int val, int min, int max)
+/* Roland to General Midi patch table. Still needs much work. */
+static const byte mt32_to_gmidi[128] = {
+ 0, 1, 2, 4, 4, 5, 5, 3, 16, 17, 18, 18, 19,
+ 19, 20, 21, 6, 6, 6, 7, 7, 7, 8, 8, 62, 63,
+ 62, 63, 38, 39, 38, 39, 88, 89, 52, 113, 97, 96, 91,
+ 85, 14, 101, 68, 95, 86, 103, 88, 80, 48, 49, 51, 45,
+ 40, 40, 42, 42, 43, 46, 46, 24, 25, 26, 27, 104, 32,
+ 33, 34, 39, 36, 37, 38, 35, 79, 73, 72, 72, 74, 75,
+ 64, 65, 66, 67, 71, 71, 68, 69, 70, 22, 56, 59, 57,
+ 63, 60, 60, 58, 61, 61, 11, 11, 12, 88, 9, 14, 13,
+ 12, 107, 111, 77, 78, 78, 76, 121, 47, 117, 127, 115, 118,
+ 116, 118, 94, 115, 9, 55, 124, 123, 125, 126, 127
+};
+
+
+
+/* Put IMUSE specific classes here, instead of in a .h file
+ * they will only be used from this file, so it will reduce
+ * compile time */
+
+class IMuse;
+class IMuseDriver;
+
+struct Part;
+struct MidiChannelAdl;
+struct MidiChannelGM;
+struct Instrument;
+
+
+struct HookDatas {
+ byte _jump,_transpose;
+ byte _part_onoff[16];
+ byte _part_volume[16];
+ byte _part_program[16];
+ byte _part_transpose[16];
+
+ int query_param(int param, byte chan);
+ int set(byte cls, byte value, byte chan);
+};
+
+
+struct Player {
+ IMuse *_se;
+
+ Part *_parts;
+ bool _active;
+ bool _scanning;
+ int _id;
+ byte _priority;
+ byte _volume;
+ int8 _pan;
+ int8 _transpose;
+ int8 _detune;
+ uint _vol_chan;
+ byte _vol_eff;
+
+ uint _song_index;
+ uint _track_index;
+ uint _timer_counter;
+ uint _loop_to_beat;
+ uint _loop_from_beat;
+ uint _loop_counter;
+ uint _loop_to_tick;
+ uint _loop_from_tick;
+ uint32 _tempo;
+ uint32 _tempo_eff; /* NoSave */
+ uint32 _cur_pos;
+ uint32 _next_pos;
+ uint32 _song_offset;
+ uint32 _timer_speed; /* NoSave */
+ uint _tick_index;
+ uint _beat_index;
+ uint _ticks_per_beat;
+ byte _speed; /* NoSave */
+ bool _abort;
+
+ HookDatas _hook;
+
+ /* Player part */
+ void hook_clear();
+ void clear();
+ bool start_sound(int sound);
+ void uninit_parts();
+ byte *parse_midi(byte *s);
+ void key_off(uint8 chan, byte data);
+ void key_on(uint8 chan, byte data, byte velocity);
+ void part_set_transpose(uint8 chan, byte relative, int8 b);
+ void parse_sysex(byte *p, uint len);
+ void maybe_jump(byte *data);
+ void maybe_set_transpose(byte *data);
+ void maybe_part_onoff(byte *data);
+ void maybe_set_volume(byte *data);
+ void maybe_set_program(byte *data);
+ void maybe_set_transpose_part(byte *data);
+ uint update_actives();
+ Part *get_part(uint8 part);
+ void turn_off_pedals();
+ int set_vol(byte vol);
+ int get_param(int param, byte chan);
+ int query_part_param(int param, byte chan);
+ int set_transpose(byte relative, int b);
+ void set_priority(int pri);
+ void set_pan(int pan);
+ void set_detune(int detune);
+ void turn_off_parts();
+ void play_active_notes();
+ void cancel_volume_fade();
+
+ static void decode_sysex_bytes(byte *src, byte *dst, int len);
+
+ void clear_active_note(int chan, byte note);
+ void set_active_note(int chan, byte note);
+ void clear_active_notes();
+
+ /* Sequencer part */
+ bool set_loop(uint count, uint tobeat, uint totick, uint frombeat, uint fromtick);
+ void clear_loop();
+ void set_speed(byte speed);
+ bool jump(uint track, uint beat, uint tick);
+ void uninit_seq();
+ void set_tempo(uint32 data);
+ int start_seq_sound(int sound);
+ void find_sustaining_notes(byte *a, byte *b, uint32 l);
+ int scan(uint totrack, uint tobeat, uint totick);
+ int query_param(int param);
+
+ int fade_vol(byte vol, int time);
+ void sequencer_timer();
+};
+
+struct VolumeFader {
+ Player *player;
+ bool active;
+ byte curvol;
+ uint16 speed_lo_max,num_steps;
+ int8 speed_hi;
+ int8 direction;
+ int8 speed_lo;
+ uint16 speed_lo_counter;
+
+ void initialize() { active = false; }
+ void on_timer();
+};
+
+struct SustainingNotes {
+ SustainingNotes *next;
+ SustainingNotes *prev;
+ Player *player;
+ byte note,chan;
+ uint32 off_pos;
+ uint32 pos;
+ uint16 counter;
+};
+
+struct CommandQueue {
+ uint16 array[8];
+};
+
+
+struct IsNoteCmdData {
+ byte chan;
+ byte note;
+ byte vel;
+};
+
+
+
+struct MidiChannel {
+ Part *_part;
+ MidiChannelAdl *adl() { return (MidiChannelAdl*)this; }
+ MidiChannelGM *gm() { return (MidiChannelGM*)this; }
+};
+
+
+struct MidiChannelGM : MidiChannel {
+ byte _chan;
+ uint16 _actives[8];
+};
+
+
+struct Part {
+ int _slot;
+ IMuseDriver *_drv;
+ Part *_next, *_prev;
+ MidiChannel *_mc;
+ Player *_player;
+ int16 _pitchbend;
+ byte _pitchbend_factor;
+ int8 _transpose,_transpose_eff;
+ byte _vol,_vol_eff;
+ int8 _detune,_detune_eff;
+ int8 _pan,_pan_eff;
+ bool _on;
+ byte _modwheel;
+ bool _pedal;
+ byte _program;
+ int8 _pri;
+ byte _pri_eff;
+ byte _chan;
+ byte _effect_level;
+ byte _chorus;
+ byte _percussion;
+ byte _bank;
+
+ void key_on(byte note, byte velocity);
+ void key_off(byte note);
+ void set_param(byte param, int value);
+ void init(IMuseDriver *_driver);
+ void setup(Player *player);
+ void uninit();
+ void off();
+ void silence();
+ void set_instrument(uint b);
+ void set_instrument(Instrument *data);
+
+ void set_transpose(int8 transpose);
+ void set_vol(uint8 volume);
+ void set_detune(int8 detune);
+ void set_pri(int8 pri);
+ void set_pan(int8 pan);
+ void set_modwheel(uint value);
+ void set_pedal(bool value);
+ void set_pitchbend(int value);
+ void release_pedal();
+ void set_program(byte program);
+ void set_chorus(uint chorus);
+ void set_effect_level(uint level);
+
+ int update_actives(uint16 *active);
+ void set_pitchbend_factor(uint8 value);
+ void set_onoff(bool on);
+ void fix_after_load();
+
+ void update_pris();
+
+ void changed(byte what);
+};
+
+/* Abstract IMuse driver class */
+class IMuseDriver {
+public:
+ enum {
+ pcMod = 1,
+ pcVolume = 2,
+ pcPedal = 4,
+ pcModwheel = 8,
+ pcPan = 16,
+ pcEffectLevel = 32,
+ pcProgram = 64,
+ pcChorus = 128,
+ pcAll = 255,
+ };
+
+ virtual void on_timer() = 0;
+ virtual uint32 get_base_tempo() = 0;
+ virtual byte get_hardware_type() = 0;
+ virtual void init(IMuse *eng, OSystem *syst) = 0;
+ virtual void update_pris() = 0;
+ virtual void set_instrument(uint slot, byte *instr) = 0;
+ virtual void part_set_instrument(Part *part, Instrument *instr) = 0;
+ virtual void part_key_on(Part *part, byte note, byte velocity) = 0;
+ virtual void part_key_off(Part *part, byte note) = 0;
+ virtual void part_off(Part *part) = 0;
+ virtual void part_changed(Part *part,byte what) = 0;
+ virtual void part_set_param(Part *part, byte param, int value) = 0;
+ virtual int part_update_active(Part *part,uint16 *active) = 0;
+};
+
+
+// WARNING: This is the internal variant of the IMUSE class.
+// imuse.h contains a public version of the same class.
+// the public version, only contains a set of methods.
+class IMuse {
+friend struct Player;
+private:
+ IMuseDriver *_driver;
+
+ byte **_base_sounds;
+
+ byte _locked;
+ byte _hardware_type;
+
+public:
+ bool _mt32emulate;
+private:
+
+
+ bool _paused;
+ bool _active_volume_faders;
+ bool _initialized;
+ byte _volume_fader_counter;
+
+ int _game_tempo;
+
+ uint _queue_end, _queue_pos, _queue_sound;
+ byte _queue_adding;
+
+ SustainingNotes *_sustain_notes_used;
+ SustainingNotes *_sustain_notes_free;
+ SustainingNotes *_sustain_notes_head;
+
+ byte _queue_marker;
+ byte _queue_cleared;
+ byte _master_volume;
+ byte _music_volume; /* Global music volume. Percantage */
+
+ uint16 _trigger_count;
+
+ uint16 _channel_volume[8];
+ uint16 _channel_volume_eff[8]; /* NoSave */
+ uint16 _volchan_table[8];
+
+ Player _players[8];
+ SustainingNotes _sustaining_notes[24];
+ VolumeFader _volume_fader[8];
+ Part _parts[32];
+
+ uint16 _active_notes[128];
+ CommandQueue _cmd_queue[64];
+
+ byte *findTag(int sound, char *tag, int index);
+ int get_queue_sound_status(int sound);
+ Player *allocate_player(byte priority);
+ void handle_marker(uint id, byte data);
+ int get_channel_volume(uint a);
+ void init_players();
+ void init_parts();
+ void init_volume_fader();
+ void init_sustaining_notes();
+ void init_queue();
+
+ void sequencer_timers();
+ void expire_sustain_notes();
+ void expire_volume_faders();
+
+ Part *allocate_part(byte pri);
+
+ int enqueue_command(int a, int b, int c, int d, int e, int f, int g);
+ int enqueue_trigger(int sound, int marker);
+ int query_queue(int param);
+ Player *get_player_byid(int id);
+
+ int get_volchan_entry(uint a);
+ int set_volchan_entry(uint a, uint b);
+ int set_channel_volume(uint chan, uint vol);
+ void update_volumes();
+ void reset_tick();
+ VolumeFader *allocate_volume_fader();
+
+ int set_volchan(int sound, int volchan);
+
+ void fix_parts_after_load();
+ void fix_players_after_load(Scumm *scumm);
+
+ static int saveReference(IMuse *me, byte type, void *ref);
+ static void *loadReference(IMuse *me, byte type, int ref);
+
+ void lock();
+ void unlock();
+
+public:
+ Part *parts_ptr() { return _parts; }
+ IMuseDriver *driver() { return _driver; }
+
+ int initialize(OSystem *syst, MidiDriver *midi, SoundMixer *mixer);
+
+ /* Public interface */
+
+ enum {
+ PROP_TEMPO_BASE = 1,
+ PROP_MT32_EMULATE = 2,
+ };
+
+ void on_timer();
+ void pause(bool paused);
+ int terminate();
+ int save_or_load(Serializer *ser, Scumm *scumm);
+ int set_music_volume(uint vol);
+ int get_music_volume();
+ int set_master_volume(uint vol);
+ int get_master_volume();
+ bool start_sound(int sound);
+ int stop_sound(int sound);
+ int stop_all_sounds();
+ int get_sound_status(int sound);
+ int32 do_command(int a, int b, int c, int d, int e, int f, int g, int h);
+ int clear_queue();
+ void setBase(byte **base);
+
+ uint32 property(int prop, uint32 value);
+
+ static IMuse *create(OSystem *syst, MidiDriver *midi, SoundMixer *mixer);
+};
+
+
+/* IMuseAdlib classes */
+
+struct Struct10 {
+ byte active;
+ int16 cur_val;
+ int16 count;
+ uint16 param;
+ int16 start_value;
+ byte loop;
+ byte table_a[4];
+ byte table_b[4];
+ int8 unk3;
+ int8 modwheel;
+ int8 modwheel_last;
+ uint16 speed_lo_max;
+ uint16 num_steps;
+ int16 speed_hi;
+ int8 direction;
+ uint16 speed_lo;
+ uint16 speed_lo_counter;
+};
+
+struct Struct11 {
+ int16 modify_val;
+ byte param,flag0x40,flag0x10;
+ Struct10 *s10;
+};
+
+struct InstrumentExtra {
+ byte a,b,c,d,e,f,g,h;
+};
+
+struct Instrument {
+ byte flags_1;
+ byte oplvl_1;
+ byte atdec_1;
+ byte sustrel_1;
+ byte waveform_1;
+ byte flags_2;
+ byte oplvl_2;
+ byte atdec_2;
+ byte sustrel_2;
+ byte waveform_2;
+ byte feedback;
+ byte flags_a;
+ InstrumentExtra extra_a;
+ byte flags_b;
+ InstrumentExtra extra_b;
+ byte duration;
+};
+
+struct MidiChannelAdl : MidiChannel {
+ MidiChannelAdl *_next,*_prev;
+ byte _waitforpedal;
+ byte _note;
+ byte _channel;
+ byte _twochan;
+ byte _vol_1,_vol_2;
+ int16 _duration;
+
+ Struct10 _s10a;
+ Struct11 _s11a;
+ Struct10 _s10b;
+ Struct11 _s11b;
+};
+
+struct IMuseAdlib : public IMuseDriver {
+private:
+ FM_OPL *_opl;
+ byte *_adlib_reg_cache;
+ IMuse *_se;
+ SoundMixer *_mixer;
+
+ int _adlib_timer_counter;
+
+ uint16 channel_table_2[9];
+ int _midichan_index;
+ int _next_tick;
+ uint16 curnote_table[9];
+ MidiChannelAdl _midi_channels[9];
+
+ Instrument _part_instr[32];
+ Instrument _glob_instr[32];
+
+ void adlib_key_off(int chan);
+ void adlib_note_on(int chan, byte note, int mod);
+ void adlib_note_on_ex(int chan, byte note, int mod);
+ int adlib_read_param(int chan, byte data);
+ void adlib_setup_channel(int chan, Instrument *instr, byte vol_1, byte vol_2);
+ byte adlib_read(byte port) { return _adlib_reg_cache[port]; }
+ void adlib_set_param(int channel, byte param, int value);
+ void adlib_key_onoff(int channel);
+ void adlib_write(byte port, byte value);
+ void adlib_playnote(int channel, int note);
+
+ MidiChannelAdl *allocate_midichan(byte pri);
+
+ void reset_tick();
+ void mc_off(MidiChannel *mc);
+
+ static void link_mc(Part *part, MidiChannelAdl *mc);
+ static void mc_inc_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11 *s11);
+ static void mc_init_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11 *s11, byte flags, InstrumentExtra *ie);
+ static void struct10_init(Struct10 *s10, InstrumentExtra *ie);
+ static byte struct10_ontimer(Struct10 *s10, Struct11 *s11);
+ static void struct10_setup(Struct10 *s10);
+ static int random_nr(int a);
+ void mc_key_on(MidiChannel *mc, byte note, byte velocity);
+
+ static void premix_proc(void *param, int16 *buf, uint len);
+
+public:
+ IMuseAdlib(SoundMixer *mixer) { _mixer = mixer; }
+ void uninit();
+ void init(IMuse *eng, OSystem *syst);
+ void update_pris() { }
+ void generate_samples(int16 *buf, int len);
+ void on_timer();
+ void set_instrument(uint slot, byte *instr);
+ void part_set_instrument(Part *part, Instrument *instr);
+ void part_key_on(Part *part, byte note, byte velocity);
+ void part_key_off(Part *part, byte note);
+ void part_set_param(Part *part, byte param, int value);
+ void part_changed(Part *part,byte what);
+ void part_off(Part *part);
+ int part_update_active(Part *part,uint16 *active);
+ void adjust_priorities() {}
+
+ uint32 get_base_tempo() {
+#ifdef _WIN32_WCE
+ return 0x1F0000 * 2; // Sampled down to 11 kHz
+#else //_WIN32_WCE
+ return 0x1924E0;
+#endif //_WIN32_WCE
+ }
+
+ byte get_hardware_type() { return 1; }
+};
+
+
+/* IMuseGM classes */
+
+class IMuseGM : public IMuseDriver {
+ IMuse *_se;
+ OSystem *_system;
+ MidiDriver *_md;
+ MidiChannelGM _midi_channels[9];
+
+ int16 _midi_pitchbend_last[16];
+ uint8 _midi_volume_last[16];
+ bool _midi_pedal_last[16];
+ byte _midi_modwheel_last[16];
+ byte _midi_effectlevel_last[16];
+ byte _midi_chorus_last[16];
+ int8 _midi_pan_last[16];
+
+
+ void midiPitchBend(byte chan, int16 pitchbend);
+ void midiVolume(byte chan, byte volume);
+ void midiPedal(byte chan, bool pedal);
+ void midiModWheel(byte chan, byte modwheel);
+ void midiEffectLevel(byte chan, byte level);
+ void midiChorus(byte chan, byte chorus);
+ void midiControl0(byte chan, byte value);
+ void midiProgram(byte chan, byte program);
+ void midiPan(byte chan, int8 pan);
+ void midiNoteOn(byte chan, byte note, byte velocity);
+ void midiNoteOff(byte chan, byte note);
+ void midiSilence(byte chan);
+ void midiInit();
+
+public:
+ IMuseGM(MidiDriver *midi) { _md = midi; }
+
+ void uninit();
+ void init(IMuse *eng, OSystem *os);
+ void update_pris();
+ void part_off(Part *part);
+ int part_update_active(Part *part,uint16 *active);
+
+ void on_timer() {}
+ void set_instrument(uint slot, byte *instr) {}
+ void part_set_instrument(Part *part, Instrument *instr) {}
+ void part_set_param(Part *part, byte param, int value) {}
+ void part_key_on(Part *part, byte note, byte velocity);
+ void part_key_off(Part *part, byte note);
+ void part_changed(Part *part,byte what);
+
+ static int midi_driver_thread(void *param);
+
+ uint32 get_base_tempo() { return 0x400000; }
+ byte get_hardware_type() { return 5; }
+};
+
+
+
+//*********************************
+//**** IMUSE helper functions ****
+//*********************************
+
+
+static int clamp(int val, int min, int max)
{
if (val < min)
return min;
@@ -45,7 +642,7 @@ int clamp(int val, int min, int max)
return val;
}
-int transpose_clamp(int a, int b, int c)
+static int transpose_clamp(int a, int b, int c)
{
if (b > a)
a += (b - a + 11) / 12 * 12;
@@ -54,7 +651,7 @@ int transpose_clamp(int a, int b, int c)
return a;
}
-uint32 get_delta_time(byte **s)
+static uint32 get_delta_time(byte **s)
{
byte *d = *s, b;
uint32 time = 0;
@@ -66,12 +663,12 @@ uint32 get_delta_time(byte **s)
return time;
}
-uint read_word(byte *a)
+static uint read_word(byte *a)
{
return (a[0] << 8) + a[1];
}
-void skip_midi_cmd(byte **song_ptr)
+static void skip_midi_cmd(byte **song_ptr)
{
byte *s, code;
@@ -97,7 +694,7 @@ void skip_midi_cmd(byte **song_ptr)
*song_ptr = s;
}
-int is_note_cmd(byte **a, IsNoteCmdData * isnote)
+static int is_note_cmd(byte **a, IsNoteCmdData * isnote)
{
byte *s = *a;
byte code;
@@ -142,17 +739,17 @@ int is_note_cmd(byte **a, IsNoteCmdData * isnote)
/**********************************************************************/
-void SoundEngine::lock()
+void IMuse::lock()
{
_locked++;
}
-void SoundEngine::unlock()
+void IMuse::unlock()
{
_locked--;
}
-byte *SoundEngine::findTag(int sound, char *tag, int index)
+byte *IMuse::findTag(int sound, char *tag, int index)
{
byte *ptr = NULL;
int32 size, pos;
@@ -161,7 +758,7 @@ byte *SoundEngine::findTag(int sound, char *tag, int index)
ptr = _base_sounds[sound];
if (ptr == NULL) {
- debug(1, "SoundEngine::findTag completely failed finding sound %d",
+ debug(1, "IMuse::findTag completely failed finding sound %d",
sound);
return 0;
}
@@ -176,12 +773,12 @@ byte *SoundEngine::findTag(int sound, char *tag, int index)
return ptr + pos + 8;
pos += READ_BE_UINT32_UNALIGNED(ptr + pos + 4) + 8;
}
- debug(1, "SoundEngine::findTag failed finding sound %d", sound);
+ debug(1, "IMuse::findTag failed finding sound %d", sound);
return NULL;
}
-bool SoundEngine::start_sound(int sound)
+bool IMuse::start_sound(int sound)
{
Player *player;
void *mdhd;
@@ -203,7 +800,7 @@ bool SoundEngine::start_sound(int sound)
}
-Player *SoundEngine::allocate_player(byte priority)
+Player *IMuse::allocate_player(byte priority)
{
Player *player = _players, *best = NULL;
int i;
@@ -225,7 +822,7 @@ Player *SoundEngine::allocate_player(byte priority)
return NULL;
}
-void SoundEngine::init_players()
+void IMuse::init_players()
{
Player *player = _players;
int i;
@@ -236,7 +833,7 @@ void SoundEngine::init_players()
}
}
-void SoundEngine::init_sustaining_notes()
+void IMuse::init_sustaining_notes()
{
SustainingNotes *next = NULL, *sn = _sustaining_notes;
int i;
@@ -251,7 +848,7 @@ void SoundEngine::init_sustaining_notes()
_sustain_notes_free = next;
}
-void SoundEngine::init_volume_fader()
+void IMuse::init_volume_fader()
{
VolumeFader *vf = _volume_fader;
int i;
@@ -262,7 +859,7 @@ void SoundEngine::init_volume_fader()
_active_volume_faders = false;
}
-void SoundEngine::init_parts()
+void IMuse::init_parts()
{
Part *part;
int i;
@@ -273,7 +870,7 @@ void SoundEngine::init_parts()
}
}
-int SoundEngine::stop_sound(int sound)
+int IMuse::stop_sound(int sound)
{
Player *player = _players;
int i;
@@ -288,7 +885,7 @@ int SoundEngine::stop_sound(int sound)
return r;
}
-int SoundEngine::stop_all_sounds()
+int IMuse::stop_all_sounds()
{
Player *player = _players;
int i;
@@ -300,7 +897,7 @@ int SoundEngine::stop_all_sounds()
return 0;
}
-void SoundEngine::on_timer()
+void IMuse::on_timer()
{
if (_locked || _paused)
return;
@@ -315,7 +912,7 @@ void SoundEngine::on_timer()
unlock();
}
-void SoundEngine::sequencer_timers()
+void IMuse::sequencer_timers()
{
Player *player = _players;
int i;
@@ -366,7 +963,7 @@ void Player::sequencer_timer()
}
}
-void SoundEngine::handle_marker(uint id, byte data)
+void IMuse::handle_marker(uint id, byte data)
{
uint16 *p;
uint pos;
@@ -404,14 +1001,14 @@ void SoundEngine::handle_marker(uint id, byte data)
_queue_end = pos;
}
-int SoundEngine::get_channel_volume(uint a)
+int IMuse::get_channel_volume(uint a)
{
if (a < 8)
return _channel_volume_eff[a];
return _master_volume;
}
-Part *SoundEngine::allocate_part(byte pri)
+Part *IMuse::allocate_part(byte pri)
{
Part *part, *best = NULL;
int i;
@@ -432,7 +1029,7 @@ Part *SoundEngine::allocate_part(byte pri)
return best;
}
-void SoundEngine::expire_sustain_notes()
+void IMuse::expire_sustain_notes()
{
SustainingNotes *sn, *next;
Player *player;
@@ -464,7 +1061,7 @@ void SoundEngine::expire_sustain_notes()
}
}
-void SoundEngine::expire_volume_faders()
+void IMuse::expire_volume_faders()
{
VolumeFader *vf;
int i;
@@ -512,7 +1109,7 @@ void VolumeFader::on_timer()
}
}
-int SoundEngine::get_sound_status(int sound)
+int IMuse::get_sound_status(int sound)
{
int i;
Player *player;
@@ -524,7 +1121,7 @@ int SoundEngine::get_sound_status(int sound)
return get_queue_sound_status(sound);
}
-int SoundEngine::get_queue_sound_status(int sound)
+int IMuse::get_queue_sound_status(int sound)
{
uint16 *a;
int i, j;
@@ -541,7 +1138,7 @@ int SoundEngine::get_queue_sound_status(int sound)
return 0;
}
-int SoundEngine::set_volchan(int sound, int volchan)
+int IMuse::set_volchan(int sound, int volchan)
{
int r;
int i;
@@ -587,7 +1184,7 @@ int SoundEngine::set_volchan(int sound, int volchan)
}
}
-int SoundEngine::clear_queue()
+int IMuse::clear_queue()
{
_queue_adding = false;
_queue_cleared = true;
@@ -597,7 +1194,7 @@ int SoundEngine::clear_queue()
return 0;
}
-int SoundEngine::enqueue_command(int a, int b, int c, int d, int e, int f,
+int IMuse::enqueue_command(int a, int b, int c, int d, int e, int f,
int g)
{
uint16 *p;
@@ -635,7 +1232,7 @@ int SoundEngine::enqueue_command(int a, int b, int c, int d, int e, int f,
}
}
-int SoundEngine::query_queue(int param)
+int IMuse::query_queue(int param)
{
switch (param) {
case 0: /* get trigger count */
@@ -653,12 +1250,12 @@ int SoundEngine::query_queue(int param)
}
}
-int SoundEngine::get_music_volume()
+int IMuse::get_music_volume()
{
return _music_volume;
}
-int SoundEngine::set_music_volume(uint vol)
+int IMuse::set_music_volume(uint vol)
{
if (vol > 100)
vol = 100;
@@ -670,7 +1267,7 @@ int SoundEngine::set_music_volume(uint vol)
return 0;
}
-int SoundEngine::set_master_volume(uint vol)
+int IMuse::set_master_volume(uint vol)
{
int i;
if (vol > 127)
@@ -680,26 +1277,26 @@ int SoundEngine::set_master_volume(uint vol)
vol = vol / (100 / _music_volume);
_master_volume = vol;
- _s->_sound_volume_master = vol;
+// _s->_sound_volume_master = vol;
for (i = 0; i != 8; i++)
_channel_volume_eff[i] = (_channel_volume[i] + 1) * vol >> 7;
update_volumes();
return 0;
}
-int SoundEngine::get_master_volume()
+int IMuse::get_master_volume()
{
return _master_volume;
}
-int SoundEngine::terminate()
+int IMuse::terminate()
{
return 0;
/* not implemented */
}
-int SoundEngine::enqueue_trigger(int sound, int marker)
+int IMuse::enqueue_trigger(int sound, int marker)
{
uint16 *p;
uint pos;
@@ -724,7 +1321,7 @@ int SoundEngine::enqueue_trigger(int sound, int marker)
return 0;
}
-int32 SoundEngine::do_command(int a, int b, int c, int d, int e, int f, int g,
+int32 IMuse::do_command(int a, int b, int c, int d, int e, int f, int g,
int h)
{
byte cmd = a & 0xFF;
@@ -754,8 +1351,12 @@ int32 SoundEngine::do_command(int a, int b, int c, int d, int e, int f, int g,
return set_channel_volume(b, c);
case 18:
return set_volchan_entry(b, c);
+
+ case 2:
+ case 3:
+ return 0;
default:
- warning("SoundEngine::do_command invalid command %d", cmd);
+ warning("IMuse::do_command invalid command %d", cmd);
}
} else if (param == 1) {
@@ -826,7 +1427,7 @@ int32 SoundEngine::do_command(int a, int b, int c, int d, int e, int f, int g,
case 24:
return 0;
default:
- warning("SoundEngine::do_command default midi command %d", cmd);
+ warning("IMuse::do_command default midi command %d", cmd);
return -1;
}
}
@@ -834,7 +1435,7 @@ int32 SoundEngine::do_command(int a, int b, int c, int d, int e, int f, int g,
return -1;
}
-int SoundEngine::set_channel_volume(uint chan, uint vol)
+int IMuse::set_channel_volume(uint chan, uint vol)
{
if (chan >= 8 || vol > 127)
return -1;
@@ -845,7 +1446,7 @@ int SoundEngine::set_channel_volume(uint chan, uint vol)
return 0;
}
-void SoundEngine::update_volumes()
+void IMuse::update_volumes()
{
Player *player;
int i;
@@ -856,7 +1457,7 @@ void SoundEngine::update_volumes()
}
}
-int SoundEngine::set_volchan_entry(uint a, uint b)
+int IMuse::set_volchan_entry(uint a, uint b)
{
if (a >= 8)
return -1;
@@ -924,7 +1525,7 @@ int HookDatas::set(byte cls, byte value, byte chan)
}
-VolumeFader *SoundEngine::allocate_volume_fader()
+VolumeFader *IMuse::allocate_volume_fader()
{
VolumeFader *vf;
int i;
@@ -941,7 +1542,7 @@ VolumeFader *SoundEngine::allocate_volume_fader()
return vf;
}
-Player *SoundEngine::get_player_byid(int id)
+Player *IMuse::get_player_byid(int id)
{
int i;
Player *player, *found = NULL;
@@ -956,25 +1557,55 @@ Player *SoundEngine::get_player_byid(int id)
return found;
}
-int SoundEngine::get_volchan_entry(uint a)
+int IMuse::get_volchan_entry(uint a)
{
if (a < 8)
return _volchan_table[a];
return -1;
}
-int SoundEngine::initialize(Scumm *scumm, SoundDriver * driver)
+uint32 IMuse::property(int prop, uint32 value) {
+ switch(prop) {
+ case PROP_TEMPO_BASE:
+ _game_tempo = value;
+ break;
+
+ case PROP_MT32_EMULATE:
+ _mt32emulate = !!value;
+ break;
+ }
+ return 0;
+}
+
+void IMuse::setBase(byte **base) {
+ _base_sounds = base;
+}
+
+
+IMuse *IMuse::create(OSystem *syst, MidiDriver *midi, SoundMixer *mixer) {
+ IMuse *i = new IMuse;
+ i->initialize(syst, midi, mixer);
+ return i;
+}
+
+
+int IMuse::initialize(OSystem *syst, MidiDriver *midi, SoundMixer *mixer)
{
int i;
- if (_initialized)
- return -1;
+
+ IMuseDriver *driv;
- scumm->_soundEngine = this;
- _s = scumm;
+ if (midi == NULL) {
+ driv = new IMuseAdlib(mixer);
+ } else {
+ driv = new IMuseGM(midi);
+ }
- _driver = driver;
+ _driver = driv;
+ _hardware_type = driv->get_hardware_type();
+ _game_tempo = driv->get_base_tempo();
- _hardware_type = driver->get_hardware_type();
+ driv->init(this,syst);
_master_volume = 127;
if (_music_volume < 1)
@@ -989,14 +1620,12 @@ int SoundEngine::initialize(Scumm *scumm, SoundDriver * driver)
init_queue();
init_parts();
- _driver->init(this, scumm->_system);
-
_initialized = true;
return 0;
}
-void SoundEngine::init_queue()
+void IMuse::init_queue()
{
_queue_adding = false;
_queue_pos = 0;
@@ -1004,14 +1633,12 @@ void SoundEngine::init_queue()
_trigger_count = 0;
}
-void SoundEngine::pause(bool paused)
+void IMuse::pause(bool paused)
{
lock();
-#if 0
int i;
Part *part;
- MidiChannel *mc;
for (i = ARRAYSIZE(_parts), part = _parts; i != 0; i--, part++) {
if (part->_player) {
@@ -1020,10 +1647,9 @@ void SoundEngine::pause(bool paused)
} else {
part->set_vol(part->_vol);
}
- part->vol_changed();
+ part->changed(IMuseDriver::pcVolume);
}
}
-#endif
_paused = paused;
@@ -1149,11 +1775,8 @@ void Player::set_tempo(uint32 b)
{
uint32 i, j;
- if (_se->_s->_gameTempo < 1000)
- i = _se->_driver->get_base_tempo();
- else
- i = _se->_s->_gameTempo;
-
+ i = _se->_game_tempo;
+
j = _tempo = b;
while (i & 0xFFFF0000 || j & 0xFFFF0000) {
@@ -2112,7 +2735,7 @@ enum {
TYPE_PLAYER = 2,
};
-int SoundEngine::saveReference(SoundEngine *me, byte type, void *ref)
+int IMuse::saveReference(IMuse *me, byte type, void *ref)
{
switch (type) {
case TYPE_PART:
@@ -2124,7 +2747,7 @@ int SoundEngine::saveReference(SoundEngine *me, byte type, void *ref)
}
}
-void *SoundEngine::loadReference(SoundEngine *me, byte type, int ref)
+void *IMuse::loadReference(IMuse *me, byte type, int ref)
{
switch (type) {
case TYPE_PART:
@@ -2136,19 +2759,19 @@ void *SoundEngine::loadReference(SoundEngine *me, byte type, int ref)
}
}
-int SoundEngine::save_or_load(Serializer * ser)
+int IMuse::save_or_load(Serializer * ser, Scumm *scumm)
{
const SaveLoadEntry mainEntries[] = {
- MKLINE(SoundEngine, _queue_end, sleUint8),
- MKLINE(SoundEngine, _queue_pos, sleUint8),
- MKLINE(SoundEngine, _queue_sound, sleUint16),
- MKLINE(SoundEngine, _queue_adding, sleByte),
- MKLINE(SoundEngine, _queue_marker, sleByte),
- MKLINE(SoundEngine, _queue_cleared, sleByte),
- MKLINE(SoundEngine, _master_volume, sleByte),
- MKLINE(SoundEngine, _trigger_count, sleUint16),
- MKARRAY(SoundEngine, _channel_volume[0], sleUint16, 8),
- MKARRAY(SoundEngine, _volchan_table[0], sleUint16, 8),
+ MKLINE(IMuse, _queue_end, sleUint8),
+ MKLINE(IMuse, _queue_pos, sleUint8),
+ MKLINE(IMuse, _queue_sound, sleUint16),
+ MKLINE(IMuse, _queue_adding, sleByte),
+ MKLINE(IMuse, _queue_marker, sleByte),
+ MKLINE(IMuse, _queue_cleared, sleByte),
+ MKLINE(IMuse, _master_volume, sleByte),
+ MKLINE(IMuse, _trigger_count, sleUint16),
+ MKARRAY(IMuse, _channel_volume[0], sleUint16, 8),
+ MKARRAY(IMuse, _volchan_table[0], sleUint16, 8),
MKEND()
};
@@ -2246,7 +2869,7 @@ int SoundEngine::save_or_load(Serializer * ser)
if (!ser->isSaving()) {
/* Load all sounds that we need */
- fix_players_after_load();
+ fix_players_after_load(scumm);
init_sustaining_notes();
_active_volume_faders = true;
fix_parts_after_load();
@@ -2259,7 +2882,7 @@ int SoundEngine::save_or_load(Serializer * ser)
#undef MKLINE
#undef MKEND
-void SoundEngine::fix_parts_after_load()
+void IMuse::fix_parts_after_load()
{
Part *part;
int i;
@@ -2272,7 +2895,7 @@ void SoundEngine::fix_parts_after_load()
/* Only call this routine from the main thread,
* since it uses getResourceAddress */
-void SoundEngine::fix_players_after_load()
+void IMuse::fix_players_after_load(Scumm *scumm)
{
Player *player = _players;
int i;
@@ -2280,7 +2903,7 @@ void SoundEngine::fix_players_after_load()
for (i = ARRAYSIZE(_players); i != 0; i--, player++) {
if (player->_active) {
player->set_tempo(player->_tempo);
- _s->getResourceAddress(rtSound, player->_id);
+ scumm->getResourceAddress(rtSound, player->_id);
}
}
}
@@ -2288,19 +2911,19 @@ void SoundEngine::fix_players_after_load()
void Part::set_detune(int8 detune)
{
_detune_eff = clamp((_detune = detune) + _player->_detune, -128, 127);
- changed(SoundDriver::pcMod);
+ changed(IMuseDriver::pcMod);
}
void Part::set_pitchbend(int value)
{
_pitchbend = value * _pitchbend_factor >> 6;
- changed(SoundDriver::pcMod);
+ changed(IMuseDriver::pcMod);
}
void Part::set_vol(uint8 vol)
{
_vol_eff = ((_vol = vol) + 1) * _player->_vol_eff >> 7;
- changed(SoundDriver::pcVolume);
+ changed(IMuseDriver::pcVolume);
}
void Part::set_pri(int8 pri)
@@ -2311,38 +2934,38 @@ void Part::set_pri(int8 pri)
void Part::set_pan(int8 pan)
{
_pan_eff = clamp((_pan = pan) + _player->_pan, -64, 63);
- changed(SoundDriver::pcPan);
+ changed(IMuseDriver::pcPan);
}
void Part::set_transpose(int8 transpose)
{
_transpose_eff = transpose_clamp((_transpose = transpose) +
_player->_transpose, -12, 12);
- changed(SoundDriver::pcMod);
+ changed(IMuseDriver::pcMod);
}
void Part::set_pedal(bool value)
{
_pedal = value;
- changed(SoundDriver::pcPedal);
+ changed(IMuseDriver::pcPedal);
}
void Part::set_modwheel(uint value)
{
_modwheel = value;
- changed(SoundDriver::pcModwheel);
+ changed(IMuseDriver::pcModwheel);
}
void Part::set_chorus(uint chorus)
{
_chorus = chorus;
- changed(SoundDriver::pcChorus);
+ changed(IMuseDriver::pcChorus);
}
void Part::set_effect_level(uint level)
{
_effect_level = level;
- changed(SoundDriver::pcEffectLevel);
+ changed(IMuseDriver::pcEffectLevel);
}
void Part::fix_after_load()
@@ -2388,7 +3011,7 @@ void Part::key_off(byte note)
_drv->part_key_off(this, note);
}
-void Part::init(SoundDriver * driver)
+void Part::init(IMuseDriver * driver)
{
_drv = driver;
_player = NULL;
@@ -2478,7 +3101,7 @@ void Part::set_program(byte program)
if (_program != program || _bank != 0) {
_program = program;
_bank = 0;
- changed(SoundDriver::pcProgram);
+ changed(IMuseDriver::pcProgram);
}
}
@@ -2486,5 +3109,1269 @@ void Part::set_instrument(uint b)
{
_bank = (byte)(b >> 8);
_program = (byte)b;
- changed(SoundDriver::pcProgram);
+ changed(IMuseDriver::pcProgram);
+}
+
+
+//********************************************
+//***** ADLIB PART OF IMUSE STARTS HERE ******
+//********************************************
+
+
+static byte lookup_table[64][32];
+const byte volume_table[] = {
+ 0, 4, 7, 11,
+ 13, 16, 18, 20,
+ 22, 24, 26, 27,
+ 29, 30, 31, 33,
+ 34, 35, 36, 37,
+ 38, 39, 40, 41,
+ 42, 43, 44, 44,
+ 45, 46, 47, 47,
+ 48, 49, 49, 50,
+ 51, 51, 52, 53,
+ 53, 54, 54, 55,
+ 55, 56, 56, 57,
+ 57, 58, 58, 59,
+ 59, 60, 60, 60,
+ 61, 61, 62, 62,
+ 62, 63, 63, 63
+};
+
+int lookup_volume(int a, int b)
+{
+ if (b == 0)
+ return 0;
+
+ if (b == 31)
+ return a;
+
+ if (a < -63 || a > 63) {
+ return b * (a + 1) >> 5;
+ }
+
+ if (b < 0) {
+ if (a < 0) {
+ return lookup_table[-a][-b];
+ } else {
+ return -lookup_table[a][-b];
+ }
+ } else {
+ if (a < 0) {
+ return -lookup_table[-a][b];
+ } else {
+ return lookup_table[a][b];
+ }
+ }
}
+
+void create_lookup_table()
+{
+ int i, j;
+ int sum;
+
+ for (i = 0; i < 64; i++) {
+ sum = i;
+ for (j = 0; j < 32; j++) {
+ lookup_table[i][j] = sum >> 5;
+ sum += i;
+ }
+ }
+ for (i = 0; i < 64; i++)
+ lookup_table[i][0] = 0;
+}
+
+MidiChannelAdl *IMuseAdlib::allocate_midichan(byte pri)
+{
+ MidiChannelAdl *ac, *best = NULL;
+ int i;
+
+ for (i = 0; i < 9; i++) {
+ if (++_midichan_index >= 9)
+ _midichan_index = 0;
+ ac = &_midi_channels[_midichan_index];
+ if (!ac->_part)
+ return ac;
+ if (!ac->_next) {
+ if (ac->_part->_pri_eff <= pri) {
+ pri = ac->_part->_pri_eff;
+ best = ac;
+ }
+ }
+ }
+
+ if (best)
+ mc_off(best);
+ else; //debug(1, "Denying adlib channel request");
+ return best;
+}
+
+void IMuseAdlib::premix_proc(void *param, int16 *buf, uint len) {
+ ((IMuseAdlib*)param)->generate_samples(buf, len);
+}
+
+void IMuseAdlib::init(IMuse *eng, OSystem *syst)
+{
+ int i;
+ MidiChannelAdl *mc;
+
+ _se = eng;
+
+ for (i = 0, mc = _midi_channels; i != ARRAYSIZE(_midi_channels); i++, mc++) {
+ mc->_channel = i;
+ mc->_s11a.s10 = &mc->_s10b;
+ mc->_s11b.s10 = &mc->_s10a;
+ }
+
+ _adlib_reg_cache = (byte *)calloc(256, 1);
+
+ _opl = OPLCreate(OPL_TYPE_YM3812, 3579545, syst->property(OSystem::PROP_GET_SAMPLE_RATE,0));
+
+ adlib_write(1, 0x20);
+ adlib_write(8, 0x40);
+ adlib_write(0xBD, 0x00);
+ create_lookup_table();
+
+ _mixer->setup_premix(this, premix_proc);
+}
+
+void IMuseAdlib::adlib_write(byte port, byte value)
+{
+ if (_adlib_reg_cache[port] == value)
+ return;
+ _adlib_reg_cache[port] = value;
+
+ OPLWriteReg(_opl, port, value);
+}
+
+void IMuseAdlib::adlib_key_off(int chan)
+{
+ byte port = chan + 0xB0;
+ adlib_write(port, adlib_read(port) & ~0x20);
+}
+
+struct AdlibSetParams {
+ byte a, b, c, d;
+};
+
+static const byte channel_mappings[9] = {
+ 0, 1, 2, 8,
+ 9, 10, 16, 17,
+ 18
+};
+
+static const byte channel_mappings_2[9] = {
+ 3, 4, 5, 11,
+ 12, 13, 19, 20,
+ 21
+};
+
+static const AdlibSetParams adlib_setparam_table[] = {
+ {0x40, 0, 63, 63}, /* level */
+ {0xE0, 2, 0, 0}, /* unused */
+ {0x40, 6, 192, 0}, /* level key scaling */
+ {0x20, 0, 15, 0}, /* modulator frequency multiple */
+ {0x60, 4, 240, 15}, /* attack rate */
+ {0x60, 0, 15, 15}, /* decay rate */
+ {0x80, 4, 240, 15}, /* sustain level */
+ {0x80, 0, 15, 15}, /* release rate */
+ {0xE0, 0, 3, 0}, /* waveform select */
+ {0x20, 7, 128, 0}, /* amp mod */
+ {0x20, 6, 64, 0}, /* vib */
+ {0x20, 5, 32, 0}, /* eg typ */
+ {0x20, 4, 16, 0}, /* ksr */
+ {0xC0, 0, 1, 0}, /* decay alg */
+ {0xC0, 1, 14, 0} /* feedback */
+};
+
+void IMuseAdlib::adlib_set_param(int channel, byte param, int value)
+{
+ const AdlibSetParams *as;
+ byte port;
+
+ assert(channel >= 0 && channel < 9);
+
+ if (param <= 12) {
+ port = channel_mappings_2[channel];
+ } else if (param <= 25) {
+ param -= 13;
+ port = channel_mappings[channel];
+ } else if (param <= 27) {
+ param -= 13;
+ port = channel;
+ } else if (param == 28 || param == 29) {
+ if (param == 28)
+ value -= 15;
+ else
+ value -= 383;
+ value <<= 4;
+ channel_table_2[channel] = value;
+ adlib_playnote(channel, curnote_table[channel] + value);
+ return;
+ } else {
+ return;
+ }
+
+ as = &adlib_setparam_table[param];
+ if (as->d)
+ value = as->d - value;
+ port += as->a;
+ adlib_write(port, (adlib_read(port) & ~as->c) | (((byte)value) << as->b));
+}
+
+static const byte octave_numbers[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7
+};
+
+static const byte note_numbers[] = {
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 3, 4, 5, 6, 7, 8, 9, 10
+};
+
+static const byte note_to_f_num[] = {
+ 90, 91, 92, 92, 93, 94, 94, 95,
+ 96, 96, 97, 98, 98, 99, 100, 101,
+ 101, 102, 103, 104, 104, 105, 106, 107,
+ 107, 108, 109, 110, 111, 111, 112, 113,
+ 114, 115, 115, 116, 117, 118, 119, 120,
+ 121, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 157, 158, 159, 160,
+ 161, 162, 163, 165, 166, 167, 168, 169,
+ 171, 172, 173, 174, 176, 177, 178, 180,
+ 181, 182, 184, 185, 186, 188, 189, 190,
+ 192, 193, 194, 196, 197, 199, 200, 202,
+ 203, 205, 206, 208, 209, 211, 212, 214,
+ 215, 217, 218, 220, 222, 223, 225, 226,
+ 228, 230, 231, 233, 235, 236, 238, 240,
+ 242, 243, 245, 247, 249, 251, 252, 254,
+};
+
+void IMuseAdlib::adlib_playnote(int channel, int note)
+{
+ byte old, oct, notex;
+ int note2;
+ int i;
+
+ note2 = (note >> 7) - 4;
+
+ oct = octave_numbers[note2] << 2;
+ notex = note_numbers[note2];
+
+ old = adlib_read(channel + 0xB0);
+ if (old & 0x20) {
+ old &= ~0x20;
+ if (oct > old) {
+ if (notex < 6) {
+ notex += 12;
+ oct -= 4;
+ }
+ } else if (oct < old) {
+ if (notex > 11) {
+ notex -= 12;
+ oct += 4;
+ }
+ }
+ }
+
+ i = (notex << 3) + ((note >> 4) & 0x7);
+ adlib_write(channel + 0xA0, note_to_f_num[i]);
+ adlib_write(channel + 0xB0, oct | 0x20);
+}
+
+void IMuseAdlib::adlib_note_on(int chan, byte note, int mod)
+{
+ int code;
+ assert(chan >= 0 && chan < 9);
+ code = (note << 7) + mod;
+ curnote_table[chan] = code;
+ adlib_playnote(chan, channel_table_2[chan] + code);
+}
+
+void IMuseAdlib::adlib_note_on_ex(int chan, byte note, int mod)
+{
+ int code;
+ assert(chan >= 0 && chan < 9);
+ code = (note << 7) + mod;
+ curnote_table[chan] = code;
+ channel_table_2[chan] = 0;
+ adlib_playnote(chan, code);
+}
+
+void IMuseAdlib::adlib_key_onoff(int channel)
+{
+ byte val;
+ byte port = channel + 0xB0;
+ assert(channel >= 0 && channel < 9);
+
+ val = adlib_read(port);
+ adlib_write(port, val & ~0x20);
+ adlib_write(port, val | 0x20);
+}
+
+void IMuseAdlib::adlib_setup_channel(int chan, Instrument * instr,
+ byte vol_1, byte vol_2)
+{
+ byte port;
+
+ assert(chan >= 0 && chan < 9);
+
+ port = channel_mappings[chan];
+ adlib_write(port + 0x20, instr->flags_1);
+ adlib_write(port + 0x40, (instr->oplvl_1 | 0x3F) - vol_1);
+ adlib_write(port + 0x60, ~instr->atdec_1);
+ adlib_write(port + 0x80, ~instr->sustrel_1);
+ adlib_write(port + 0xE0, instr->waveform_1);
+
+ port = channel_mappings_2[chan];
+ adlib_write(port + 0x20, instr->flags_2);
+ adlib_write(port + 0x40, (instr->oplvl_2 | 0x3F) - vol_2);
+ adlib_write(port + 0x60, ~instr->atdec_2);
+ adlib_write(port + 0x80, ~instr->sustrel_2);
+ adlib_write(port + 0xE0, instr->waveform_2);
+
+ adlib_write((byte)chan + 0xC0, instr->feedback);
+}
+
+int IMuseAdlib::adlib_read_param(int chan, byte param)
+{
+ const AdlibSetParams *as;
+ byte val;
+ byte port;
+
+ assert(chan >= 0 && chan < 9);
+
+ if (param <= 12) {
+ port = channel_mappings_2[chan];
+ } else if (param <= 25) {
+ param -= 13;
+ port = channel_mappings[chan];
+ } else if (param <= 27) {
+ param -= 13;
+ port = chan;
+ } else if (param == 28) {
+ return 0xF;
+ } else if (param == 29) {
+ return 0x17F;
+ } else {
+ return 0;
+ }
+
+ as = &adlib_setparam_table[param];
+ val = adlib_read(port + as->a);
+ val &= as->c;
+ val >>= as->b;
+ if (as->d)
+ val = as->d - val;
+
+ return val;
+}
+
+void IMuseAdlib::generate_samples(int16 * data, int len)
+{
+ int step;
+
+ if (!_opl) {
+ memset(data, 0, len * sizeof(int16));
+ return;
+ }
+
+ do {
+ step = len;
+ if (step > _next_tick)
+ step = _next_tick;
+ YM3812UpdateOne(_opl, data, step);
+
+ if (!(_next_tick -= step)) {
+ _se->on_timer();
+ reset_tick();
+ }
+ data += step;
+ } while (len -= step);
+}
+
+
+void IMuseAdlib::reset_tick()
+{
+ _next_tick = 88;
+}
+
+void IMuseAdlib::on_timer()
+{
+ MidiChannelAdl *mc;
+ int i;
+
+ _adlib_timer_counter += 0xD69;
+ while (_adlib_timer_counter >= 0x411B) {
+ _adlib_timer_counter -= 0x411B;
+ mc = _midi_channels;
+ for (i = 0; i != ARRAYSIZE(_midi_channels); i++, mc++) {
+ if (!mc->_part)
+ continue;
+ if (mc->_duration && (mc->_duration -= 0x11) <= 0) {
+ mc_off(mc);
+ return;
+ }
+ if (mc->_s10a.active) {
+ mc_inc_stuff(mc, &mc->_s10a, &mc->_s11a);
+ }
+ if (mc->_s10b.active) {
+ mc_inc_stuff(mc, &mc->_s10b, &mc->_s11b);
+ }
+ }
+ }
+}
+
+const byte param_table_1[16] = {
+ 29, 28, 27, 0,
+ 3, 4, 7, 8,
+ 13, 16, 17, 20,
+ 21, 30, 31, 0
+};
+
+const uint16 param_table_2[16] = {
+ 0x2FF, 0x1F, 0x7, 0x3F,
+ 0x0F, 0x0F, 0x0F, 0x3,
+ 0x3F, 0x0F, 0x0F, 0x0F,
+ 0x3, 0x3E, 0x1F, 0
+};
+
+static const uint16 num_steps_table[] = {
+ 1, 2, 4, 5,
+ 6, 7, 8, 9,
+ 10, 12, 14, 16,
+ 18, 21, 24, 30,
+ 36, 50, 64, 82,
+ 100, 136, 160, 192,
+ 240, 276, 340, 460,
+ 600, 860, 1200, 1600
+};
+
+int IMuseAdlib::random_nr(int a)
+{
+ static byte _rand_seed = 1;
+ if (_rand_seed & 1) {
+ _rand_seed >>= 1;
+ _rand_seed ^= 0xB8;
+ } else {
+ _rand_seed >>= 1;
+ }
+ return _rand_seed * a >> 8;
+}
+
+void IMuseAdlib::struct10_setup(Struct10 * s10)
+{
+ int b, c, d, e, f, g, h;
+ byte t;
+
+ b = s10->unk3;
+ f = s10->active - 1;
+
+ t = s10->table_a[f];
+ e = num_steps_table[lookup_table[t & 0x7F][b]];
+ if (t & 0x80) {
+ e = random_nr(e);
+ }
+ if (e == 0)
+ e++;
+
+ s10->num_steps = s10->speed_lo_max = e;
+
+ if (f != 2) {
+ c = s10->param;
+ g = s10->start_value;
+ t = s10->table_b[f];
+ d = lookup_volume(c, (t & 0x7F) - 31);
+ if (t & 0x80) {
+ d = random_nr(d);
+ }
+ if (d + g > c) {
+ h = c - g;
+ } else {
+ h = d;
+ if (d + g < 0)
+ h = -g;
+ }
+ h -= s10->cur_val;
+ } else {
+ h = 0;
+ }
+
+ s10->speed_hi = h / e;
+ if (h < 0) {
+ h = -h;
+ s10->direction = -1;
+ } else {
+ s10->direction = 1;
+ }
+
+ s10->speed_lo = h % e;
+ s10->speed_lo_counter = 0;
+}
+
+byte IMuseAdlib::struct10_ontimer(Struct10 * s10, Struct11 * s11)
+{
+ byte result = 0;
+ int i;
+
+ if (s10->count && (s10->count -= 17) <= 0) {
+ s10->active = 0;
+ return 0;
+ }
+
+ i = s10->cur_val + s10->speed_hi;
+ s10->speed_lo_counter += s10->speed_lo;
+ if (s10->speed_lo_counter >= s10->speed_lo_max) {
+ s10->speed_lo_counter -= s10->speed_lo_max;
+ i += s10->direction;
+ }
+ if (s10->cur_val != i || s10->modwheel != s10->modwheel_last) {
+ s10->cur_val = i;
+ s10->modwheel_last = s10->modwheel;
+ i = lookup_volume(i, s10->modwheel_last);
+ if (i != s11->modify_val) {
+ s11->modify_val = i;
+ result = 1;
+ }
+ }
+
+ if (!--s10->num_steps) {
+ s10->active++;
+ if (s10->active > 4) {
+ if (s10->loop) {
+ s10->active = 1;
+ result |= 2;
+ struct10_setup(s10);
+ } else {
+ s10->active = 0;
+ }
+ } else {
+ struct10_setup(s10);
+ }
+ }
+
+ return result;
+}
+
+void IMuseAdlib::struct10_init(Struct10 * s10, InstrumentExtra * ie)
+{
+ s10->active = 1;
+ s10->cur_val = 0;
+ s10->modwheel_last = 31;
+ s10->count = ie->a;
+ if (s10->count)
+ s10->count *= 63;
+ s10->table_a[0] = ie->b;
+ s10->table_a[1] = ie->d;
+ s10->table_a[2] = ie->f;
+ s10->table_a[3] = ie->g;
+
+ s10->table_b[0] = ie->c;
+ s10->table_b[1] = ie->e;
+ s10->table_b[2] = 0;
+ s10->table_b[3] = ie->h;
+
+ struct10_setup(s10);
+}
+
+void IMuseAdlib::mc_init_stuff(MidiChannelAdl *mc, Struct10 * s10,
+ Struct11 * s11, byte flags,
+ InstrumentExtra * ie)
+{
+ Part *part = mc->_part;
+
+ s11->modify_val = 0;
+ s11->flag0x40 = flags & 0x40;
+ s10->loop = flags & 0x20;
+ s11->flag0x10 = flags & 0x10;
+ s11->param = param_table_1[flags & 0xF];
+ s10->param = param_table_2[flags & 0xF];
+ s10->unk3 = 31;
+ if (s11->flag0x40) {
+ s10->modwheel = part->_modwheel >> 2;
+ } else {
+ s10->modwheel = 31;
+ }
+
+ switch (s11->param) {
+ case 0:
+ s10->start_value = mc->_vol_2;
+ break;
+ case 13:
+ s10->start_value = mc->_vol_1;
+ break;
+ case 30:
+ s10->start_value = 31;
+ s11->s10->modwheel = 0;
+ break;
+ case 31:
+ s10->start_value = 0;
+ s11->s10->unk3 = 0;
+ break;
+ default:
+ s10->start_value = ((IMuseAdlib*)part->_drv)->adlib_read_param(mc->_channel, s11->param);
+ }
+
+ struct10_init(s10, ie);
+}
+
+void IMuseAdlib::mc_inc_stuff(MidiChannelAdl *mc, Struct10 * s10,
+ Struct11 * s11)
+{
+ byte code;
+ Part *part = mc->_part;
+
+ code = struct10_ontimer(s10, s11);
+
+ if (code & 1) {
+ switch (s11->param) {
+ case 0:
+ mc->_vol_2 = s10->start_value + s11->modify_val;
+ ((IMuseAdlib*)part->_drv)->adlib_set_param(mc->_channel, 0,
+ volume_table[lookup_table[mc->_vol_2]
+ [part->_vol_eff >> 2]]);
+ break;
+ case 13:
+ mc->_vol_1 = s10->start_value + s11->modify_val;
+ if (mc->_twochan) {
+ ((IMuseAdlib*)part->_drv)->adlib_set_param(mc->_channel, 13,
+ volume_table[lookup_table[mc->_vol_1]
+ [part->_vol_eff >> 2]]);
+ } else {
+ ((IMuseAdlib*)part->_drv)->adlib_set_param(mc->_channel, 13, mc->_vol_1);
+ }
+ break;
+ case 30:
+ s11->s10->modwheel = (char)s11->modify_val;
+ break;
+ case 31:
+ s11->s10->unk3 = (char)s11->modify_val;
+ break;
+ default:
+ ((IMuseAdlib*)part->_drv)->adlib_set_param(mc->_channel, s11->param,
+ s10->start_value + s11->modify_val);
+ break;
+ }
+ }
+
+ if (code & 2 && s11->flag0x10)
+ ((IMuseAdlib*)part->_drv)->adlib_key_onoff(mc->_channel);
+}
+
+void IMuseAdlib::part_changed(Part *part, byte what)
+{
+ MidiChannelAdl *mc;
+
+ if (what & pcProgram) {
+ if (part->_program < 32) {
+ part_set_instrument(part, &_glob_instr[part->_program]);
+ }
+ }
+
+ if (what & pcMod) {
+ for (mc = part->_mc->adl(); mc; mc = mc->_next) {
+ adlib_note_on(mc->_channel, mc->_note + part->_transpose_eff,
+ part->_pitchbend + part->_detune_eff);
+ }
+ }
+
+ if (what & pcVolume) {
+ for (mc = part->_mc->adl(); mc; mc = mc->_next) {
+ adlib_set_param(mc->_channel, 0, volume_table[lookup_table[mc->_vol_2]
+ [part->_vol_eff >> 2]]);
+ if (mc->_twochan) {
+ adlib_set_param(mc->_channel, 13,
+ volume_table[lookup_table[mc->_vol_1]
+ [part->_vol_eff >> 2]]);
+ }
+ }
+ }
+
+ if (what & pcPedal) {
+ if (!part->_pedal) {
+ for (mc = (MidiChannelAdl *)part->_mc; mc; mc = mc->_next) {
+ if (mc->_waitforpedal)
+ mc_off(mc);
+ }
+ }
+ }
+
+ if (what & pcModwheel) {
+ for (mc = (MidiChannelAdl *)part->_mc; mc; mc = mc->_next) {
+ if (mc->_s10a.active && mc->_s11a.flag0x40)
+ mc->_s10a.modwheel = part->_modwheel >> 2;
+ if (mc->_s10b.active && mc->_s11b.flag0x40)
+ mc->_s10b.modwheel = part->_modwheel >> 2;
+ }
+ }
+}
+
+void IMuseAdlib::mc_key_on(MidiChannel * mc2, byte note, byte velocity)
+{
+ MidiChannelAdl *mc = (MidiChannelAdl *)mc2;
+ Part *part = mc->_part;
+ Instrument *instr = &_part_instr[part->_slot];
+ int c;
+ byte vol_1, vol_2;
+
+ mc->_twochan = instr->feedback & 1;
+ mc->_note = note;
+ mc->_waitforpedal = false;
+ mc->_duration = instr->duration;
+ if (mc->_duration != 0)
+ mc->_duration *= 63;
+
+ vol_1 =
+ (instr->oplvl_1 & 0x3F) +
+ lookup_table[velocity >> 1][instr->waveform_1 >> 2];
+ if (vol_1 > 0x3F)
+ vol_1 = 0x3F;
+ mc->_vol_1 = vol_1;
+
+ vol_2 =
+ (instr->oplvl_2 & 0x3F) +
+ lookup_table[velocity >> 1][instr->waveform_2 >> 2];
+ if (vol_2 > 0x3F)
+ vol_2 = 0x3F;
+ mc->_vol_2 = vol_2;
+
+ c = part->_vol_eff >> 2;
+
+ vol_2 = volume_table[lookup_table[vol_2][c]];
+ if (mc->_twochan)
+ vol_1 = volume_table[lookup_table[vol_1][c]];
+
+ adlib_setup_channel(mc->_channel, instr, vol_1, vol_2);
+ adlib_note_on_ex(mc->_channel, part->_transpose_eff + note,
+ part->_detune_eff + part->_pitchbend);
+
+ if (instr->flags_a & 0x80) {
+ mc_init_stuff(mc, &mc->_s10a, &mc->_s11a, instr->flags_a,
+ &instr->extra_a);
+ } else {
+ mc->_s10a.active = 0;
+ }
+
+ if (instr->flags_b & 0x80) {
+ mc_init_stuff(mc, &mc->_s10b, &mc->_s11b, instr->flags_b,
+ &instr->extra_b);
+ } else {
+ mc->_s10b.active = 0;
+ }
+}
+
+void IMuseAdlib::set_instrument(uint slot, byte *data)
+{
+ if (slot < 32) {
+ memcpy(&_glob_instr[slot], data, sizeof(Instrument));
+ }
+}
+
+
+void IMuseAdlib::link_mc(Part *part, MidiChannelAdl *mc)
+{
+ mc->_part = part;
+ mc->_next = (MidiChannelAdl *)part->_mc;
+ part->_mc = mc;
+ mc->_prev = NULL;
+
+ if (mc->_next)
+ mc->_next->_prev = mc;
+}
+
+void IMuseAdlib::part_key_on(Part *part, byte note, byte velocity)
+{
+ MidiChannelAdl *mc;
+
+ mc = allocate_midichan(part->_pri_eff);
+ if (!mc)
+ return;
+
+ link_mc(part, mc);
+ mc_key_on(mc, note, velocity);
+}
+
+void IMuseAdlib::part_key_off(Part *part, byte note)
+{
+ MidiChannelAdl *mc;
+
+ for (mc = (MidiChannelAdl *)part->_mc; mc; mc = mc->_next) {
+ if (mc->_note == note) {
+ if (part->_pedal)
+ mc->_waitforpedal = true;
+ else
+ mc_off(mc);
+ }
+ }
+}
+
+struct AdlibInstrSetParams {
+ byte param;
+ byte shl;
+ byte mask;
+};
+
+#define MKLINE(_a_,_b_,_c_) { (int)&((Instrument*)0)->_a_, _b_, ((1<<(_c_))-1)<<(_b_) }
+static const AdlibInstrSetParams adlib_instr_params[69] = {
+ MKLINE(oplvl_2, 0, 6),
+ MKLINE(waveform_2, 2, 5),
+ MKLINE(oplvl_2, 6, 2),
+ MKLINE(flags_2, 0, 4),
+ MKLINE(atdec_2, 4, 4),
+ MKLINE(atdec_2, 0, 4),
+ MKLINE(sustrel_2, 4, 4),
+ MKLINE(sustrel_2, 0, 4),
+ MKLINE(waveform_2, 0, 2),
+ MKLINE(flags_2, 7, 1),
+ MKLINE(flags_2, 6, 1),
+ MKLINE(flags_2, 5, 1),
+ MKLINE(flags_2, 4, 1),
+
+ MKLINE(oplvl_1, 0, 6),
+ MKLINE(waveform_1, 2, 5),
+ MKLINE(oplvl_1, 6, 2),
+ MKLINE(flags_1, 0, 4),
+ MKLINE(atdec_1, 4, 4),
+ MKLINE(atdec_1, 0, 4),
+ MKLINE(sustrel_1, 4, 4),
+ MKLINE(sustrel_1, 0, 4),
+ MKLINE(waveform_1, 0, 2),
+ MKLINE(flags_1, 7, 1),
+ MKLINE(flags_1, 6, 1),
+ MKLINE(flags_1, 5, 1),
+ MKLINE(flags_1, 4, 1),
+
+ MKLINE(feedback, 0, 1),
+ MKLINE(feedback, 1, 3),
+
+ MKLINE(flags_a, 7, 1),
+ MKLINE(flags_a, 6, 1),
+ MKLINE(flags_a, 5, 1),
+ MKLINE(flags_a, 4, 1),
+ MKLINE(flags_a, 0, 4),
+ MKLINE(extra_a.a, 0, 8),
+ MKLINE(extra_a.b, 0, 7),
+ MKLINE(extra_a.c, 0, 7),
+ MKLINE(extra_a.d, 0, 7),
+ MKLINE(extra_a.e, 0, 7),
+ MKLINE(extra_a.f, 0, 7),
+ MKLINE(extra_a.g, 0, 7),
+ MKLINE(extra_a.h, 0, 7),
+ MKLINE(extra_a.b, 7, 1),
+ MKLINE(extra_a.c, 7, 1),
+ MKLINE(extra_a.d, 7, 1),
+ MKLINE(extra_a.e, 7, 1),
+ MKLINE(extra_a.f, 7, 1),
+ MKLINE(extra_a.g, 7, 1),
+ MKLINE(extra_a.h, 7, 1),
+
+ MKLINE(flags_b, 7, 1),
+ MKLINE(flags_b, 6, 1),
+ MKLINE(flags_b, 5, 1),
+ MKLINE(flags_b, 4, 1),
+ MKLINE(flags_b, 0, 4),
+ MKLINE(extra_b.a, 0, 8),
+ MKLINE(extra_b.b, 0, 7),
+ MKLINE(extra_b.c, 0, 7),
+ MKLINE(extra_b.d, 0, 7),
+ MKLINE(extra_b.e, 0, 7),
+ MKLINE(extra_b.f, 0, 7),
+ MKLINE(extra_b.g, 0, 7),
+ MKLINE(extra_b.h, 0, 7),
+ MKLINE(extra_b.b, 7, 1),
+ MKLINE(extra_b.c, 7, 1),
+ MKLINE(extra_b.d, 7, 1),
+ MKLINE(extra_b.e, 7, 1),
+ MKLINE(extra_b.f, 7, 1),
+ MKLINE(extra_b.g, 7, 1),
+ MKLINE(extra_b.h, 7, 1),
+
+ MKLINE(duration, 0, 8),
+};
+#undef MKLINE
+
+void IMuseAdlib::part_set_param(Part *part, byte param, int value)
+{
+ const AdlibInstrSetParams *sp = &adlib_instr_params[param];
+ byte *p = (byte *)&_part_instr[part->_slot] + sp->param;
+ *p = (*p & ~sp->mask) | (value << sp->shl);
+
+ if (param < 28) {
+ MidiChannelAdl *mc;
+
+ for (mc = (MidiChannelAdl *)part->_mc; mc; mc = mc->_next) {
+ adlib_set_param(mc->_channel, param, value);
+ }
+ }
+}
+
+void IMuseAdlib::part_off(Part *part)
+{
+ MidiChannelAdl *mc = (MidiChannelAdl *)part->_mc;
+ part->_mc = NULL;
+ for (; mc; mc = mc->_next) {
+ mc_off(mc);
+ }
+}
+
+void IMuseAdlib::mc_off(MidiChannel * mc2)
+{
+ MidiChannelAdl *mc = (MidiChannelAdl *)mc2, *tmp;
+
+ adlib_key_off(mc->_channel);
+
+ tmp = mc->_prev;
+
+ if (mc->_next)
+ mc->_next->_prev = tmp;
+ if (tmp)
+ tmp->_next = mc->_next;
+ else
+ mc->_part->_mc = mc->_next;
+ mc->_part = NULL;
+}
+
+void IMuseAdlib::part_set_instrument(Part *part, Instrument * instr)
+{
+ Instrument *i = &_part_instr[part->_slot];
+ memcpy(i, instr, sizeof(Instrument));
+}
+
+int IMuseAdlib::part_update_active(Part *part, uint16 *active)
+{
+ uint16 bits;
+ int count = 0;
+ MidiChannelAdl *mc;
+
+ bits = 1 << part->_chan;
+
+ for (mc = part->_mc->adl(); mc; mc = mc->_next) {
+ if (!(active[mc->_note] & bits)) {
+ active[mc->_note] |= bits;
+ count++;
+ }
+ }
+ return count;
+}
+
+//********************************************
+//** GENERAL MIDI PART OF IMUSE STARTS HERE **
+//********************************************
+
+void IMuseGM::midiPitchBend(byte chan, int16 pitchbend)
+{
+ uint16 tmp;
+
+ if (_midi_pitchbend_last[chan] != pitchbend) {
+ _midi_pitchbend_last[chan] = pitchbend;
+ tmp = (pitchbend << 2) + 0x2000;
+ _md->send(((tmp >> 7) & 0x7F) << 16 | (tmp & 0x7F) << 8 | 0xE0 | chan);
+ }
+}
+
+void IMuseGM::midiVolume(byte chan, byte volume)
+{
+ if (_midi_volume_last[chan] != volume) {
+ _midi_volume_last[chan] = volume;
+ _md->send(volume << 16 | 7 << 8 | 0xB0 | chan);
+ }
+}
+void IMuseGM::midiPedal(byte chan, bool pedal)
+{
+ if (_midi_pedal_last[chan] != pedal) {
+ _midi_pedal_last[chan] = pedal;
+ _md->send(pedal << 16 | 64 << 8 | 0xB0 | chan);
+ }
+}
+
+void IMuseGM::midiModWheel(byte chan, byte modwheel)
+{
+ if (_midi_modwheel_last[chan] != modwheel) {
+ _midi_modwheel_last[chan] = modwheel;
+ _md->send(modwheel << 16 | 1 << 8 | 0xB0 | chan);
+ }
+}
+
+void IMuseGM::midiEffectLevel(byte chan, byte level)
+{
+ if (_midi_effectlevel_last[chan] != level) {
+ _midi_effectlevel_last[chan] = level;
+ _md->send(level << 16 | 91 << 8 | 0xB0 | chan);
+ }
+}
+
+void IMuseGM::midiChorus(byte chan, byte chorus)
+{
+ if (_midi_chorus_last[chan] != chorus) {
+ _midi_chorus_last[chan] = chorus;
+ _md->send(chorus << 16 | 93 << 8 | 0xB0 | chan);
+ }
+}
+
+void IMuseGM::midiControl0(byte chan, byte value)
+{
+ _md->send(value << 16 | 0 << 8 | 0xB0 | chan);
+}
+
+
+void IMuseGM::midiProgram(byte chan, byte program)
+{
+ if ((chan + 1) != 10) { /* Ignore percussion prededed by patch change */
+ if (_se->_mt32emulate)
+ program = mt32_to_gmidi[program];
+
+ _md->send(program << 8 | 0xC0 | chan);
+ }
+}
+
+void IMuseGM::midiPan(byte chan, int8 pan)
+{
+ if (_midi_pan_last[chan] != pan) {
+ _midi_pan_last[chan] = pan;
+ _md->send(((pan - 64) & 0x7F) << 16 | 10 << 8 | 0xB0 | chan);
+ }
+}
+
+void IMuseGM::midiNoteOn(byte chan, byte note, byte velocity)
+{
+ _md->send(velocity << 16 | note << 8 | 0x90 | chan);
+}
+
+void IMuseGM::midiNoteOff(byte chan, byte note)
+{
+ _md->send(note << 8 | 0x80 | chan);
+}
+
+void IMuseGM::midiSilence(byte chan)
+{
+ _md->send((64 << 8) | 0xB0 | chan);
+ _md->send((123 << 8) | 0xB0 | chan);
+}
+
+
+void IMuseGM::part_key_on(Part *part, byte note, byte velocity)
+{
+ MidiChannelGM *mc = part->_mc->gm();
+
+ if (mc) {
+ mc->_actives[note >> 4] |= (1 << (note & 0xF));
+ midiNoteOn(mc->_chan, note, velocity);
+ } else if (part->_percussion) {
+ midiVolume(SPECIAL_CHANNEL, part->_vol_eff);
+ midiProgram(SPECIAL_CHANNEL, part->_bank);
+ midiNoteOn(SPECIAL_CHANNEL, note, velocity);
+ }
+}
+
+void IMuseGM::part_key_off(Part *part, byte note)
+{
+ MidiChannelGM *mc = part->_mc->gm();
+
+ if (mc) {
+ mc->_actives[note >> 4] &= ~(1 << (note & 0xF));
+ midiNoteOff(mc->_chan, note);
+ } else if (part->_percussion) {
+ midiNoteOff(SPECIAL_CHANNEL, note);
+ }
+}
+
+int IMuseGM::midi_driver_thread(void *param) {
+ IMuseGM *mid = (IMuseGM*) param;
+ int old_time, cur_time;
+
+ old_time = mid->_system->get_msecs();
+
+ for(;;) {
+ mid->_system->delay_msecs(10);
+
+ cur_time = mid->_system->get_msecs();
+ while (old_time < cur_time) {
+ old_time += 10;
+ mid->_se->on_timer();
+ }
+ }
+}
+
+void IMuseGM::init(IMuse *eng, OSystem *syst)
+{
+ int i;
+ MidiChannelGM *mc;
+
+ _system = syst;
+
+ /* open midi driver */
+ int result = _md->open(MidiDriver::MO_SIMPLE);
+ if (result)
+ error("IMuseGM::error = %s", MidiDriver::get_error_name(result));
+
+ /* Install the on_timer thread */
+ syst->create_thread(midi_driver_thread, this);
+ _se = eng;
+
+ for (i = 0, mc = _midi_channels; i != ARRAYSIZE(_midi_channels); i++, mc++)
+ mc->_chan = i;
+}
+
+void IMuseGM::update_pris()
+{
+ Part *part, *hipart;
+ int i;
+ byte hipri, lopri;
+ MidiChannelGM *mc, *lomc;
+
+ while (true) {
+ hipri = 0;
+ hipart = NULL;
+ for (i = 32, part = _se->parts_ptr(); i; i--, part++) {
+ if (part->_player && !part->_percussion && part->_on && !part->_mc
+ && part->_pri_eff >= hipri) {
+ hipri = part->_pri_eff;
+ hipart = part;
+ }
+ }
+
+ if (!hipart)
+ return;
+
+ lopri = 255;
+ lomc = NULL;
+ for (i = ARRAYSIZE(_midi_channels), mc = _midi_channels;; mc++) {
+ if (!mc->_part) {
+ lomc = mc;
+ break;
+ }
+ if (mc->_part->_pri_eff <= lopri) {
+ lopri = mc->_part->_pri_eff;
+ lomc = mc;
+ }
+
+ if (!--i) {
+ if (lopri >= hipri)
+ return;
+ lomc->_part->off();
+ break;
+ }
+ }
+
+ hipart->_mc = lomc;
+ lomc->_part = hipart;
+ hipart->changed(pcAll);
+ }
+}
+
+int IMuseGM::part_update_active(Part *part, uint16 *active)
+{
+ int i, j;
+ uint16 *act, mask, bits;
+ int count = 0;
+
+ bits = 1 << part->_chan;
+
+ act = part->_mc->gm()->_actives;
+
+ for (i = 8; i; i--) {
+ mask = *act++;
+ if (mask) {
+ for (j = 16; j; j--, mask >>= 1, active++) {
+ if (mask & 1 && !(*active & bits)) {
+ *active |= bits;
+ count++;
+ }
+ }
+ } else {
+ active += 16;
+ }
+ }
+ return count;
+}
+
+void IMuseGM::part_changed(Part *part, byte what)
+{
+ MidiChannelGM *mc;
+
+ /* Mark for re-schedule if program changed when in pre-state */
+ if (what & pcProgram && part->_percussion) {
+ part->_percussion = false;
+ update_pris();
+ }
+
+ if (!(mc = part->_mc->gm()))
+ return;
+
+ if (what & pcMod)
+ midiPitchBend(mc->_chan,
+ clamp(part->_pitchbend + part->_detune_eff +
+ (part->_transpose_eff << 7), -2048, 2047));
+
+ if (what & pcVolume)
+ midiVolume(mc->_chan, part->_vol_eff);
+
+ if (what & pcPedal)
+ midiPedal(mc->_chan, part->_pedal);
+
+ if (what & pcModwheel)
+ midiModWheel(mc->_chan, part->_modwheel);
+
+ if (what & pcPan)
+ midiPan(mc->_chan, part->_pan_eff);
+
+ if (what & pcEffectLevel)
+ midiEffectLevel(mc->_chan, part->_effect_level);
+
+ if (what & pcProgram) {
+ if (part->_bank) {
+ midiControl0(mc->_chan, part->_bank);
+ midiProgram(mc->_chan, part->_program);
+ midiControl0(mc->_chan, 0);
+ } else {
+ midiProgram(mc->_chan, part->_program);
+ }
+ }
+
+ if (what & pcChorus)
+ midiChorus(mc->_chan, part->_effect_level);
+}
+
+
+void IMuseGM::part_off(Part *part)
+{
+ MidiChannelGM *mc = part->_mc->gm();
+ if (mc) {
+ part->_mc = NULL;
+ mc->_part = NULL;
+ memset(mc->_actives, 0, sizeof(mc->_actives));
+ midiSilence(mc->_chan);
+ }
+}
+
diff --git a/sound/imuse.h b/sound/imuse.h
new file mode 100644
index 0000000000..fc2cacbd0d
--- /dev/null
+++ b/sound/imuse.h
@@ -0,0 +1,46 @@
+
+//WARNING: These is only the public interface to the IMUSE class
+//This is safe as long as none of the methods are virtual,
+//and as long as no variables are put here.
+//Removing the private parts from the public class definition,
+//means that the internals of IMuse can change without having to
+//recompile all files that depend on this interface.
+//Also, it probably decreases compile times, since the IMuse specific
+//classes only will be parsed once (which is when imuse.cpp is compiled)
+
+
+//If you change stuff here, you *MUST* change stuff in imuse.cpp as well
+
+class IMuse {
+public:
+ /* making a dummy constructor means that this object will never be
+ * instanciated on its own */
+
+public:
+ enum {
+ PROP_TEMPO_BASE = 1,
+ PROP_MT32_EMULATE = 2,
+ };
+
+ void on_timer();
+ void pause(bool paused);
+ int terminate();
+ int save_or_load(Serializer *ser, Scumm *scumm);
+ int set_music_volume(uint vol);
+ int get_music_volume();
+ int set_master_volume(uint vol);
+ int get_master_volume();
+ bool start_sound(int sound);
+ int stop_sound(int sound);
+ int stop_all_sounds();
+ int get_sound_status(int sound);
+ int32 do_command(int a, int b, int c, int d, int e, int f, int g, int h);
+ int clear_queue();
+ void setBase(byte **base);
+ uint32 property(int prop, uint32 value);
+
+ static IMuse *create(OSystem *syst, MidiDriver *midi, SoundMixer *mixer);
+
+ static IMuse *create_adlib(OSystem *syst, SoundMixer *mixer) { return create(syst, NULL, mixer); }
+ static IMuse *create_midi(OSystem *syst, MidiDriver *midi) { return create(syst, midi, NULL); }
+};
diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp
index 7a881e7cb1..b8d365be29 100644
--- a/sound/mididrv.cpp
+++ b/sound/mididrv.cpp
@@ -30,11 +30,9 @@
#include <devices/timer.h>
#endif
-
#include "stdafx.h"
#include "scumm.h"
-#include "gmidi.h"
-
+#include "mididrv.h"
#ifdef WIN32
@@ -326,9 +324,6 @@ const char *MidiDriver::get_error_name(int error_code) {
#if 0
-
-
-
void MidiDriver::midiInit()
{
if (MidiInitialized != true) {
@@ -686,4 +681,51 @@ void MidiDriver::midiInitNull()
warning
("Music not enabled - MIDI support selected with no MIDI driver available. Try Adlib");
}
-#endif \ No newline at end of file
+
+
+
+/* old header stuff.. */
+/* General Midi header file */
+#define SEQ_MIDIPUTC 5
+#define SPECIAL_CHANNEL 9
+#define DEVICE_NUM 0
+
+
+
+#ifdef __APPLE__CW
+ #include <QuickTimeComponents.h>
+ #include "QuickTimeMusic.h"
+
+ NoteAllocator qtNoteAllocator;
+ NoteChannel qtNoteChannel[16];
+ NoteRequest simpleNoteRequest;
+#endif
+
+#ifdef WIN32
+ #include <winsock.h>
+#elif defined(UNIX)
+ #include <sys/time.h>
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+#endif
+
+#ifdef __MORPHOS__
+ #include <exec/types.h>
+ #include <devices/amidi.h>
+
+ #define NO_PPCINLINE_STDARG
+ #define NO_PPCINLINE_VARARGS
+ #include <clib/alib_protos.h>
+ #include <proto/exec.h>
+ #undef CMD_INVALID
+
+ extern struct IOMidiRequest *ScummMidiRequest;
+#endif
+
+#endif /* 0 */ \ No newline at end of file
diff --git a/sound/gmidi.h b/sound/mididrv.h
index 7e9d7e8db5..228e36ee7e 100644
--- a/sound/gmidi.h
+++ b/sound/mididrv.h
@@ -1,11 +1,3 @@
-#if !defined(gmidi_h)
-#define gmidi_h
-
-/* General Midi header file */
-#define SEQ_MIDIPUTC 5
-#define SPECIAL_CHANNEL 9
-#define DEVICE_NUM 0
-
struct MidiEvent {
uint32 delta;
uint32 event;
@@ -105,56 +97,3 @@ MidiDriver *MidiDriver_TIMIDITY_create();
MidiDriver *MidiDriver_SEQ_create();
MidiDriver *MidiDriver_QT_create();
MidiDriver *MidiDriver_AMIDI_create();
-
-
-
-/* Roland to General Midi patch table. Still needs much work. */
-static const byte mt32_to_gmidi[128] = {
- 0, 1, 2, 4, 4, 5, 5, 3, 16, 17, 18, 18, 19,
- 19, 20, 21, 6, 6, 6, 7, 7, 7, 8, 8, 62, 63,
- 62, 63, 38, 39, 38, 39, 88, 89, 52, 113, 97, 96, 91,
- 85, 14, 101, 68, 95, 86, 103, 88, 80, 48, 49, 51, 45,
- 40, 40, 42, 42, 43, 46, 46, 24, 25, 26, 27, 104, 32,
- 33, 34, 39, 36, 37, 38, 35, 79, 73, 72, 72, 74, 75,
- 64, 65, 66, 67, 71, 71, 68, 69, 70, 22, 56, 59, 57,
- 63, 60, 60, 58, 61, 61, 11, 11, 12, 88, 9, 14, 13,
- 12, 107, 111, 77, 78, 78, 76, 121, 47, 117, 127, 115, 118,
- 116, 118, 94, 115, 9, 55, 124, 123, 125, 126, 127
-};
-
-#ifdef __APPLE__CW
- #include <QuickTimeComponents.h>
- #include "QuickTimeMusic.h"
-
- NoteAllocator qtNoteAllocator;
- NoteChannel qtNoteChannel[16];
- NoteRequest simpleNoteRequest;
-#endif
-
-#ifdef WIN32
- #include <winsock.h>
-#elif defined(UNIX)
- #include <sys/time.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-#endif
-
-#ifdef __MORPHOS__
- #include <exec/types.h>
- #include <devices/amidi.h>
-
- #define NO_PPCINLINE_STDARG
- #define NO_PPCINLINE_VARARGS
- #include <clib/alib_protos.h>
- #include <proto/exec.h>
- #undef CMD_INVALID
-
- extern struct IOMidiRequest *ScummMidiRequest;
-#endif
-#endif /* defined(gmidi_h) */
diff --git a/sound/mixer.cpp b/sound/mixer.cpp
new file mode 100644
index 0000000000..add23d9e91
--- /dev/null
+++ b/sound/mixer.cpp
@@ -0,0 +1,491 @@
+#include "stdafx.h"
+#include "scumm.h"
+#include "cdmusic.h"
+
+void SoundMixer::uninsert(Channel *chan) {
+
+ for(int i=0; i!=NUM_CHANNELS; i++) {
+ if (_channels[i] == chan) {
+ if (_handles[i]) {
+ *_handles[i] = 0;
+ _handles[i] = NULL;
+ }
+ _channels[i] = NULL;
+ return;
+ }
+ }
+ error("SoundMixer::channel_deleted chan not found");
+}
+
+void SoundMixer::insert(PlayingSoundHandle *handle, Channel *chan) {
+ for(int i=0; i!=NUM_CHANNELS; i++) {
+ if (_channels[i] == NULL) {
+ _channels[i] = chan;
+ _handles[i] = handle;
+ if (handle)
+ *handle = i + 1;
+ return;
+ }
+ }
+
+ warning("SoundMixer::insert out of mixer slots");
+ chan->destroy();
+}
+
+
+void SoundMixer::play_raw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags) {
+ insert(handle, new Channel_RAW(this, sound, size, rate, flags));
+}
+
+void SoundMixer::mix(int16 *buf, uint len) {
+ if (_premix_proc) {
+ _premix_proc(_premix_param, buf, len);
+ } else {
+ /* no premixer available, zero the buf out */
+ memset(buf, 0, len * sizeof(int16));
+ }
+
+ /* now mix all channels */
+ for(int i=0; i!=NUM_CHANNELS; i++)
+ if (_channels[i])
+ _channels[i]->mix(buf, len);
+}
+
+void SoundMixer::on_generate_samples(void *s, byte *samples, int len) {
+ ((SoundMixer*)s)->mix((int16*)samples, len>>1);
+}
+
+void SoundMixer::bind_to_system(OSystem *syst) {
+ _volume_table = (int16*)calloc(256*sizeof(int16),1);
+
+ uint rate = (uint)syst->property(OSystem::PROP_GET_SAMPLE_RATE, 0);
+
+ _output_rate = rate;
+
+ if (rate == 0)
+ error("OSystem returned invalid sample rate");
+
+ syst->set_sound_proc(this, on_generate_samples, OSystem::SOUND_16BIT);
+}
+
+void SoundMixer::stop_all() {
+ for(int i=0; i!=NUM_CHANNELS; i++)
+ if (_channels[i])
+ _channels[i]->destroy();
+}
+
+void SoundMixer::stop(PlayingSoundHandle psh) {
+ if (psh && _channels[psh-1])
+ _channels[psh-1]->destroy();
+}
+
+
+bool SoundMixer::has_active_channel() {
+ for(int i=0; i!=NUM_CHANNELS; i++)
+ if (_channels[i])
+ return true;
+ return false;
+}
+
+void SoundMixer::setup_premix(void *param, PremixProc *proc) {
+ _premix_param = param;
+ _premix_proc = proc;
+}
+
+void SoundMixer::set_volume(int volume) {
+ for(int i=0; i!=256; i++)
+ _volume_table[i] =((int8)i) * volume;
+}
+
+
+/* RAW mixer */
+SoundMixer::Channel_RAW::Channel_RAW(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags) {
+ _mixer = mixer;
+ _flags = flags;
+ _ptr = sound;
+ _pos = 0;
+ _fp_pos = 0;
+ _fp_speed = (1 << 16) * rate / mixer->_output_rate;
+
+ /* adjust the magnitute to prevent division error */
+ while (size & 0xFFFF0000)
+ size >>= 1, rate >>= 1;
+
+ _size = size * mixer->_output_rate / rate;
+}
+
+void SoundMixer::Channel_RAW::mix(int16 *data, uint len) {
+ byte *s, *s_org = NULL;
+ uint32 fp_pos;
+
+ if (len > _size)
+ len = _size;
+ _size -= len;
+
+ /*
+ * simple support for fread() reading of samples
+ */
+ if (_flags & FLAG_FILE) {
+ /* determine how many samples to read from the file */
+ uint num = len * _fp_speed >> 16;
+
+ s_org = (byte*)malloc(num);
+ if (s_org == NULL)
+ error("Channel_RAW::mix out of memory");
+
+ uint num_read = fread(s_org, 1, num, (FILE*)_ptr);
+ if (num - num_read != 0)
+ memset(s_org + num_read, 0x80, num - num_read);
+
+ s = s_org;
+ fp_pos = 0;
+ } else {
+ s = (byte*)_ptr + _pos;
+ fp_pos = _fp_pos;
+ }
+
+ const uint32 fp_speed = _fp_speed;
+ const int16 *vol_tab = _mixer->_volume_table;
+
+ if (_flags & FLAG_UNSIGNED) {
+ do {
+ fp_pos += fp_speed;
+ *data++ += vol_tab[*s ^ 0x80];
+ s += fp_pos >> 16;
+ fp_pos &= 0x0000FFFF;
+ } while (--len);
+ } else {
+ do {
+ fp_pos += fp_speed;
+ *data++ += vol_tab[*s];
+ s += fp_pos >> 16;
+ fp_pos &= 0x0000FFFF;
+ } while (--len);
+ }
+
+ _pos = s - (byte*) _ptr;
+ _fp_pos = fp_pos;
+
+ if (_flags & FLAG_FILE) {
+ free(s_org);
+ }
+
+ if (!_size)
+ destroy();
+}
+
+void SoundMixer::Channel_RAW::destroy() {
+ if (_flags & FLAG_AUTOFREE)
+ free(_ptr);
+ _mixer->uninsert(this);
+ delete this;
+}
+
+
+/* MP3 mixer goes here */
+
+#if 0
+
+#ifdef COMPRESSED_SOUND_FILE
+void Scumm::playSfxSound_MP3(void *sound, uint32 size)
+{
+ MixerChannel *mc = allocateMixer();
+
+ if (!mc) {
+ warning("No mixer channel available");
+ return;
+ }
+
+ mc->type = MIXER_MP3;
+ mc->_sfx_sound = sound;
+
+ mad_stream_init(&mc->sound_data.mp3.stream);
+
+
+
+#ifdef _WIN32_WCE
+
+ // 11 kHz on WinCE
+
+ mad_stream_options((mad_stream *) & mc->sound_data.mp3.stream,
+ MAD_OPTION_HALFSAMPLERATE);
+
+#endif
+
+
+ mad_frame_init(&mc->sound_data.mp3.frame);
+ mad_synth_init(&mc->sound_data.mp3.synth);
+ mc->sound_data.mp3.position = 0;
+ mc->sound_data.mp3.pos_in_frame = 0xFFFFFFFF;
+ mc->sound_data.mp3.size = size;
+ /* This variable is the number of samples to cut at the start of the MP3
+ file. This is needed to have lip-sync as the MP3 file have some miliseconds
+ of blank at the start (as, I suppose, the MP3 compression algorithm need to
+ have some silence at the start to really be efficient and to not distort
+ too much the start of the sample).
+
+ This value was found by experimenting out. If you recompress differently your
+ .SO3 file, you may have to change this value.
+
+ When using Lame, it seems that the sound starts to have some volume about 50 ms
+ from the start of the sound => we skip about 1024 samples.
+ */
+ mc->sound_data.mp3.silence_cut = 1024;
+}
+#endif
+
+#ifdef COMPRESSED_SOUND_FILE
+static inline int scale_sample(mad_fixed_t sample)
+{
+ /* round */
+ sample += (1L << (MAD_F_FRACBITS - 16));
+
+ /* clip */
+ if (sample >= MAD_F_ONE)
+ sample = MAD_F_ONE - 1;
+ else if (sample < -MAD_F_ONE)
+ sample = -MAD_F_ONE;
+
+ /* quantize and scale to not saturate when mixing a lot of channels */
+ return sample >> (MAD_F_FRACBITS + 2 - 16);
+}
+#endif
+
+void MixerChannel::mix(int16 * data, uint32 len)
+{
+ if (!_sfx_sound)
+ return;
+
+#ifdef COMPRESSED_SOUND_FILE
+ if (type == MIXER_STANDARD) {
+#endif
+ int8 *s;
+ uint32 fp_pos, fp_speed;
+
+ if (len > sound_data.standard._sfx_size)
+ len = sound_data.standard._sfx_size;
+ sound_data.standard._sfx_size -= len;
+
+ s = (int8 *) _sfx_sound + sound_data.standard._sfx_pos;
+ fp_pos = sound_data.standard._sfx_fp_pos;
+ fp_speed = sound_data.standard._sfx_fp_speed;
+
+ do {
+ fp_pos += fp_speed;
+ *data++ += (*s << 6);
+ s += fp_pos >> 16;
+ fp_pos &= 0x0000FFFF;
+ } while (--len);
+
+ sound_data.standard._sfx_pos = s - (int8 *) _sfx_sound;
+ sound_data.standard._sfx_fp_speed = fp_speed;
+ sound_data.standard._sfx_fp_pos = fp_pos;
+
+ if (!sound_data.standard._sfx_size)
+ clear();
+#ifdef COMPRESSED_SOUND_FILE
+ } else {
+ if (type == MIXER_MP3) {
+ mad_fixed_t const *ch;
+ while (1) {
+ ch =
+ sound_data.mp3.synth.pcm.samples[0] + sound_data.mp3.pos_in_frame;
+ while ((sound_data.mp3.pos_in_frame < sound_data.mp3.synth.pcm.length)
+ && (len > 0)) {
+ if (sound_data.mp3.silence_cut > 0) {
+ sound_data.mp3.silence_cut--;
+ } else {
+ *data++ += scale_sample(*ch++);
+ len--;
+ }
+ sound_data.mp3.pos_in_frame++;
+ }
+ if (len == 0)
+ return;
+
+ if (sound_data.mp3.position >= sound_data.mp3.size) {
+ clear();
+ return;
+ }
+
+ mad_stream_buffer(&sound_data.mp3.stream,
+ ((unsigned char *)_sfx_sound) +
+ sound_data.mp3.position,
+ sound_data.mp3.size + MAD_BUFFER_GUARD -
+ sound_data.mp3.position);
+
+ if (mad_frame_decode(&sound_data.mp3.frame, &sound_data.mp3.stream) ==
+ -1) {
+ /* End of audio... */
+ if (sound_data.mp3.stream.error == MAD_ERROR_BUFLEN) {
+ clear();
+ return;
+ } else if (!MAD_RECOVERABLE(sound_data.mp3.stream.error)) {
+ error("MAD frame decode error !");
+ }
+ }
+ mad_synth_frame(&sound_data.mp3.synth, &sound_data.mp3.frame);
+ sound_data.mp3.pos_in_frame = 0;
+ sound_data.mp3.position =
+ (unsigned char *)sound_data.mp3.stream.next_frame -
+ (unsigned char *)_sfx_sound;
+ }
+ } else if (type == MIXER_MP3_CDMUSIC) {
+ mad_fixed_t const *ch;
+ mad_timer_t frame_duration;
+ static long last_pos = 0;
+
+ if (!sound_data.mp3_cdmusic.playing)
+ return;
+
+ while (1) {
+
+ // See if we just skipped
+ if (ftell(sound_data.mp3_cdmusic.file) != last_pos) {
+ int skip_loop;
+
+ // Read the new data
+ memset(_sfx_sound, 0,
+ sound_data.mp3_cdmusic.buffer_size + MAD_BUFFER_GUARD);
+ sound_data.mp3_cdmusic.size =
+ fread(_sfx_sound, 1, sound_data.mp3_cdmusic.buffer_size,
+ sound_data.mp3_cdmusic.file);
+ if (!sound_data.mp3_cdmusic.size) {
+ sound_data.mp3_cdmusic.playing = false;
+ return;
+ }
+ last_pos = ftell(sound_data.mp3_cdmusic.file);
+ // Resync
+ mad_stream_buffer(&sound_data.mp3_cdmusic.stream,
+ (unsigned char *)_sfx_sound,
+ sound_data.mp3_cdmusic.size);
+ skip_loop = 2;
+ while (skip_loop != 0) {
+ if (mad_frame_decode(&sound_data.mp3_cdmusic.frame,
+ &sound_data.mp3_cdmusic.stream) == 0) {
+ /* Do not decrease duration - see if it's a problem */
+ skip_loop--;
+ if (skip_loop == 0) {
+ mad_synth_frame(&sound_data.mp3_cdmusic.synth,
+ &sound_data.mp3_cdmusic.frame);
+ }
+ } else {
+ if (!MAD_RECOVERABLE(sound_data.mp3_cdmusic.stream.error)) {
+ debug(1, "Unrecoverable error while skipping !");
+ sound_data.mp3_cdmusic.playing = false;
+ return;
+ }
+ }
+ }
+ // We are supposed to be in synch
+ mad_frame_mute(&sound_data.mp3_cdmusic.frame);
+ mad_synth_mute(&sound_data.mp3_cdmusic.synth);
+ // Resume decoding
+ if (mad_frame_decode(&sound_data.mp3_cdmusic.frame,
+ &sound_data.mp3_cdmusic.stream) == 0) {
+ sound_data.mp3_cdmusic.position =
+ (unsigned char *)sound_data.mp3_cdmusic.stream.next_frame -
+ (unsigned char *)_sfx_sound;
+ sound_data.mp3_cdmusic.pos_in_frame = 0;
+ } else {
+ sound_data.mp3_cdmusic.playing = false;
+ return;
+ }
+ }
+ // Get samples, play samples ...
+
+ ch = sound_data.mp3_cdmusic.synth.pcm.samples[0] +
+ sound_data.mp3_cdmusic.pos_in_frame;
+ while ((sound_data.mp3_cdmusic.pos_in_frame <
+ sound_data.mp3_cdmusic.synth.pcm.length) && (len > 0)) {
+ *data++ += scale_sample(*ch++);
+ len--;
+ sound_data.mp3_cdmusic.pos_in_frame++;
+ }
+ if (len == 0) {
+ return;
+ }
+ // See if we have finished
+ // May be incorrect to check the size at the end of a frame but I suppose
+ // they are short enough :)
+
+ frame_duration = sound_data.mp3_cdmusic.frame.header.duration;
+
+ mad_timer_negate(&frame_duration);
+ mad_timer_add(&sound_data.mp3_cdmusic.duration, frame_duration);
+ if (mad_timer_compare(sound_data.mp3_cdmusic.duration, mad_timer_zero)
+ < 0) {
+ sound_data.mp3_cdmusic.playing = false;
+ }
+
+ if (mad_frame_decode(&sound_data.mp3_cdmusic.frame,
+ &sound_data.mp3_cdmusic.stream) == -1) {
+
+ if (sound_data.mp3_cdmusic.stream.error == MAD_ERROR_BUFLEN) {
+ int not_decoded;
+
+ if (!sound_data.mp3_cdmusic.stream.next_frame) {
+ memset(_sfx_sound, 0,
+ sound_data.mp3_cdmusic.buffer_size + MAD_BUFFER_GUARD);
+ sound_data.mp3_cdmusic.size =
+ fread(_sfx_sound, 1, sound_data.mp3_cdmusic.buffer_size,
+ sound_data.mp3_cdmusic.file);
+ sound_data.mp3_cdmusic.position = 0;
+ not_decoded = 0;
+ } else {
+ not_decoded = sound_data.mp3_cdmusic.stream.bufend -
+ sound_data.mp3_cdmusic.stream.next_frame;
+ memcpy(_sfx_sound, sound_data.mp3_cdmusic.stream.next_frame,
+ not_decoded);
+
+ sound_data.mp3_cdmusic.size =
+ fread((unsigned char *)_sfx_sound + not_decoded, 1,
+ sound_data.mp3_cdmusic.buffer_size - not_decoded,
+ sound_data.mp3_cdmusic.file);
+ }
+ last_pos = ftell(sound_data.mp3_cdmusic.file);
+ sound_data.mp3_cdmusic.stream.error = MAD_ERROR_NONE;
+ // Restream
+ mad_stream_buffer(&sound_data.mp3_cdmusic.stream,
+ (unsigned char *)_sfx_sound,
+ sound_data.mp3_cdmusic.size + not_decoded);
+ if (mad_frame_decode
+ (&sound_data.mp3_cdmusic.frame,
+ &sound_data.mp3_cdmusic.stream) == -1) {
+ debug(1, "Error decoding after restream %d !",
+ sound_data.mp3.stream.error);
+ }
+ } else if (!MAD_RECOVERABLE(sound_data.mp3.stream.error)) {
+ error("MAD frame decode error in MP3 CDMUSIC !");
+ }
+ }
+
+ mad_synth_frame(&sound_data.mp3_cdmusic.synth,
+ &sound_data.mp3_cdmusic.frame);
+ sound_data.mp3_cdmusic.pos_in_frame = 0;
+ sound_data.mp3_cdmusic.position =
+ (unsigned char *)sound_data.mp3_cdmusic.stream.next_frame -
+ (unsigned char *)_sfx_sound;
+ }
+ }
+ }
+#endif
+}
+
+void MixerChannel::clear()
+{
+ free(_sfx_sound);
+ _sfx_sound = NULL;
+
+#ifdef COMPRESSED_SOUND_FILE
+ if (type == MIXER_MP3) {
+ mad_synth_finish(&sound_data.mp3.synth);
+ mad_frame_finish(&sound_data.mp3.frame);
+ mad_stream_finish(&sound_data.mp3.stream);
+ }
+#endif
+}
+
+#endif
+
+
diff --git a/sound/mixer.h b/sound/mixer.h
new file mode 100644
index 0000000000..e2002a9e87
--- /dev/null
+++ b/sound/mixer.h
@@ -0,0 +1,157 @@
+#ifndef _mixer_h_included
+#define _mixer_h_included
+
+typedef uint32 PlayingSoundHandle;
+
+class SoundMixer {
+private:
+ class Channel {
+ public:
+ virtual void mix(int16 *data, uint len) = 0;
+ virtual void destroy() = 0;
+ };
+
+ class Channel_RAW : public Channel {
+ SoundMixer *_mixer;
+ void *_ptr;
+ uint32 _pos;
+ uint32 _size;
+ uint32 _fp_speed;
+ uint32 _fp_pos;
+ byte _flags;
+
+
+ public:
+ void mix(int16 *data, uint len);
+ void destroy();
+
+ Channel_RAW(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags);
+ };
+
+#ifdef COMPRESSED_SOUND_FILE
+
+ class Channel_RAW : public Channel {
+ SoundMixer *_mixer;
+
+ public:
+ void mix(int16 *data, uint len);
+ void destroy();
+
+ Channel_MP3(SoundMixer *mixer, void *sound, uint rate);
+ };
+
+#endif
+
+ static void on_generate_samples(void *s, byte *samples, int len);
+
+public:
+ typedef void PremixProc(void *param, int16 *data, uint len);
+
+ uint _output_rate;
+
+ int16 *_volume_table;
+
+ enum {
+ NUM_CHANNELS = 16,
+ };
+
+ void *_premix_param;
+ PremixProc *_premix_proc;
+
+ Channel *_channels[NUM_CHANNELS];
+ PlayingSoundHandle *_handles[NUM_CHANNELS];
+
+ void insert(PlayingSoundHandle *handle, Channel *chan);
+ void uninsert(Channel *chan);
+
+ /* start playing a raw sound */
+ enum {
+ FLAG_AUTOFREE = 1,
+ FLAG_UNSIGNED = 2, /* unsigned samples */
+ FLAG_FILE = 4, /* sound is a FILE * that's read from */
+ };
+ void play_raw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags);
+
+ /* Premix procedure, useful when using fmopl adlib */
+ void setup_premix(void *param, PremixProc *proc);
+
+ /* mix */
+ void mix(int16 *buf, uint len);
+
+ /* stop all currently playing sounds */
+ void stop_all();
+
+ /* stop playing a specific sound */
+ void stop(PlayingSoundHandle psh);
+
+ /* is any channel active? */
+ bool has_active_channel();
+
+ /* bind to the OSystem object => mixer will be
+ * invoked automatically when samples need
+ * to be generated */
+ void bind_to_system(OSystem *syst);
+
+ /* set the volume, 0-256 */
+ void set_volume(int volume);
+
+};
+
+
+struct MP3OffsetTable { /* Compressed Sound (.SO3) */
+ int org_offset;
+ int new_offset;
+ int num_tags;
+ int compressed_size;
+};
+
+
+
+#if 0
+typedef enum { /* Mixer types */
+ MIXER_STANDARD,
+ MIXER_MP3,
+ MIXER_MP3_CDMUSIC
+} MixerType;
+
+struct MixerChannel { /* Mixer Channel */
+ void *_sfx_sound;
+ MixerType type;
+ union {
+ struct {
+ uint32 _sfx_pos;
+ uint32 _sfx_size;
+ uint32 _sfx_fp_speed;
+ uint32 _sfx_fp_pos;
+ } standard;
+#ifdef COMPRESSED_SOUND_FILE
+ struct {
+ struct mad_stream stream;
+ struct mad_frame frame;
+ struct mad_synth synth;
+ uint32 silence_cut;
+ uint32 pos_in_frame;
+ uint32 position;
+ uint32 size;
+ } mp3;
+ struct {
+ struct mad_stream stream;
+ struct mad_frame frame;
+ struct mad_synth synth;
+ uint32 pos_in_frame;
+ uint32 position;
+ uint32 size;
+ uint32 buffer_size;
+ mad_timer_t duration;
+ bool playing;
+ FILE *file;
+ } mp3_cdmusic;
+#endif
+ } sound_data;
+ void mix(int16 *data, uint32 len);
+ void clear();
+};
+#endif
+
+
+#endif /* _mixer_h_included */
diff --git a/system.h b/system.h
index 69f4a9ee49..8bfd7a85c0 100644
--- a/system.h
+++ b/system.h
@@ -3,7 +3,7 @@
class OSystem {
public:
typedef int ThreadProc(void *param);
- typedef void SoundProc(void *param, int16 *buf, int len);
+ typedef void SoundProc(void *param, byte *buf, int len);
struct Event {
int event_code;
@@ -34,17 +34,17 @@ public:
};
enum {
- PARAM_TOGGLE_FULLSCREEN = 1,
- PARAM_WINDOW_CAPTION = 2,
- PARAM_OPEN_CD = 3,
- PARAM_HOTSWAP_GFX_MODE = 4,
- PARAM_SHOW_DEFAULT_CURSOR = 5,
+ PROP_TOGGLE_FULLSCREEN = 1,
+ PROP_SET_WINDOW_CAPTION = 2,
+ PROP_OPEN_CD = 3,
+ PROP_SET_GFX_MODE = 4,
+ PROP_SHOW_DEFAULT_CURSOR = 5,
+ PROP_GET_SAMPLE_RATE = 6,
};
enum {
- SOUND_NONE = 0,
- SOUND_8BIT = 1,
- SOUND_16BIT = 2,
+ SOUND_8BIT = 0,
+ SOUND_16BIT = 1,
};
// Set colors of the palette
@@ -52,7 +52,7 @@ public:
// Set the size of the video bitmap.
// Typically, 320x200
- virtual void init_size(uint w, uint h, byte sound) = 0;
+ virtual void init_size(uint w, uint h) = 0;
// Draw a bitmap to screen.
// The screen will not be updated to reflect the new bitmap
@@ -87,9 +87,12 @@ public:
virtual bool poll_event(Event *event) = 0;
// Set the function to be invoked whenever samples need to be generated
- virtual void set_sound_proc(void *param, SoundProc *proc) = 0;
+ // Format is the sample type format.
+ // Only 16-bit signed mode is needed for simon & scumm
+ virtual void set_sound_proc(void *param, SoundProc *proc, byte format) = 0;
- virtual uint32 set_param(int param, uint32 value) = 0;
+ // Get or set a property
+ virtual uint32 property(int param, uint32 value) = 0;
// Quit
virtual void quit() = 0;
diff --git a/wince/pocketpc.cpp b/wince/pocketpc.cpp
index 698cf47de8..2cd7953ad4 100644
--- a/wince/pocketpc.cpp
+++ b/wince/pocketpc.cpp
@@ -155,7 +155,7 @@ Scumm scumm;
ScummDebugger debugger;
Gui gui;
-SoundEngine sound;
+IMuse sound;
SOUND_DRIVER_TYPE snd_driv;
@@ -953,7 +953,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLin
int argc = 3;
char* argv[3];
char argdir[MAX_PATH];
- SoundEngine *se;
+ IMuse *se;
sound_activated = true;
hide_toolbar = false;
@@ -984,7 +984,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLin
keypad_init();
registry_init();
- se = (SoundEngine*)scumm._soundEngine;
+ se = scumm._imuse;
se->set_music_volume(scumm._sound_volume_music);
se->set_master_volume(scumm._sound_volume_master);
diff --git a/windows.cpp b/windows.cpp
index 1265842b76..6e4037409a 100644
--- a/windows.cpp
+++ b/windows.cpp
@@ -22,7 +22,6 @@
#include <assert.h>
#include "scumm.h"
-#include "sound.h"
#include "cdmusic.h"
#include "gui.h"
@@ -108,7 +107,7 @@ int sel;
Scumm scumm;
ScummDebugger debugger;
Gui gui;
-SoundEngine sound;
+IMuse sound;
SOUND_DRIVER_TYPE snd_driv;
WndMan wm[1];
diff --git a/x11.cpp b/x11.cpp
index d2e9928bc0..3d249ac2a1 100644
--- a/x11.cpp
+++ b/x11.cpp
@@ -24,7 +24,6 @@
#include "stdafx.h"
#include "scumm.h"
#include "gui.h"
-#include "sound.h"
#include "cdmusic.h"
#include "mp3_cd.h"
@@ -50,7 +49,7 @@
Scumm scumm;
ScummDebugger debugger;
Gui gui;
-SoundEngine sound;
+IMuse sound;
SOUND_DRIVER_TYPE snd_driv;
static unsigned char *local_fb;