VirtualBox

Changeset 75975 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Dec 5, 2018 3:28:59 PM (6 years ago)
Author:
vboxsync
Message:

AC97: Fixed recording gain controls to avoid incorrectly reducing the level. See bugref:9321

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DevIchAc97.cpp

    r75606 r75975  
    128128 * @{ */
    129129#define AC97_BARS_VOL_MASK              0x1f   /**< Volume mask for the Baseline Audio Register Set (5.7.2). */
    130 #define AC97_BARS_VOL_STEPS             31     /**< Volume steps for the Baseline Audio Register Set (5.7.2). */
     130#define AC97_BARS_GAIN_MASK             0x0f   /**< Gain mask for the Baseline Audio Register Set. */
    131131#define AC97_BARS_VOL_MUTE_SHIFT        15     /**< Mute bit shift for the Baseline Audio Register Set (5.7.2). */
    132132/** @} */
     
    21052105     *  these bits are set to 1."
    21062106     *
    2107      * Linux ALSA depends on this behavior.
     2107     * Linux ALSA depends on this behavior to detect that only 5 bits are used for volume
     2108     * control and the optional 6th bit is not used. Note that this logic only applies to the
     2109     * master volume controls.
    21082110     */
    2109     /// @todo Does this apply to anything other than the master volume control?
    2110     if (uVal & RT_BIT(5))  /* D5 bit set? */
    2111         uVal |= RT_BIT(4) | RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0);
    2112     if (uVal & RT_BIT(13)) /* D13 bit set? */
    2113         uVal |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8);
     2111    if ((index == AC97_Master_Volume_Mute) || (index == AC97_Headphone_Volume_Mute) || (index == AC97_Master_Volume_Mono_Mute))
     2112    {
     2113        if (uVal & RT_BIT(5))  /* D5 bit set? */
     2114            uVal |= RT_BIT(4) | RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0);
     2115        if (uVal & RT_BIT(13)) /* D13 bit set? */
     2116            uVal |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8);
     2117    }
    21142118
    21152119    const bool    fCtlMuted    = (uVal >> AC97_BARS_VOL_MUTE_SHIFT) & 1;
     
    21622166
    21632167            case PDMAUDIOMIXERCTL_MIC_IN:
    2164                 pSink = pThis->pSinkMicIn;
    2165                 break;
    2166 
    21672168            case PDMAUDIOMIXERCTL_LINE_IN:
    2168                 pSink = pThis->pSinkLineIn;
     2169                /* These are recognized but do nothing. */
    21692170                break;
    21702171
     
    21772178        if (pSink)
    21782179            rc = AudioMixerSinkSetVolume(pSink, &Vol);
     2180    }
     2181
     2182    ichac97MixerSet(pThis, index, uVal);
     2183
     2184    if (RT_FAILURE(rc))
     2185        LogFlowFunc(("Failed with %Rrc\n", rc));
     2186
     2187    return rc;
     2188}
     2189
     2190/**
     2191 * Sets the gain of a specific AC'97 recording control.
     2192 *
     2193 * NB: gain support is currently not implemented in PDM audio.
     2194 *
     2195 * @returns IPRT status code.
     2196 * @param   pThis               AC'97 state.
     2197 * @param   index               AC'97 mixer index to set volume for.
     2198 * @param   enmMixerCtl         Corresponding audio mixer sink.
     2199 * @param   uVal                Volume value to set.
     2200 */
     2201static int ichac97R3MixerSetGain(PAC97STATE pThis, int index, PDMAUDIOMIXERCTL enmMixerCtl, uint32_t uVal)
     2202{
     2203    /*
     2204     * For AC'97 recording controls, each additional step means +1.5dB gain with
     2205     * zero being 0dB gain and 15 being +22.5dB gain.
     2206     */
     2207    const bool    fCtlMuted     = (uVal >> AC97_BARS_VOL_MUTE_SHIFT) & 1;
     2208          uint8_t uCtlGainLeft  = (uVal >> 8) & AC97_BARS_GAIN_MASK;
     2209          uint8_t uCtlGainRight = uVal & AC97_BARS_GAIN_MASK;
     2210
     2211    Assert(uCtlGainLeft  <= 255 / AC97_DB_FACTOR);
     2212    Assert(uCtlGainRight <= 255 / AC97_DB_FACTOR);
     2213
     2214    LogFunc(("index=0x%x, uVal=%RU32, enmMixerCtl=%RU32\n", index, uVal, enmMixerCtl));
     2215    LogFunc(("uCtlGainLeft=%RU8, uCtlGainRight=%RU8 ", uCtlGainLeft, uCtlGainRight));
     2216
     2217    uint8_t lVol = PDMAUDIO_VOLUME_MAX + uCtlGainLeft  * AC97_DB_FACTOR;
     2218    uint8_t rVol = PDMAUDIO_VOLUME_MAX + uCtlGainRight * AC97_DB_FACTOR;
     2219
     2220    /* We do not currently support gain. Since AC'97 does not support attenuation
     2221     * for the recording input, the best we can do is set the maximum volume.
     2222     */
     2223# ifndef VBOX_WITH_AC97_GAIN_SUPPORT
     2224    /* NB: Currently there is no gain support, only attenuation. Since AC'97 does not
     2225     * support attenuation for the recording inputs, the best we can do is set the
     2226     * maximum volume.
     2227     */
     2228    lVol = rVol = PDMAUDIO_VOLUME_MAX;
     2229# endif
     2230
     2231    Log(("-> fMuted=%RTbool, lVol=%RU8, rVol=%RU8\n", fCtlMuted, lVol, rVol));
     2232
     2233    int rc = VINF_SUCCESS;
     2234
     2235    if (pThis->pMixer) /* Device can be in reset state, so no mixer available. */
     2236    {
     2237        PDMAUDIOVOLUME Vol   = { fCtlMuted, lVol, rVol };
     2238        PAUDMIXSINK    pSink = NULL;
     2239
     2240        switch (enmMixerCtl)
     2241        {
     2242            case PDMAUDIOMIXERCTL_MIC_IN:
     2243                pSink = pThis->pSinkMicIn;
     2244                break;
     2245
     2246            case PDMAUDIOMIXERCTL_LINE_IN:
     2247                pSink = pThis->pSinkLineIn;
     2248                break;
     2249
     2250            default:
     2251                AssertFailed();
     2252                rc = VERR_NOT_SUPPORTED;
     2253                break;
     2254        }
     2255
     2256        if (pSink) {
     2257            rc = AudioMixerSinkSetVolume(pSink, &Vol);
     2258            /* There is only one AC'97 recording gain control. If line in
     2259             * is changed, also update the microphone. If the optional dedicated
     2260             * microphone is changed, only change that.
     2261             * NB: The codecs we support do not have the dedicated microphone control.
     2262             */
     2263            if ((pSink == pThis->pSinkLineIn) && pThis->pSinkMicIn)
     2264                rc = AudioMixerSinkSetVolume(pSink, &Vol);
     2265        }
    21792266    }
    21802267
     
    23582445    ichac97R3MixerSetVolume(pThis, AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_FRONT,         0x8808);
    23592446    ichac97R3MixerSetVolume(pThis, AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN,       0x8808);
    2360     ichac97R3MixerSetVolume(pThis, AC97_Mic_Volume_Mute,     PDMAUDIOMIXERCTL_MIC_IN,        0x8808);
     2447    ichac97R3MixerSetVolume(pThis, AC97_Mic_Volume_Mute,     PDMAUDIOMIXERCTL_MIC_IN,        0x8008);
     2448
     2449    /* The default for record controls is 0 dB gain with mute on. */
     2450    ichac97R3MixerSetGain(pThis, AC97_Record_Gain_Mute,      PDMAUDIOMIXERCTL_LINE_IN,       0x8000);
     2451    ichac97R3MixerSetGain(pThis, AC97_Record_Gain_Mic_Mute,  PDMAUDIOMIXERCTL_MIC_IN,        0x8000);
    23612452
    23622453    return VINF_SUCCESS;
     
    33343425                    /* Newer Ubuntu guests rely on that when controlling gain and muting
    33353426                     * the recording (capturing) levels. */
    3336                     ichac97R3MixerSetVolume(pThis, uPortIdx, PDMAUDIOMIXERCTL_LINE_IN, u32Val);
     3427                    ichac97R3MixerSetGain(pThis, uPortIdx, PDMAUDIOMIXERCTL_LINE_IN, u32Val);
    33373428#else
    33383429                    rc = VINF_IOM_R3_IOPORT_WRITE;
     
    33423433#ifdef IN_RING3
    33433434                    /* Ditto; see note above. */
    3344                     ichac97R3MixerSetVolume(pThis, uPortIdx, PDMAUDIOMIXERCTL_MIC_IN,  u32Val);
     3435                    ichac97R3MixerSetGain(pThis, uPortIdx, PDMAUDIOMIXERCTL_MIC_IN,  u32Val);
    33453436#else
    33463437                    rc = VINF_IOM_R3_IOPORT_WRITE;
     
    36243715
    36253716    ichac97R3MixerRecordSelect(pThis, ichac97MixerGet(pThis, AC97_Record_Select));
    3626 # define V_(a, b) ichac97R3MixerSetVolume(pThis, a, b, ichac97MixerGet(pThis, a))
    3627     V_(AC97_Master_Volume_Mute,  PDMAUDIOMIXERCTL_VOLUME_MASTER);
    3628     V_(AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_FRONT);
    3629     V_(AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN);
    3630     V_(AC97_Mic_Volume_Mute,     PDMAUDIOMIXERCTL_MIC_IN);
    3631 # undef V_
     3717    ichac97R3MixerSetVolume(pThis, AC97_Master_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME_MASTER, ichac97MixerGet(pThis, AC97_Master_Volume_Mute));
     3718    ichac97R3MixerSetVolume(pThis, AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_FRONT, ichac97MixerGet(pThis, AC97_PCM_Out_Volume_Mute));
     3719    ichac97R3MixerSetVolume(pThis, AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN, ichac97MixerGet(pThis, AC97_Line_In_Volume_Mute));
     3720    ichac97R3MixerSetVolume(pThis, AC97_Mic_Volume_Mute, PDMAUDIOMIXERCTL_MIC_IN, ichac97MixerGet(pThis, AC97_Mic_Volume_Mute));
     3721    ichac97R3MixerSetGain(pThis, AC97_Record_Gain_Mic_Mute, PDMAUDIOMIXERCTL_MIC_IN, ichac97MixerGet(pThis, AC97_Record_Gain_Mic_Mute));
     3722    ichac97R3MixerSetGain(pThis, AC97_Record_Gain_Mute, PDMAUDIOMIXERCTL_LINE_IN, ichac97MixerGet(pThis, AC97_Record_Gain_Mute));
    36323723    if (pThis->uCodecModel == AC97_CODEC_AD1980)
    36333724        if (ichac97MixerGet(pThis, AC97_AD_Misc) & AC97_AD_MISC_HPSEL)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette