diff --git a/audio/audio_driver.c b/audio/audio_driver.c index 1daab6cf50..dfa853cfa1 100644 --- a/audio/audio_driver.c +++ b/audio/audio_driver.c @@ -45,6 +45,16 @@ #define AUDIO_BUFFER_FREE_SAMPLES_COUNT (8 * 1024) +/** + * db_to_gain: + * @db : Decibels. + * + * Converts decibels to voltage gain. + * + * Returns: voltage gain value. + **/ +#define db_to_gain(db) (powf(10.0f, (db) / 20.0f)) + static const audio_driver_t *audio_drivers[] = { #ifdef HAVE_ALSA &audio_alsa, @@ -361,6 +371,12 @@ static bool audio_driver_deinit_internal(void) return true; } +static void audio_driver_mixer_init(unsigned out_rate) +{ + audio_mixer_init(out_rate); +} + + static bool audio_driver_init_internal(bool audio_cb_inited) { unsigned new_rate = 0; @@ -527,7 +543,7 @@ static bool audio_driver_init_internal(bool audio_cb_inited) audio_driver_free_samples_count = 0; - audio_mixer_init(settings->uints.audio_out_rate); + audio_driver_mixer_init(settings->uints.audio_out_rate); /* Threaded driver is initially stopped. */ if ( @@ -665,7 +681,7 @@ static void audio_driver_flush(const int16_t *data, size_t samples) if (audio_mixer_active) { bool override = audio_driver_mixer_mute_enable ? true : - (audio_driver_mixer_volume_gain != 0.0f) ? true : false; + (audio_driver_mixer_volume_gain != 1.0f) ? true : false; float mixer_gain = !audio_driver_mixer_mute_enable ? audio_driver_mixer_volume_gain : 0.0f; audio_mixer_mix(audio_driver_output_samples_buf, @@ -1071,7 +1087,7 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params) audio_mixer_stop_cb_t stop_cb = audio_mixer_play_stop_cb; bool looped = false; void *buf = NULL; - + if (!audio_driver_mixer_get_free_stream_slot(&free_slot)) return false; @@ -1157,7 +1173,7 @@ static void audio_driver_mixer_play_stream_internal(unsigned i, bool looped) switch (audio_mixer_streams[i].state) { case AUDIO_STREAM_STATE_STOPPED: - audio_mixer_streams[i].voice = audio_mixer_play(audio_mixer_streams[i].handle, looped, audio_mixer_streams[i].volume, audio_mixer_streams[i].stop_cb); + audio_mixer_streams[i].voice = audio_mixer_play(audio_mixer_streams[i].handle, looped, 1.0f, audio_mixer_streams[i].stop_cb); set_state = true; break; case AUDIO_STREAM_STATE_PLAYING: @@ -1180,6 +1196,29 @@ void audio_driver_mixer_play_stream_looped(unsigned i) audio_driver_mixer_play_stream_internal(i, true); } +float audio_driver_mixer_get_stream_volume(unsigned i) +{ + if (i >= AUDIO_MIXER_MAX_STREAMS) + return 0.0f; + + return audio_mixer_streams[i].volume; +} + +void audio_driver_mixer_set_stream_volume(unsigned i, float vol) +{ + audio_mixer_voice_t *voice = NULL; + + if (i >= AUDIO_MIXER_MAX_STREAMS) + return; + + audio_mixer_streams[i].volume = vol; + + voice = audio_mixer_streams[i].voice; + + if (voice) + audio_mixer_voice_set_volume(voice, db_to_gain(vol)); +} + void audio_driver_mixer_stop_stream(unsigned i) { bool set_state = false; @@ -1205,6 +1244,7 @@ void audio_driver_mixer_stop_stream(unsigned i) if (voice) audio_mixer_stop(voice); audio_mixer_streams[i].state = AUDIO_STREAM_STATE_STOPPED; + audio_mixer_streams[i].volume = 1.0f; } } @@ -1235,8 +1275,8 @@ void audio_driver_mixer_remove_stream(unsigned i) if (handle) audio_mixer_destroy(handle); audio_mixer_streams[i].state = AUDIO_STREAM_STATE_NONE; - audio_mixer_streams[i].volume = 0.0f; audio_mixer_streams[i].stop_cb = NULL; + audio_mixer_streams[i].volume = 0.0f; audio_mixer_streams[i].handle = NULL; audio_mixer_streams[i].voice = NULL; } @@ -1452,15 +1492,6 @@ void audio_set_bool(enum audio_action action, bool val) } } -/** - * db_to_gain: - * @db : Decibels. - * - * Converts decibels to voltage gain. - * - * Returns: voltage gain value. - **/ -#define db_to_gain(db) (powf(10.0f, (db) / 20.0f)) void audio_set_float(enum audio_action action, float val) { diff --git a/audio/audio_driver.h b/audio/audio_driver.h index 0b3f991e4c..440e563ba1 100644 --- a/audio/audio_driver.h +++ b/audio/audio_driver.h @@ -296,6 +296,10 @@ void audio_driver_mixer_play_stream_looped(unsigned i); void audio_driver_mixer_stop_stream(unsigned i); +float audio_driver_mixer_get_stream_volume(unsigned i); + +void audio_driver_mixer_set_stream_volume(unsigned i, float vol); + void audio_driver_mixer_remove_stream(unsigned i); enum resampler_quality audio_driver_get_resampler_quality(void); diff --git a/libretro-common/audio/audio_mixer.c b/libretro-common/audio/audio_mixer.c index d7a99a4dec..685e4f8716 100644 --- a/libretro-common/audio/audio_mixer.c +++ b/libretro-common/audio/audio_mixer.c @@ -1236,3 +1236,19 @@ void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bo *sample = 1.0f; } } + +float audio_mixer_voice_get_volume(audio_mixer_voice_t *voice) +{ + if (!voice) + return 0.0f; + + return voice->volume; +} + +void audio_mixer_voice_set_volume(audio_mixer_voice_t *voice, float val) +{ + if (!voice) + return; + + voice->volume = val; +} diff --git a/libretro-common/include/audio/audio_mixer.h b/libretro-common/include/audio/audio_mixer.h index a9c588372e..bb8d35d0c7 100644 --- a/libretro-common/include/audio/audio_mixer.h +++ b/libretro-common/include/audio/audio_mixer.h @@ -73,6 +73,10 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, void audio_mixer_stop(audio_mixer_voice_t* voice); +float audio_mixer_voice_get_volume(audio_mixer_voice_t *voice); + +void audio_mixer_voice_set_volume(audio_mixer_voice_t *voice, float val); + void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bool override); RETRO_END_DECLS diff --git a/menu/cbs/menu_cbs_get_value.c b/menu/cbs/menu_cbs_get_value.c index 45827cc6da..a015d5ec39 100644 --- a/menu/cbs/menu_cbs_get_value.c +++ b/menu/cbs/menu_cbs_get_value.c @@ -31,6 +31,7 @@ #include "../../tasks/tasks_internal.h" #include "../../input/input_driver.h" +#include "../../audio/audio_driver.h" #include "../../core.h" #include "../../core_info.h" #include "../../configuration.h" @@ -56,6 +57,26 @@ extern struct key_desc key_descriptors[RARCH_MAX_KEYS]; +static void menu_action_setting_audio_mixer_stream_volume( + file_list_t* list, + unsigned *w, unsigned type, unsigned i, + const char *label, + char *s, size_t len, + const char *entry_label, + const char *path, + char *s2, size_t len2) +{ + unsigned offset = (type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN); + + *w = 19; + strlcpy(s2, path, len2); + + if (offset >= AUDIO_MIXER_MAX_STREAMS) + return; + + snprintf(s, len, "%.2f dB", audio_driver_mixer_get_stream_volume(offset)); +} + static void menu_action_setting_disp_set_label_cheat_num_passes( file_list_t* list, unsigned *w, unsigned type, unsigned i, @@ -2094,7 +2115,13 @@ static int menu_cbs_init_bind_get_string_representation_compare_label( static int menu_cbs_init_bind_get_string_representation_compare_type( menu_file_list_cbs_t *cbs, unsigned type) { - if (type >= MENU_SETTINGS_INPUT_DESC_BEGIN + if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END) + { + BIND_ACTION_GET_VALUE(cbs, + menu_action_setting_audio_mixer_stream_volume); + } + else if (type >= MENU_SETTINGS_INPUT_DESC_BEGIN && type <= MENU_SETTINGS_INPUT_DESC_END) { BIND_ACTION_GET_VALUE(cbs, diff --git a/menu/cbs/menu_cbs_left.c b/menu/cbs/menu_cbs_left.c index c39289f671..ecd86c7d0c 100644 --- a/menu/cbs/menu_cbs_left.c +++ b/menu/cbs/menu_cbs_left.c @@ -333,6 +333,23 @@ static int shader_action_parameter_left(unsigned type, const char *label, bool w return ret; } +static int audio_mixer_stream_volume_left(unsigned type, const char *label, + bool wraparound) +{ + unsigned offset = (type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN); + float orig_volume = 0.0f; + + if (offset >= AUDIO_MIXER_MAX_STREAMS) + return 0; + + orig_volume = audio_driver_mixer_get_stream_volume(offset); + orig_volume = orig_volume - 1.00f; + + audio_driver_mixer_set_stream_volume(offset, orig_volume); + + return 0; +} + static int action_left_cheat(unsigned type, const char *label, bool wraparound) { @@ -865,6 +882,11 @@ static int menu_cbs_init_bind_left_compare_type(menu_file_list_cbs_t *cbs, { BIND_ACTION_LEFT(cbs, action_left_cheat); } + else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END) + { + BIND_ACTION_LEFT(cbs, audio_mixer_stream_volume_left); + } else if (type >= MENU_SETTINGS_SHADER_PARAMETER_0 && type <= MENU_SETTINGS_SHADER_PARAMETER_LAST) { diff --git a/menu/cbs/menu_cbs_right.c b/menu/cbs/menu_cbs_right.c index 82b287240e..decb95bed4 100644 --- a/menu/cbs/menu_cbs_right.c +++ b/menu/cbs/menu_cbs_right.c @@ -30,6 +30,7 @@ #include "../menu_setting.h" #include "../menu_shader.h" +#include "../../audio/audio_driver.h" #include "../../configuration.h" #include "../../core.h" #include "../../core_info.h" @@ -204,6 +205,24 @@ static int action_right_scroll(unsigned type, const char *label, return 0; } +static int audio_mixer_stream_volume_right(unsigned type, const char *label, + bool wraparound) +{ + unsigned offset = (type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN); + float orig_volume = 0.0f; + + if (offset >= AUDIO_MIXER_MAX_STREAMS) + return 0; + + orig_volume = audio_driver_mixer_get_stream_volume(offset); + orig_volume = orig_volume + 1.00f; + + audio_driver_mixer_set_stream_volume(offset, orig_volume); + + return 0; +} + + static int action_right_goto_tab(void) { menu_ctx_list_t list_info; @@ -483,6 +502,11 @@ static int menu_cbs_init_bind_right_compare_type(menu_file_list_cbs_t *cbs, { BIND_ACTION_RIGHT(cbs, action_right_cheat); } + else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END) + { + BIND_ACTION_RIGHT(cbs, audio_mixer_stream_volume_right); + } else if (type >= MENU_SETTINGS_SHADER_PARAMETER_0 && type <= MENU_SETTINGS_SHADER_PARAMETER_LAST) { diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index 4564ecdf8a..7917cc9b0d 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -28,6 +28,7 @@ #include "../menu_setting.h" #include "../menu_shader.h" +#include "../../audio/audio_driver.h" #include "../../configuration.h" #include "../../core.h" #include "../../core_info.h" @@ -49,6 +50,18 @@ cbs->action_start_ident = #name; #endif +static int action_start_audio_mixer_stream_volume(unsigned type, const char *label) +{ + unsigned offset = (type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN); + + if (offset >= AUDIO_MIXER_MAX_STREAMS) + return 0; + + audio_driver_mixer_set_stream_volume(offset, 1.0f); + + return 0; +} + static int action_start_remap_file_load(unsigned type, const char *label) { input_remapping_set_defaults(true); @@ -369,6 +382,13 @@ int menu_cbs_init_bind_start(menu_file_list_cbs_t *cbs, if (!cbs) return -1; + if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END) + { + BIND_ACTION_START(cbs, action_start_audio_mixer_stream_volume); + return 0; + } + BIND_ACTION_START(cbs, action_start_lookup_setting); if (menu_cbs_init_bind_start_compare_label(cbs) == 0) diff --git a/menu/menu_cbs.c b/menu/menu_cbs.c index 33d4b5a01e..957dc6068a 100644 --- a/menu/menu_cbs.c +++ b/menu/menu_cbs.c @@ -20,7 +20,7 @@ #include "menu_cbs.h" #include "../verbosity.h" -#if 0 +#if 1 #define DEBUG_LOG #endif diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index d9e8a5fd1d..3cd2b6f2dc 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -4265,10 +4265,13 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) char lbl_play_looped[128]; char lbl_remove[128]; char lbl_stop[128]; + char lbl_volume[128]; unsigned id = info->type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_BEGIN; lbl_remove[0] = lbl_stop[0] = lbl_play[0] = lbl_play_looped[0] = '\0'; + lbl_volume[0] = '\0'; + snprintf(lbl_volume, sizeof(lbl_volume), "mixer_stream_%d_action_volume", id); snprintf(lbl_stop, sizeof(lbl_stop), "mixer_stream_%d_action_stop", id); snprintf(lbl_remove, sizeof(lbl_remove), "mixer_stream_%d_action_remove", id); snprintf(lbl_play, sizeof(lbl_play), "mixer_stream_%d_action_play", id); @@ -4298,6 +4301,12 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) MSG_UNKNOWN, (MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_BEGIN + id), 0, 0); + menu_entries_append_enum(info->list, + "Volume", + lbl_volume, + MSG_UNKNOWN, + (MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + id), + 0, 0); } info->need_push = true; diff --git a/menu/menu_driver.h b/menu/menu_driver.h index d31d08b56b..c9286ede6b 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -201,6 +201,8 @@ enum menu_settings_type MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_BEGIN + 7, MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN, MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN + 7, + MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN, + MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + 7, MENU_SETTINGS_BIND_BEGIN, MENU_SETTINGS_BIND_LAST = MENU_SETTINGS_BIND_BEGIN + RARCH_ANALOG_RIGHT_Y_MINUS, MENU_SETTINGS_BIND_ALL_LAST = MENU_SETTINGS_BIND_BEGIN + RARCH_MENU_TOGGLE, diff --git a/tasks/task_audio_mixer.c b/tasks/task_audio_mixer.c index 9ba7b6ad64..69772849fe 100644 --- a/tasks/task_audio_mixer.c +++ b/tasks/task_audio_mixer.c @@ -89,7 +89,7 @@ static void task_audio_mixer_handle_upload_ogg(void *task_data, if (!img) return; - params.volume = 0.0f; + params.volume = 1.0f; params.type = AUDIO_MIXER_TYPE_OGG; params.state = AUDIO_STREAM_STATE_PLAYING; params.buf = img->buf; @@ -111,7 +111,7 @@ static void task_audio_mixer_handle_upload_flac(void *task_data, if (!img) return; - params.volume = 0.0f; + params.volume = 1.0f; params.type = AUDIO_MIXER_TYPE_FLAC; params.state = AUDIO_STREAM_STATE_PLAYING; params.buf = img->buf; @@ -133,7 +133,7 @@ static void task_audio_mixer_handle_upload_mp3(void *task_data, if (!img) return; - params.volume = 0.0f; + params.volume = 1.0f; params.type = AUDIO_MIXER_TYPE_MP3; params.state = AUDIO_STREAM_STATE_PLAYING; params.buf = img->buf; @@ -155,7 +155,7 @@ static void task_audio_mixer_handle_upload_mod(void *task_data, if (!img) return; - params.volume = 0.0f; + params.volume = 1.0f; params.type = AUDIO_MIXER_TYPE_MOD; params.state = AUDIO_STREAM_STATE_PLAYING; params.buf = img->buf; @@ -177,7 +177,7 @@ static void task_audio_mixer_handle_upload_wav(void *task_data, if (!img) return; - params.volume = 0.0f; + params.volume = 1.0f; params.type = AUDIO_MIXER_TYPE_WAV; params.state = AUDIO_STREAM_STATE_PLAYING; params.buf = img->buf;