MENUITEM SEPARATOR
MENUITEM "&Music", 420
+ POPUP "Volume"
+ {
+ MENUITEM "100%", 460
+ MENUITEM "90%", 461
+ MENUITEM "80%", 462
+ MENUITEM "70%", 463
+ MENUITEM "60%", 464
+ MENUITEM "50%", 465
+ MENUITEM "40%", 466
+ MENUITEM "30%", 467
+ MENUITEM "20%", 468
+ MENUITEM "10%", 469
+ }
MENUITEM "&Pause music when inactive", 421
MENUITEM "&Open music folder", 422
MENUITEM SEPARATOR
MENUITEM "&Sound", 410
+ POPUP "Volume"
+ {
+ MENUITEM "100%", 470
+ MENUITEM "90%", 471
+ MENUITEM "80%", 472
+ MENUITEM "70%", 473
+ MENUITEM "60%", 474
+ MENUITEM "50%", 475
+ MENUITEM "40%", 476
+ MENUITEM "30%", 477
+ MENUITEM "20%", 478
+ MENUITEM "10%", 479
+ }
MENUITEM "&Open sound folder", 411
MENUITEM SEPARATOR
MENUITEM "&HTML dump", 450
MENUITEM SEPARATOR
MENUITEM "\83X\83R\83A(&C)", 120
MENUITEM "\83\80\81[\83r\81[(&M)", 121
- MENUITEM SEPARATOR
+ MENUITEM SEPARATOR
MENUITEM "\8fI\97¹(&X)", 130
}
}
MENUITEM SEPARATOR
MENUITEM "BGM(&M)", 420
+ POPUP "\89¹\97Ê"
+ {
+ MENUITEM "100%", 460
+ MENUITEM "90%", 461
+ MENUITEM "80%", 462
+ MENUITEM "70%", 463
+ MENUITEM "60%", 464
+ MENUITEM "50%", 465
+ MENUITEM "40%", 466
+ MENUITEM "30%", 467
+ MENUITEM "20%", 468
+ MENUITEM "10%", 469
+ }
MENUITEM "\83A\83N\83e\83B\83u\8e\9e\82Ì\82ÝBGM\8dÄ\90¶(&M)", 421
MENUITEM "BGM\90Ý\92è\83t\83H\83\8b\83_\82ð\8aJ\82(&O)", 422
MENUITEM SEPARATOR
MENUITEM "\8cø\89Ê\89¹(&S)", 410
+ POPUP "\89¹\97Ê"
+ {
+ MENUITEM "100%", 470
+ MENUITEM "90%", 471
+ MENUITEM "80%", 472
+ MENUITEM "70%", 473
+ MENUITEM "60%", 474
+ MENUITEM "50%", 475
+ MENUITEM "40%", 476
+ MENUITEM "30%", 477
+ MENUITEM "20%", 478
+ MENUITEM "10%", 479
+ }
MENUITEM "\8cø\89Ê\89¹\90Ý\92è\83t\83H\83\8b\83_\82ð\8aJ\82(&P)", 411
MENUITEM SEPARATOR
MENUITEM "\89æ\96Ê\82ðHTML\82Å\95Û\91¶(&H)...", 450
#include "game-option/runtime-arguments.h"
bool arg_sound; /* Command arg -- Request special sounds */
+int arg_sound_volume_table_index;
bool arg_music; /* Command arg -- Request special musics */
+int arg_music_volume_table_index;
byte arg_graphics; /* Command arg -- Request graphics mode */
bool arg_monochrome; /* Command arg -- Request monochrome mode */
bool arg_force_original; /* Command arg -- Request original keyset */
#include "system/angband.h"
extern bool arg_music;
+extern int arg_music_volume_table_index;
extern bool arg_sound;
+extern int arg_sound_volume_table_index;
extern byte arg_graphics;
extern bool arg_monochrome;
extern bool arg_force_original;
#include "wizard/spoiler-util.h"
#include "wizard/wizard-spoiler.h"
#include "world/world.h"
+#include <algorithm>
#include <commdlg.h>
#include <cstdlib>
#include <direct.h>
strcpy(buf, arg_sound ? "1" : "0");
WritePrivateProfileStringA("Angband", "Sound", buf, ini_file);
+ WritePrivateProfileStringA("Angband", "SoundVolumeTableIndex", std::to_string(arg_sound_volume_table_index).data(), ini_file);
strcpy(buf, arg_music ? "1" : "0");
WritePrivateProfileStringA("Angband", "Music", buf, ini_file);
strcpy(buf, use_pause_music_inactive ? "1" : "0");
+ WritePrivateProfileStringA("Angband", "MusicVolumeTableIndex", std::to_string(arg_music_volume_table_index).data(), ini_file);
WritePrivateProfileStringA("Angband", "MusicPauseInactive", buf, ini_file);
wsprintfA(buf, "%d", current_bg_mode);
arg_bigtile = (GetPrivateProfileIntA("Angband", "Bigtile", false, ini_file) != 0);
use_bigtile = arg_bigtile;
arg_sound = (GetPrivateProfileIntA("Angband", "Sound", 0, ini_file) != 0);
+ arg_sound_volume_table_index = std::clamp<int>(GetPrivateProfileIntA("Angband", "SoundVolumeTableIndex", 0, ini_file), 0, SOUND_VOLUME_TABLE.size() - 1);
arg_music = (GetPrivateProfileIntA("Angband", "Music", 0, ini_file) != 0);
+ arg_music_volume_table_index = std::clamp<int>(GetPrivateProfileIntA("Angband", "MusicVolumeTableIndex", 0, ini_file), 0, main_win_music::VOLUME_TABLE.size() - 1);
use_pause_music_inactive = (GetPrivateProfileIntA("Angband", "MusicPauseInactive", 0, ini_file) != 0);
current_bg_mode = static_cast<bg_mode>(GetPrivateProfileIntA("Angband", "BackGround", 0, ini_file));
GetPrivateProfileStringA("Angband", "BackGroundBitmap", DEFAULT_BG_FILENAME, wallpaper_file, 1023, ini_file);
if (!use_sound) {
return 1;
}
- return play_sound(v);
+ return play_sound(v, SOUND_VOLUME_TABLE[arg_sound_volume_table_index]);
}
/*!
CheckMenuItem(hm, IDM_OPTIONS_NEW2_GRAPHICS, (arg_graphics == enum2i(graphics_mode::GRAPHICS_HENGBAND) ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(hm, IDM_OPTIONS_BIGTILE, (arg_bigtile ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(hm, IDM_OPTIONS_MUSIC, (arg_music ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuRadioItem(hm, IDM_OPTIONS_MUSIC_VOLUME_100, IDM_OPTIONS_MUSIC_VOLUME_010,
+ IDM_OPTIONS_MUSIC_VOLUME_100 + arg_music_volume_table_index, MF_BYCOMMAND);
CheckMenuItem(hm, IDM_OPTIONS_MUSIC_PAUSE_INACTIVE, (use_pause_music_inactive ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(hm, IDM_OPTIONS_SOUND, (arg_sound ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuRadioItem(hm, IDM_OPTIONS_SOUND_VOLUME_100, IDM_OPTIONS_SOUND_VOLUME_010,
+ IDM_OPTIONS_SOUND_VOLUME_100 + arg_sound_volume_table_index, MF_BYCOMMAND);
CheckMenuItem(hm, IDM_OPTIONS_NO_BG, ((current_bg_mode == bg_mode::BG_NONE) ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(hm, IDM_OPTIONS_BG, ((current_bg_mode == bg_mode::BG_ONE) ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(hm, IDM_OPTIONS_PRESET_BG, ((current_bg_mode == bg_mode::BG_PRESET) ? MF_CHECKED : MF_UNCHECKED));
}
break;
}
+ case IDM_OPTIONS_MUSIC_VOLUME_100:
+ case IDM_OPTIONS_MUSIC_VOLUME_090:
+ case IDM_OPTIONS_MUSIC_VOLUME_080:
+ case IDM_OPTIONS_MUSIC_VOLUME_070:
+ case IDM_OPTIONS_MUSIC_VOLUME_060:
+ case IDM_OPTIONS_MUSIC_VOLUME_050:
+ case IDM_OPTIONS_MUSIC_VOLUME_040:
+ case IDM_OPTIONS_MUSIC_VOLUME_030:
+ case IDM_OPTIONS_MUSIC_VOLUME_020:
+ case IDM_OPTIONS_MUSIC_VOLUME_010: {
+ arg_music_volume_table_index = wCmd - IDM_OPTIONS_MUSIC_VOLUME_100;
+ if (use_music) {
+ main_win_music::set_music_volume(main_win_music::VOLUME_TABLE[arg_music_volume_table_index]);
+ }
+ break;
+ }
case IDM_OPTIONS_MUSIC_PAUSE_INACTIVE: {
use_pause_music_inactive = !use_pause_music_inactive;
break;
change_sound_mode(arg_sound);
break;
}
+ case IDM_OPTIONS_SOUND_VOLUME_100:
+ case IDM_OPTIONS_SOUND_VOLUME_090:
+ case IDM_OPTIONS_SOUND_VOLUME_080:
+ case IDM_OPTIONS_SOUND_VOLUME_070:
+ case IDM_OPTIONS_SOUND_VOLUME_060:
+ case IDM_OPTIONS_SOUND_VOLUME_050:
+ case IDM_OPTIONS_SOUND_VOLUME_040:
+ case IDM_OPTIONS_SOUND_VOLUME_030:
+ case IDM_OPTIONS_SOUND_VOLUME_020:
+ case IDM_OPTIONS_SOUND_VOLUME_010: {
+ arg_sound_volume_table_index = wCmd - IDM_OPTIONS_SOUND_VOLUME_100;
+ break;
+ }
case IDM_OPTIONS_OPEN_SOUND_DIR: {
std::vector<char> buf(MAIN_WIN_MAX_PATH);
path_build(&buf[0], MAIN_WIN_MAX_PATH, ANGBAND_DIR_XTRA_SOUND, "sound.cfg");
return 0;
}
case MM_MCINOTIFY: {
- main_win_music::on_mci_notify(wParam, lParam);
+ main_win_music::on_mci_notify(wParam, lParam, main_win_music::VOLUME_TABLE[arg_music_volume_table_index]);
return 0;
}
#define IDM_OPTIONS_PRESET_BG 442
#define IDM_OPTIONS_OPEN_BG 449
+#define IDM_OPTIONS_MUSIC_VOLUME_100 460
+#define IDM_OPTIONS_MUSIC_VOLUME_090 461
+#define IDM_OPTIONS_MUSIC_VOLUME_080 462
+#define IDM_OPTIONS_MUSIC_VOLUME_070 463
+#define IDM_OPTIONS_MUSIC_VOLUME_060 464
+#define IDM_OPTIONS_MUSIC_VOLUME_050 465
+#define IDM_OPTIONS_MUSIC_VOLUME_040 466
+#define IDM_OPTIONS_MUSIC_VOLUME_030 467
+#define IDM_OPTIONS_MUSIC_VOLUME_020 468
+#define IDM_OPTIONS_MUSIC_VOLUME_010 469
+
+#define IDM_OPTIONS_SOUND_VOLUME_100 470
+#define IDM_OPTIONS_SOUND_VOLUME_090 471
+#define IDM_OPTIONS_SOUND_VOLUME_080 472
+#define IDM_OPTIONS_SOUND_VOLUME_070 473
+#define IDM_OPTIONS_SOUND_VOLUME_060 474
+#define IDM_OPTIONS_SOUND_VOLUME_050 475
+#define IDM_OPTIONS_SOUND_VOLUME_040 476
+#define IDM_OPTIONS_SOUND_VOLUME_030 477
+#define IDM_OPTIONS_SOUND_VOLUME_020 478
+#define IDM_OPTIONS_SOUND_VOLUME_010 479
+
#define IDM_DUMP_SCREEN_HTML 450
#include "term/z-term.h"
#include "util/angband-files.h"
#include "world/world.h"
+#include <algorithm>
+#include <digitalv.h>
+#include <limits>
bool use_pause_music_inactive = false;
static int current_music_type = TERM_XTRA_MUSIC_MUTE;
return 0;
}
+void set_music_volume(int volume)
+{
+ if (current_music_type == TERM_XTRA_MUSIC_MUTE) {
+ return;
+ }
+
+ MCI_DGV_SETAUDIO_PARMSW mci_vol{};
+ mci_vol.dwItem = MCI_DGV_SETAUDIO_VOLUME;
+ mci_vol.dwValue = volume;
+ mciSendCommandW(
+ mci_open_parms.wDeviceID,
+ MCI_SETAUDIO,
+ MCI_DGV_SETAUDIO_ITEM | MCI_DGV_SETAUDIO_VALUE,
+ (DWORD)&mci_vol);
+}
+
/*
* Notify event
*/
-void on_mci_notify(WPARAM wFlags, LONG lDevID)
+void on_mci_notify(WPARAM wFlags, LONG lDevID, int volume)
{
if (wFlags == MCI_NOTIFY_SUCCESSFUL) {
// play a music (repeat)
+ set_music_volume(volume);
mciSendCommandW(lDevID, MCI_SEEK, MCI_SEEK_TO_START | MCI_WAIT, 0);
mciSendCommandW(lDevID, MCI_PLAY, MCI_NOTIFY, (DWORD)&mci_play_parms);
}
#include "main/music-definitions-table.h"
+#include <array>
#include <windows.h>
extern bool use_pause_music_inactive;
errr play_music_scene(int val);
void pause_music(void);
void resume_music(void);
-void on_mci_notify(WPARAM wFlags, LONG lDevID);
+void set_music_volume(int volume);
+void on_mci_notify(WPARAM wFlags, LONG lDevID, int volume);
+
+/*! 音量 100%,90%,…,10% それぞれに割り当てる実際の値(音量の指定可能範囲:0~1000) */
+constexpr std::array<int, 10> VOLUME_TABLE = { { 1000, 800, 600, 450, 350, 250, 170, 100, 50, 20 } };
}
* @brief Windows版固有実装(効果音)
*/
+#define NOMINMAX
+
#include "main-win/main-win-sound.h"
#include "main-win/main-win-cfg-reader.h"
#include "main-win/main-win-define.h"
std::queue<sound_res *> sound_queue;
/*!
+ * @brief PCMデータの振幅を変調する
+ *
+ * 引数で与えられたPCMデータの振幅を mult/div 倍に変調する。
+ * PCMデータのサンプリングビット数は bits_per_sample 引数で指定する。
+ * 変調した値がサンプリングビット数で表現可能な範囲に収まらない場合は表現可能な範囲の最大値/最小値に制限する。
+ * サンプリングビット数で有効なのは 8 か 16 のみであり、それ以外の値が指定された場合はなにも行わない。
+ *
+ * @param bits_per_sample PCMデータのサンプリングビット数 (8 or 16)
+ * @param pcm_buf PCMデータバッファ領域へのポインタ
+ * @param bufsize PCMデータバッファ領域のサイズ
+ * @param mult 振幅変調倍率 mult/div の mult
+ * @param div 振幅変調倍率 mult/div の div
+ */
+static void modulate_amplitude(int bits_per_sample, BYTE *pcm_buf, size_t bufsize, int mult, int div)
+{
+ auto modulate = [mult, div](auto sample) {
+ using sample_t = decltype(sample);
+ constexpr auto min = std::numeric_limits<sample_t>::min();
+ constexpr auto max = std::numeric_limits<sample_t>::max();
+ const auto modulated_sample = std::clamp<int>(sample * mult / div, min, max);
+ return static_cast<sample_t>(modulated_sample);
+ };
+
+ switch (bits_per_sample) {
+ case 8:
+ for (auto i = 0U; i < bufsize; ++i) {
+ pcm_buf[i] = modulate(pcm_buf[i]);
+ }
+ break;
+
+ case 16:
+ for (auto i = 0U; i < bufsize; i += 2) {
+ const auto sample = static_cast<int16_t>((static_cast<uint16_t>(pcm_buf[i + 1]) << 8) | static_cast<uint16_t>(pcm_buf[i]));
+ const auto modulated_sample = modulate(sample);
+ pcm_buf[i + 1] = static_cast<uint16_t>(modulated_sample) >> 8;
+ pcm_buf[i] = static_cast<uint16_t>(modulated_sample) & 0xFF;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*!
* 効果音の再生と管理キューへの追加.
*
* @param wf WAVEFORMATEXへのポインタ
* @retval true 正常に処理された
* @retval false 処理エラー
*/
-static bool add_sound_queue(const WAVEFORMATEX *wf, BYTE *buf, DWORD bufsize)
+static bool add_sound_queue(const WAVEFORMATEX *wf, BYTE *buf, DWORD bufsize, int volume)
{
// 再生完了データをキューから削除する
while (!sound_queue.empty()) {
return false;
}
+ modulate_amplitude(wf->wBitsPerSample, buf, bufsize, volume, SOUND_VOLUME_MAX);
+
WAVEHDR *wh = &res->wh;
wh->lpData = (LPSTR)buf;
wh->dwBufferLength = bufsize;
* @retval true 正常に処理された
* @retval false 処理エラー
*/
-static bool play_sound_impl(char *filename)
+static bool play_sound_impl(char *filename, int volume)
{
wav_reader reader;
if (!reader.open(filename)) {
return false;
}
- return add_sound_queue(wf, data_buffer, reader.get_data_chunk()->cksize);
+ return add_sound_queue(wf, data_buffer, reader.get_data_chunk()->cksize, volume);
}
/*!
* @retval 1 設定なし
* @retval -1 PlaySoundの戻り値が正常終了以外
*/
-errr play_sound(int val)
+errr play_sound(int val, int volume)
{
concptr filename = sound_cfg_data->get_rand(TERM_XTRA_SOUND, val);
if (!filename) {
char buf[MAIN_WIN_MAX_PATH];
path_build(buf, MAIN_WIN_MAX_PATH, ANGBAND_DIR_XTRA_SOUND, filename);
- if (play_sound_impl(buf)) {
+ if (play_sound_impl(buf, volume)) {
return 0;
}
#include "main-win/main-win-cfg-reader.h"
#include "system/h-type.h"
+#include <array>
extern concptr ANGBAND_DIR_XTRA_SOUND;
extern CfgData *sound_cfg_data;
void load_sound_prefs(void);
void finalize_sound(void);
-errr play_sound(int val);
+errr play_sound(int val, int volume);
+
+/*! 音量 100%,90%,…,10% それぞれに割り当てる実際の値(効果音の音声データの振幅を volume/SOUND_VOLUME_MAX 倍する) */
+constexpr std::array<int, 10> SOUND_VOLUME_TABLE = { { 1000, 800, 600, 450, 350, 250, 170, 100, 50, 20 } };
+constexpr auto SOUND_VOLUME_MAX = SOUND_VOLUME_TABLE.front();