diff --git a/src/audio/mixer.cpp b/src/audio/mixer.cpp index d2de4a6f70..21f1ec0b58 100644 --- a/src/audio/mixer.cpp +++ b/src/audio/mixer.cpp @@ -350,6 +350,7 @@ Channel::Channel() stopping = false; source = 0; deletesourceondone = false; + group = MIXER_GROUP_NONE; } Channel::~Channel() @@ -430,6 +431,11 @@ bool Channel::SetOffset(unsigned long offset) return false; } +void Channel::SetGroup(int group) +{ + Channel::group = group; +} + Mixer::Mixer() { effectbuffer = 0; @@ -600,7 +606,6 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) break; } - int volume = channel.volume; uint8* dataconverted = 0; const uint8* tomix = 0; @@ -658,12 +663,16 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) mixlength = length - loaded; } - int startvolume = channel.oldvolume; - int endvolume = channel.volume; + float volumeadjust = (gConfigSound.master_volume / 100.0f); + if (channel.group == MIXER_GROUP_MUSIC) { + volumeadjust *= (gConfigSound.music_volume / 100.0f); + } + int startvolume = (int)(channel.oldvolume * volumeadjust); + int endvolume = (int)(channel.volume * volumeadjust); if (channel.stopping) { endvolume = 0; } - int mixvolume = volume; + int mixvolume = (int)(channel.volume * volumeadjust); if (startvolume != endvolume) { // fade between volume levels to smooth out sound and minimize clicks from sudden volume changes if (!effectbufferloaded) { @@ -836,6 +845,11 @@ int Mixer_Channel_SetOffset(void* channel, unsigned long offset) return ((Channel*)channel)->SetOffset(offset); } +void Mixer_Channel_SetGroup(void* channel, int group) +{ + ((Channel*)channel)->SetGroup(group); +} + void* Mixer_Play_Music(int pathid, int loop, int streaming) { if (streaming) { @@ -854,6 +868,7 @@ void* Mixer_Play_Music(int pathid, int loop, int streaming) if (!channel) { delete source_samplestream; } + channel->SetGroup(MIXER_GROUP_MUSIC); return channel; } else { delete source_samplestream; @@ -861,7 +876,11 @@ void* Mixer_Play_Music(int pathid, int loop, int streaming) } } else { if (gMixer.LoadMusic(pathid)) { - return gMixer.Play(*gMixer.musicsources[pathid], MIXER_LOOP_INFINITE, false, false); + Channel* channel = gMixer.Play(*gMixer.musicsources[pathid], MIXER_LOOP_INFINITE, false, false); + if (channel) { + channel->SetGroup(MIXER_GROUP_MUSIC); + } + return channel; } } return 0; diff --git a/src/audio/mixer.h b/src/audio/mixer.h index b313bde76b..679f7ef0af 100644 --- a/src/audio/mixer.h +++ b/src/audio/mixer.h @@ -29,6 +29,11 @@ #define MIXER_LOOP_NONE 0 #define MIXER_LOOP_INFINITE -1 +enum { + MIXER_GROUP_NONE, + MIXER_GROUP_MUSIC, +}; + #ifdef __cplusplus #include @@ -124,6 +129,7 @@ public: bool IsPlaying(); unsigned long GetOffset(); bool SetOffset(unsigned long offset); + void SetGroup(int group); friend class Mixer; @@ -140,6 +146,7 @@ private: bool deletesourceondone; bool stopping; int oldvolume; + int group; SpeexResamplerState* resampler; Source* source; }; @@ -188,6 +195,7 @@ void Mixer_Channel_Rate(void* channel, double rate); int Mixer_Channel_IsPlaying(void* channel); unsigned long Mixer_Channel_GetOffset(void* channel); int Mixer_Channel_SetOffset(void* channel, unsigned long offset); +void Mixer_Channel_SetGroup(void* channel, int group); void* Mixer_Play_Music(int pathid, int loop, int streaming); static int DStoMixerVolume(int volume) { return (int)(SDL_MIX_MAXVOLUME * (SDL_pow(10, (float)volume / 2000))); }; diff --git a/src/config.c b/src/config.c index a7157668b7..1a6986dec7 100644 --- a/src/config.c +++ b/src/config.c @@ -191,6 +191,8 @@ config_property_definition _soundDefinitions[] = { { offsetof(sound_configuration, title_music), "title_music", CONFIG_VALUE_TYPE_UINT8, 2, NULL }, { offsetof(sound_configuration, sound), "sound", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, { offsetof(sound_configuration, ride_music), "ride_music", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(sound_configuration, master_volume), "master_volume", CONFIG_VALUE_TYPE_UINT8, 100, NULL }, + { offsetof(sound_configuration, music_volume), "music_volume", CONFIG_VALUE_TYPE_UINT8, 100, NULL }, }; config_property_definition _cheatDefinitions[] = { diff --git a/src/config.h b/src/config.h index 7765f6b3ad..4007453576 100644 --- a/src/config.h +++ b/src/config.h @@ -156,6 +156,8 @@ typedef struct { uint8 title_music; uint8 sound; uint8 ride_music; + uint8 master_volume; + uint8 music_volume; } sound_configuration; typedef struct { diff --git a/src/peep/peep.c b/src/peep/peep.c index 1b0a053f9d..eb9f257a9c 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -4578,6 +4578,9 @@ void peep_update_crowd_noise() #ifdef USE_MIXER if (!gCrowdSoundChannel) { gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2, MIXER_LOOP_INFINITE, false); + if (gCrowdSoundChannel) { + Mixer_Channel_SetGroup(gCrowdSoundChannel, MIXER_GROUP_NONE); + } } if (gCrowdSoundChannel) { Mixer_Channel_Volume(gCrowdSoundChannel, DStoMixerVolume(volume)); diff --git a/src/platform/shared.c b/src/platform/shared.c index 7b40e019fa..28f0f42914 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -187,11 +187,11 @@ void platform_draw() uint32 *dst = pixels; for (int i = width * height; i > 0; i--) *(dst++) = *(uint32 *)(&gPaletteHWMapped[*src++]); } else - if (((pitch == width * 2) + 3) & ~3) { + if (pitch == (((width * 2) + 3) & ~3)) { uint16 *dst = pixels; for (int i = width * height; i > 0; i--) *(dst++) = *(uint16 *)(&gPaletteHWMapped[*src++]); } else - if (((pitch == width) + 3) & ~3) { + if (pitch == (((width) + 3) & ~3)) { uint8 *dst = pixels; for (int i = width * height; i > 0; i--) *(dst++) = *(uint8 *)(&gPaletteHWMapped[*src++]); } diff --git a/src/windows/options.c b/src/windows/options.c index 7354337362..91d4e2cc84 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -26,6 +26,7 @@ * Padding between the widgets and the window needs reducing, an artifact from originally being inside group boxes. */ +#include #include "../addresses.h" #include "../audio/audio.h" #include "../audio/mixer.h" @@ -102,6 +103,8 @@ enum WINDOW_OPTIONS_WIDGET_IDX { WIDX_MUSIC_CHECKBOX, WIDX_TITLE_MUSIC, WIDX_TITLE_MUSIC_DROPDOWN, + WIDX_MASTER_VOLUME, + WIDX_MUSIC_VOLUME, // Controls WIDX_SCREEN_EDGE_SCROLLING = WIDX_PAGE_START, @@ -185,6 +188,8 @@ static rct_widget window_options_audio_widgets[] = { { WWT_CHECKBOX, 1, 10, 229, 84, 95, STR_MUSIC, STR_NONE }, // enable / disable music { WWT_DROPDOWN, 1, 155, 299, 98, 109, STR_NONE, STR_NONE }, // title music { WWT_DROPDOWN_BUTTON, 1, 288, 298, 99, 108, 876, STR_NONE }, + { WWT_SCROLL, 1, 155, 299, 68, 80, 1, STR_NONE }, // master volume + { WWT_SCROLL, 1, 155, 299, 83, 95, 1, STR_NONE }, // music volume { WIDGETS_END }, }; @@ -252,6 +257,7 @@ static void window_options_dropdown(); static void window_options_update(rct_window *w); static void window_options_invalidate(); static void window_options_paint(); +static void window_options_scrollgetsize(); static void window_options_text_input(); static void* window_options_events[] = { @@ -270,7 +276,7 @@ static void* window_options_events[] = { window_options_emptysub, window_options_emptysub, window_options_emptysub, - window_options_emptysub, + window_options_scrollgetsize, window_options_emptysub, window_options_emptysub, window_options_emptysub, @@ -931,6 +937,7 @@ static void window_options_dropdown() static void window_options_invalidate() { rct_window *w; + rct_widget* widget; sint32 currentSoundDevice; window_get_register(w); @@ -1027,12 +1034,24 @@ static void window_options_invalidate() widget_set_checkbox_value(w, WIDX_SOUND_CHECKBOX, gConfigSound.sound); widget_set_checkbox_value(w, WIDX_MUSIC_CHECKBOX, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8)); + if(w->frame_no == 0){ // initialize only on first frame, otherwise the scrollbars wont be able to be modified + widget = &window_options_audio_widgets[WIDX_MASTER_VOLUME]; + w->scrolls[0].h_left = (sint16)ceil((gConfigSound.master_volume / 100.0f) * (w->scrolls[0].h_right - ((widget->right - widget->left) - 1))); + widget = &window_options_audio_widgets[WIDX_MUSIC_VOLUME]; + w->scrolls[1].h_left = (sint16)ceil((gConfigSound.music_volume / 100.0f) * (w->scrolls[1].h_right - ((widget->right - widget->left) - 1))); + } + + widget_scroll_update_thumbs(w, WIDX_MASTER_VOLUME); + widget_scroll_update_thumbs(w, WIDX_MUSIC_VOLUME); + window_options_audio_widgets[WIDX_SOUND].type = WWT_DROPDOWN; window_options_audio_widgets[WIDX_SOUND_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_options_audio_widgets[WIDX_SOUND_CHECKBOX].type = WWT_CHECKBOX; window_options_audio_widgets[WIDX_MUSIC_CHECKBOX].type = WWT_CHECKBOX; window_options_audio_widgets[WIDX_TITLE_MUSIC].type = WWT_DROPDOWN; window_options_audio_widgets[WIDX_TITLE_MUSIC_DROPDOWN].type = WWT_DROPDOWN_BUTTON; + window_options_audio_widgets[WIDX_MASTER_VOLUME].type = WWT_SCROLL; + window_options_audio_widgets[WIDX_MUSIC_VOLUME].type = WWT_SCROLL; break; case WINDOW_OPTIONS_PAGE_CONTROLS: @@ -1096,6 +1115,24 @@ static void window_options_update(rct_window *w) // Tab animation w->frame_no++; widget_invalidate(w, WIDX_TAB_1 + w->page); + + rct_widget *widget; + if (w->page == WINDOW_OPTIONS_PAGE_AUDIO) { + widget = &window_options_audio_widgets[WIDX_MASTER_VOLUME]; + uint8 master_volume = (uint8)(((float)w->scrolls[0].h_left / (w->scrolls[0].h_right - ((widget->right - widget->left) - 1))) * 100); + widget = &window_options_audio_widgets[WIDX_MUSIC_VOLUME]; + uint8 music_volume = (uint8)(((float)w->scrolls[1].h_left / (w->scrolls[1].h_right - ((widget->right - widget->left) - 1))) * 100); + if (master_volume != gConfigSound.master_volume) { + gConfigSound.master_volume = master_volume; + config_save_default(); + } + if (music_volume != gConfigSound.music_volume) { + gConfigSound.music_volume = music_volume; + config_save_default(); + } + widget_invalidate(w, WIDX_MASTER_VOLUME); + widget_invalidate(w, WIDX_MUSIC_VOLUME); + } } /** @@ -1201,6 +1238,20 @@ static void window_options_update_height_markers() gfx_invalidate_screen(); } +static void window_options_scrollgetsize() +{ + rct_window *w; + short scrollIndex; + + window_scroll_get_registers(w, scrollIndex); + + if (w->page == WINDOW_OPTIONS_PAGE_AUDIO) { + int width = 1000; + int height = 0; + window_scrollsize_set_registers(width, height); + } +} + static void window_options_text_input(){ short widgetIndex; rct_window *w;