Index: trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 354)
+++ trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 355)
@@ -40,5 +40,9 @@
 
 #undef LOG_VOICES
+#ifndef VBOX
 //#define USE_MIXER
+#else
+#define USE_MIXER
+#endif
 
 #define AC97_SSM_VERSION 1
@@ -79,5 +83,9 @@
 };
 
+#ifndef VBOX
 #define SOFT_VOLUME
+#else
+#undef  SOFT_VOLUME
+#endif
 #define SR_FIFOE BIT(4)          /* rwc, fifo error */
 #define SR_BCIS  BIT(3)          /* rwc, buffer completion interrupt status */
@@ -499,4 +507,20 @@
     rvol = VOL_MASK - ((VOL_MASK * rvol) / 255);
     lvol = VOL_MASK - ((VOL_MASK * lvol) / 255);
+
+#ifdef VBOX
+    /*
+     * From AC'97 SoundMax Codec AD1981A: "Because AC '97 defines 6-bit volume registers, to
+     * maintain compatibility whenever the D5 or D13 bits are set to `1,' their respective
+     * lower five volume bits are automatically set to `1' by the Codec logic. On readback,
+     * all lower 5 bits will read ones whenever these bits are set to `1.'"
+     *
+     *  Linux ALSA depends on this behavior.
+     */
+    if (val & BIT(5))
+        val |= BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0);
+    if (val & BIT(13))
+        val |= BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8);
+#endif
+
     mixer_store (s, index, val);
 }
Index: trunk/src/VBox/Devices/Audio/audio.c
===================================================================
--- trunk/src/VBox/Devices/Audio/audio.c	(revision 354)
+++ trunk/src/VBox/Devices/Audio/audio.c	(revision 355)
@@ -133,4 +133,13 @@
 };
 
+#ifdef VBOX
+volume_t pcm_out_volume =
+{
+    0,
+    UINT_MAX,
+    UINT_MAX
+};
+#endif
+
 /* http://www.df.lth.se/~john_e/gems/gem002d.html */
 /* http://www.multi-platforms.com/Tips/PopCount.htm */
@@ -885,5 +894,9 @@
     swlim = audio_MIN (swlim, samples);
     if (swlim) {
+#ifndef VBOX
         sw->conv (sw->buf, buf, swlim, &sw->vol);
+#else
+        sw->conv (sw->buf, buf, swlim, &pcm_out_volume);
+#endif
     }
 
@@ -1699,4 +1712,52 @@
         }
     }
+}
+
+void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol)
+{
+    if (sw)
+    {
+        sw->vol.mute = mute;
+        sw->vol.l    = (uint32_t)lvol * 0x808080; /* maximum is INT_MAX = 0x7fffffff */
+        sw->vol.r    = (uint32_t)rvol * 0x808080; /* maximum is INT_MAX = 0x7fffffff */
+    }
+}
+
+void AUD_set_volume (audmixerctl_t mt, int *mute, uint8_t *lvol, uint8_t *rvol)
+{
+    volume_t *vol = NULL;
+    const char *name;
+
+    switch (mt)
+    {
+        case AUD_MIXER_VOLUME:
+            name = "MASTER";
+            vol = &pcm_out_volume;
+            break;
+        case AUD_MIXER_PCM:
+            name = "PCM_OUT";
+            break;
+        case AUD_MIXER_LINE_IN:
+            name = "LINE_IN";
+            break;
+        default:
+            return;
+
+    }
+
+    if (vol)
+    {
+        vol->mute  = *mute;
+        vol->l     = ((uint32_t)*lvol) * 0x808080; /* maximum is INT_MAX = 0x7fffffff */
+        vol->r     = ((uint32_t)*rvol) * 0x808080; /* maximum is INT_MAX = 0x7fffffff */
+    }
+#if 0
+    LogRel(("AUDIO: Set '%s' volume to %d%%/%d%%\n", name, (*lvol*100)/255, (*rvol*100)/255l));
+#endif
+}
+
+void AUD_set_record_source (audrecsource_t *ars, audrecsource_t *als)
+{
+    LogRel(("AUDIO: set_record_source ars=%d als=%d (not implemented)\n", *ars, *als));
 }
 
Index: trunk/src/VBox/Devices/Audio/audio.h
===================================================================
--- trunk/src/VBox/Devices/Audio/audio.h	(revision 354)
+++ trunk/src/VBox/Devices/Audio/audio.h	(revision 355)
@@ -55,4 +55,21 @@
     AUD_CNOTIFY_DISABLE
 } audcnotification_e;
+
+typedef enum
+{
+    AUD_MIXER_VOLUME,
+    AUD_MIXER_PCM,
+    AUD_MIXER_LINE_IN
+} audmixerctl_t;
+
+typedef enum
+{
+    AUD_REC_MIC,
+    AUD_REC_CD,
+    AUD_REC_VIDEO,
+    AUD_REC_AUX,
+    AUD_REC_LINE_IN,
+    AUD_REC_PHONE
+} audrecsource_t;
 
 struct audio_capture_ops {
@@ -141,4 +158,8 @@
 uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts);
 
+void AUD_set_volume_out (SWVoiceOut *po, int mute, uint8_t lvol, uint8_t rvol);
+void AUD_set_volume (audmixerctl_t mt, int *mute, uint8_t *lvol, uint8_t *rvol);
+void AUD_set_record_source (audrecsource_t *ars, audrecsource_t *als);
+
 static inline void *advance (void *p, int incr)
 {
@@ -159,5 +180,5 @@
     __typeof (b) tb = b;                        \
     ((ta)>(tb)?(tb):(ta));                      \
-}))
+ }))
 
 #define audio_MAX(a, b) ( __extension__ ({      \
@@ -165,5 +186,5 @@
     __typeof (b) tb = b;                        \
     ((ta)<(tb)?(tb):(ta));                      \
-}))
+ }))
 #else
 #define audio_MIN(a, b) ((a)>(b)?(b):(a))
Index: trunk/src/VBox/Devices/Audio/audio_int.h
===================================================================
--- trunk/src/VBox/Devices/Audio/audio_int.h	(revision 354)
+++ trunk/src/VBox/Devices/Audio/audio_int.h	(revision 355)
@@ -26,5 +26,9 @@
 
 #ifdef CONFIG_COREAUDIO
+#ifndef VBOX
 #define FLOAT_MIXENG
+#else
+#undef  FLOAT_MIXENG
+#endif
 /* #define RECIPROCAL */
 #endif
Index: trunk/src/VBox/Devices/Audio/mixeng.c
===================================================================
--- trunk/src/VBox/Devices/Audio/mixeng.c	(revision 354)
+++ trunk/src/VBox/Devices/Audio/mixeng.c	(revision 355)
@@ -28,9 +28,14 @@
 #include "audio.h"
 #include <iprt/alloc.h>
+#ifdef VBOX
+#include <iprt/asm.h>
+#endif
 
 #define AUDIO_CAP "mixeng"
 #include "audio_int.h"
 
+#ifndef VBOX
 #define NOVOL
+#endif
 
 /* 8 bit */
Index: trunk/src/VBox/Devices/Audio/mixeng.h
===================================================================
--- trunk/src/VBox/Devices/Audio/mixeng.h	(revision 354)
+++ trunk/src/VBox/Devices/Audio/mixeng.h	(revision 355)
@@ -27,4 +27,9 @@
 struct HWVoiceOut;
 
+#ifdef VBOX
+/* use faster ASMMult2xS32RetS64 */
+typedef struct { int mute;  uint32_t r; uint32_t l; } volume_t;
+typedef struct { int64_t l; int64_t r; } st_sample_t;
+#else /* !VBOX */
 #ifdef FLOAT_MIXENG
 typedef float real_t;
@@ -35,4 +40,5 @@
 typedef struct { int64_t l; int64_t r; } st_sample_t;
 #endif
+#endif /* VBOX */
 
 typedef void (t_sample) (st_sample_t *dst, const void *src,
Index: trunk/src/VBox/Devices/Audio/mixeng_template.h
===================================================================
--- trunk/src/VBox/Devices/Audio/mixeng_template.h	(revision 354)
+++ trunk/src/VBox/Devices/Audio/mixeng_template.h	(revision 355)
@@ -35,4 +35,11 @@
 #define VOL(a, b) a
 #else
+#ifdef VBOX
+#ifdef SIGNED
+#define VOL(a, b) ((ASMMult2xS32RetS64(a, b) >> 31))
+#else
+#define VOL(a, b) ((ASMMult2xU32RetU64(a, b) >> 31))
+#endif
+#else /* !VBOX */
 #ifdef FLOAT_MIXENG
 #define VOL(a, b) ((a) * (b))
@@ -41,4 +48,5 @@
 #endif
 #endif
+#endif /* !VBOX */
 
 #define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
