audio_driver_coreaudio.cpp 22 KB

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