From 0102df00b3e2485b084f11a8270a2365d1aa7cbc Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Tue, 24 Mar 2020 15:44:53 +0300 Subject: [PATCH] sound: fix voices in menu --- src/CMakeLists.txt | 9 +-- src/menu.c | 38 ++++++------- src/menu.h | 2 +- src/openal/sound.c | 73 ++++++++++++++++-------- src/sdlmixer/sound.c | 132 ++++++++++++++++++++++++++----------------- src/sound.h | 3 + 6 files changed, 154 insertions(+), 103 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e33b832..fcbd51a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,8 +5,9 @@ option(WITH_OPENGL "Build with OpenGL render" ON) option(WITH_SOFTWARE "Build with Software render" ON) option(SOUND_DRIVER "Build with selected sound driver" "OpenAL") -set(WITH_OPENAL (SOUND_DRIVER EQUALS "OpenAL")) -set(WITH_SDLMIXER (SOUND_DRIVER EQUALS "SDL_mixer")) +string(TOUPPER "${SOUND_DRIVER}" SOUND_DRIVER) +string(COMPARE EQUAL "${SOUND_DRIVER}" "OPENAL" WITH_OPENAL) +string(COMPARE EQUAL "${SOUND_DRIVER}" "SDLMIXER" WITH_SDLMIXER) set(D2D_GAME_ROOT .) set(D2D_OPENGL_ROOT ${D2D_GAME_ROOT}/gl) @@ -35,7 +36,7 @@ elseif(WITH_SDLMIXER) set(D2D_SOUND_INCLUDE_DIR "${SDLMIXER_INCLUDE_DIR}") set(D2D_SOUND_LIBRARY "${SDLMIXER_LIBRARY}") else(WITH_OPENAL) - message(FATAL_ERROR "Select SOUND_DRIVER as OpenAL or SDL_mixer") + message(FATAL_ERROR "Select SOUND_DRIVER as 'OPENAL' or 'SDLMIXER'") endif(WITH_OPENAL) if (WITH_OPENGL) @@ -69,6 +70,6 @@ endif (WITH_OPENGL) if (WITH_SOFTWARE) add_executable(doom2d-soft ${D2D_GAME_SRC} ${D2D_SOUND_SRC} ${D2D_SDL_SRC} ${D2D_SOFTWARE_SRC}) - target_include_directories(doom2d-soft PRIVATE "${D2D_GAME_ROOT}" "${D2D_SOUND_LIBRARY}" "${SDL_INCLUDE_DIR}") + target_include_directories(doom2d-soft PRIVATE "${D2D_GAME_ROOT}" "${D2D_SOUND_INCLUDE_DIR}" "${SDL_INCLUDE_DIR}") target_link_libraries(doom2d-soft "${D2D_SOUND_LIBRARY}" "${SDL_LIBRARY}") endif (WITH_SOFTWARE) diff --git a/src/menu.c b/src/menu.c index 95fbbf6..7f44950 100644 --- a/src/menu.c +++ b/src/menu.c @@ -148,33 +148,27 @@ static void *csnd1,*csnd2,*msnd1,*msnd2,*msnd3,*msnd4,*msnd5,*msnd6; static int movsndt=0; static byte cbuf[32]; -static snd_t *voc=NULL; -static int voc_ch=0; +static snd_t *voc; +static int voc_ch; static void GMV_stop (void) { - if(voc) { - if(voc_ch) {S_stop(voc_ch);voc_ch=0;} - free(voc);voc=NULL; + if (voc != NULL) { + if (voc_ch) { + S_stop(voc_ch); + voc_ch = 0; + } + S_free(voc); + voc = NULL; } } -void GMV_say (char *nm) { - // TODO fix this - /* - int r,len; - snd_t *p; - byte *d; - - if((r=F_findres(nm))==-1) return; - if(!(p=malloc((len=F_getreslen(r))+16))) return; - p->len=len;p->rate=11000; - p->lstart=p->llen=0; - GMV_stop(); - F_loadres(r,p+1,0,len); - for(d=(byte*)(p+1);len;--len,++d) *d^=128; - voc=p; - voc_ch=S_play(voc,-1,1024,255); - */ +void GMV_say (const char nm[8]) { + snd_t *snd = S_load(nm); + if (snd) { + GMV_stop(); + voc = S_load(nm); + voc_ch = S_play(voc, 0, 255); + } } static void GM_set (menu_t *m) { diff --git a/src/menu.h b/src/menu.h index fedd702..bb6d829 100644 --- a/src/menu.h +++ b/src/menu.h @@ -48,7 +48,7 @@ extern menu_t *mnu; extern byte gm_redraw; extern short lastkey; -void GMV_say (char *nm); +void GMV_say (const char nm[8]); void G_keyf (int key, int down); void G_code (void); int GM_act (void); diff --git a/src/openal/sound.c b/src/openal/sound.c index af75aa3..d046803 100644 --- a/src/openal/sound.c +++ b/src/openal/sound.c @@ -103,7 +103,7 @@ static void convert_this_ext (Uint32 src_format, int src_chan, int src_rate, Uin } } -static openal_snd *new_openal_snd (const void *data, dword len, dword rate, dword lstart, dword llen) { +static openal_snd *new_openal_snd (const void *data, dword len, dword rate, dword lstart, dword llen, int sign) { assert(data); ALuint buffer = 0; openal_snd *snd = NULL; @@ -111,7 +111,7 @@ static openal_snd *new_openal_snd (const void *data, dword len, dword rate, dwor int newlen = 0; // for some reason 8bit formats makes psshshshsh // TODO do this without SDL - convert_this_ext(AUDIO_S8, 1, rate, AUDIO_S16SYS, 1, rate, data, len, &newdata, &newlen); + convert_this_ext(sign ? AUDIO_S8 : AUDIO_U8, 1, rate, AUDIO_S16SYS, 1, rate, data, len, &newdata, &newlen); if (newdata != NULL) { alGenBuffers(1, &buffer); if (alGetError() == AL_NO_ERROR) { @@ -135,30 +135,35 @@ static openal_snd *new_openal_snd (const void *data, dword len, dword rate, dwor } snd_t *S_get (int id) { + void *handle; openal_snd *snd = NULL; - void *handle = M_lock(id); - if (context != NULL && handle != NULL) { - byte *data = handle; - dword len = F_getreslen(id); - dword rate = 8000; - dword lstart = 0; - dword llen = 0; - if (len > 16) { - dmi *hdr = handle; - dword hdr_len = int2host(hdr->len); - dword hdr_rate = int2host(hdr->rate); - dword hdr_lstart = int2host(hdr->lstart); - dword hdr_llen = int2host(hdr->llen); - if (hdr_len <= len - 8 && hdr_lstart + hdr_llen <= len - 16) { - data = hdr->data; - len = hdr_len; - rate = hdr_rate; - lstart = hdr_lstart; - llen = hdr_llen; + if (context != NULL) { + handle = M_lock(id); + if (handle != NULL) { + void *data = handle; + dword len = F_getreslen(id); + dword rate = 11025; + dword lstart = 0; + dword llen = 0; + int sign = 0; + if (len > 16) { + dmi *hdr = handle; + dword hdr_len = int2host(hdr->len); + dword hdr_rate = int2host(hdr->rate); + dword hdr_lstart = int2host(hdr->lstart); + dword hdr_llen = int2host(hdr->llen); + if (hdr_len <= len - 8 && hdr_lstart + hdr_llen <= len - 16) { + data = hdr->data; + len = hdr_len; + rate = hdr_rate; + lstart = hdr_lstart; + llen = hdr_llen; + sign = 1; + } } + snd = new_openal_snd(data, len, rate, lstart, llen, sign); + M_unlock(handle); } - snd = new_openal_snd(data, len, rate, lstart, llen); - M_unlock(handle); } return (snd_t*)snd; } @@ -167,6 +172,28 @@ snd_t *S_load (const char name[8]) { return S_get(F_findres(name)); } +void S_free (snd_t *s) { + int i; + ALint h; + openal_snd *snd = (openal_snd*)s; + if (snd != NULL) { + assert(snd->base.tag = TAG_OAL1); + if (context != NULL) { + for (i = 0; i < MAX_CHANNELS; i++) { + alGetSourcei(sources[i], AL_BUFFER, &h); + if (h == snd->buffer) { + alSourceStop(sources[i]); + alSourcei(sources[i], AL_BUFFER, 0); + } + } + alDeleteBuffers(1, &snd->buffer); + assert(alGetError() == AL_NO_ERROR); + } + snd->base.tag = 0; + free(s); + } +} + void S_init (void) { assert(device == NULL && context == NULL); const ALCint attrs[] = {ALC_MONO_SOURCES, MAX_CHANNELS, 0}; diff --git a/src/sdlmixer/sound.c b/src/sdlmixer/sound.c index 026e01f..93c1b63 100644 --- a/src/sdlmixer/sound.c +++ b/src/sdlmixer/sound.c @@ -13,19 +13,19 @@ #define TAG_MIX1 0x4d495831 #pragma pack(1) -struct dmi { +typedef struct dmi { Uint32 len; // length [bytes] Uint32 rate; // freq [Hz] Uint32 lstart; // loop start offset [bytes] Uint32 llen; // loop length [bytes] Uint8 data[]; // sound data -}; +} dmi; #pragma pack() -struct sound { +typedef struct sdlmixer_snd { snd_t base; Mix_Chunk *c; -}; +} sdlmixer_snd; short snd_vol; // public 0..128 @@ -75,7 +75,7 @@ void S_updatemusic (void) { } -/* sound */ +/* Sound */ void S_init (void) { assert(devinit == 0); @@ -86,16 +86,17 @@ void S_init (void) { devinit = 1; } else { logo("S_init: Mix_OpenAudio: %s\n", Mix_GetError()); + SDL_QuitSubSystem(SDL_INIT_AUDIO); } } else { logo("S_init: SDL_InitSubSytem: %s\n", SDL_GetError()); } } -static Mix_Chunk *convert_this (int rate, const Uint8 *buf, int len) { +static Mix_Chunk *convert_this (int rate, int sign, const Uint8 *buf, int len) { SDL_AudioCVT cvt; Mix_Chunk *c = NULL; - if (SDL_BuildAudioCVT(&cvt, AUDIO_S8, 1, rate, devformat, devchannels, devfreq) != -1) { + if (SDL_BuildAudioCVT(&cvt, sign ? AUDIO_S8 : AUDIO_U8, 1, rate, devformat, devchannels, devfreq) != -1) { int maxlen = len * cvt.len_mult; Uint8 *maxbuf = malloc(maxlen); if (maxbuf != NULL) { @@ -120,44 +121,55 @@ static Mix_Chunk *convert_this (int rate, const Uint8 *buf, int len) { return c; } -// TODO load raw sounds with voices +static sdlmixer_snd *new_sdlmixer_snd (const void *data, dword len, dword rate, dword lstart, dword llen, int sign) { + Mix_Chunk *c = NULL; + sdlmixer_snd *snd = NULL; + c = convert_this(rate, sign, data, len); + if (c != NULL) { + snd = malloc(sizeof(sdlmixer_snd)); + if (snd != NULL) { + snd->base.tag = TAG_MIX1; + snd->c = c; + } else { + free(c->abuf); + free(c); + } + } + return snd; +} snd_t *S_get (int id) { - if (!devinit) { - return NULL; - } - struct dmi *snd = M_lock(id); - struct sound *res = NULL; - if (snd != NULL) { - int rlen = F_getreslen(id); - if (rlen > 16) { - Uint32 len = int2host(snd->len); - Uint32 rate = int2host(snd->rate); - Uint32 lstart = int2host(snd->lstart); - Uint32 llen = int2host(snd->llen); - if (len <= rlen - 8 && lstart + llen <= rlen - 16) { - Mix_Chunk *c = convert_this(rate, snd->data, len); - if (c != NULL) { - res = malloc(sizeof(struct sound)); - if (res != NULL) { - res->base.tag = TAG_MIX1; - res->c = c; - // TODO loops - } else { - free(c); - } + void *handle; + sdlmixer_snd *snd = NULL; + if (devinit != NULL) { + handle = M_lock(id); + if (handle != NULL) { + void *data = handle; + dword len = F_getreslen(id); + dword rate = 11025; + dword lstart = 0; + dword llen = 0; + int sign = 0; + if (len > 16) { + dmi *hdr = handle; + dword hdr_len = int2host(hdr->len); + dword hdr_rate = int2host(hdr->rate); + dword hdr_lstart = int2host(hdr->lstart); + dword hdr_llen = int2host(hdr->llen); + if (hdr_len <= len - 8 && hdr_lstart + hdr_llen <= len - 16) { + data = hdr->data; + len = hdr_len; + rate = hdr_rate; + lstart = hdr_lstart; + llen = hdr_llen; + sign = 1; } - } else { - logo("S_get(%i): invalid header {len=%u:rate=%u:lstart=%u:llen=%u:rlen=%i}\n", id, len, rate, lstart, llen, rlen); } - } else { - logo("S_load(%i): too short\n", id); + snd = new_sdlmixer_snd(data, len, rate, lstart, llen, sign); + M_unlock(handle); } - M_unlock(snd); - } else { - logo("S_load(%i): not found\n", id); } - return (snd_t*)res; + return (snd_t*)snd; } snd_t *S_load (const char name[8]) { @@ -165,29 +177,43 @@ snd_t *S_load (const char name[8]) { return S_get(id); } +void S_free (snd_t *s) { + int i; + sdlmixer_snd *snd = (sdlmixer_snd*)s; + if (snd != NULL) { + assert(snd->base.tag == TAG_MIX1); + if (devinit) { + for (i = 0; i < devchunkchannels; i++) { + if (Mix_GetChunk(i) == snd->c) { + Mix_HaltChannel(i); + } + } + } + free(snd->c->abuf); + free(snd->c); + free(snd); + } +} + short S_play (snd_t *s, short c, short v) { + short channel = 0; + sdlmixer_snd *snd = (sdlmixer_snd*)s; assert(c >= 0 && c <= 8); assert(v >= 0 && v <= 255); - short channel = 0; - if (devinit) { - if (s) { - struct sound *snd = (struct sound *)s; - assert(snd->base.tag == TAG_MIX1); - // TODO care about global volume level - snd->c->volume = v * MIX_MAX_VOLUME / 255; - channel = Mix_PlayChannel(c <= 0 ? -1 : c - 1, snd->c, 0); - channel = channel == -1 ? 0 : channel + 1; - } + if (devinit && snd != NULL) { + assert(snd->base.tag == TAG_MIX1); + // TODO care about global volume level + snd->c->volume = v * MIX_MAX_VOLUME / 255; + channel = Mix_PlayChannel(c <= 0 ? -1 : c - 1, snd->c, 0); + channel = channel == -1 ? 0 : channel + 1; } return channel; } void S_stop (short c) { assert(c >= 0 && c <= 8); - if (devinit) { - if (c > 0) { - Mix_HaltChannel(c - 1); - } + if (devinit && c > 0) { + Mix_HaltChannel(c - 1); } } diff --git a/src/sound.h b/src/sound.h index ca2e044..8851b85 100644 --- a/src/sound.h +++ b/src/sound.h @@ -40,6 +40,9 @@ snd_t *S_get (int id); // Get sound handle for resource with name snd_t *S_load (const char name[8]); +// Stop sound and free handle +void S_free (snd_t *s); + // Initialize sound subsystem void S_init (void); -- 2.29.2