wrote new mixer class,
cleaned up sound header files, integrated mixer into scummvm & simon svn-id: r3937
This commit is contained in:
parent
a5e3dbb85d
commit
ac62a7cb2e
32 changed files with 2917 additions and 2661 deletions
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
2
gfx.cpp
2
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);
|
||||
|
|
9
gui.cpp
9
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
3
main.cpp
3
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
17
scumm.h
17
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];
|
||||
|
||||
|
|
36
scummvm.cpp
36
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;
|
||||
|
|
32
scummvm.dsp
32
scummvm.dsp
|
@ -121,28 +121,32 @@ LINK32=link.exe
|
|||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\adlib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\fmopl.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\gmidi.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\gmidi.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\imuse.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\imuse.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\mididrv.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound\mididrv.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
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
|
||||
|
|
75
sdl.cpp
75
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:
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "scummsys.h"
|
||||
#include "system.h"
|
||||
#include "mixer.h"
|
||||
#include "simon.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
|
392
sound.cpp
392
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,85 +564,17 @@ 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;
|
||||
return !_mixer->has_active_channel();
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
void Scumm::playBundleSound(char *sound)
|
||||
{
|
||||
warning("playBundleSound: %s", 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));
|
||||
}
|
||||
|
|
645
sound.h
645
sound.h
|
@ -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
|
989
sound/adlib.cpp
989
sound/adlib.cpp
|
@ -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;
|
||||
}
|
||||
|
314
sound/gmidi.cpp
314
sound/gmidi.cpp
|
@ -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);
|
||||
}
|
||||
}
|
2081
sound/imuse.cpp
2081
sound/imuse.cpp
File diff suppressed because it is too large
Load diff
46
sound/imuse.h
Normal file
46
sound/imuse.h
Normal file
|
@ -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); }
|
||||
};
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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 */
|
|
@ -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) */
|
491
sound/mixer.cpp
Normal file
491
sound/mixer.cpp
Normal file
|
@ -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
|
||||
|
||||
|
157
sound/mixer.h
Normal file
157
sound/mixer.h
Normal file
|
@ -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 */
|
27
system.h
27
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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
3
x11.cpp
3
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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue