(Audio mixer) Ability to individually set volume per stream

This commit is contained in:
twinaphex 2018-04-30 17:51:01 +02:00
parent 01e85b321b
commit 5aeab54ab7
12 changed files with 180 additions and 21 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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,

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)

View File

@ -20,7 +20,7 @@
#include "menu_cbs.h"
#include "../verbosity.h"
#if 0
#if 1
#define DEBUG_LOG
#endif

View File

@ -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;

View File

@ -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,

View File

@ -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;