如何从通过远程桌面访问的 PC 的音频输入进行录制?
我正在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我找到了答案,感谢: 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.