DEADSOFTWARE

sound: fix voices in menu
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Tue, 24 Mar 2020 12:44:53 +0000 (15:44 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Tue, 24 Mar 2020 12:44:53 +0000 (15:44 +0300)
src/CMakeLists.txt
src/menu.c
src/menu.h
src/openal/sound.c
src/sdlmixer/sound.c
src/sound.h

index e33b8325772008742ac6eb957f73c781366ff332..fcbd51ad9a14ecab8613a20008e412e35d9ffd67 100644 (file)
@@ -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)
index 95fbbf660dc7fbfc2ad2b8019314c5171d332d58..7f44950493624f25d6ab8ccd6b67e21009d718e6 100644 (file)
@@ -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) {
index fedd702301d2eacffe63c981c441caa40becc189..bb6d829777bcde7f8f7886cb3c1cd13fd2d19a84 100644 (file)
@@ -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);
index af75aa381eeef080d04619e3f3a3cd4d2ce0888a..d046803dc4d0f0018d6039b5e73e3b91726160bb 100644 (file)
@@ -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};
index 026e01fec9486d79a499196d596c412ccc2e618a..93c1b6350f3cd9ae3935a1c4dde5071fcf2391e8 100644 (file)
 #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);
   }
 }
 
index ca2e044a8b4e49617bc850d4b79bf9918cf4be5d..8851b8513320a4d6870faeebee0b6b24473edda1 100644 (file)
@@ -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);