void mixer_setvolume(mixer_t *mixer, float l, float r) { ao_control_vol_t vol; vol.right=r; vol.left=l; if(mixer->audio_out){ if(soft_vol || CONTROL_OK != mixer->audio_out->control(AOCONTROL_SET_VOLUME,&vol)) { if (!mixer->afilter) return; else { // af_volume uses values in dB float db_vals[AF_NCH]; int i; db_vals[0] = (l / 100.0) * (soft_vol_max / 100.0); db_vals[1] = (r / 100.0) * (soft_vol_max / 100.0); for (i = 2; i < AF_NCH; i++) { db_vals[i] = ((l + r) / 100.0) * (soft_vol_max / 100.0) / 2.0; } af_to_dB (AF_NCH, db_vals, db_vals, 20.0); if (!af_control_any_rev(mixer->afilter, AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) { mp_msg(MSGT_GLOBAL, MSGL_INFO, MSGTR_InsertingAfVolume); if (af_add(mixer->afilter, "volume")) { if (!af_control_any_rev(mixer->afilter, AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) { mp_msg(MSGT_GLOBAL, MSGL_ERR, MSGTR_NoVolume); return; } } } } } } mixer->muted=0; }
void mixer_setbalance(mixer_t *mixer, float val) { float level[AF_NCH]; int i; af_control_ext_t arg_ext = { .arg = level }; af_instance_t* af_pan_balance; if(!mixer->afilter) return; if (af_control_any_rev(mixer->afilter, AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val)) return; if (!(af_pan_balance = af_add(mixer->afilter, "pan"))) { mp_msg(MSGT_GLOBAL, MSGL_ERR, MSGTR_NoBalance); return; } af_init(mixer->afilter); /* make all other channels pass thru since by default pan blocks all */ memset(level, 0, sizeof(level)); for (i = 2; i < AF_NCH; i++) { arg_ext.ch = i; level[i] = 1.f; af_pan_balance->control(af_pan_balance, AF_CONTROL_PAN_LEVEL | AF_CONTROL_SET, &arg_ext); level[i] = 0.f; } af_pan_balance->control(af_pan_balance, AF_CONTROL_PAN_BALANCE | AF_CONTROL_SET, &val); }
static int try_filter(struct MPContext *mpctx, char *name, char *label, char **args) { struct dec_audio *d_audio = mpctx->d_audio; if (af_find_by_label(d_audio->afilter, label)) return 0; struct af_instance *af = af_add(d_audio->afilter, name, args); if (!af) return -1; af->label = talloc_strdup(af, label); return 1; }
static void setvolume_internal(mixer_t *mixer, float l, float r) { struct ao_control_vol vol = {.left = l, .right = r}; if (!mixer->softvol) { // relies on the driver data being permanent (so ptr stays valid) mixer->restore_volume = mixer->ao->no_persistent_volume ? mixer->ao->driver->info->short_name : NULL; if (ao_control(mixer->ao, AOCONTROL_SET_VOLUME, &vol) != CONTROL_OK) mp_tmsg(MSGT_GLOBAL, MSGL_ERR, "[Mixer] Failed to change audio output volume.\n"); return; } mixer->restore_volume = "softvol"; if (!mixer->afilter) return; // af_volume uses values in dB float db_vals[AF_NCH]; int i; db_vals[0] = (l / 100.0) * (mixer->softvol_max / 100.0); db_vals[1] = (r / 100.0) * (mixer->softvol_max / 100.0); for (i = 2; i < AF_NCH; i++) db_vals[i] = ((l + r) / 100.0) * (mixer->softvol_max / 100.0) / 2.0; af_to_dB(AF_NCH, db_vals, db_vals, 20.0); if (!af_control_any_rev(mixer->afilter, AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals)) { mp_tmsg(MSGT_GLOBAL, mixer->softvol ? MSGL_V : MSGL_WARN, "[Mixer] No hardware mixing, inserting volume filter.\n"); if (!(af_add(mixer->afilter, "volume") && af_control_any_rev(mixer->afilter, AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals))) mp_tmsg(MSGT_GLOBAL, MSGL_ERR, "[Mixer] No volume control available.\n"); } }