ref: 166c3d2e9b5ee469f226f42dd8cfe74ba6ff6be0
dir: /src/setup/sound.c/
//
// Copyright(C) 2005-2014 Simon Howard
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program 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.
//
// Sound control menu
#include <stdlib.h>
#include "SDL_mixer.h"
#include "textscreen.h"
#include "m_config.h"
#include "m_misc.h"
#include "mode.h"
#include "sound.h"
#define WINDOW_HELP_URL "http://www.chocolate-doom.org/setup-sound"
typedef enum
{
SFXMODE_DISABLED,
SFXMODE_DIGITAL,
SFXMODE_PCSPEAKER,
NUM_SFXMODES
} sfxmode_t;
static char *sfxmode_strings[] =
{
"Disabled",
"Digital",
"PC speaker"
};
typedef enum
{
MUSICMODE_DISABLED,
MUSICMODE_OPL,
MUSICMODE_GUS,
MUSICMODE_NATIVE,
MUSICMODE_CD,
NUM_MUSICMODES
} musicmode_t;
static char *musicmode_strings[] =
{
"Disabled",
"OPL (Adlib/SB)",
"GUS (emulated)",
"Native MIDI",
"CD audio"
};
typedef enum
{
OPLMODE_OPL2,
OPLMODE_OPL3,
NUM_OPLMODES,
} oplmode_t;
static char *opltype_strings[] =
{
"OPL2",
"OPL3"
};
static char *cfg_extension[] = { "cfg", NULL };
// Config file variables:
int snd_sfxdevice = SNDDEVICE_SB;
int snd_musicdevice = SNDDEVICE_SB;
int snd_samplerate = 44100;
int opl_io_port = 0x388;
int snd_cachesize = 64 * 1024 * 1024;
int snd_maxslicetime_ms = 28;
char *snd_musiccmd = "";
int snd_pitchshift = 0;
char *snd_dmxoption = "";
static int numChannels = 8;
static int sfxVolume = 8;
static int musicVolume = 8;
static int voiceVolume = 15;
static int show_talk = 0;
static int use_libsamplerate = 0;
static float libsamplerate_scale = 0.65;
static char *timidity_cfg_path = NULL;
static char *gus_patch_path = NULL;
static int gus_ram_kb = 1024;
// DOS specific variables: these are unused but should be maintained
// so that the config file can be shared between chocolate
// doom and doom.exe
static int snd_sbport = 0;
static int snd_sbirq = 0;
static int snd_sbdma = 0;
static int snd_mport = 0;
// GUI variables:
static int snd_sfxmode;
static int snd_musicmode;
static int snd_oplmode;
static void UpdateSndDevices(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data))
{
switch (snd_sfxmode)
{
case SFXMODE_DISABLED:
snd_sfxdevice = SNDDEVICE_NONE;
break;
case SFXMODE_PCSPEAKER:
snd_sfxdevice = SNDDEVICE_PCSPEAKER;
break;
case SFXMODE_DIGITAL:
snd_sfxdevice = SNDDEVICE_SB;
break;
}
switch (snd_musicmode)
{
case MUSICMODE_DISABLED:
snd_musicdevice = SNDDEVICE_NONE;
break;
case MUSICMODE_NATIVE:
snd_musicdevice = SNDDEVICE_GENMIDI;
break;
case MUSICMODE_OPL:
snd_musicdevice = SNDDEVICE_SB;
break;
case MUSICMODE_GUS:
snd_musicdevice = SNDDEVICE_GUS;
break;
case MUSICMODE_CD:
snd_musicdevice = SNDDEVICE_CD;
break;
}
switch (snd_oplmode)
{
default:
case OPLMODE_OPL2:
snd_dmxoption = "";
break;
case OPLMODE_OPL3:
snd_dmxoption = "-opl3";
break;
}
}
static txt_dropdown_list_t *OPLTypeSelector(void)
{
txt_dropdown_list_t *result;
if (snd_dmxoption != NULL && strstr(snd_dmxoption, "-opl3") != NULL)
{
snd_oplmode = OPLMODE_OPL3;
}
else
{
snd_oplmode = OPLMODE_OPL2;
}
result = TXT_NewDropdownList(&snd_oplmode, opltype_strings, 2);
TXT_SignalConnect(result, "changed", UpdateSndDevices, NULL);
return result;
}
static void UpdateExtraTable(TXT_UNCAST_ARG(widget),
TXT_UNCAST_ARG(extra_table))
{
TXT_CAST_ARG(txt_table_t, extra_table);
TXT_ClearTable(extra_table);
switch (snd_musicmode)
{
case MUSICMODE_OPL:
TXT_AddWidgets(extra_table,
TXT_NewLabel("OPL type"),
OPLTypeSelector(),
NULL);
break;
case MUSICMODE_GUS:
TXT_AddWidgets(extra_table,
TXT_NewLabel("GUS patch path:"),
TXT_TABLE_OVERFLOW_RIGHT,
TXT_NewFileSelector(&gus_patch_path, 34,
"Select path to GUS patches",
TXT_DIRECTORY),
TXT_TABLE_OVERFLOW_RIGHT,
NULL);
break;
case MUSICMODE_NATIVE:
TXT_AddWidgets(extra_table,
TXT_NewLabel("Timidity configuration file:"),
TXT_TABLE_OVERFLOW_RIGHT,
TXT_NewFileSelector(&timidity_cfg_path, 34,
"Select Timidity config file",
cfg_extension),
TXT_TABLE_OVERFLOW_RIGHT,
NULL);
break;
default:
break;
}
}
void ConfigSound(void)
{
txt_window_t *window;
txt_table_t *extra_table;
txt_dropdown_list_t *sfx_mode_control;
txt_dropdown_list_t *music_mode_control;
int num_sfx_modes, num_music_modes;
// Work out what sfx mode we are currently using:
if (snd_sfxdevice == SNDDEVICE_PCSPEAKER)
{
snd_sfxmode = SFXMODE_PCSPEAKER;
}
else if (snd_sfxdevice >= SNDDEVICE_SB)
{
snd_sfxmode = SFXMODE_DIGITAL;
}
else
{
snd_sfxmode = SFXMODE_DISABLED;
}
// Is music enabled?
switch (snd_musicdevice)
{
case SNDDEVICE_GENMIDI:
snd_musicmode = MUSICMODE_NATIVE;
break;
case SNDDEVICE_CD:
snd_musicmode = MUSICMODE_CD;
break;
case SNDDEVICE_SB:
case SNDDEVICE_ADLIB:
case SNDDEVICE_AWE32:
snd_musicmode = MUSICMODE_OPL;
break;
case SNDDEVICE_GUS:
snd_musicmode = MUSICMODE_GUS;
break;
default:
snd_musicmode = MUSICMODE_DISABLED;
break;
}
// Doom has PC speaker sound effects, but others do not:
if (gamemission == doom)
{
num_sfx_modes = NUM_SFXMODES;
}
else
{
num_sfx_modes = NUM_SFXMODES - 1;
}
// Hexen has CD audio; others do not.
if (gamemission == hexen)
{
num_music_modes = NUM_MUSICMODES;
}
else
{
num_music_modes = NUM_MUSICMODES - 1;
}
// Build the window
window = TXT_NewWindow("Sound configuration");
TXT_SetWindowHelpURL(window, WINDOW_HELP_URL);
TXT_SetTableColumns(window, 2);
TXT_SetColumnWidths(window, 19, 15);
TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP,
TXT_SCREEN_W / 2, 5);
TXT_AddWidgets(window,
TXT_NewSeparator("Sound effects"),
TXT_NewLabel("Sound effects"),
sfx_mode_control = TXT_NewDropdownList(&snd_sfxmode,
sfxmode_strings,
num_sfx_modes),
TXT_NewLabel("Sound channels"),
TXT_NewSpinControl(&numChannels, 1, 8),
TXT_NewLabel("SFX volume"),
TXT_NewSpinControl(&sfxVolume, 0, 15),
NULL);
// Only show for games that implemented pitch shifting:
if (gamemission == doom || gamemission == heretic || gamemission == hexen)
{
TXT_AddWidgets(window,
TXT_NewCheckBox("Pitch-shifted sounds",
&snd_pitchshift),
TXT_TABLE_OVERFLOW_RIGHT,
NULL);
}
if (gamemission == strife)
{
TXT_AddWidgets(window,
TXT_NewLabel("Voice volume"),
TXT_NewSpinControl(&voiceVolume, 0, 15),
TXT_NewCheckBox("Show text with voices", &show_talk),
TXT_TABLE_OVERFLOW_RIGHT,
NULL);
}
TXT_AddWidgets(window,
TXT_NewSeparator("Music"),
TXT_NewLabel("Music"),
music_mode_control = TXT_NewDropdownList(&snd_musicmode,
musicmode_strings,
num_music_modes),
TXT_NewLabel("Music volume"),
TXT_NewSpinControl(&musicVolume, 0, 15),
extra_table = TXT_NewTable(2),
TXT_TABLE_OVERFLOW_RIGHT,
NULL);
TXT_SetColumnWidths(extra_table, 19, 15);
TXT_SignalConnect(sfx_mode_control, "changed", UpdateSndDevices, NULL);
TXT_SignalConnect(music_mode_control, "changed", UpdateSndDevices, NULL);
// Update extra_table when the music mode is changed, and build it now.
TXT_SignalConnect(music_mode_control, "changed",
UpdateExtraTable, extra_table);
UpdateExtraTable(music_mode_control, extra_table);
}
void BindSoundVariables(void)
{
M_BindIntVariable("snd_sfxdevice", &snd_sfxdevice);
M_BindIntVariable("snd_musicdevice", &snd_musicdevice);
M_BindIntVariable("snd_channels", &numChannels);
M_BindIntVariable("snd_samplerate", &snd_samplerate);
M_BindIntVariable("sfx_volume", &sfxVolume);
M_BindIntVariable("music_volume", &musicVolume);
M_BindIntVariable("use_libsamplerate", &use_libsamplerate);
M_BindFloatVariable("libsamplerate_scale", &libsamplerate_scale);
M_BindIntVariable("gus_ram_kb", &gus_ram_kb);
M_BindStringVariable("gus_patch_path", &gus_patch_path);
M_BindStringVariable("timidity_cfg_path", &timidity_cfg_path);
M_BindIntVariable("snd_sbport", &snd_sbport);
M_BindIntVariable("snd_sbirq", &snd_sbirq);
M_BindIntVariable("snd_sbdma", &snd_sbdma);
M_BindIntVariable("snd_mport", &snd_mport);
M_BindIntVariable("snd_maxslicetime_ms", &snd_maxslicetime_ms);
M_BindStringVariable("snd_musiccmd", &snd_musiccmd);
M_BindStringVariable("snd_dmxoption", &snd_dmxoption);
M_BindIntVariable("snd_cachesize", &snd_cachesize);
M_BindIntVariable("opl_io_port", &opl_io_port);
M_BindIntVariable("snd_pitchshift", &snd_pitchshift);
if (gamemission == strife)
{
M_BindIntVariable("voice_volume", &voiceVolume);
M_BindIntVariable("show_talk", &show_talk);
}
timidity_cfg_path = M_StringDuplicate("");
gus_patch_path = M_StringDuplicate("");
// All versions of Heretic and Hexen did pitch-shifting.
// Most versions of Doom did not and Strife never did.
snd_pitchshift = gamemission == heretic || gamemission == hexen;
// Default sound volumes - different games use different values.
switch (gamemission)
{
case doom:
default:
sfxVolume = 8; musicVolume = 8;
break;
case heretic:
case hexen:
sfxVolume = 10; musicVolume = 10;
break;
case strife:
sfxVolume = 8; musicVolume = 13;
break;
}
// Before SDL_mixer version 1.2.11, MIDI music caused the game
// to crash when it looped. If this is an old SDL_mixer version,
// disable MIDI.
#ifdef __MACOSX__
{
const SDL_version *v = Mix_Linked_Version();
if (SDL_VERSIONNUM(v->major, v->minor, v->patch)
< SDL_VERSIONNUM(1, 2, 11))
{
snd_musicdevice = SNDDEVICE_NONE;
}
}
#endif
}