From 8834003afae3b01a23a77091f934353eae73f961 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 26 Feb 2017 22:14:10 +0100 Subject: games/doom: music support (thanks qu7uux) --- sys/src/games/doom/d_main.c | 9 +- sys/src/games/doom/i_sound.c | 259 +++++++++++++++++++------------------------ sys/src/games/doom/i_sound.h | 6 +- sys/src/games/doom/s_sound.c | 10 +- sys/src/games/doom/w_wad.h | 3 - 5 files changed, 122 insertions(+), 165 deletions(-) (limited to 'sys/src') diff --git a/sys/src/games/doom/d_main.c b/sys/src/games/doom/d_main.c index f42b34e40..6f1e86215 100644 --- a/sys/src/games/doom/d_main.c +++ b/sys/src/games/doom/d_main.c @@ -326,6 +326,7 @@ void D_Display (void) if (!wipe) { I_FinishUpdate (); // page flip or blit buffer + I_UpdateSound (); return; } @@ -347,6 +348,8 @@ void D_Display (void) I_UpdateNoBlit (); M_Drawer (); // menu is drawn even on top of wipes I_FinishUpdate (); // page flip or blit buffer + if (!done) + I_UpdateSound (); } while (!done); } @@ -397,12 +400,6 @@ void D_DoomLoop (void) // Update display, next frame, with current state. D_Display (); - - // Sound mixing for the buffer is snychronous. - I_UpdateSound(); - - // Update sound output. - I_SubmitSound(); } } diff --git a/sys/src/games/doom/i_sound.c b/sys/src/games/doom/i_sound.c index a9a9cc3cd..ab83084d5 100644 --- a/sys/src/games/doom/i_sound.c +++ b/sys/src/games/doom/i_sound.c @@ -4,6 +4,7 @@ #include "i_sound.h" #include "w_wad.h" // W_GetNumForName() #include "z_zone.h" +#include "m_argv.h" /* The number of internal mixing channels, ** the samples calculated for each mixing step, @@ -12,21 +13,23 @@ */ /* Needed for calling the actual sound output. */ -#define SAMPLECOUNT (512<<2) +#define AUDFREQ 44100 +#define SFXFREQ 11025 +#define SAMPLECOUNT (AUDFREQ/TICRATE) #define NUM_CHANNELS 8 /* The actual lengths of all sound effects. */ int lengths[NUMSFX]; /* The actual output device. */ -static int audio_fd; +static int audio_fd = -1; /* The global mixing buffer. ** Basically, samples from all active internal channels ** are modified and added, and stored in the buffer ** that is submitted to the audio device. */ -signed short mixbuffer[SAMPLECOUNT*2]; +uchar mixbuf[SAMPLECOUNT*4]; /* The channel step amount... */ uint channelstep[NUM_CHANNELS]; @@ -67,6 +70,10 @@ int vol_lookup[128*256]; int* channelleftvol_lookup[NUM_CHANNELS]; int* channelrightvol_lookup[NUM_CHANNELS]; +extern boolean mus_paused; + +static int mpfd[2] = {-1, -1}; + static void* getsfx(char *sfxname, int *len) { uchar *sfx; @@ -129,9 +136,11 @@ void I_InitSound(void) int i; audio_fd = open("/dev/audio", OWRITE); - if(audio_fd < 0) - printf("WARN Failed to open /dev/audio, sound disabled\n"); - + if(audio_fd < 0){ + fprint(2, "I_InitSound: disabling sound: %r\n"); + return; + } + I_InitMusic(); /* Initialize external data (all sounds) at start, keep static. */ for (i=1 ; i> 16; - /* Limit to LSB??? */ - channelstepremainder[ chan ] &= 65536-1; - - /* Check whether we are done. */ - if (channels[ chan ] >= channelsend[ chan ]) - channels[ chan ] = 0; - } + int l, r, i, v; + uchar *p; + + if(audio_fd < 0) + return; + memset(mixbuf, 0, sizeof mixbuf); + if(mpfd[0]>=0 && !mus_paused && readn(mpfd[0], mixbuf, sizeof mixbuf) < 0){ + fprint(2, "I_UpdateSound: disabling music: %r\n"); + I_ShutdownMusic(); + } + p = mixbuf; + while(p < mixbuf + sizeof mixbuf){ + l = 0; + r = 0; + for(i=0; i> 16; + channelstepremainder[i] &= 0xffff; + if(channels[i] >= channelsend[i]) + channels[i] = 0; + } + for(i=0; i 0x7fff) + v = 0x7fff; + else if(v < -0x8000) + v = -0x8000; + p[0] = v; + p[1] = v >> 8; + + v = (short)(p[3] << 8 | p[2]); + v = v * snd_MusicVolume / 15; + v += r; + if(v > 0x7fff) + v = 0x7fff; + else if(v < -0x8000) + v = -0x8000; + p[2] = v; + p[3] = v >> 8; } - - /* Clamp to range. */ - if (dl > 0x7fff) - dl = 0x7fff; - else if (dl < -0x8000) - dl = -0x8000; - if (dr > 0x7fff) - dr = 0x7fff; - else if (dr < -0x8000) - dr = -0x8000; - - *leftout = dl; - *rightout = dr; - - /* Increment current pointers in mixbuffer. */ - leftout += step; - rightout += step; - - *leftout = dl; - *rightout = dr; - leftout += step; - rightout += step; - - *leftout = dl; - *rightout = dr; - leftout += step; - rightout += step; - - *leftout = dl; - *rightout = dr; - leftout += step; - rightout += step; } -} - -void I_SubmitSound(void) -{ - if(audio_fd >= 0) - write(audio_fd, mixbuffer, sizeof mixbuffer); + if(snd_SfxVolume|snd_MusicVolume) + write(audio_fd, mixbuf, sizeof mixbuf); } void I_ShutdownSound(void) @@ -440,9 +390,10 @@ addsfx(int id, int vol, int step, int sep) return rc; } -int I_StartSound(int id, int vol, int sep, int pitch, int priority) +int I_StartSound(int id, int vol, int sep, int pitch, int) { - USED(priority); + if(audio_fd < 0) + return -1; id = addsfx(id, vol, steptable[pitch], sep); return id; } @@ -471,53 +422,71 @@ void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) void I_InitMusic(void) { -// printf("PORTME i_sound.c I_InitMusic\n"); } void I_ShutdownMusic(void) { -// printf("PORTME i_sound.c I_ShutdownMusic\n"); -} - -void I_SetMusicVolume(int volume) -{ - USED(volume); -// printf("PORTME i_sound.c I_SetMusicVolume\n"); -} - -void I_PauseSong(int handle) -{ - USED(handle); -// printf("PORTME i_sound.c I_PauseSong\n"); + if(mpfd[0] >= 0){ + close(mpfd[0]); + mpfd[0] = -1; + waitpid(); + } } -void I_ResumeSong(int handle) +void I_SetMusicVolume(int) { - USED(handle); -// printf("PORTME i_sound.c I_ResumeSong\n"); } -int I_RegisterSong(void *data) +void I_PauseSong(int) { - USED(data); -// printf("PORTME i_sound.c I_RegisterSong\n"); - return 0; } -void I_PlaySong(int handle, int looping) +void I_ResumeSong(int) { - USED(handle, looping); -// printf("PORTME i_sound.c I_PlaySong\n"); } -void I_StopSong(int handle) +void I_PlaySong(musicinfo_t *m, int loop) { - USED(handle); -// printf("PORTME i_sound.c I_StopSong\n"); + char name[64]; + int n; + + if(M_CheckParm("-nomusic")) + return; + I_ShutdownMusic(); + if(pipe(mpfd) < 0) + return; + switch(rfork(RFPROC|RFFDG|RFNAMEG)){ + case -1: + fprint(2, "I_PlaySong: %r\n"); + break; + case 0: + dup(mpfd[1], 1); + close(mpfd[1]); + close(mpfd[0]); + close(0); + snprint(name, sizeof(name), "/tmp/%s.mus", m->name); + if(create(name, ORDWR, 0666) != 0) + sysfatal("create: %r"); + n = W_LumpLength(m->lumpnum); + if(write(0, m->data, n) != n) + sysfatal("write: %r"); + if(seek(0, 0, 0) != 0) + sysfatal("seek: %r"); + if(bind("/fd/1", "/dev/audio", MREPL) < 0) + sysfatal("bind: %r"); + while(loop && fork() > 0){ + if(waitpid() < 0 || write(1, "", 0) < 0) + exits(nil); + } + execl("/bin/dmus", "dmus", name, m->name, nil); + execl("/bin/play", "play", name, nil); + sysfatal("execl: %r"); + default: + close(mpfd[1]); + } } -void I_UnRegisterSong(int handle) +void I_StopSong(int) { - USED(handle); -// printf("PORTME i_sound.c I_UnregisterSong\n"); + I_ShutdownMusic(); } diff --git a/sys/src/games/doom/i_sound.h b/sys/src/games/doom/i_sound.h index ae711a271..b9d9ac538 100644 --- a/sys/src/games/doom/i_sound.h +++ b/sys/src/games/doom/i_sound.h @@ -35,7 +35,6 @@ void I_InitSound(void); // ... update sound buffer and audio device at runtime... void I_UpdateSound(void); -void I_SubmitSound(void); // ... shut down and relase at program termination. void I_ShutdownSound(void); @@ -90,20 +89,17 @@ void I_SetMusicVolume(int volume); // PAUSE game handling. void I_PauseSong(int handle); void I_ResumeSong(int handle); -// Registers a song handle to song data. -int I_RegisterSong(void *data); // Called by anything that wishes to start music. // plays a song, and when the song is done, // starts playing it again in an endless loop. // Horrible thing to do, considering. void I_PlaySong -( int handle, +( musicinfo_t *m, int looping ); // Stops a song over 3 seconds. void I_StopSong(int handle); // See above (register), then think backwards -void I_UnRegisterSong(int handle); diff --git a/sys/src/games/doom/s_sound.c b/sys/src/games/doom/s_sound.c index 18567ec26..3574bcc76 100644 --- a/sys/src/games/doom/s_sound.c +++ b/sys/src/games/doom/s_sound.c @@ -113,10 +113,10 @@ int snd_MusicVolume = 15; // whether songs are mus_paused -static boolean mus_paused; +boolean mus_paused; // music currently being played -static musicinfo_t* mus_playing=0; +musicinfo_t* mus_playing=0; // following is set // by the defaults code in M_misc: @@ -548,7 +548,6 @@ void S_SetMusicVolume(int volume) volume); } - I_SetMusicVolume(127); I_SetMusicVolume(volume); snd_MusicVolume = volume; } @@ -605,10 +604,10 @@ S_ChangeMusic // load & register it music->data = (void *) W_CacheLumpNum(music->lumpnum, PU_MUSIC); - music->handle = I_RegisterSong(music->data); + music->handle = 0; // play it - I_PlaySong(music->handle, looping); + I_PlaySong(music, looping); mus_playing = music; } @@ -622,7 +621,6 @@ void S_StopMusic(void) I_ResumeSong(mus_playing->handle); I_StopSong(mus_playing->handle); - I_UnRegisterSong(mus_playing->handle); Z_ChangeTag(mus_playing->data, PU_CACHE); mus_playing->data = 0; diff --git a/sys/src/games/doom/w_wad.h b/sys/src/games/doom/w_wad.h index 9aa4bf5a3..588df4351 100644 --- a/sys/src/games/doom/w_wad.h +++ b/sys/src/games/doom/w_wad.h @@ -67,9 +67,6 @@ void W_ReadLump (int lump, void *dest); void* W_CacheLumpNum (int lump, int tag); void* W_CacheLumpName (char* name, int tag); - - - #endif //----------------------------------------------------------------------------- // -- cgit v1.2.3