66 AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
67 AudioObjectSetPropertyData(kAudioObjectSystemObject, &theAddress, 0, NULL,
sizeof(CFRunLoopRef), &theRunLoop);
125 AudioObjectPropertyAddress address;
126 address.mSelector = kAudioHardwarePropertyDevices;
127 address.mScope = kAudioObjectPropertyScopeGlobal;
128 address.mElement = kAudioObjectPropertyElementMaster;
133 VUserLog(
"Error: Couldn't register device change listener: %s", description);
149 VUserLog(
"Error: Unbalanced VuoAudio_use() / _disuse() calls.");
155 AudioObjectPropertyAddress address;
156 address.mSelector = kAudioHardwarePropertyDevices;
157 address.mScope = kAudioObjectPropertyScopeGlobal;
158 address.mElement = kAudioObjectPropertyElementMaster;
163 VUserLog(
"Error: Couldn't unregister device change listener: %s", description);
230int VuoAudio_receivedEvent(
void *outputBuffer,
void *inputBuffer,
unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status,
void *userData)
240 status == RTAUDIO_INPUT_OVERFLOW ?
"overflow"
241 : (status == RTAUDIO_OUTPUT_UNDERFLOW ?
"underflow" :
"error"),
243 ai->inputDevice.name);
246 ai->outputTriggers.fire(streamTime);
249 if (ai->inputTriggers.size())
254 unsigned int samplesPerSecond = ai->rta->getStreamSampleRate();
257 for (
VuoInteger i = 0; i < ai->inputDevice.channelCount; ++i)
265 ai->inputTriggers.fire(channels);
270 double *outputBufferDouble = (
double *)outputBuffer;
271 unsigned int outputChannelCount = ai->outputDevice.channelCount;
273 memset(outputBufferDouble, 0, nBufferFrames*
sizeof(
VuoReal)*outputChannelCount);
276 dispatch_sync(ai->pendingOutputQueue, ^{
280 bool pendingOutput = false;
281 for (pendingOutputType::iterator it = ai->pendingOutput.begin(); it != ai->pendingOutput.end(); ++it)
282 while (!it->second.empty())
284 VuoRelease(it->second.front());
286 pendingOutput = true;
290 VUserLog(
"This audio device (%s) doesn't support output.", ai->outputDevice.name);
296 for (pendingOutputType::iterator it = ai->pendingOutput.begin(); it != ai->pendingOutput.end(); ++it)
298 void *
id = it->first;
299 if (it->second.empty())
301 if (ai->lastOutputSample.find(
id) == ai->lastOutputSample.end())
304 for (
unsigned int channel = 0; channel < outputChannelCount; ++channel)
306 if (ai->lastOutputSample[
id].find(channel) == ai->lastOutputSample[id].end())
310 VuoReal lastOutputSample = ai->lastOutputSample[id][channel];
312 outputBufferDouble[nBufferFrames*(channel) + i] =
VuoReal_lerp(lastOutputSample, 0, (
float)i/nBufferFrames);
315 ai->lastOutputSample[id].erase(ai->lastOutputSample[
id].find(channel));
322 for (
unsigned int channel = 0; channel < outputChannelCount; ++channel)
328 if (ai->lastOutputSample[
id].find(channel) == ai->lastOutputSample[
id].end())
337 outputBufferDouble[nBufferFrames*channel + i] = (
float)i/nBufferFrames * as.
samples[i];
344 outputBufferDouble[nBufferFrames*(channel) + i] += as.
samples[i];
378 Class avCaptureDeviceClass = objc_getClass(
"AVCaptureDevice");
379 if (class_getClassMethod(avCaptureDeviceClass, sel_getUid(
"authorizationStatusForMediaType:")))
381 CFStringRef mediaType = CFStringCreateWithCString(NULL,
"soun", kCFStringEncodingUTF8);
382 long status = ((long (*)(id, SEL, CFStringRef))objc_msgSend)((
id)avCaptureDeviceClass, sel_getUid(
"authorizationStatusForMediaType:"), mediaType);
383 CFRelease(mediaType);
386 VUserLog(
"Warning: Audio input may be unavailable due to system restrictions. Check System Settings > Privacy & Security > Microphone.");
389 VUserLog(
"Error: Audio input is unavailable due to system restrictions. Check System Settings > Privacy & Security > Microphone.");
392 ai =
new _VuoAudio_internal;
393 ai->inputDevice.id = deviceId;
394 ai->outputDevice.id = deviceId;
403 ai->rta =
new RtAudio();
406 RtAudio::StreamParameters inputParameters;
407 inputParameters.deviceId = deviceId;
408 inputParameters.nChannels = ai->rta->getDeviceInfo(deviceId).inputChannels;
409 ai->inputDevice.name =
VuoText_make(ai->rta->getDeviceInfo(deviceId).name.c_str());
411 ai->inputDevice.channelCount = inputParameters.nChannels;
413 RtAudio::StreamParameters outputParameters;
414 outputParameters.deviceId = deviceId;
415 outputParameters.nChannels = ai->rta->getDeviceInfo(deviceId).outputChannels;
416 ai->outputDevice.name =
VuoText_make(ai->rta->getDeviceInfo(deviceId).name.c_str());
418 ai->outputDevice.channelCount = outputParameters.nChannels;
420 RtAudio::StreamOptions options;
421 options.flags = RTAUDIO_NONINTERLEAVED;
426 outputParameters.nChannels ? &outputParameters : NULL,
427 inputParameters.nChannels ? &inputParameters : NULL,
435 ai->rta->startStream();
437 catch (RtAudioError &error)
440 VUserLog(
"Failed to open the audio device (%d): %s", deviceId, error.what());
664 __block
bool found =
false;
668 if (device.
id != -1 && device.
id == item.
id)
670 VUserLog(
"Matched by ID: %s",json_object_to_json_string(VuoAudioInputDevice_getJson(item)));
671 setRealizedDevice(item);
686 VUserLog(
"Matched by model and name: %s",json_object_to_json_string(VuoAudioInputDevice_getJson(item)));
687 setRealizedDevice(item);
700 VUserLog(
"Matched by model or name: %s",json_object_to_json_string(VuoAudioInputDevice_getJson(item)));
701 setRealizedDevice(item);
711 __block RtAudio *temporaryRTA;
717 temporaryRTA =
new RtAudio();
720 int defaultID = temporaryRTA->getDefaultInputDevice();
722 if (item.
id == defaultID)
724 VUserLog(
"Using default device: %s",json_object_to_json_string(VuoAudioInputDevice_getJson(item)));
725 setRealizedDevice(item);
734 catch (RtAudioError &error)
736 VUserLog(
"Error: Couldn't enumerate audio devices: %s", error.what());
742 VUserLog(
"No matching device found.");
773 __block
bool found =
false;
777 if (device.
id != -1 && device.
id == item.
id)
779 VUserLog(
"Matched by ID: %s",json_object_to_json_string(VuoAudioOutputDevice_getJson(item)));
780 setRealizedDevice(item);
795 VUserLog(
"Matched by model and name: %s",json_object_to_json_string(VuoAudioOutputDevice_getJson(item)));
796 setRealizedDevice(item);
809 VUserLog(
"Matched by model or name: %s",json_object_to_json_string(VuoAudioOutputDevice_getJson(item)));
810 setRealizedDevice(item);
820 __block RtAudio *temporaryRTA;
826 temporaryRTA =
new RtAudio();
829 int defaultID = temporaryRTA->getDefaultOutputDevice();
831 if (item.
id == defaultID)
833 VUserLog(
"Using default device: %s",json_object_to_json_string(VuoAudioOutputDevice_getJson(item)));
834 setRealizedDevice(item);
843 catch (RtAudioError &error)
845 VUserLog(
"Error: Couldn't enumerate audio devices: %s", error.what());
851 VUserLog(
"No matching device found.");