how can I record from the audio input of a PC being accessed via remote desktop?
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;
开发者_JAVA百科 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?
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.
精彩评论