From dbfaa4949fe7c5be64cf3e98b1875b711656ff67 Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Sun, 22 Mar 2020 12:13:26 +0300 Subject: [PATCH] sound: separate and rewrite --- src/CMakeLists.txt | 6 +- src/items.c | 2 +- src/menu.c | 7 +- src/miscc.c | 34 +++---- src/music.c | 233 ------------------------------------------- src/sdlmixer/sound.c | 217 ++++++++++++++++++++++++++++++++++++++++ src/sound.c | 150 ---------------------------- src/sound.h | 38 ++++--- src/view.c | 1 - 9 files changed, 264 insertions(+), 424 deletions(-) delete mode 100644 src/music.c create mode 100644 src/sdlmixer/sound.c delete mode 100644 src/sound.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1a511c6..9558278 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,7 @@ set(D2D_GAME_ROOT .) set(D2D_OPENGL_ROOT ${D2D_GAME_ROOT}/gl) set(D2D_SOFTWARE_ROOT ${D2D_GAME_ROOT}/soft) set(D2D_SDL_ROOT ${D2D_GAME_ROOT}/sdl) +set(D2D_SDLMIXER_ROOT ${D2D_GAME_ROOT}/sdlmixer) find_package(SDL REQUIRED) find_package(SDL_mixer REQUIRED) @@ -19,6 +20,7 @@ aux_source_directory(${D2D_GAME_ROOT} D2D_GAME_SRC) aux_source_directory(${D2D_OPENGL_ROOT} D2D_OPENGL_SRC) aux_source_directory(${D2D_SOFTWARE_ROOT} D2D_SOFTWARE_SRC) aux_source_directory(${D2D_SDL_ROOT} D2D_SDL_SRC) +aux_source_directory(${D2D_SDLMIXER_ROOT} D2D_SDLMIXER_SRC) if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) @@ -39,13 +41,13 @@ message(STATUS "SOFTWARE: " ${WITH_SOFTWARE}) message(STATUS "OPENGL: " ${WITH_OPENGL}) if (WITH_OPENGL) - add_executable(doom2d-gl ${D2D_GAME_SRC} ${D2D_SDL_SRC} ${D2D_OPENGL_SRC}) + add_executable(doom2d-gl ${D2D_GAME_SRC} ${D2D_SDL_SRC} ${D2D_SDLMIXER_SRC} ${D2D_OPENGL_SRC}) target_include_directories(doom2d-gl PRIVATE "${D2D_GAME_ROOT}" "${SDL_INCLUDE_DIR}" "${SDLMIXER_INCLUDE_DIR}" "${OPENGL_INCLUDE_DIR}") target_link_libraries(doom2d-gl "${SDL_LIBRARY}" "${SDLMIXER_LIBRARY}" "${OPENGL_LIBRARY}") endif (WITH_OPENGL) if (WITH_SOFTWARE) - add_executable(doom2d-soft ${D2D_GAME_SRC} ${D2D_SDL_SRC} ${D2D_SOFTWARE_SRC}) + add_executable(doom2d-soft ${D2D_GAME_SRC} ${D2D_SDL_SRC} ${D2D_SDLMIXER_SRC} ${D2D_SOFTWARE_SRC}) target_include_directories(doom2d-soft PRIVATE "${D2D_GAME_ROOT}" "${SDL_INCLUDE_DIR}" "${SDLMIXER_INCLUDE_DIR}") target_link_libraries(doom2d-soft "${SDL_LIBRARY}" "${SDLMIXER_LIBRARY}") endif (WITH_SOFTWARE) diff --git a/src/items.c b/src/items.c index 49f954b..b0f079a 100644 --- a/src/items.c +++ b/src/items.c @@ -208,7 +208,7 @@ static void takesnd (int t) { {tsndtm=Z_sound(snd[1],128);return;} if(t==I_MEGA || t==I_INVL || t==I_SUPER) {tsndtm=Z_sound(snd[2],192);return;} - tsndtm=Z_sound(snd[0],256); + tsndtm=Z_sound(snd[0], 255); } void IT_act (void) { diff --git a/src/menu.c b/src/menu.c index 5a59b87..95fbbf6 100644 --- a/src/menu.c +++ b/src/menu.c @@ -159,6 +159,8 @@ static void GMV_stop (void) { } void GMV_say (char *nm) { + // TODO fix this + /* int r,len; snd_t *p; byte *d; @@ -172,6 +174,7 @@ void GMV_say (char *nm) { for(d=(byte*)(p+1);len;--len,++d) *d^=128; voc=p; voc_ch=S_play(voc,-1,1024,255); + */ } static void GM_set (menu_t *m) { @@ -299,8 +302,8 @@ static void GM_command (int c) { F_freemus(); GMV_stop(); #ifndef DEMO - c=Z_sound(M_lock(qsnd[myrand(QSND_NUM)]),256);//for(c=(Z_sound(M_lock(qsnd[random2(QSND_NUM)]),256)+9)<<16,timer=0;timerlen = int2host(snd->len); - snd->rate = int2host(snd->rate); - snd->lstart = int2host(snd->lstart); - snd->llen = int2host(snd->llen); - } - return snd; + s[0] = 'D'; + s[1] = 'S'; + strncpy(&s[2], n, 6); + return S_load(s); } -int Z_sound(void *s,int v) { - //if(snd_type==-1) return 0; - if(!s) return 0; - S_play(s,-1,1024,v); - return F_getreslen(((int*)s)[-1])/605; +int Z_sound (void *s, int v) { + if (s != NULL) { + S_play(s, 0, v); + // TODO ??? + //S_play(s, -1, 1024, v); + //return F_getreslen(((int*)s)[-1])/605; + return 0; + } else { + return 0; + } } #define GAS_START (MN__LAST-MN_DEMON+5) diff --git a/src/music.c b/src/music.c deleted file mode 100644 index ddd74b0..0000000 --- a/src/music.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - Copyright (C) Prikol Software 1996-1997 - Copyright (C) Aleksey Volynskov 1996-1997 - Copyright (C) 2011 - - This file is part of the Doom2D:Rembo project. - - Doom2D:Rembo is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. - - Doom2D:Rembo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see or - write to the Free Software Foundation, Inc., - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "glob.h" -#include "files.h" -#include "music.h" -#include "error.h" -#include "game.h" -#include -#include - -short mus_vol = 50; -char music_random = ON; -int music_time = 3; -int music_fade = 5; - -static Uint32 muscount; -static Mix_Music * muslo; -static int musdisabled = 1; -static int volsetcount = 0; - -void S_initmusic (void) { - if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { - fprintf(stderr, "\nUnable to initialize audio: %s\n", SDL_GetError()); - musdisabled=1; - return; - } - - if (Mix_OpenAudio(22050, AUDIO_S16, 1, 1000) < 0) { - fprintf(stderr, "Error initializing SDL_mixer: %s\n", Mix_GetError()); - musdisabled=1; - return; - } - } - - muslo=NULL; - - muscount=0; - - musdisabled = (mus_vol==0); - - S_volumemusic(mus_vol); -} - -void S_donemusic (void) { - if (SDL_WasInit(SDL_INIT_AUDIO)) { - F_freemus(); - Mix_CloseAudio(); - SDL_QuitSubSystem(SDL_INIT_AUDIO); - } -} - -void S_startmusic (int time) { - if (musdisabled) return; - Mix_PlayMusic(muslo, -1); - Mix_VolumeMusic(mus_vol); - muscount=time*60*1000/DELAY; -} - -void S_stopmusic (void) { - if (musdisabled) return; - Mix_HaltMusic(); - muscount = 0; -} - -void S_volumemusic (int v) { - if (musdisabled) return; - mus_vol = v; - if (mus_vol>128) mus_vol=128; - if (mus_vol<0) mus_vol=0; - if (mus_vol==0 && Mix_PlayingMusic()) { - S_stopmusic(); - } - else if (mus_vol>0 && !Mix_PlayingMusic()) { - S_startmusic(music_time); - } - else { - Mix_VolumeMusic(v); - } -} - -static struct { - Uint8 ascii; - Uint8 asciilc; - char *ch; -} atrans[] = { - {0x80, 0xA0, "A"},//А - {0x81, 0xA1, "B"},//Б - {0x82, 0xA2, "V"},//В - {0x83, 0xA3, "G"},//Г - {0x84, 0xA4, "D"},//Д - {0x85, 0xA5, "E"},//Е - {0x86, 0xA6, "ZH"},//Ж - {0x87, 0xA7, "Z"},//З - {0x88, 0xA8, "I"},//И - {0x89, 0xA9, "J"},//Й - {0x8A, 0xAA, "K"},//К - {0x8B, 0xAB, "L"},//Л - {0x8C, 0xAC, "M"},//М - {0x8D, 0xAD, "N"},//Н - {0x8E, 0xAE, "O"},//О - {0x8F, 0xAF, "P"},//П - {0x90, 0xE0, "R"},//Р - {0x91, 0xE1, "S"},//С - {0x92, 0xE2, "T"},//Т - {0x93, 0xE3, "U"},//У - {0x94, 0xE4, "F"},//Ф - {0x95, 0xE5, "H"},//Х - {0x96, 0xE6, "C"},//Ц - {0x97, 0xE7, "CH"},//Ч - {0x98, 0xE8, "SH"},//Ш - {0x99, 0xE9, "SCH"},//Щ - {0x9A, 0xEA, "X"},//Ъ - {0x9B, 0xEB, "Y"},//Ы - {0x9C, 0xEC, "J"},//Ь - {0x9D, 0xED, "E"},//Э - {0x9E, 0xEE, "JU"},//Ю - {0x9F, 0xEF, "JA"},//Я - {0} -}; - -static char *get_trans_char (Uint8 c) -{ - int i = 0; - while (atrans[i].ascii) { - - if (atrans[i].ascii == c || atrans[i].asciilc == c) { - return atrans[i].ch; - } - i++; - } - return NULL; -} - -static void trans_ascii_str (char *dest, char *src) -{ - char *p = dest; - int i; - for (i=0; i0) { - if (muscount < music_fade*1100/DELAY) { - Mix_FadeOutMusic(music_fade*1000); - } - muscount--; - if (muscount==0) { - if (music_random) F_randmus(g_music); - else F_nextmus(g_music); - F_freemus(); - F_loadmus(g_music); - S_startmusic(music_time); - } - } -} diff --git a/src/sdlmixer/sound.c b/src/sdlmixer/sound.c new file mode 100644 index 0000000..026e01f --- /dev/null +++ b/src/sdlmixer/sound.c @@ -0,0 +1,217 @@ +#include "glob.h" +#include "sound.h" +#include "music.h" +#include "misc.h" // int2host +#include "memory.h" // M_lock M_unlock +#include "files.h" // F_findres +#include "error.h" + +#include +#include +#include + +#define TAG_MIX1 0x4d495831 + +#pragma pack(1) +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 +}; +#pragma pack() + +struct sound { + snd_t base; + Mix_Chunk *c; +}; + +short snd_vol; // public 0..128 + +static int devfreq = MIX_DEFAULT_FREQUENCY; +static Uint32 devformat = AUDIO_S16SYS; // MIX_DEFAULT_FORMAT +static int devchannels = 1; // MIX_DEFAULT_CHANNELS; +static int devchunksize = 1024; +static int devchunkchannels = 8; +static int devinit; + +/* music */ + +short mus_vol; +char music_random; +int music_time; +int music_fade; + +void S_initmusic (void) { + +} + +void S_donemusic (void) { + +} + +void S_startmusic (int time) { + +} + +void S_stopmusic (void) { + +} + +void S_volumemusic (int v) { + +} + +void F_loadmus (char n[8]) { + +} + +void F_freemus (void) { + +} + +void S_updatemusic (void) { + +} + +/* sound */ + +void S_init (void) { + assert(devinit == 0); + logo("S_init: initialize sound\n"); + if (SDL_InitSubSystem(SDL_INIT_AUDIO) == 0) { + if (Mix_OpenAudio(devfreq, devformat, devchannels, devchunksize) == 0) { + Mix_AllocateChannels(devchunkchannels); + devinit = 1; + } else { + logo("S_init: Mix_OpenAudio: %s\n", Mix_GetError()); + } + } else { + logo("S_init: SDL_InitSubSytem: %s\n", SDL_GetError()); + } +} + +static Mix_Chunk *convert_this (int rate, const Uint8 *buf, int len) { + SDL_AudioCVT cvt; + Mix_Chunk *c = NULL; + if (SDL_BuildAudioCVT(&cvt, AUDIO_S8, 1, rate, devformat, devchannels, devfreq) != -1) { + int maxlen = len * cvt.len_mult; + Uint8 *maxbuf = malloc(maxlen); + if (maxbuf != NULL) { + memcpy(maxbuf, buf, len); + cvt.buf = maxbuf; + cvt.len = len; + if (SDL_ConvertAudio(&cvt) == 0) { + c = malloc(sizeof(Mix_Chunk)); + if (c != NULL) { + c->allocated = 0; + c->abuf = maxbuf; + c->alen = len * cvt.len_ratio; + c->volume = MIX_MAX_VOLUME; + } else { + free(maxbuf); + } + } else { + free(maxbuf); + } + } + } + return c; +} + +// TODO load raw sounds with voices + +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); + } + } + } 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); + } + M_unlock(snd); + } else { + logo("S_load(%i): not found\n", id); + } + return (snd_t*)res; +} + +snd_t *S_load (const char name[8]) { + int id = F_findres(name); + return S_get(id); +} + +short S_play (snd_t *s, short c, short v) { + 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; + } + } + return channel; +} + +void S_stop (short c) { + assert(c >= 0 && c <= 8); + if (devinit) { + if (c > 0) { + Mix_HaltChannel(c - 1); + } + } +} + +void S_volume (int v) { + snd_vol = min(max(v, 0), 128); + if (devinit) { + // TODO change relativelly for every channel + Mix_Volume(-1, v * MIX_MAX_VOLUME / 128); + } +} + +void S_wait (void) { + if (devinit) { + while (Mix_Playing(-1) > 0) { + SDL_Delay(10); + } + } +} + +void S_done (void) { + if (devinit) { + // TODO free memory + Mix_AllocateChannels(0); + Mix_CloseAudio(); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + } +} diff --git a/src/sound.c b/src/sound.c deleted file mode 100644 index 4a4077d..0000000 --- a/src/sound.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - Copyright (C) Prikol Software 1996-1997 - Copyright (C) Aleksey Volynskov 1996-1997 - Copyright (C) 2011 - - This file is part of the Doom2D:Rembo project. - - Doom2D:Rembo is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. - - Doom2D:Rembo is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see or - write to the Free Software Foundation, Inc., - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "glob.h" -#include "sound.h" -#include "error.h" -#include -#include - -#define NUM_CHANNELS 16 -#define NUM_CHUNKS 300 - -short snd_vol = 50; - -static int snddisabled = 1; -static struct { - snd_t *s; - Mix_Chunk *c; -} chunks[NUM_CHUNKS]; - -void S_init (void) { - logo("S_init: настройка звука\n"); - if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { - fprintf(stderr, "\nUnable to initialize audio: %s\n", SDL_GetError()); - snddisabled=1; - return; - } - - if (Mix_OpenAudio(22050, AUDIO_S16, 1, 1000) < 0) { - fprintf(stderr, "Error initializing SDL_mixer: %s\n", Mix_GetError()); - snddisabled=1; - return; - } - - if (Mix_AllocateChannels(NUM_CHANNELS)!=NUM_CHANNELS) { - fprintf(stderr, "Error allocation channels: %s\n", Mix_GetError()); - snddisabled=1; - return; - } - } - - int i; - for (i=0; ilen; - SDL_AudioCVT cvt; - SDL_BuildAudioCVT(&cvt, AUDIO_S8, 1, s->rate, AUDIO_S16, 1, 22050); - if (!(cvt.buf = malloc(dlen*cvt.len_mult))) ERR_fatal("Out of memory\n");; - memcpy(cvt.buf, data, dlen); - cvt.len = dlen; - SDL_ConvertAudio(&cvt); - - Mix_Chunk *chunk; - if (!(chunk = malloc(sizeof(Mix_Chunk)))) ERR_fatal("Out of memory\n");; - chunk->abuf=cvt.buf; - chunk->alen=cvt.len_cvt; - chunk->allocated=0; - chunk->volume=(float)v/255*SDL_MIX_MAXVOLUME; - - chunks[fi].s = s; - chunks[fi].c = chunk; - - return chunk; -} - -void free_chunks (void) { - if (snddisabled) return; - Mix_HaltChannel(-1); - int i; - for (i=0; iabuf); - free(chunks[i].c); - chunks[i].c = NULL; - chunks[i].s = NULL; - } - } -} - -short S_play(snd_t *s, short c, unsigned r, short v) { - if (snddisabled) return 0; - Mix_Chunk *chunk = get_chunk(s,r,v); - if (chunk==NULL) return 0; - return Mix_PlayChannel(c, chunk, 0); -} - -void S_stop (short c) { - Mix_HaltChannel(c); -} - -void S_volume (int v) { - if (snddisabled) return; - snd_vol=v; - if (snd_vol>128) snd_vol=128; - if (snd_vol<0) snd_vol=0; - Mix_Volume(-1, snd_vol); -} - -void S_wait (void) { - if (snddisabled) return; - while (Mix_Playing(-1)) { - SDL_Delay(10); - } -} diff --git a/src/sound.h b/src/sound.h index 5f71e34..ca2e044 100644 --- a/src/sound.h +++ b/src/sound.h @@ -27,33 +27,41 @@ #ifndef SOUND_H_INCLUDED #define SOUND_H_INCLUDED -// заголовок инструмента (DMI) -#pragma pack(1) typedef struct { - unsigned int len; // длина в байтах - unsigned int rate; // частота в Гц. - unsigned int lstart; // начало повтора в байтах от начала данных - unsigned int llen; // длина повтора в байтах + int tag; } snd_t; -#pragma pack() -// громкость звука и музыки (0-128) +// Sound volume 0..128 extern short snd_vol; +// Get sound handle for resource +snd_t *S_get (int id); + +// Get sound handle for resource with name +snd_t *S_load (const char name[8]); + +// Initialize sound subsystem void S_init (void); + +// Deinitialize sound subsystem void S_done (void); -// проиграть звук s на канале c (1-8), частоте r и громкости v (0-255) -// возвращает номер канала, на котором играется звук -// если c==0, то звук попадет в любой свободный канал -// r - это относительная частота (обычно 1024) -short S_play (snd_t *s, short c, unsigned r, short v); +// Play sound on channel with volume . +// = sound handle (NULL is ignored) +// = 1..8 or 0 for any free +// = 0..255 +// return used channel or zero on error +short S_play (snd_t *s, short c, short v); -// остановить звук на канале c (1-8) +// Stop sound on channel +// = 0..8 (0 ignored) void S_stop (short c); +// Set sound volume to , also affects variable snd_vol +// = 0..128 void S_volume (int v); -void free_chunks (void); + +// Wait before all sounds end playing void S_wait (void); #endif /* SOUND_H_INCLUDED */ diff --git a/src/view.c b/src/view.c index 1819698..77985e1 100644 --- a/src/view.c +++ b/src/view.c @@ -102,7 +102,6 @@ void W_init (void) { PL_init(); MN_init(); R_loadsky(1); - free_chunks(); } static void unpack (void *buf, int len, void *obuf) { -- 2.29.2