如何从通过远程桌面访问的 PC 的音频输入进行录制?

发布于 2024-11-15 08:24:01 字数 5990 浏览 3 评论 0原文

我正在 Borland Turbo C++ (2006) 中编写一个应用程序,并在 Windows XP Pro 下运行,我想在其中将音频输入记录到数据缓冲区中,以便随后可以对时间响应进行 FFT。

当应用程序在本地运行时,以下代码工作正常:

short int       pluck_data[T_SAMPLES][CHANNELS];

//---------------------------------------------------------------------------

int __fastcall CheckResult(char* func_name, int result)
{
  int   return_value = 1;           // set return_value for fail by default
  char  msg[100];

  if(result == MMSYSERR_NOERROR)    // function call returned without error
    return_value = 0;
  else                              // function call returned error
  {
    switch(result)
    {
      case MMSYSERR_ALLOCATED:
        sprintf(msg, "%s: Specified resource is already allocated.", func_name);
        break;
      case MMSYSERR_BADDEVICEID:
        sprintf(msg, "%s: Specified device identifier is out of range.", func_name);
        break;
      case MMSYSERR_INVALHANDLE:
        sprintf(msg, "%s: Specified device handle is invalid.", func_name);
        break;
      case MMSYSERR_NODRIVER:
        sprintf(msg, "%s: No device driver is present.", func_name);
        break;
      case MMSYSERR_NOMEM:
        sprintf(msg, "%s: Unable to allocate or lock memory.", func_name);
        break;
      case WAVERR_BADFORMAT:
        sprintf(msg, "%s: Attempted to open with an unsupported waveform-audio format.", func_name);
        break;
      case WAVERR_STILLPLAYING:
        sprintf(msg, "%s: The buffer pointed to by the pwh parameter is still in the queue.", func_name);
        break;
      case WAVERR_UNPREPARED:
        sprintf(msg, "%s: The buffer pointed to by the pwh parameter hasn't been prepared.", func_name);
        break;
      default:
        sprintf(msg, "%s: Unknown error.", func_name);
    }
    ReportError(hWnd, msg, log_fptr);
  } // else function call returned error
  return return_value;
}

//---------------------------------------------------------------------------

int __fastcall RecordString()
{
  int           return_value = 1;           // set return_value for fail by default
  WAVEINCAPS    dev_capability;
  HWAVEIN       dev_handle;
  WAVEFORMATEX  rec_format;
  WAVEHDR       rec_header;
  int           result;
  char          msg[100];

  result = waveInGetNumDevs();      // get number of audio input devices
  if(result != 1)
  {
    if(result == 0)
      sprintf(msg, "No waveform-audio input devices present.");
    else
      sprintf(msg, "More than one waveform-audio input device present.");
    ReportError(hWnd, msg, log_fptr);
  }
  else
  {
    // only 1 audio input device; test its capabilities
    result = waveInGetDevCaps(0,&dev_capability,sizeof(dev_capability));
    if(CheckResult("waveInGetDevCaps", result) == 0)
    {
      // test if device supports 96kHz, Stereo, 16-bit format WAVE_FORMAT_96S16
      if ((dev_capability.dwFormats & WAVE_FORMAT_96S16) == 0)
      {
        sprintf(msg, "waveInGetDevCaps: WAVE_FORMAT_96S16 not supported");
        ReportError(hWnd, msg, log_fptr);
      }
      else
      {
        // initialise required record format
        rec_format.wFormatTag = WAVE_FORMAT_PCM;
        rec_format.nChannels = CHANNELS;                                    // 2
        rec_format.nSamplesPerSec = SAMPLE_RATE;                            // 96000
        rec_format.nAvgBytesPerSec = BYTES_PER_SAMPLE * SAMPLE_RATE;        // 384000
        rec_format.nBlockAlign = BYTES_PER_SAMPLE;                          // 4
        rec_format.wBitsPerSample = SAMPLE_BITS;                            // 16
        rec_format.cbSize = 0;
        // open audio input device requesting format 96kHz, Stereo, 16-bit
        result = waveInOpen(&dev_handle, WAVE_MAPPER, &rec_format, 0, 0, 0);
        if(CheckResult("waveInOpen", result) == 0)
        {
          // initialise header for data buffer
          rec_header.lpData = (char*)&pluck_data;
          rec_header.dwBufferLength = sizeof(pluck_data);
          rec_header.dwFlags = 0;
          // prepare header for data buffer
          result = waveInPrepareHeader(dev_handle, &rec_header, sizeof(rec_header));
          if(CheckResult("waveInPrepareHeader", result) == 0)
          {
            // connect data buffer to audio input device
            result = waveInAddBuffer(dev_handle, &rec_header, sizeof(rec_header));
            if(CheckResult("waveInAddBuffer", result) == 0)
            {
              // start recording
              result = waveInStart(dev_handle);
              if(CheckResult("waveInStart", result) == 0)
              {
                // recording - poll flag until data buffer full
                while((rec_header.dwFlags & WHDR_DONE ) == 0); // wait for flag to be set
                // buffer now full
                // reset/stop recording
                result = waveInReset(dev_handle);
                if(CheckResult("waveInReset", result) == 0)
                {
                  // unprepare header for data buffer
                  result = waveInUnprepareHeader(dev_handle, &rec_header, sizeof(rec_header));
                  if(CheckResult("waveInUnprepareHeader", result) == 0)
                  {
                    // close audio input device
                    result = waveInClose(dev_handle);
                    if(CheckResult("waveInClose", result) == 0)
                      return_value = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  return return_value;
}

但是,如果我尝试通过远程桌面(从运行 Win XP Home 的 PC)运行此程序,则对 waveInGetNumDevs() 的调用将返回零。

作为替代方案,我从 RecordString() 函数中删除了对 waveInGetNumDevs()、waveInGetDevCaps() 和 waveInOpen() 的调用,而是在程序启动时仅运行一次。 (对 waveInClose() 的调用也从 RecordString() 中删除。)现在,如果我在主机 PC 上启动程序,以便它成功调用 waveInOpen() 并检索音频输入设备的句柄 (HWAVEIN dev_handle),然后我可以切换到通过远程桌面访问该主机(当​​程序仍在运行时)并且 RecordString() 函数仍然可以正常工作。因此,一旦获得设备句柄,就可以通过远程桌面进行音频输入;问题是如何获取句柄。

有没有一种方法可以通过远程桌面运行整个应用程序,而不必在主机 PC 上本地启动它?

I am writing an application, in Borland Turbo C++ (2006) and running under Windows XP Pro, in which I want to record from the audio input into a data buffer so that I can subsequently FFT the time response.

When the application is run locally the following code works fine:

short int       pluck_data[T_SAMPLES][CHANNELS];

//---------------------------------------------------------------------------

int __fastcall CheckResult(char* func_name, int result)
{
  int   return_value = 1;           // set return_value for fail by default
  char  msg[100];

  if(result == MMSYSERR_NOERROR)    // function call returned without error
    return_value = 0;
  else                              // function call returned error
  {
    switch(result)
    {
      case MMSYSERR_ALLOCATED:
        sprintf(msg, "%s: Specified resource is already allocated.", func_name);
        break;
      case MMSYSERR_BADDEVICEID:
        sprintf(msg, "%s: Specified device identifier is out of range.", func_name);
        break;
      case MMSYSERR_INVALHANDLE:
        sprintf(msg, "%s: Specified device handle is invalid.", func_name);
        break;
      case MMSYSERR_NODRIVER:
        sprintf(msg, "%s: No device driver is present.", func_name);
        break;
      case MMSYSERR_NOMEM:
        sprintf(msg, "%s: Unable to allocate or lock memory.", func_name);
        break;
      case WAVERR_BADFORMAT:
        sprintf(msg, "%s: Attempted to open with an unsupported waveform-audio format.", func_name);
        break;
      case WAVERR_STILLPLAYING:
        sprintf(msg, "%s: The buffer pointed to by the pwh parameter is still in the queue.", func_name);
        break;
      case WAVERR_UNPREPARED:
        sprintf(msg, "%s: The buffer pointed to by the pwh parameter hasn't been prepared.", func_name);
        break;
      default:
        sprintf(msg, "%s: Unknown error.", func_name);
    }
    ReportError(hWnd, msg, log_fptr);
  } // else function call returned error
  return return_value;
}

//---------------------------------------------------------------------------

int __fastcall RecordString()
{
  int           return_value = 1;           // set return_value for fail by default
  WAVEINCAPS    dev_capability;
  HWAVEIN       dev_handle;
  WAVEFORMATEX  rec_format;
  WAVEHDR       rec_header;
  int           result;
  char          msg[100];

  result = waveInGetNumDevs();      // get number of audio input devices
  if(result != 1)
  {
    if(result == 0)
      sprintf(msg, "No waveform-audio input devices present.");
    else
      sprintf(msg, "More than one waveform-audio input device present.");
    ReportError(hWnd, msg, log_fptr);
  }
  else
  {
    // only 1 audio input device; test its capabilities
    result = waveInGetDevCaps(0,&dev_capability,sizeof(dev_capability));
    if(CheckResult("waveInGetDevCaps", result) == 0)
    {
      // test if device supports 96kHz, Stereo, 16-bit format WAVE_FORMAT_96S16
      if ((dev_capability.dwFormats & WAVE_FORMAT_96S16) == 0)
      {
        sprintf(msg, "waveInGetDevCaps: WAVE_FORMAT_96S16 not supported");
        ReportError(hWnd, msg, log_fptr);
      }
      else
      {
        // initialise required record format
        rec_format.wFormatTag = WAVE_FORMAT_PCM;
        rec_format.nChannels = CHANNELS;                                    // 2
        rec_format.nSamplesPerSec = SAMPLE_RATE;                            // 96000
        rec_format.nAvgBytesPerSec = BYTES_PER_SAMPLE * SAMPLE_RATE;        // 384000
        rec_format.nBlockAlign = BYTES_PER_SAMPLE;                          // 4
        rec_format.wBitsPerSample = SAMPLE_BITS;                            // 16
        rec_format.cbSize = 0;
        // open audio input device requesting format 96kHz, Stereo, 16-bit
        result = waveInOpen(&dev_handle, WAVE_MAPPER, &rec_format, 0, 0, 0);
        if(CheckResult("waveInOpen", result) == 0)
        {
          // initialise header for data buffer
          rec_header.lpData = (char*)&pluck_data;
          rec_header.dwBufferLength = sizeof(pluck_data);
          rec_header.dwFlags = 0;
          // prepare header for data buffer
          result = waveInPrepareHeader(dev_handle, &rec_header, sizeof(rec_header));
          if(CheckResult("waveInPrepareHeader", result) == 0)
          {
            // connect data buffer to audio input device
            result = waveInAddBuffer(dev_handle, &rec_header, sizeof(rec_header));
            if(CheckResult("waveInAddBuffer", result) == 0)
            {
              // start recording
              result = waveInStart(dev_handle);
              if(CheckResult("waveInStart", result) == 0)
              {
                // recording - poll flag until data buffer full
                while((rec_header.dwFlags & WHDR_DONE ) == 0); // wait for flag to be set
                // buffer now full
                // reset/stop recording
                result = waveInReset(dev_handle);
                if(CheckResult("waveInReset", result) == 0)
                {
                  // unprepare header for data buffer
                  result = waveInUnprepareHeader(dev_handle, &rec_header, sizeof(rec_header));
                  if(CheckResult("waveInUnprepareHeader", result) == 0)
                  {
                    // close audio input device
                    result = waveInClose(dev_handle);
                    if(CheckResult("waveInClose", result) == 0)
                      return_value = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  return return_value;
}

But if I try to run this program via Remote Desktop (from a PC running Win XP Home) the call to waveInGetNumDevs() returns zero.

As an alternative I removed the calls to waveInGetNumDevs(), waveInGetDevCaps(), and waveInOpen() from the RecordString() function and instead run these just once when the program starts. (The call to waveInClose() was also removed from RecordString().) Now, if I start the program on the host PC so that it has successfully called waveInOpen() and retrieved the handle to the audio input device (HWAVEIN dev_handle), I can then switch to accessing this host PC via Remote Desktop (while the program is still running) and the RecordString() function still works OK. So it would seem that the audio input is available via Remote Desktop once the device handle has been obtained; the problem is getting the handle.

Is there a way that I can run the whole application via Remote Desktop, instead of having to start it locally at the host PC?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心碎无痕… 2024-11-22 08:24:02

我找到了答案,感谢: http: //www.wikihow.com/Hear-Audio-from-the-Remote-PC-when-Using-Remote-Desktop

启动远程桌面时,单击“选项”按钮,然后选择“本地资源”选项卡,并确保“远程计算机声音”设置为“留在远程计算机”。

现在,通过远程桌面运行时,问题中显示的原始代码可以正常工作。

I found the answer thanks to: http://www.wikihow.com/Hear-Audio-from-the-Remote-PC-when-Using-Remote-Desktop

When starting Remote Desktop click on the "Options" button, then select the "Local Resources" tab, and ensure that "Remote computer sound" is set to "Leave at remote computer".

The original code shown in the question now works ok when run via Remote Desktop.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文