Index: /trunk/src/VBox/Devices/Audio/DrvHostDebugAudio.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DrvHostDebugAudio.cpp	(revision 87842)
+++ /trunk/src/VBox/Devices/Audio/DrvHostDebugAudio.cpp	(revision 87843)
@@ -7,5 +7,5 @@
 
 /*
- * Copyright (C) 2016-2020 Oracle Corporation
+ * Copyright (C) 2016-2021 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -19,5 +19,8 @@
 
 #include <iprt/alloc.h>
+#include <iprt/rand.h>
 #include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
+
+#include <math.h>
 
 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
@@ -42,4 +45,8 @@
         struct
         {
+            /** Frequency (in Hz) of the sine wave to generate. */
+            uint16_t   uFreqHz;
+            /** Current sample index for generate the sine wave. */
+            uint64_t   uSample;
             /** Timestamp of last captured samples. */
             uint64_t   tsLastCaptured;
@@ -77,5 +84,5 @@
 
     pBackendCfg->cMaxStreamsOut = 1; /* Output; writing to a file. */
-    pBackendCfg->cMaxStreamsIn  = 0; /** @todo Right now we don't support any input (capturing, injecting from a file). */
+    pBackendCfg->cMaxStreamsIn  = 1; /* Input; generates a sine wave. */
 
     return VINF_SUCCESS;
@@ -116,18 +123,15 @@
 
 
-static int debugCreateStreamIn(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg,
-                               PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
-{
-    RT_NOREF(pDrv, pStreamDbg, pCfgReq, pCfgAcq);
-
-    return VINF_SUCCESS;
-}
-
-
-static int debugCreateStreamOut(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg,
-                                PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
-{
-    RT_NOREF(pDrv, pCfgAcq);
-
+/**
+ * Creates a debug output .WAV file on the host with the specified stream configuration.
+ *
+ * @returns VBox status code.
+ * @param   pDrv                Driver instance.
+ * @param   pStreamDbg          Debug audio stream to create file for.
+ * @param   fIn                 Whether this is an input or output stream to create file for.
+ * @param   pCfg                Stream configuration to create .wAV file with.
+ */
+static int debugCreateFile(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg, bool fIn, PPDMAUDIOSTREAMCFG pCfg)
+{
     char szTemp[RTPATH_MAX];
     int rc = RTPathTemp(szTemp, sizeof(szTemp));
@@ -135,5 +139,5 @@
     {
         char szFile[RTPATH_MAX];
-        rc = DrvAudioHlpFileNameGet(szFile, RT_ELEMENTS(szFile), szTemp, "DebugAudioOut",
+        rc = DrvAudioHlpFileNameGet(szFile, RT_ELEMENTS(szFile), szTemp, fIn ? "DebugAudioIn" : "DebugAudioOut",
                                     pDrv->pDrvIns->iInstance, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAGS_NONE);
         if (RT_SUCCESS(rc))
@@ -143,9 +147,9 @@
             {
                 rc = DrvAudioHlpFileOpen(pStreamDbg->pFile, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE,
-                                         &pCfgReq->Props);
+                                         &pCfg->Props);
             }
 
             if (RT_FAILURE(rc))
-                LogRel(("DebugAudio: Creating output file '%s' failed with %Rrc\n", szFile, rc));
+                LogRel(("DebugAudio: Creating %sput file '%s' failed with %Rrc\n", fIn ? "in" : "out", szFile, rc));
         }
         else
@@ -159,4 +163,36 @@
 
 
+static int debugCreateStreamIn(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg,
+                               PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
+{
+    RT_NOREF(pDrv, pCfgReq);
+
+    pStreamDbg->In.uSample   = 0; /* Initialize sample index. */
+
+    const uint16_t auFreqsHz[] = { 400, 600, 750, 800, 1000, 1200, 1400, 1600 };
+
+    /* Chose a random frequency so that every time a recording is started (hopefully) another tone will be generated. */
+    pStreamDbg->In.uFreqHz   = auFreqsHz[RTRandU32Ex(0, RT_ELEMENTS(auFreqsHz) - 1)];
+
+    pCfgAcq->Props.uHz         = 22050; /* 22,5 kHz. */
+    pCfgAcq->Props.cbSample    = 2;     /* 16-bit samples. */
+    pCfgAcq->Props.cChannels   = 1;     /* Mono. */
+    pCfgAcq->Props.fSigned     = true;
+    pCfgAcq->Props.fSwapEndian = false;
+    pCfgAcq->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfgAcq->Props.cbSample, pCfgAcq->Props.cChannels);
+
+    return debugCreateFile(pDrv, pStreamDbg, true /* fIn */, pCfgAcq);
+}
+
+
+static int debugCreateStreamOut(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg,
+                                PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
+{
+    RT_NOREF(pDrv, pCfgAcq);
+
+    return debugCreateFile(pDrv, pStreamDbg, false /* fIn */, pCfgReq);
+}
+
+
 /**
  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
@@ -219,9 +255,37 @@
                                                            void *pvBuf, uint32_t uBufSize, uint32_t *puRead)
 {
-    RT_NOREF(pInterface, pStream, pvBuf, uBufSize);
-
-    /* Never capture anything. */
+    RT_NOREF(pInterface);
+
+    PDEBUGAUDIOSTREAM  pStreamDbg = (PDEBUGAUDIOSTREAM)pStream;
+
+    PPDMAUDIOSTREAMCFG pCfg = pStreamDbg->pCfg;
+    AssertPtr(pCfg);
+
+    Assert(uBufSize % pCfg->Props.cbSample == 0);
+
+    uint16_t *paBuf = (uint16_t *)pvBuf;
+
+    /* Generate a simple mono sine wave. */
+    for (size_t i = 0; i < uBufSize / pCfg->Props.cbSample; i++)
+    {
+        paBuf[i] = 32760 * sin((2.f * float(3.1415) * pStreamDbg->In.uFreqHz) / pCfg->Props.uHz * pStreamDbg->In.uSample);
+        if (pStreamDbg->In.uSample == UINT64_MAX)
+        {
+            pStreamDbg->In.uSample = 0;
+            continue;
+        }
+
+        pStreamDbg->In.uSample++;
+    }
+
+    int rc = DrvAudioHlpFileWrite(pStreamDbg->pFile, pvBuf, uBufSize, 0 /* fFlags */);
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("DebugAudio: Writing input failed with %Rrc\n", rc));
+        return rc;
+    }
+
     if (puRead)
-        *puRead = 0;
+        *puRead = uBufSize;
 
     return VINF_SUCCESS;
@@ -238,8 +302,5 @@
 static int debugDestroyStreamOut(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg)
 {
-    RT_NOREF(pDrv);
-
-    DrvAudioHlpFileDestroy(pStreamDbg->pFile);
-
+    RT_NOREF(pDrv, pStreamDbg);
     return VINF_SUCCESS;
 }
@@ -267,4 +328,6 @@
     if (RT_SUCCESS(rc))
     {
+        DrvAudioHlpFileDestroy(pStreamDbg->pFile);
+
         DrvAudioHlpStreamCfgFree(pStreamDbg->pCfg);
         pStreamDbg->pCfg = NULL;
@@ -294,7 +357,11 @@
 static DECLCALLBACK(uint32_t) drvHostDebugAudioHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
 {
-    RT_NOREF(pInterface, pStream);
-
-    return 0; /* Never capture anything. */
+    RT_NOREF(pInterface);
+
+    PDEBUGAUDIOSTREAM pStreamDbg = (PDEBUGAUDIOSTREAM)pStream;
+
+    AssertPtr(pStreamDbg->pCfg);
+
+    return DrvAudioHlpMilliToBytes(10 /* ms */, &pStreamDbg->pCfg->Props);
 }
 
