summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makefile.static4
-rw-r--r--src/configuration.cpp16
-rw-r--r--src/game.cpp12
-rw-r--r--src/gui/gui.cpp2
-rw-r--r--src/gui/setup.cpp5
-rw-r--r--src/gui/setup.h3
-rw-r--r--src/main.cpp17
-rw-r--r--src/sound/sound.cpp318
-rw-r--r--src/sound/sound.h76
9 files changed, 172 insertions, 281 deletions
diff --git a/makefile.static b/makefile.static
index 05fec246..c9eb9368 100644
--- a/makefile.static
+++ b/makefile.static
@@ -4,9 +4,9 @@ CXXFLAGS += -g -march=i686 -O2 -Wall -D__DEBUG
# excessive optimizations for pentium pro and later
#CXXFLAGS +=-Wall -march=i686 -O3 -fexpensive-optimizations -pipe -fomit-frame-pointer -funroll-loops -fexceptions
-CXXFLAGS +=`allegro-config --cflags release`
+CXXFLAGS +=`allegro-config --cflags release` `sdl-config --cflags` -fexceptions
-LIBS := -ljgmod `allegro-config --libs release` -lguichan_allegro -lguichan
+LIBS := `allegro-config --libs release` `sdl-config --libs` -lSDL_mixer -lguichan_allegro -lguichan
include file.list
diff --git a/src/configuration.cpp b/src/configuration.cpp
index a7f07aeb..4debdb16 100644
--- a/src/configuration.cpp
+++ b/src/configuration.cpp
@@ -100,7 +100,9 @@ bool Configuration::write(std::string filename) {
out.write(tmp, strlen(tmp));
strcpy(tmp, "");
}
- std::cout << "Configuration::write(" << optionTmp.key << ", \"" << optionTmp.stringValue << "\" / " << optionTmp.numericValue << ")\n";
+ #ifdef __DEBUG
+ std::cout << "Configuration::write(" << optionTmp.key << ", \"" << optionTmp.stringValue << "\" / " << optionTmp.numericValue << ")\n";
+ #endif
out.write("\n", 1);
}
@@ -163,11 +165,9 @@ void Configuration::setValue(std::string key, float value) {
\param deflt default option if not there or error
*/
std::string Configuration::getValue(std::string key, std::string deflt) {
- for (iter = iniOptions.begin(); iter != iniOptions.end(); iter++) {
- if(iter->key == key)
- return iter->stringValue;
+ if(keyExists(key)) {
+ return iter->stringValue;
}
-
return deflt;
}
@@ -177,11 +177,9 @@ std::string Configuration::getValue(std::string key, std::string deflt) {
\param deflt default option if not there or error
*/
float Configuration::getValue(std::string key, float deflt) {
- for (iter = iniOptions.begin(); iter != iniOptions.end(); iter++) {
- if(iter->key == key)
- return iter->numericValue;
+ if(keyExists(key)) {
+ return iter->numericValue;
}
-
return deflt;
}
diff --git a/src/game.cpp b/src/game.cpp
index 21c5aa3a..8e8c8036 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -40,7 +40,7 @@
char map_path[480];
-extern TmwSound sound;
+extern Sound sound;
unsigned short dest_x, dest_y, src_x, src_y;
unsigned int player_x, player_y;
@@ -121,7 +121,7 @@ void do_init() {
error("Could not find map file");
}
- sound.StartMOD("./data/sound/Mods/somemp.xm", -1);
+ sound.startBgm("./data/sound/Mods/somemp.xm", -1);
// Initialize timers
tick_time = 0;
@@ -228,9 +228,9 @@ void do_input() {
if (key[KEY_F1]) {
save_bitmap("./data/graphic/screenshot.bmp", buffer, NULL);
} else if (key[KEY_F12]){
- sound.SetAdjVol( 1, 1, 1);
+ sound.adjustVolume(1);
} else if (key[KEY_F11]){
- sound.SetAdjVol(-1,-1,-1);
+ sound.adjustVolume(-1);
}
if (key[KEY_F5] && action_time) {
if (player_node->action == STAND)
@@ -707,7 +707,9 @@ void do_parse() {
// Level up
case 0x019b:
if(RFIFOL(2)==player_node->id) {
- sound.StartWAV("./data/sound/wavs/level.wav", 10);
+ SOUND_SID sound_id = sound.loadItem("./data/sound/wavs/level.wav");
+ sound.startItem(sound_id, 64);
+ sound.clearCache();
}
break;
// Emotion
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index 24069cda..e8217cf8 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -50,7 +50,7 @@ BITMAP *gui_bitmap;
bool drag;
DATAFILE *gui_gfx;
-extern TmwSound sound;
+extern Sound sound;
/* very internal update stuff */
int (*gui__external_slider_callback)(void *, int);
diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp
index 233a36a5..d4396408 100644
--- a/src/gui/setup.cpp
+++ b/src/gui/setup.cpp
@@ -27,7 +27,8 @@
*/
#include "setup.h"
-#include <allegro.h>
+
+extern Sound sound;
/*
* Metod returns the number of elements in container
@@ -153,8 +154,10 @@ void Setup::action(const std::string& eventId)
/* Sound settings */
if(soundCheckBox->isMarked() == true) {
config.setValue("sound",1);
+ sound.init(32, 20);
} else {
config.setValue("sound",0);
+ sound.close();
}
} else if(eventId == "cancel") {
diff --git a/src/gui/setup.h b/src/gui/setup.h
index 55343229..f1e10036 100644
--- a/src/gui/setup.h
+++ b/src/gui/setup.h
@@ -35,6 +35,7 @@
#include <winalleg.h>
#endif
+#include "../sound/sound.h"
/*
* The list model for modes list
@@ -71,7 +72,7 @@ class Setup : public Window, public gcn::ActionListener {
public:
void action(const std::string& eventId);
- static Setup * create_setup();
+ static Setup * create_setup();
};
#endif
diff --git a/src/main.cpp b/src/main.cpp
index 07eafbf0..eb830773 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -91,7 +91,7 @@ unsigned char stretch_mode, screen_mode;
char *dir;
// new sound-engine /- kth5
-TmwSound sound;
+Sound sound;
// ini file configuration reader
Configuration config;
@@ -267,6 +267,7 @@ void exit_engine() {
config.write(dir);
delete dir;
gui_exit();
+ SDL_Quit();
destroy_bitmap(buffer);
allegro_exit();
}
@@ -276,9 +277,15 @@ int main() {
init_engine();
// initialize sound-engine and start playing intro-theme /-kth5
try {
- if (config.getValue("sound", 0) == 1)
- sound.Init(32, 20);
- sound.SetVol(128, 128, 128);
+ if (config.getValue("sound", 0) == 1) {
+ SDL_Init(SDL_INIT_AUDIO);
+ sound.init(32, 20);
+ }
+ sound.setVolume(64);
+
+ /* left here to serve as an example ;)
+ SOUND_SID id = sound.loadItem("./data/sound/wavs/level.wav");
+ sound.startItem(id, 70);*/
} catch (const char *err) {
ok("Sound Engine", err);
warning(err);
@@ -299,7 +306,7 @@ int main() {
charSelect();
break;
case GAME:
- sound.StopBGM();
+ sound.stopBgm();
status("GAME");
map_start();
if( state==GAME )
diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp
index da65461e..2505f203 100644
--- a/src/sound/sound.cpp
+++ b/src/sound/sound.cpp
@@ -39,137 +39,86 @@
truments can be a result.
32/20 sounds realistic here.
*/
-void TmwSound::Init(int voices, int mod_voices) {
- isOk = -1;
-
- if(mod_voices >= voices)
- throw("No voices left for SFX! Sound will be disabled!");
-
- install_timer();
- reserve_voices (voices, -1);
-
- #ifdef WIN32
- if (install_sound (DIGI_AUTODETECT, MIDI_AUTODETECT, NULL) < 0)
- #else
- if (install_sound (DIGI_AUTODETECT, MIDI_NONE, NULL) < 0)
- #endif
- throw("Could not initialize sound... :-(");
-
-
- if (install_mod (mod_voices) < 0)
- throw("Could not install MOD player... :-(");
-
- mod = NULL;
- mid = NULL;
- sfx = NULL;
+void Sound::init(int voices, int mod_voices) {
+ if(isOk == 0) {
+ throw("Sound engine cannot be initialized twice!\n");
+ }
+ bgm = NULL;
+ int audio_rate = 44100;
+ Uint16 audio_format = AUDIO_S16; /* 16-bit stereo */
+ int audio_channels = 2;
+ int audio_buffers = 4096;
+
+ if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)) {
+ #ifndef __DEBUG
+ throw("Unable to open audio device!\n");
+ #else
+ throw(Mix_GetError());
+ #endif
+ }
+
+ Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
+
pan = 128;
- pitch=1000;
-
- items = 0;
-
+ items = -1;
isOk = 0;
+
+ #ifdef __DEBUG
+ std::cout << "Sound::Init() Initializing Sound\n";
+ #endif
}
/**
- \brief set the volume value-range: 0-255
- \param digi for digital playback
- \param mid for midi playback
- \param mod for... aw, you guess ^^
-
+ \brief set the volume value-range: 0-128
+ \param music volume value
+
NOTE:
- all values may only be between 0-255 where 0 means
+ all values may only be between 0-128 where 0 means
muted.
*/
-void TmwSound::SetVol(int digi, int mid, int mod) {
+void Sound::setVolume(int music) {
if(isOk==-1)
return;
- set_volume(digi, mid);
- set_mod_volume(mod);
- set_hardware_volume(digi, mid);
-
- if(isMaxVol(vol_digi + digi)==false) vol_digi += digi;
- if(isMaxVol(vol_midi + mid) ==false) vol_midi += mid;
- if(isMaxVol(vol_mod + mod) ==false) vol_mod += mod;
+
+ if(isMaxVol(music) == false) {
+ vol_music = music;
+ Mix_VolumeMusic(vol_music);
+ }
}
/**
\brief adjusts current volume
- \param adigi for digital playback
- \param amid for midi playback
- \param amod for... aw, you guess ^^
-
- NOTE:
- all values may only be between 0-255 where 0 means
- muted.
-*/
-void TmwSound::SetAdjVol(int adigi, int amid, int amod) {
- if(isOk==-1)
- return;
- set_volume(vol_digi + adigi, vol_midi + amid);
- set_mod_volume(vol_mod + amod);
-
- if(isMaxVol(vol_digi + adigi)==false) vol_digi += adigi;
- if(isMaxVol(vol_midi + amid) ==false) vol_midi += amid;
- if(isMaxVol(vol_mod + amod) ==false) vol_mod += amod;
-}
-
-/**
- \brief start BGM using a midi file
- \param in full path of midi file
- \param loop how many times should the midi be looped? (-1 = infinite)
-
- NOTE:
- playing midi does not steal away any voices but
- does not work w/ most soundcards w/o software
- emulation. this means that *nix-users will most
- probably be left out. do not use this unless we
- find a way to always get it to work. :-)
-
- at this point of time only standard RMI midi files
- can be played. so no m$ extensions like GS and such.
+ \param amusic volume difference
*/
-void TmwSound::StartMIDI(char *in, int loop) {
+void Sound::adjustVolume(int amusic) {
if(isOk==-1)
return;
-
- mid = load_midi(in);
- if (!mid) {
- isOk=-1;
- throw("Could not load MIDI file!");
+
+ if(isMaxVol(vol_music + amusic) == false) {
+ vol_music += amusic;
+ Mix_VolumeMusic(vol_music);
}
-
- play_midi(mid, TRUE);
}
/**
- \brief start BGM using a mod file
- \param in full path of mod file
+ \brief start BGM
+ \param in full path to file
\param loop how many times should the midi be looped? (-1 = infinite)
-
- NOTE:
- playing mod is a pretty good choice. most of the work
- is being done by the cpu so it's not dependend on the
- sound-card how things sound. if it works, it just
- works! ;-)
-
- JGMOD supports several formats:
- MOD
- S3M
- XM
- Unreal
- and S3M (in UMX extension)
*/
-void TmwSound::StartMOD(char * in, int loop) {
+void Sound::startBgm(char * in, int loop) {
if(isOk==-1)
return;
-
- mod = load_mod(in);
- if(!mod) {
- isOk=-1;
- throw("Error reading MOD file...");
+
+ if(bgm != NULL) {
+ stopBgm();
}
- play_mod(mod, TRUE);
+
+ bgm = Mix_LoadMUS(in);
+ Mix_PlayMusic(bgm, loop);
+ #ifdef __DEBUG
+ std::cout << "Sound::startBgm() Playing \"" << in << "\" " << loop << " times\n";
+ #endif
}
/**
@@ -182,123 +131,79 @@ void TmwSound::StartMOD(char * in, int loop) {
passing NULL to the playing functions only means to make
playback stop.
*/
-void TmwSound::StopBGM() {
- if(isOk==-1)
- return;
-
- play_midi(NULL,-1);
- stop_mod();
-
- mod = NULL;
- mid = NULL;
-}
-
-/**
- \brief play short sample usually for sfx
- \param in full path to the sample file
- \param pan panning of the sound, values can be 0-255 where 128 is the middle
-
- NOTE:
- later on this will be a subsequent call to another
- function that preloads all wavs corresponding to
- the current area (e.g. monster screams) to memory.
- right now the function loads the file from hdd
- everytime you want it to be played. this is kind of
- resource intensive even though most OS'ses cache a
- already loaded file for some time.
-
- allegro supports different formats but this is not
- stated clear enough - these will work for sure:
- WAV
- VOC
-
- i don't know what kind of samples are necessary so we
- need to test this thoroughly.
-*/
-void TmwSound::StartWAV(char * in, int pan) {
- if(isOk==-1)
+void Sound::stopBgm() {
+ if(isOk==-1) {
return;
-
- sfx = load_sample(in);
- if (!sfx)
- throw("Error reading WAV file...");
-
- play_sample(sfx, vol_digi, pan, pitch, FALSE);
+ }
+
+ #ifdef __DEBUG
+ std::cout << "Sound::stopBgm()\n";
+ #endif
+
+ if(bgm != NULL) {
+ Mix_HaltMusic();
+ Mix_FreeMusic(bgm);
+ bgm = NULL;
+ }
}
/**
\brief preloads a sound-item into buffer
\param fpath full path to file
- \param type type of item (TMWSOUND_MOD, TMWSOUND_MID, TMWSOUND_SFX)
+ \param type type of item (SOUND_MOD, SOUND_MID, SOUND_SFX)
NOTE:
- only TMWSOUND_SFX items get preloaded. everything
- else will only store the full path to the file.
-
please make sure that the object is not loaded more
- than once since the function will not be able to run
- checks for its own!
+ than once since the function will not run any checks
+ on its own!
the return value should be kept as a reference to the
object loaded. if not it is practicaly lost.
*/
-TMWSOUND_SID TmwSound::LoadItem(char *fpath, char type) {
- POOL_ITEM item;
- if(type == TMWSOUND_SFX) {
- if(!(item.data = (void*)load_sample(fpath)))
- throw(sprintf("Unable to load sample: %s\n", fpath));
+SOUND_SID Sound::loadItem(char *fpath) {
+ #ifdef __DEBUG
+ std::cout << "Sound::loadItem() precaching \"" << fpath << "\"\n";
+ #endif
+ Mix_Chunk *newItem;
+ if(newItem = Mix_LoadWAV(fpath)) {
+ soundpool[++items] = newItem;
+ #ifdef __DEBUG
+ std::cout << "Sound::loadItem() success SOUND_SID = " << items << std::endl;
+ #endif
+ return items;
}
-
- items++;
- item.id = items;
- item.type = type;
- item.fname = fpath;
-
- soundpool.push_front(item);
- return item.id;
+
+ return 0;
}
/**
- \brief unloads an item from the soundpool
- \param id id returned by LoadItem()
+ \brief plays an item in soundpool
+ \param id id returned to the item in the soundpool
+ \param volume volume the sound should be played with (possible range: 0-128)
*/
-void TmwSound::UnloadItem(TMWSOUND_SID id) {
- int cnt = 0;
- POOL_ITEM item;
- for(sounditem = soundpool.begin(); sounditem != soundpool.end(); sounditem++) {
- item = *sounditem;
- if(item.id == id) {
- destroy_sample((SAMPLE*)item.data);
- soundpool.erase(sounditem);
- return;
- }
- cnt++;
+void Sound::startItem(SOUND_SID id, int volume) {
+ if(soundpool[id]) {
+ #ifdef __DEBUG
+ std::cout << "Sound::startItem() playing SOUND_SID = " << id << std::endl;
+ #endif
+ Mix_VolumeChunk(soundpool[id], volume);
+ Mix_PlayChannel(-1, soundpool[id], 0);
}
}
/**
- \brief plays an item in soundpool
- \param id id returned by LoadItem()
- \param loop loop n times (-1 is infinite)
+ \brief wipe all items off the cache
*/
-void TmwSound::PlayItem(TMWSOUND_SID id, int loop) {
- POOL_ITEM item;
- for(sounditem = soundpool.begin(); sounditem != soundpool.end(); sounditem++) {
- item = *sounditem;
- if(item.id = id) {
- switch(item.type) {
- case TMWSOUND_SFX :
- play_sample((SAMPLE*)item.data, vol_digi, pan, pitch, FALSE);
- break;
- case TMWSOUND_MOD :
- StartMOD((char*)item.fname.c_str(),loop);
- break;
- case TMWSOUND_MID :
- StartMIDI((char*)item.fname.c_str(),loop);
- break;
- }
- }
+void Sound::clearCache() {
+ for(SOUND_SID i = 0; i == items; i++) {
+ Mix_FreeChunk(soundpool[i]);
+ soundpool[i] = NULL;
}
+
+ soundpool.clear();
+ #ifdef __DEBUG
+ std::cout << "Sound::clearCache() wiped all items off the cache\n";
+ #endif
}
/**
@@ -306,26 +211,25 @@ void TmwSound::PlayItem(TMWSOUND_SID id, int loop) {
NOTE:
normally you won't need to call this since this is
- done by allegro when shutting itself down. but if
+ done by SDL when shutting itself down. but if
you find a reason to delete the sound-engine from
memory (e.g. garbage-collection) feel free to use
it. :-P
*/
-void TmwSound::Close(void) {
- mod = NULL;
- mid = NULL;
- sfx = NULL;
-
- remove_mod();
- remove_sound();
+void Sound::close(void) {
isOk = -1;
+ clearCache();
+ Mix_CloseAudio();
+ #ifdef __DEBUG
+ std::cout << "Sound::close() shutting down Sound\n";
+ #endif
}
/**
\brief checks if value equals min-/maximum volume and returns
true if that's the case.
*/
-bool TmwSound::isMaxVol(int vol) {
- if( vol > 0 && vol < 255 ) return false;
+bool Sound::isMaxVol(int vol) {
+ if( vol > 0 && vol < 128 ) return false;
else return true;
}
diff --git a/src/sound/sound.h b/src/sound/sound.h
index 8df4eb08..a1055b02 100644
--- a/src/sound/sound.h
+++ b/src/sound/sound.h
@@ -26,82 +26,58 @@
#ifdef WIN32
#pragma warning(disable:4312)
#endif
-#include <allegro.h>
-#include <jgmod.h>
-#include <list>
+#include <SDL.h>
+#include <SDL_mixer.h>
+#include <map>
#include <string>
#include <fstream>
-/** mod file */
-#define TMWSOUND_MOD 1
-/** midi file */
-#define TMWSOUND_MID 2
-/** sample file */
-#define TMWSOUND_SFX 3
+#ifdef __DEBUG
+ #include <iostream>
+#endif
-typedef unsigned short TMWSOUND_SID ;
+typedef short SOUND_SID ;
/**
* Sound engine
*
* \ingroup CORE
*/
-class TmwSound {
+class Sound {
public:
- void Init(int, int);
- void Close();
-
- void StartMIDI(char *, int);
- void StartMOD(char *, int);
- void StopBGM();
+ void init(int, int);
+ void close();
- void StartWAV(char *, int);
- void SetVol(int, int, int);
- void SetAdjVol(int, int, int);
+ void startBgm(char *, int);
+ void stopBgm();
+
+ void setVolume(int);
+ void adjustVolume(int);
- TMWSOUND_SID LoadItem(char *, char);
- void UnloadItem(TMWSOUND_SID);
- void PlayItem(TMWSOUND_SID, int);
+ SOUND_SID loadItem(char *);
+ void startItem(SOUND_SID, int);
+
+ void clearCache();
- TmwSound() {isOk=-1;}
+ Sound() {isOk=-1;}
/** if allegro is shut down or object is deleted any BGM is
stopped and SFX run out */
- ~TmwSound() {StopBGM(); Close();};
+ ~Sound() {stopBgm(); close();};
private:
/** initial value is -1 which means error or noninitialzed.
you can only play sounds and bgm if this is 0.
that should be the case after calling Init() successfully */
int isOk;
- MIDI * mid;
- JGMOD * mod;
- SAMPLE * sfx;
-
int pan;
- int pitch;
-
- int ret;
- int vol_digi;
- int vol_midi;
- int vol_mod;
-
- /** structure can hold a sound item's attributes and data (sample-only) */
- typedef struct POOL_ITEM {
- /** incremental id of pool item */
- TMWSOUND_SID id;
- /** type of item */
- char type;
- /** (file-)name of sfx only kept for human reasons ^_^ */
- std::string fname;
- /** generic data */
- void * data;
- };
+ int vol_music;
+ Mix_Music *bgm;
+
/** list of preloaded sound data / items */
- std::list<POOL_ITEM> soundpool;
- std::list<POOL_ITEM>::iterator sounditem;
- TMWSOUND_SID items;
+ std::map<int, Mix_Chunk*> soundpool;
+ SOUND_SID items;
bool isMaxVol(int);
};