hw/audio/hda-codec.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
According Intel's High Definition Audio Specification (Revision 1.0a,
Section 7.3.4.10: Amplifier Capabilities), the amplifier gain levels
should be evenly spaced in dB, i.e. using a log scale instead of linear.
Here, the hda-codec reports amplifier levels from 0 to -48 dB at 1-dB
steps matching the 8-bit dynamic range, and the -49 dB level is mapped
to 0 (muted).
Signed-off-by: Yuanqing Li <liyq.yuanqing@outlook.com>
---
hw/audio/hda-codec.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
index c51d8ba617..c2aa71624b 100644
--- a/hw/audio/hda-codec.c
+++ b/hw/audio/hda-codec.c
@@ -121,7 +121,7 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
#define QEMU_HDA_PCM_FORMATS (AC_SUPPCM_BITS_16 | \
0x1fc /* 16 -> 96 kHz */)
#define QEMU_HDA_AMP_NONE (0)
-#define QEMU_HDA_AMP_STEPS 0x4a
+#define QEMU_HDA_AMP_STEPS 0x31 /* 20 * log10(255) = 48 dB dynamic range */
#define PARAM mixemu
#define HDA_MIXER
@@ -433,6 +433,14 @@ static void hda_audio_set_running(HDAAudioStream *st, bool running)
}
}
+/* first muted; then from -48 dB to 0 dB */
+static const uint32_t hda_vol_table[] = {
+ 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5,
+ 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, 20, 23, 26,
+ 29, 32, 36, 40, 45, 51, 57, 64, 72, 81, 90, 102, 114, 128, 143,
+ 161, 181, 203, 227, 255
+}
+
static void hda_audio_set_amp(HDAAudioStream *st)
{
bool muted;
@@ -446,8 +454,8 @@ static void hda_audio_set_amp(HDAAudioStream *st)
left = st->mute_left ? 0 : st->gain_left;
right = st->mute_right ? 0 : st->gain_right;
- left = left * 255 / QEMU_HDA_AMP_STEPS;
- right = right * 255 / QEMU_HDA_AMP_STEPS;
+ left = hda_vol_table[left];
+ right = hda_vol_table[right];
if (!st->state->mixer) {
return;
--
2.41.0
Hi
On Sun, Jul 30, 2023 at 5:52 PM Yuanqing Li <liyq.yuanqing@outlook.com> wrote:
>
> According Intel's High Definition Audio Specification (Revision 1.0a,
> Section 7.3.4.10: Amplifier Capabilities), the amplifier gain levels
> should be evenly spaced in dB, i.e. using a log scale instead of linear.
>
> Here, the hda-codec reports amplifier levels from 0 to -48 dB at 1-dB
> steps matching the 8-bit dynamic range, and the -49 dB level is mapped
> to 0 (muted).
>
> Signed-off-by: Yuanqing Li <liyq.yuanqing@outlook.com>
> ---
> hw/audio/hda-codec.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
> index c51d8ba617..c2aa71624b 100644
> --- a/hw/audio/hda-codec.c
> +++ b/hw/audio/hda-codec.c
> @@ -121,7 +121,7 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as)
> #define QEMU_HDA_PCM_FORMATS (AC_SUPPCM_BITS_16 | \
> 0x1fc /* 16 -> 96 kHz */)
> #define QEMU_HDA_AMP_NONE (0)
> -#define QEMU_HDA_AMP_STEPS 0x4a
> +#define QEMU_HDA_AMP_STEPS 0x31 /* 20 * log10(255) = 48 dB dynamic range */
>
> #define PARAM mixemu
> #define HDA_MIXER
> @@ -433,6 +433,14 @@ static void hda_audio_set_running(HDAAudioStream *st, bool running)
> }
> }
>
> +/* first muted; then from -48 dB to 0 dB */
> +static const uint32_t hda_vol_table[] = {
> + 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5,
> + 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, 20, 23, 26,
> + 29, 32, 36, 40, 45, 51, 57, 64, 72, 81, 90, 102, 114, 128, 143,
> + 161, 181, 203, 227, 255
> +}
It was not clear to me which scale is applied by the backend. I guess
mixeng uses linear, and thus all others should too.
> +
> static void hda_audio_set_amp(HDAAudioStream *st)
> {
> bool muted;
> @@ -446,8 +454,8 @@ static void hda_audio_set_amp(HDAAudioStream *st)
> left = st->mute_left ? 0 : st->gain_left;
> right = st->mute_right ? 0 : st->gain_right;
>
> - left = left * 255 / QEMU_HDA_AMP_STEPS;
> - right = right * 255 / QEMU_HDA_AMP_STEPS;
> + left = hda_vol_table[left];
> + right = hda_vol_table[right];
>
Whoo, better check bounds here. (value can go up to AC_AMP_GAIN 0x7f,
reading the code)
Definitely not trivial material imho
--
Marc-André Lureau
© 2016 - 2026 Red Hat, Inc.