From bf4857d3d4c67a0f185a99b63003e7fa43cbe2c4 Mon Sep 17 00:00:00 2001 From: Deanna Phillips Date: Sun, 10 Feb 2008 18:32:08 -0500 Subject: [PATCH] Add an SDL sound backend and use it instead of spawning an external player. SDL and SDL_mixer are now required. You may get them from: http://www.libsdl.org http://www.libsdl.org/projects/SDL_mixer/ If you have problems building, try uncommenting the extra SDLLIBS and SDLINCLUDES variables in src/sim/makefile. --- res/micropolis.tcl | 24 +---- src/sim/makefile | 12 ++- src/sim/s_msg.c | 2 +- src/sim/w_sound.c | 213 +++++++++++++++++++++++++++++++++++++-------- src/sim/w_sprite.c | 4 +- src/sim/w_tk.c | 1 + 6 files changed, 193 insertions(+), 63 deletions(-) diff --git a/res/micropolis.tcl b/res/micropolis.tcl index 6c6c03a..01f8749 100644 --- a/res/micropolis.tcl +++ b/res/micropolis.tcl @@ -938,21 +938,11 @@ proc UISetChannelVolume {win chan vol} { proc EchoPlaySound {soundspec} { - # Temporary workaround to tell Python Sugar app to play sound. - global Sound ResourceDir - if {$Sound} { - #echo PlaySound [lindex $soundspec 0] - signal ignore SIGCHLD - exec "${ResourceDir}/sounds/player" "${ResourceDir}/sounds/[string tolower [lindex $soundspec 0]].wav" & - } } proc UIMakeSoundOn {win chan sound {opts ""}} { - # Send message to Python to play sound. - EchoPlaySound $sound - - #UIDoSoundOn $win "play $sound -replay -channel $chan $opts" + playsound $chan $sound $opts } @@ -964,11 +954,6 @@ proc UIStartSoundOn {win chan sound {opts ""}} { } -proc UIStopSoundOn {win chan sound {opts ""}} { - UIDoSoundOn $win "stop $sound" -} - - proc UIMakeSound {chan sound {opts ""}} { # Send message to Python to play sound. EchoPlaySound $sound @@ -985,11 +970,6 @@ proc UIStartSound {chan sound {opts ""}} { } -proc UIStopSound {chan sound {opts ""}} { - UIDoSound "sound stop $sound" -} - - proc SetupSoundServer {win} { AddSoundServer $win } @@ -2537,7 +2517,7 @@ proc EditorToolUp {w x y} { case [$w ToolState] in \ 7 { # bulldozer - UIStopSoundOn $w edit 1 + stopdozer } \ 10 { # chalk StopChalk $w diff --git a/src/sim/makefile b/src/sim/makefile index 13c22c5..9705d6e 100644 --- a/src/sim/makefile +++ b/src/sim/makefile @@ -5,6 +5,12 @@ TCLXHOME = ../tclx TCLLIBRARY = /usr/local/lib/tcl TKLIBRARY = /usr/local/lib/tk +SDLINCLUDE = +SDLLIBS = -lSDL -lSDL_mixer + +#SDLINCLUDE += $$(pkg-config -cflags sdl) +#SDLLIBS += $$(pkg-config -libs sdl) + CC = gcc OPTFLAGS = -O3 @@ -26,7 +32,8 @@ INCLUDES = \ -I$(XINCLUDE) \ -I$(TCLHOME) \ -I$(TCLXHOME)/src \ - -I$(TKHOME) + -I$(TKHOME) \ + $(SDLINCLUDE) CPPFLAGS = $(INCLUDES) @@ -35,7 +42,8 @@ LIBS = $(TCLXHOME)/libtk.a \ -lm \ -lX11 \ -lXext \ - -lXpm + -lXpm \ + $(SDLLIBS) SRCS = \ sim.c \ diff --git a/src/sim/s_msg.c b/src/sim/s_msg.c index 330f125..d820607 100644 --- a/src/sim/s_msg.c +++ b/src/sim/s_msg.c @@ -340,7 +340,7 @@ doMessage(void) MakeSound("city", "Siren"); break; case 21: - MakeSound("city", "Monster -speed [MonsterSpeed]"); + MakeSound("city", "Monster"); break; case 30: MakeSound("city", "Explosion-Low"); diff --git a/src/sim/w_sound.c b/src/sim/w_sound.c index b9b323c..2602183 100644 --- a/src/sim/w_sound.c +++ b/src/sim/w_sound.c @@ -1,3 +1,7 @@ +/* + * Portions Copyright (c) 2008 Deanna Phillips + */ + /* w_sound.c * * Micropolis, Unix Version. This game was released for the Unix platform @@ -59,103 +63,240 @@ * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY * NOT APPLY TO YOU. */ +#include +#include #include "sim.h" +#define SIM_NSOUNDS 47 +#define SIM_NCHANNELS 32 +#define DOZER_CHANNEL 0 +#define DOZER_SOUND "rumble.wav" + +struct sound { + char *id; + char *file; + Mix_Chunk *wave; +}; + +struct sound sounds[SIM_NSOUNDS] = { + { "A", "a.wav", NULL }, + { "Aaah", "aaah.wav", NULL }, + { "Airport", "airport.wav", NULL }, + { "Beep", "beep.wav", NULL }, + { "Boing", "boing.wav", NULL }, + { "Bop", "bop.wav", NULL }, + { "Build", "build.wav", NULL }, + { "Bulldozer", "bulldozer.wav", NULL }, + { "Chalk", "chalk.wav", NULL }, + { "Coal", "coal.wav", NULL }, + { "Com", "com.wav", NULL }, + { "Computer", "computer.wav", NULL }, + { "Cuckoo", "cuckoo.wav", NULL }, + { "E", "e.wav", NULL }, + { "Eraser", "eraser.wav", NULL }, + { "Explosion-High", "explosion-high.wav", NULL }, + { "Explosion-Low", "explosion-low.wav", NULL }, + { "Fire", "fire.wav", NULL }, + { "HeavyTraffic", "heavytraffic.wav", NULL }, + { "HonkHonk-High", "honkhonk-high.wav", NULL }, + { "HonkHonk-Low", "honkhonk-low.wav", NULL }, + { "HonkHonk-Med", "honkhonk-med.wav", NULL }, + { "Ignition", "ignition.wav", NULL }, + { "Ind", "ind.wav", NULL }, + { "Monster", "monster.wav", NULL }, + { "Nuclear", "nuclear.wav", NULL }, + { "O", "o.wav", NULL }, + { "Oop", "oop.wav", NULL }, + { "Park", "park.wav", NULL }, + { "Player", "player.wav", NULL }, + { "Police", "police.wav", NULL }, + { "QuackQuack", "quackquack.wav", NULL }, + { "Query", "query.wav", NULL }, + { "Rail", "rail.wav", NULL }, + { "Res", "res.wav", NULL }, + { "Road", "road.wav", NULL }, + { "Rumble", "rumble.wav", NULL }, + { "Seaport", "seaport.wav", NULL }, + { "Siren", "siren.wav", NULL }, + { "Skid", "skid.wav", NULL }, + { "Sorry", "sorry.wav", NULL }, + { "Stadium", "stadium.wav", NULL }, + { "UhUh", "uhuh.wav", NULL }, + { "Whip", "whip.wav", NULL }, + { "Wire", "wire.wav", NULL }, + { "Woosh", "woosh.wav", NULL }, + { "Zone", "zone.wav", NULL } +}; + /* Sound routines */ int SoundInitialized = 0; -short Dozing; +Mix_Chunk *rumble; InitializeSound() { - char cmd[256]; + int reserved_chans; + char buf[256]; - SoundInitialized = 1; + if (SDL_Init(SDL_INIT_AUDIO) == -1) { + fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); + return; + } - if (!UserSoundOn) return; + if (Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 1, 1024) == -1) { + fprintf(stderr, "Mix_OpenAudio: %s\n", Mix_GetError()); + return; + } + + reserved_chans = Mix_ReserveChannels(1); - Eval("UIInitializeSound"); + if (reserved_chans != 1) { + fprintf(stderr, "Mix_ReserveChannels: %s\n", Mix_GetError()); + return; + } + + if (Mix_AllocateChannels(SIM_NCHANNELS) == -1) { + fprintf(stderr, "Mix_AllocateChannels: %s\n", Mix_GetError()); + return; + } + + snprintf(buf, sizeof(buf), "%s/sounds/%s", ResourceDir, DOZER_SOUND); + rumble = Mix_LoadWAV(buf); + + if (rumble == NULL) { + printf("Mix_LoadWAV: %s\n", Mix_GetError()); + return; + } + + SoundInitialized = 1; } ShutDownSound() { - if (SoundInitialized) { - SoundInitialized = 0; - Eval("UIShutDownSound"); + int i; + SoundInitialized = 0; + + for (i = 0; i < SIM_NSOUNDS; i++) { + if (sounds[i].wave) { + Mix_FreeChunk(sounds[i].wave); + sounds[i].wave = NULL; + } + } + if (rumble) { + Mix_FreeChunk(rumble); + rumble = NULL; } + Mix_CloseAudio(); + SDL_Quit(); } MakeSound(char *channel, char *id) { char buf[256]; + int i; if (!UserSoundOn) return; - if (!SoundInitialized) InitializeSound(); + if (!SoundInitialized) return; - sprintf(buf, "UIMakeSound \"%s\" \"%s\"", channel, id); - Eval(buf); -} + for (i = 0; i < SIM_NSOUNDS; i++) { + if (!strcmp(sounds[i].id, id)) + break; + } + + if (sounds[i].wave) { + if (Mix_PlayChannel(-1, sounds[i].wave, 0) == -1) + fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError()); + return; + } + + snprintf(buf, sizeof(buf), "%s/sounds/%s", ResourceDir, + sounds[i].file); + + sounds[i].wave = Mix_LoadWAV(buf); + if (sounds[i].wave == NULL) { + fprintf(stderr, "Mix_LoadWAV: %s\n", Mix_GetError()); + return; + } + + if (Mix_PlayChannel(-1, sounds[i].wave, 0) == -1) + fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError()); +} MakeSoundOn(SimView *view, char *channel, char *id) { - char buf[256]; - if (!UserSoundOn) return; - if (!SoundInitialized) InitializeSound(); + if (!SoundInitialized) return; - sprintf(buf, "UIMakeSoundOn %s \"%s\" \"%s\"", - Tk_PathName(view->tkwin), channel, id); - Eval(buf); + MakeSound(channel, id); } StartBulldozer(void) { + size_t size; + char buf[256]; + if (!UserSoundOn) return; - if (!SoundInitialized) InitializeSound(); - if (!Dozing) { - DoStartSound("edit", "1"); - Dozing = 1; + if (!SoundInitialized) return; + + if (Mix_PlayChannel(DOZER_CHANNEL, rumble, 4) == -1) { + printf("Mix_PlayChannel: %s\n", Mix_GetError()); + return; } } StopBulldozer(void) { - if ((!UserSoundOn) || (!SoundInitialized)) return; - DoStopSound("1"); - Dozing = 0; + if (!UserSoundOn) return; + if (!SoundInitialized) return; + + Mix_HaltChannel(DOZER_CHANNEL); } -/* comefrom: doKeyEvent */ +/* XXX comefrom: doKeyEvent */ SoundOff(void) { - if (!SoundInitialized) InitializeSound(); - Eval("UISoundOff"); - Dozing = 0; + ShutDownSound(); } DoStartSound(char *channel, char *id) { - char buf[256]; + MakeSound(channel, id); +} - sprintf(buf, "UIStartSound %s %s", channel, id); - Eval(buf); +DoStopSound(char *id) +{ + StopBulldozer(); } +SoundCmd(CLIENT_ARGS) +{ + if (!strcmp(argv[2], "Rumble")) + StartBulldozer(); + else + MakeSound(NULL, argv[2]); + return 0; +} -DoStopSound(char *id) +DozerCmd(CLIENT_ARGS) { - char buf[256]; + StopBulldozer(); + return 0; +} - sprintf(buf, "UIStopSound %s", id); - Eval(buf); +sound_command_init() +{ + Tcl_CreateCommand(tk_mainInterp, "playsound", SoundCmd, + (ClientData)NULL, (void (*)()) NULL); + Tcl_CreateCommand(tk_mainInterp, "stopdozer", DozerCmd, + (ClientData)NULL, (void (*)()) NULL); } diff --git a/src/sim/w_sprite.c b/src/sim/w_sprite.c index 3f50989..7ecc045 100644 --- a/src/sim/w_sprite.c +++ b/src/sim/w_sprite.c @@ -849,7 +849,7 @@ DoShipSprite(SimSprite *sprite) if ((Rand16() & 3) == 1) { if ((ScenarioID == 2) && /* San Francisco */ (Rand(10) < 5)) { - MakeSound("city", "HonkHonk-Low -speed 80"); + MakeSound("city", "HonkHonk-Low"); } else { MakeSound("city", "HonkHonk-Low"); } @@ -985,7 +985,7 @@ DoMonsterSprite(SimSprite *sprite) else z = ND2[d]; d = 4; if (!sprite->sound_count) { - MakeSound("city", "Monster -speed [MonsterSpeed]"); /* monster */ + MakeSound("city", "Monster"); /* monster */ sprite->sound_count = 50 + Rand(100); } } diff --git a/src/sim/w_tk.c b/src/sim/w_tk.c index 027654d..08c16f9 100644 --- a/src/sim/w_tk.c +++ b/src/sim/w_tk.c @@ -774,6 +774,7 @@ tk_main() graph_command_init(); date_command_init(); sprite_command_init(); + sound_command_init(); #ifdef CAM cam_command_init(); -- 2.39.2