@@ -146,6 +146,9 @@ const struct mixeng_volume nominal_volume = {
.r = 1ULL << 32,
.l = 1ULL << 32,
#endif
+ .db_known = false,
+ .r_db = 0,
+ .l_db = 0
};
#ifdef AUDIO_IS_FLAWLESS_AND_NO_CHECKS_ARE_REQURIED
@@ -2089,7 +2092,8 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
}
}
-void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol)
+void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol,
+ bool db_known, double lvol_db, double rvol_db)
{
if (sw) {
HWVoiceOut *hw = sw->hw;
@@ -2097,6 +2101,9 @@ void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol)
sw->vol.mute = mute;
sw->vol.l = nominal_volume.l * lvol / 255;
sw->vol.r = nominal_volume.r * rvol / 255;
+ sw->vol.db_known = db_known;
+ sw->vol.l_db = lvol_db;
+ sw->vol.r_db = rvol_db;
if (hw->pcm_ops->ctl_out) {
hw->pcm_ops->ctl_out (hw, VOICE_VOLUME, sw);
@@ -2104,7 +2111,8 @@ void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol)
}
}
-void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol)
+void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol,
+ bool db_known, double lvol_db, double rvol_db)
{
if (sw) {
HWVoiceIn *hw = sw->hw;
@@ -2112,6 +2120,9 @@ void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol)
sw->vol.mute = mute;
sw->vol.l = nominal_volume.l * lvol / 255;
sw->vol.r = nominal_volume.r * rvol / 255;
+ sw->vol.db_known = db_known;
+ sw->vol.l_db = lvol_db;
+ sw->vol.r_db = rvol_db;
if (hw->pcm_ops->ctl_in) {
hw->pcm_ops->ctl_in (hw, VOICE_VOLUME, sw);
@@ -117,8 +117,10 @@ int AUD_is_active_out (SWVoiceOut *sw);
void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
-void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol);
-void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol);
+void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol,
+ bool db_known, double lvol_db, double rvol_db);
+void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol,
+ bool db_known, double lvol_db, double rvol_db);
SWVoiceIn *AUD_open_in (
QEMUSoundCard *card,
@@ -27,10 +27,12 @@
#ifdef FLOAT_MIXENG
typedef float mixeng_real;
-struct mixeng_volume { int mute; mixeng_real r; mixeng_real l; };
+struct mixeng_volume { int mute; mixeng_real r; mixeng_real l;
+ bool db_known; double r_db; double l_db; };
struct st_sample { mixeng_real l; mixeng_real r; };
#else
-struct mixeng_volume { int mute; int64_t r; int64_t l; };
+struct mixeng_volume { int mute; int64_t r; int64_t l;
+ bool db_known; double r_db; double l_db;};
struct st_sample { int64_t l; int64_t r; };
#endif
@@ -470,7 +470,7 @@ static void update_combined_volume_out (AC97LinkState *s)
lvol = (lvol * plvol) / 255;
rvol = (rvol * prvol) / 255;
- AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
+ AUD_set_volume_out (s->voice_po, mute, lvol, rvol, false, 0, 0);
}
static void update_volume_in (AC97LinkState *s)
@@ -481,7 +481,7 @@ static void update_volume_in (AC97LinkState *s)
get_volume (mixer_load (s, AC97_Record_Gain_Mute), 0x0f, 0,
&mute, &lvol, &rvol);
- AUD_set_volume_in (s->voice_pi, mute, lvol, rvol);
+ AUD_set_volume_in (s->voice_pi, mute, lvol, rvol, false, 0, 0);
}
static void set_volume (AC97LinkState *s, int index, uint32_t val)
@@ -32,7 +32,7 @@
(AC_AMPCAP_MUTE | \
(QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT) | \
(QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) | \
- (3 << AC_AMPCAP_STEP_SIZE_SHIFT))
+ (QEMU_HDA_AMP_STEP_SIZE << AC_AMPCAP_STEP_SIZE_SHIFT))
#else
#define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x11)
#define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x21)
@@ -119,6 +119,8 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
0x1fc /* 16 -> 96 kHz */)
#define QEMU_HDA_AMP_NONE (0)
#define QEMU_HDA_AMP_STEPS 0x4a
+#define QEMU_HDA_AMP_STEP_SIZE 3
+#define QEMU_HDA_AMP_DB_OF_STEP ((QEMU_HDA_AMP_STEP_SIZE + 1) * 0.25)
#define PARAM mixemu
#define HDA_MIXER
@@ -451,9 +453,11 @@ static void hda_audio_set_amp(HDAAudioStream *st)
return;
}
if (st->output) {
- AUD_set_volume_out(st->voice.out, muted, left, right);
+ AUD_set_volume_out(st->voice.out, muted, left, right,
+ false, 0, 0);
} else {
- AUD_set_volume_in(st->voice.in, muted, left, right);
+ AUD_set_volume_in(st->voice.in, muted, left, right,
+ false, 0, 0);
}
}
@@ -304,7 +304,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque)
&as
);
- AUD_set_volume_out(s->voice, 0, 255, 255);
+ AUD_set_volume_out(s->voice, 0, 255, 255, false, 0, 0);
s->voice_is_active = 0;
@@ -144,30 +144,36 @@ static void wm8750_vol_update(WM8750State *s)
AUD_set_volume_in(s->adc_voice[0], s->mute,
s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
- s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
+ s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]),
+ false, 0, 0);
AUD_set_volume_in(s->adc_voice[1], s->mute,
s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
- s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
+ s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]),
+ false, 0, 0);
AUD_set_volume_in(s->adc_voice[2], s->mute,
s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]),
- s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]));
+ s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1]),
+ false, 0, 0);
/* FIXME: multiply all volumes by s->outvol[0], s->outvol[1] */
/* Speaker: LOUT2VOL ROUT2VOL */
AUD_set_volume_out(s->dac_voice[0], s->mute,
s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[4]),
- s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[5]));
+ s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[5]),
+ false, 0, 0);
/* Headphone: LOUT1VOL ROUT1VOL */
AUD_set_volume_out(s->dac_voice[1], s->mute,
s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[2]),
- s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[3]));
+ s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[3]),
+ false, 0, 0);
/* MONOOUT: MONOVOL MONOVOL */
AUD_set_volume_out(s->dac_voice[2], s->mute,
s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]),
- s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]));
+ s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]),
+ false, 0, 0);
}
static void wm8750_set_format(WM8750State *s)
@@ -1271,7 +1271,8 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp)
s,
xlnx_dp_audio_callback,
&as);
- AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255);
+ AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255,
+ false, 0, 0);
xlnx_dp_audio_activate(s);
}
@@ -500,7 +500,8 @@ static int usb_audio_set_control(USBAudioState *s, uint8_t attrib,
s->out.mute, s->out.vol[0], s->out.vol[1]);
}
AUD_set_volume_out(s->out.voice, s->out.mute,
- s->out.vol[0], s->out.vol[1]);
+ s->out.vol[0], s->out.vol[1],
+ false, 0, 0);
}
return ret;
@@ -653,7 +654,8 @@ static void usb_audio_realize(USBDevice *dev, Error **errp)
s->out.voice = AUD_open_out(&s->card, s->out.voice, TYPE_USB_AUDIO,
s, output_callback, &s->out.as);
- AUD_set_volume_out(s->out.voice, s->out.mute, s->out.vol[0], s->out.vol[1]);
+ AUD_set_volume_out(s->out.voice, s->out.mute, s->out.vol[0], s->out.vol[1],
+ false, 0, 0);
AUD_set_active_out(s->out.voice, 0);
}
Signed-off-by: Yaroslav Isakov <yaroslav.isakov@gmail.com> --- audio/audio.c | 15 +++++++++++++-- audio/audio.h | 6 ++++-- audio/mixeng.h | 6 ++++-- hw/audio/ac97.c | 4 ++-- hw/audio/hda-codec-common.h | 2 +- hw/audio/hda-codec.c | 8 ++++++-- hw/audio/lm4549.c | 2 +- hw/audio/wm8750.c | 18 ++++++++++++------ hw/display/xlnx_dp.c | 3 ++- hw/usb/dev-audio.c | 6 ++++-- 10 files changed, 49 insertions(+), 21 deletions(-)