audio_driver_coreaudio.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. /*************************************************************************/
  2. /* audio_driver_coreaudio.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #ifdef COREAUDIO_ENABLED
  31. #include "audio_driver_coreaudio.h"
  32. #include "core/os/os.h"
  33. #include "core/project_settings.h"
  34. #define kOutputBus 0
  35. #define kInputBus 1
  36. #ifdef OSX_ENABLED
  37. OSStatus AudioDriverCoreAudio::input_device_address_cb(AudioObjectID inObjectID,
  38. UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses,
  39. void *inClientData) {
  40. AudioDriverCoreAudio *driver = (AudioDriverCoreAudio *)inClientData;
  41. // If our selected device is the Default call set_device to update the
  42. // kAudioOutputUnitProperty_CurrentDevice property
  43. if (driver->capture_device_name == "Default") {
  44. driver->capture_set_device("Default");
  45. }
  46. return noErr;
  47. }
  48. OSStatus AudioDriverCoreAudio::output_device_address_cb(AudioObjectID inObjectID,
  49. UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses,
  50. void *inClientData) {
  51. AudioDriverCoreAudio *driver = (AudioDriverCoreAudio *)inClientData;
  52. // If our selected device is the Default call set_device to update the
  53. // kAudioOutputUnitProperty_CurrentDevice property
  54. if (driver->device_name == "Default") {
  55. driver->set_device("Default");
  56. }
  57. return noErr;
  58. }
  59. #endif
  60. Error AudioDriverCoreAudio::init() {
  61. mutex = Mutex::create();
  62. AudioComponentDescription desc;
  63. zeromem(&desc, sizeof(desc));
  64. desc.componentType = kAudioUnitType_Output;
  65. #ifdef OSX_ENABLED
  66. desc.componentSubType = kAudioUnitSubType_HALOutput;
  67. #else
  68. desc.componentSubType = kAudioUnitSubType_RemoteIO;
  69. #endif
  70. desc.componentManufacturer = kAudioUnitManufacturer_Apple;
  71. AudioComponent comp = AudioComponentFindNext(NULL, &desc);
  72. ERR_FAIL_COND_V(comp == NULL, FAILED);
  73. OSStatus result = AudioComponentInstanceNew(comp, &audio_unit);
  74. ERR_FAIL_COND_V(result != noErr, FAILED);
  75. #ifdef OSX_ENABLED
  76. AudioObjectPropertyAddress prop;
  77. prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
  78. prop.mScope = kAudioObjectPropertyScopeGlobal;
  79. prop.mElement = kAudioObjectPropertyElementMaster;
  80. result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &output_device_address_cb, this);
  81. ERR_FAIL_COND_V(result != noErr, FAILED);
  82. #endif
  83. AudioStreamBasicDescription strdesc;
  84. zeromem(&strdesc, sizeof(strdesc));
  85. UInt32 size = sizeof(strdesc);
  86. result = AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kOutputBus, &strdesc, &size);
  87. ERR_FAIL_COND_V(result != noErr, FAILED);
  88. switch (strdesc.mChannelsPerFrame) {
  89. case 2: // Stereo
  90. case 4: // Surround 3.1
  91. case 6: // Surround 5.1
  92. case 8: // Surround 7.1
  93. channels = strdesc.mChannelsPerFrame;
  94. break;
  95. default:
  96. // Unknown number of channels, default to stereo
  97. channels = 2;
  98. break;
  99. }
  100. mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
  101. zeromem(&strdesc, sizeof(strdesc));
  102. strdesc.mFormatID = kAudioFormatLinearPCM;
  103. strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
  104. strdesc.mChannelsPerFrame = channels;
  105. strdesc.mSampleRate = mix_rate;
  106. strdesc.mFramesPerPacket = 1;
  107. strdesc.mBitsPerChannel = 16;
  108. strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
  109. strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
  110. result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc));
  111. ERR_FAIL_COND_V(result != noErr, FAILED);
  112. int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
  113. // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
  114. buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
  115. #ifdef OSX_ENABLED
  116. result = AudioUnitSetProperty(audio_unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, kOutputBus, &buffer_frames, sizeof(UInt32));
  117. ERR_FAIL_COND_V(result != noErr, FAILED);
  118. #endif
  119. unsigned int buffer_size = buffer_frames * channels;
  120. samples_in.resize(buffer_size);
  121. input_buf.resize(buffer_size);
  122. print_verbose("CoreAudio: detected " + itos(channels) + " channels");
  123. print_verbose("CoreAudio: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");
  124. AURenderCallbackStruct callback;
  125. zeromem(&callback, sizeof(AURenderCallbackStruct));
  126. callback.inputProc = &AudioDriverCoreAudio::output_callback;
  127. callback.inputProcRefCon = this;
  128. result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback));
  129. ERR_FAIL_COND_V(result != noErr, FAILED);
  130. result = AudioUnitInitialize(audio_unit);
  131. ERR_FAIL_COND_V(result != noErr, FAILED);
  132. if (GLOBAL_GET("audio/enable_audio_input")) {
  133. return capture_init();
  134. }
  135. return OK;
  136. }
  137. OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon,
  138. AudioUnitRenderActionFlags *ioActionFlags,
  139. const AudioTimeStamp *inTimeStamp,
  140. UInt32 inBusNumber, UInt32 inNumberFrames,
  141. AudioBufferList *ioData) {
  142. AudioDriverCoreAudio *ad = (AudioDriverCoreAudio *)inRefCon;
  143. if (!ad->active || !ad->try_lock()) {
  144. for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
  145. AudioBuffer *abuf = &ioData->mBuffers[i];
  146. zeromem(abuf->mData, abuf->mDataByteSize);
  147. };
  148. return 0;
  149. };
  150. ad->start_counting_ticks();
  151. for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
  152. AudioBuffer *abuf = &ioData->mBuffers[i];
  153. int frames_left = inNumberFrames;
  154. int16_t *out = (int16_t *)abuf->mData;
  155. while (frames_left) {
  156. int frames = MIN(frames_left, ad->buffer_frames);
  157. ad->audio_server_process(frames, ad->samples_in.ptrw());
  158. for (int j = 0; j < frames * ad->channels; j++) {
  159. out[j] = ad->samples_in[j] >> 16;
  160. }
  161. frames_left -= frames;
  162. out += frames * ad->channels;
  163. };
  164. };
  165. ad->stop_counting_ticks();
  166. ad->unlock();
  167. return 0;
  168. };
  169. OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon,
  170. AudioUnitRenderActionFlags *ioActionFlags,
  171. const AudioTimeStamp *inTimeStamp,
  172. UInt32 inBusNumber, UInt32 inNumberFrames,
  173. AudioBufferList *ioData) {
  174. AudioDriverCoreAudio *ad = (AudioDriverCoreAudio *)inRefCon;
  175. if (!ad->active) {
  176. return 0;
  177. }
  178. ad->lock();
  179. AudioBufferList bufferList;
  180. bufferList.mNumberBuffers = 1;
  181. bufferList.mBuffers[0].mData = ad->input_buf.ptrw();
  182. bufferList.mBuffers[0].mNumberChannels = ad->capture_channels;
  183. bufferList.mBuffers[0].mDataByteSize = ad->input_buf.size() * sizeof(int16_t);
  184. OSStatus result = AudioUnitRender(ad->input_unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList);
  185. if (result == noErr) {
  186. for (int i = 0; i < inNumberFrames * ad->capture_channels; i++) {
  187. int32_t sample = ad->input_buf[i] << 16;
  188. ad->input_buffer_write(sample);
  189. if (ad->capture_channels == 1) {
  190. // In case input device is single channel convert it to Stereo
  191. ad->input_buffer_write(sample);
  192. }
  193. }
  194. } else {
  195. ERR_PRINTS("AudioUnitRender failed, code: " + itos(result));
  196. }
  197. ad->unlock();
  198. return result;
  199. }
  200. void AudioDriverCoreAudio::start() {
  201. if (!active) {
  202. OSStatus result = AudioOutputUnitStart(audio_unit);
  203. if (result != noErr) {
  204. ERR_PRINTS("AudioOutputUnitStart failed, code: " + itos(result));
  205. } else {
  206. active = true;
  207. }
  208. }
  209. };
  210. void AudioDriverCoreAudio::stop() {
  211. if (active) {
  212. OSStatus result = AudioOutputUnitStop(audio_unit);
  213. if (result != noErr) {
  214. ERR_PRINTS("AudioOutputUnitStop failed, code: " + itos(result));
  215. } else {
  216. active = false;
  217. }
  218. }
  219. }
  220. int AudioDriverCoreAudio::get_mix_rate() const {
  221. return mix_rate;
  222. };
  223. AudioDriver::SpeakerMode AudioDriverCoreAudio::get_speaker_mode() const {
  224. return get_speaker_mode_by_total_channels(channels);
  225. };
  226. void AudioDriverCoreAudio::lock() {
  227. if (mutex)
  228. mutex->lock();
  229. };
  230. void AudioDriverCoreAudio::unlock() {
  231. if (mutex)
  232. mutex->unlock();
  233. };
  234. bool AudioDriverCoreAudio::try_lock() {
  235. if (mutex)
  236. return mutex->try_lock() == OK;
  237. return true;
  238. }
  239. void AudioDriverCoreAudio::finish() {
  240. capture_finish();
  241. if (audio_unit) {
  242. OSStatus result;
  243. lock();
  244. AURenderCallbackStruct callback;
  245. zeromem(&callback, sizeof(AURenderCallbackStruct));
  246. result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback));
  247. if (result != noErr) {
  248. ERR_PRINT("AudioUnitSetProperty failed");
  249. }
  250. if (active) {
  251. result = AudioOutputUnitStop(audio_unit);
  252. if (result != noErr) {
  253. ERR_PRINT("AudioOutputUnitStop failed");
  254. }
  255. active = false;
  256. }
  257. result = AudioUnitUninitialize(audio_unit);
  258. if (result != noErr) {
  259. ERR_PRINT("AudioUnitUninitialize failed");
  260. }
  261. #ifdef OSX_ENABLED
  262. AudioObjectPropertyAddress prop;
  263. prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
  264. prop.mScope = kAudioObjectPropertyScopeGlobal;
  265. prop.mElement = kAudioObjectPropertyElementMaster;
  266. result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop, &output_device_address_cb, this);
  267. if (result != noErr) {
  268. ERR_PRINT("AudioObjectRemovePropertyListener failed");
  269. }
  270. #endif
  271. result = AudioComponentInstanceDispose(audio_unit);
  272. if (result != noErr) {
  273. ERR_PRINT("AudioComponentInstanceDispose failed");
  274. }
  275. audio_unit = NULL;
  276. unlock();
  277. }
  278. if (mutex) {
  279. memdelete(mutex);
  280. mutex = NULL;
  281. }
  282. }
  283. Error AudioDriverCoreAudio::capture_init() {
  284. AudioComponentDescription desc;
  285. zeromem(&desc, sizeof(desc));
  286. desc.componentType = kAudioUnitType_Output;
  287. #ifdef OSX_ENABLED
  288. desc.componentSubType = kAudioUnitSubType_HALOutput;
  289. #else
  290. desc.componentSubType = kAudioUnitSubType_RemoteIO;
  291. #endif
  292. desc.componentManufacturer = kAudioUnitManufacturer_Apple;
  293. AudioComponent comp = AudioComponentFindNext(NULL, &desc);
  294. ERR_FAIL_COND_V(comp == NULL, FAILED);
  295. OSStatus result = AudioComponentInstanceNew(comp, &input_unit);
  296. ERR_FAIL_COND_V(result != noErr, FAILED);
  297. #ifdef OSX_ENABLED
  298. AudioObjectPropertyAddress prop;
  299. prop.mSelector = kAudioHardwarePropertyDefaultInputDevice;
  300. prop.mScope = kAudioObjectPropertyScopeGlobal;
  301. prop.mElement = kAudioObjectPropertyElementMaster;
  302. result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this);
  303. ERR_FAIL_COND_V(result != noErr, FAILED);
  304. #endif
  305. UInt32 flag = 1;
  306. result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag));
  307. ERR_FAIL_COND_V(result != noErr, FAILED);
  308. flag = 0;
  309. result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag));
  310. ERR_FAIL_COND_V(result != noErr, FAILED);
  311. UInt32 size;
  312. #ifdef OSX_ENABLED
  313. AudioDeviceID deviceId;
  314. size = sizeof(AudioDeviceID);
  315. AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  316. result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, NULL, &size, &deviceId);
  317. ERR_FAIL_COND_V(result != noErr, FAILED);
  318. result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID));
  319. ERR_FAIL_COND_V(result != noErr, FAILED);
  320. #endif
  321. AudioStreamBasicDescription strdesc;
  322. zeromem(&strdesc, sizeof(strdesc));
  323. size = sizeof(strdesc);
  324. result = AudioUnitGetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, &size);
  325. ERR_FAIL_COND_V(result != noErr, FAILED);
  326. switch (strdesc.mChannelsPerFrame) {
  327. case 1: // Mono
  328. capture_channels = 1;
  329. break;
  330. case 2: // Stereo
  331. capture_channels = 2;
  332. break;
  333. default:
  334. // Unknown number of channels, default to stereo
  335. capture_channels = 2;
  336. break;
  337. }
  338. mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE);
  339. zeromem(&strdesc, sizeof(strdesc));
  340. strdesc.mFormatID = kAudioFormatLinearPCM;
  341. strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
  342. strdesc.mChannelsPerFrame = capture_channels;
  343. strdesc.mSampleRate = mix_rate;
  344. strdesc.mFramesPerPacket = 1;
  345. strdesc.mBitsPerChannel = 16;
  346. strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
  347. strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
  348. result = AudioUnitSetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc));
  349. ERR_FAIL_COND_V(result != noErr, FAILED);
  350. AURenderCallbackStruct callback;
  351. zeromem(&callback, sizeof(AURenderCallbackStruct));
  352. callback.inputProc = &AudioDriverCoreAudio::input_callback;
  353. callback.inputProcRefCon = this;
  354. result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, kInputBus, &callback, sizeof(callback));
  355. ERR_FAIL_COND_V(result != noErr, FAILED);
  356. result = AudioUnitInitialize(input_unit);
  357. ERR_FAIL_COND_V(result != noErr, FAILED);
  358. return OK;
  359. }
  360. void AudioDriverCoreAudio::capture_finish() {
  361. if (input_unit) {
  362. lock();
  363. AURenderCallbackStruct callback;
  364. zeromem(&callback, sizeof(AURenderCallbackStruct));
  365. OSStatus result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(callback));
  366. if (result != noErr) {
  367. ERR_PRINT("AudioUnitSetProperty failed");
  368. }
  369. result = AudioUnitUninitialize(input_unit);
  370. if (result != noErr) {
  371. ERR_PRINT("AudioUnitUninitialize failed");
  372. }
  373. #ifdef OSX_ENABLED
  374. AudioObjectPropertyAddress prop;
  375. prop.mSelector = kAudioHardwarePropertyDefaultInputDevice;
  376. prop.mScope = kAudioObjectPropertyScopeGlobal;
  377. prop.mElement = kAudioObjectPropertyElementMaster;
  378. result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this);
  379. if (result != noErr) {
  380. ERR_PRINT("AudioObjectRemovePropertyListener failed");
  381. }
  382. #endif
  383. result = AudioComponentInstanceDispose(input_unit);
  384. if (result != noErr) {
  385. ERR_PRINT("AudioComponentInstanceDispose failed");
  386. }
  387. input_unit = NULL;
  388. unlock();
  389. }
  390. }
  391. Error AudioDriverCoreAudio::capture_start() {
  392. input_buffer_init(buffer_frames);
  393. OSStatus result = AudioOutputUnitStart(input_unit);
  394. if (result != noErr) {
  395. ERR_PRINTS("AudioOutputUnitStart failed, code: " + itos(result));
  396. }
  397. return OK;
  398. }
  399. Error AudioDriverCoreAudio::capture_stop() {
  400. if (input_unit) {
  401. OSStatus result = AudioOutputUnitStop(input_unit);
  402. if (result != noErr) {
  403. ERR_PRINTS("AudioOutputUnitStop failed, code: " + itos(result));
  404. }
  405. }
  406. return OK;
  407. }
  408. #ifdef OSX_ENABLED
  409. Array AudioDriverCoreAudio::_get_device_list(bool capture) {
  410. Array list;
  411. list.push_back("Default");
  412. AudioObjectPropertyAddress prop;
  413. prop.mSelector = kAudioHardwarePropertyDevices;
  414. prop.mScope = kAudioObjectPropertyScopeGlobal;
  415. prop.mElement = kAudioObjectPropertyElementMaster;
  416. UInt32 size = 0;
  417. AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, NULL, &size);
  418. AudioDeviceID *audioDevices = (AudioDeviceID *)malloc(size);
  419. AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &size, audioDevices);
  420. UInt32 deviceCount = size / sizeof(AudioDeviceID);
  421. for (UInt32 i = 0; i < deviceCount; i++) {
  422. prop.mScope = capture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;
  423. prop.mSelector = kAudioDevicePropertyStreamConfiguration;
  424. AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, NULL, &size);
  425. AudioBufferList *bufferList = (AudioBufferList *)malloc(size);
  426. AudioObjectGetPropertyData(audioDevices[i], &prop, 0, NULL, &size, bufferList);
  427. UInt32 channelCount = 0;
  428. for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
  429. channelCount += bufferList->mBuffers[j].mNumberChannels;
  430. free(bufferList);
  431. if (channelCount >= 1) {
  432. CFStringRef cfname;
  433. size = sizeof(CFStringRef);
  434. prop.mSelector = kAudioObjectPropertyName;
  435. AudioObjectGetPropertyData(audioDevices[i], &prop, 0, NULL, &size, &cfname);
  436. CFIndex length = CFStringGetLength(cfname);
  437. CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
  438. char *buffer = (char *)malloc(maxSize);
  439. if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) {
  440. // Append the ID to the name in case we have devices with duplicate name
  441. list.push_back(String(buffer) + " (" + itos(audioDevices[i]) + ")");
  442. }
  443. free(buffer);
  444. }
  445. }
  446. free(audioDevices);
  447. return list;
  448. }
  449. void AudioDriverCoreAudio::_set_device(const String &device, bool capture) {
  450. AudioDeviceID deviceId;
  451. bool found = false;
  452. if (device != "Default") {
  453. AudioObjectPropertyAddress prop;
  454. prop.mSelector = kAudioHardwarePropertyDevices;
  455. prop.mScope = kAudioObjectPropertyScopeGlobal;
  456. prop.mElement = kAudioObjectPropertyElementMaster;
  457. UInt32 size = 0;
  458. AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, NULL, &size);
  459. AudioDeviceID *audioDevices = (AudioDeviceID *)malloc(size);
  460. AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &size, audioDevices);
  461. UInt32 deviceCount = size / sizeof(AudioDeviceID);
  462. for (UInt32 i = 0; i < deviceCount && !found; i++) {
  463. prop.mScope = capture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;
  464. prop.mSelector = kAudioDevicePropertyStreamConfiguration;
  465. AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, NULL, &size);
  466. AudioBufferList *bufferList = (AudioBufferList *)malloc(size);
  467. AudioObjectGetPropertyData(audioDevices[i], &prop, 0, NULL, &size, bufferList);
  468. UInt32 channelCount = 0;
  469. for (UInt32 j = 0; j < bufferList->mNumberBuffers; j++)
  470. channelCount += bufferList->mBuffers[j].mNumberChannels;
  471. free(bufferList);
  472. if (channelCount >= 1) {
  473. CFStringRef cfname;
  474. size = sizeof(CFStringRef);
  475. prop.mSelector = kAudioObjectPropertyName;
  476. AudioObjectGetPropertyData(audioDevices[i], &prop, 0, NULL, &size, &cfname);
  477. CFIndex length = CFStringGetLength(cfname);
  478. CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
  479. char *buffer = (char *)malloc(maxSize);
  480. if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) {
  481. String name = String(buffer) + " (" + itos(audioDevices[i]) + ")";
  482. if (name == device) {
  483. deviceId = audioDevices[i];
  484. found = true;
  485. }
  486. }
  487. free(buffer);
  488. }
  489. }
  490. free(audioDevices);
  491. }
  492. if (!found) {
  493. // If we haven't found the desired device get the system default one
  494. UInt32 size = sizeof(AudioDeviceID);
  495. UInt32 elem = capture ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice;
  496. AudioObjectPropertyAddress property = { elem, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  497. OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, NULL, &size, &deviceId);
  498. ERR_FAIL_COND(result != noErr);
  499. found = true;
  500. }
  501. if (found) {
  502. OSStatus result = AudioUnitSetProperty(capture ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID));
  503. ERR_FAIL_COND(result != noErr);
  504. if (capture) {
  505. // Reset audio input to keep synchronisation.
  506. input_position = 0;
  507. input_size = 0;
  508. }
  509. }
  510. }
  511. Array AudioDriverCoreAudio::get_device_list() {
  512. return _get_device_list();
  513. }
  514. String AudioDriverCoreAudio::get_device() {
  515. return device_name;
  516. }
  517. void AudioDriverCoreAudio::set_device(String device) {
  518. device_name = device;
  519. if (active) {
  520. _set_device(device_name);
  521. }
  522. }
  523. void AudioDriverCoreAudio::capture_set_device(const String &p_name) {
  524. capture_device_name = p_name;
  525. if (active) {
  526. _set_device(capture_device_name, true);
  527. }
  528. }
  529. Array AudioDriverCoreAudio::capture_get_device_list() {
  530. return _get_device_list(true);
  531. }
  532. String AudioDriverCoreAudio::capture_get_device() {
  533. return capture_device_name;
  534. }
  535. #endif
  536. AudioDriverCoreAudio::AudioDriverCoreAudio() :
  537. audio_unit(NULL),
  538. input_unit(NULL),
  539. active(false),
  540. mutex(NULL),
  541. device_name("Default"),
  542. capture_device_name("Default"),
  543. mix_rate(0),
  544. channels(2),
  545. capture_channels(2),
  546. buffer_frames(0) {
  547. samples_in.clear();
  548. }
  549. AudioDriverCoreAudio::~AudioDriverCoreAudio(){};
  550. #endif