jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

565 lines
20KB

  1. /*
  2. Copyright (C) 2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackCoreAudioAdapter.h"
  16. #include "JackError.h"
  17. #include <unistd.h>
  18. namespace Jack
  19. {
  20. static void printError(OSStatus err)
  21. {
  22. switch (err) {
  23. case kAudioHardwareNoError:
  24. jack_log("error code : kAudioHardwareNoError");
  25. break;
  26. case kAudioConverterErr_FormatNotSupported:
  27. jack_log("error code : kAudioConverterErr_FormatNotSupported");
  28. break;
  29. case kAudioConverterErr_OperationNotSupported:
  30. jack_log("error code : kAudioConverterErr_OperationNotSupported");
  31. break;
  32. case kAudioConverterErr_PropertyNotSupported:
  33. jack_log("error code : kAudioConverterErr_PropertyNotSupported");
  34. break;
  35. case kAudioConverterErr_InvalidInputSize:
  36. jack_log("error code : kAudioConverterErr_InvalidInputSize");
  37. break;
  38. case kAudioConverterErr_InvalidOutputSize:
  39. jack_log("error code : kAudioConverterErr_InvalidOutputSize");
  40. break;
  41. case kAudioConverterErr_UnspecifiedError:
  42. jack_log("error code : kAudioConverterErr_UnspecifiedError");
  43. break;
  44. case kAudioConverterErr_BadPropertySizeError:
  45. jack_log("error code : kAudioConverterErr_BadPropertySizeError");
  46. break;
  47. case kAudioConverterErr_RequiresPacketDescriptionsError:
  48. jack_log("error code : kAudioConverterErr_RequiresPacketDescriptionsError");
  49. break;
  50. case kAudioConverterErr_InputSampleRateOutOfRange:
  51. jack_log("error code : kAudioConverterErr_InputSampleRateOutOfRange");
  52. break;
  53. case kAudioConverterErr_OutputSampleRateOutOfRange:
  54. jack_log("error code : kAudioConverterErr_OutputSampleRateOutOfRange");
  55. break;
  56. case kAudioHardwareNotRunningError:
  57. jack_log("error code : kAudioHardwareNotRunningError");
  58. break;
  59. case kAudioHardwareUnknownPropertyError:
  60. jack_log("error code : kAudioHardwareUnknownPropertyError");
  61. break;
  62. case kAudioHardwareIllegalOperationError:
  63. jack_log("error code : kAudioHardwareIllegalOperationError");
  64. break;
  65. case kAudioHardwareBadDeviceError:
  66. jack_log("error code : kAudioHardwareBadDeviceError");
  67. break;
  68. case kAudioHardwareBadStreamError:
  69. jack_log("error code : kAudioHardwareBadStreamError");
  70. break;
  71. case kAudioDeviceUnsupportedFormatError:
  72. jack_log("error code : kAudioDeviceUnsupportedFormatError");
  73. break;
  74. case kAudioDevicePermissionsError:
  75. jack_log("error code : kAudioDevicePermissionsError");
  76. break;
  77. case kAudioHardwareBadObjectError:
  78. jack_log("error code : kAudioHardwareBadObjectError");
  79. break;
  80. case kAudioHardwareUnsupportedOperationError:
  81. jack_log("error code : kAudioHardwareUnsupportedOperationError");
  82. break;
  83. default:
  84. jack_log("error code : unknown");
  85. break;
  86. }
  87. }
  88. OSStatus JackCoreAudioAdapter::SRNotificationCallback(AudioDeviceID inDevice,
  89. UInt32 inChannel,
  90. Boolean isInput,
  91. AudioDevicePropertyID inPropertyID,
  92. void* inClientData)
  93. {
  94. JackCoreAudioAdapter* driver = static_cast<JackCoreAudioAdapter*>(inClientData);
  95. switch (inPropertyID) {
  96. case kAudioDevicePropertyNominalSampleRate: {
  97. jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
  98. driver->fState = true;
  99. break;
  100. }
  101. }
  102. return noErr;
  103. }
  104. OSStatus JackCoreAudioAdapter::Render(void *inRefCon,
  105. AudioUnitRenderActionFlags *ioActionFlags,
  106. const AudioTimeStamp *inTimeStamp,
  107. UInt32 inBusNumber,
  108. UInt32 inNumberFrames,
  109. AudioBufferList *ioData)
  110. {
  111. JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon);
  112. AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
  113. bool failure = false;
  114. jack_nframes_t time1, time2;
  115. adapter->ResampleFactor(time1, time2);
  116. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  117. adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2);
  118. if (adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames) < inNumberFrames)
  119. failure = true;
  120. }
  121. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  122. adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1);
  123. if (adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames) < inNumberFrames)
  124. failure = true;
  125. }
  126. #ifdef DEBUG
  127. adapter->fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
  128. adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace());
  129. #endif
  130. // Reset all ringbuffers in case of failure
  131. if (failure) {
  132. jack_error("JackCoreAudioAdapter::Render ringbuffer failure... reset");
  133. adapter->ResetRingBuffers();
  134. }
  135. return noErr;
  136. }
  137. OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id)
  138. {
  139. OSStatus res;
  140. UInt32 theSize = sizeof(UInt32);
  141. AudioDeviceID inDefault;
  142. AudioDeviceID outDefault;
  143. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
  144. return res;
  145. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
  146. return res;
  147. jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
  148. // Get the device only if default input and ouput are the same
  149. if (inDefault == outDefault) {
  150. *id = inDefault;
  151. return noErr;
  152. } else {
  153. jack_error("Default input and output devices are not the same !!");
  154. return kAudioHardwareBadDeviceError;
  155. }
  156. }
  157. OSStatus JackCoreAudioAdapter::GetTotalChannels(AudioDeviceID device, int* channelCount, bool isInput)
  158. {
  159. OSStatus err = noErr;
  160. UInt32 outSize;
  161. Boolean outWritable;
  162. AudioBufferList* bufferList = 0;
  163. *channelCount = 0;
  164. err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
  165. if (err == noErr) {
  166. bufferList = (AudioBufferList*)malloc(outSize);
  167. err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
  168. if (err == noErr) {
  169. for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
  170. *channelCount += bufferList->mBuffers[i].mNumberChannels;
  171. }
  172. if (bufferList)
  173. free(bufferList);
  174. }
  175. return err;
  176. }
  177. // Setup
  178. int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
  179. const char* playback_driver_uid,
  180. char* capture_driver_name,
  181. char* playback_driver_name)
  182. {
  183. if (GetDefaultDevice(&fDeviceID) != noErr) {
  184. jack_error("Cannot open default device");
  185. return -1;
  186. }
  187. return 0;
  188. }
  189. int JackCoreAudioAdapter::SetupChannels(bool capturing,
  190. bool playing,
  191. int& inchannels,
  192. int& outchannels,
  193. int& in_nChannels,
  194. int& out_nChannels,
  195. bool strict)
  196. {
  197. OSStatus err = noErr;
  198. err = GetTotalChannels(fDeviceID, &in_nChannels, true);
  199. if (err != noErr) {
  200. jack_error("Cannot get input channel number");
  201. printError(err);
  202. return -1;
  203. }
  204. err = GetTotalChannels(fDeviceID, &out_nChannels, false);
  205. if (err != noErr) {
  206. jack_error("Cannot get output channel number");
  207. printError(err);
  208. return -1;
  209. }
  210. return 0;
  211. }
  212. int JackCoreAudioAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate)
  213. {
  214. OSStatus err = noErr;
  215. UInt32 outSize;
  216. Float64 sampleRate;
  217. // Setting buffer size
  218. outSize = sizeof(UInt32);
  219. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes);
  220. if (err != noErr) {
  221. jack_error("Cannot set buffer size %ld", nframes);
  222. printError(err);
  223. return -1;
  224. }
  225. // Get sample rate
  226. outSize = sizeof(Float64);
  227. err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
  228. if (err != noErr) {
  229. jack_error("Cannot get current sample rate");
  230. printError(err);
  231. return -1;
  232. }
  233. // If needed, set new sample rate
  234. if (samplerate != (jack_nframes_t)sampleRate) {
  235. sampleRate = (Float64)samplerate;
  236. // To get SR change notification
  237. err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
  238. if (err != noErr) {
  239. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
  240. printError(err);
  241. return -1;
  242. }
  243. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
  244. if (err != noErr) {
  245. jack_error("Cannot set sample rate = %ld", samplerate);
  246. printError(err);
  247. return -1;
  248. }
  249. // Waiting for SR change notification
  250. int count = 0;
  251. while (!fState && count++ < 100) {
  252. usleep(100000);
  253. jack_log("Wait count = %ld", count);
  254. }
  255. // Remove SR change notification
  256. AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
  257. }
  258. return 0;
  259. }
  260. int JackCoreAudioAdapter::SetupBuffers(int inchannels, int outchannels)
  261. {
  262. jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld output = %ld", inchannels, outchannels);
  263. // Prepare buffers
  264. fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
  265. if (fInputData == 0) {
  266. jack_error("Cannot allocate memory for input buffers");
  267. return -1;
  268. }
  269. fInputData->mNumberBuffers = inchannels;
  270. for (int i = 0; i < fCaptureChannels; i++) {
  271. fInputData->mBuffers[i].mNumberChannels = 1;
  272. fInputData->mBuffers[i].mDataByteSize = fBufferSize * sizeof(float);
  273. fInputData->mBuffers[i].mData = malloc(fBufferSize * sizeof(float));
  274. }
  275. return 0;
  276. }
  277. void JackCoreAudioAdapter::DisposeBuffers()
  278. {
  279. if (fInputData) {
  280. for (int i = 0; i < fCaptureChannels; i++)
  281. free(fInputData->mBuffers[i].mData);
  282. free(fInputData);
  283. fInputData = 0;
  284. }
  285. }
  286. int JackCoreAudioAdapter::OpenAUHAL(bool capturing,
  287. bool playing,
  288. int inchannels,
  289. int outchannels,
  290. int in_nChannels,
  291. int out_nChannels,
  292. jack_nframes_t nframes,
  293. jack_nframes_t samplerate,
  294. bool strict)
  295. {
  296. ComponentResult err1;
  297. UInt32 enableIO;
  298. AudioStreamBasicDescription srcFormat, dstFormat;
  299. jack_log("OpenAUHAL capturing = %ld playing = %ld playing = %ld outchannels = %ld in_nChannels = %ld out_nChannels = %ld ", capturing, playing, inchannels, inchannels, in_nChannels, out_nChannels);
  300. // AUHAL
  301. ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
  302. Component HALOutput = FindNextComponent(NULL, &cd);
  303. err1 = OpenAComponent(HALOutput, &fAUHAL);
  304. if (err1 != noErr) {
  305. jack_error("Error calling OpenAComponent");
  306. printError(err1);
  307. return -1;
  308. }
  309. err1 = AudioUnitInitialize(fAUHAL);
  310. if (err1 != noErr) {
  311. jack_error("Cannot initialize AUHAL unit");
  312. printError(err1);
  313. return -1;
  314. }
  315. // Start I/O
  316. enableIO = 1;
  317. if (capturing && inchannels > 0) {
  318. jack_log("Setup AUHAL input");
  319. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
  320. if (err1 != noErr) {
  321. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
  322. printError(err1);
  323. if (strict)
  324. return -1;
  325. }
  326. }
  327. if (playing && outchannels > 0) {
  328. jack_log("Setup AUHAL output");
  329. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
  330. if (err1 != noErr) {
  331. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
  332. printError(err1);
  333. if (strict)
  334. return -1;
  335. }
  336. }
  337. // Setup up choosen device, in both input and output cases
  338. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
  339. if (err1 != noErr) {
  340. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
  341. printError(err1);
  342. if (strict)
  343. return -1;
  344. }
  345. // Set buffer size
  346. if (capturing && inchannels > 0) {
  347. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*) & nframes, sizeof(UInt32));
  348. if (err1 != noErr) {
  349. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  350. printError(err1);
  351. if (strict)
  352. return -1;
  353. }
  354. }
  355. if (playing && outchannels > 0) {
  356. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*) & nframes, sizeof(UInt32));
  357. if (err1 != noErr) {
  358. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  359. printError(err1);
  360. if (strict)
  361. return -1;
  362. }
  363. }
  364. // Setup channel map
  365. if (capturing && inchannels > 0 && inchannels < in_nChannels) {
  366. SInt32 chanArr[in_nChannels];
  367. for (int i = 0; i < in_nChannels; i++) {
  368. chanArr[i] = -1;
  369. }
  370. for (int i = 0; i < inchannels; i++) {
  371. chanArr[i] = i;
  372. }
  373. AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
  374. if (err1 != noErr) {
  375. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
  376. printError(err1);
  377. }
  378. }
  379. if (playing && outchannels > 0 && outchannels < out_nChannels) {
  380. SInt32 chanArr[out_nChannels];
  381. for (int i = 0; i < out_nChannels; i++) {
  382. chanArr[i] = -1;
  383. }
  384. for (int i = 0; i < outchannels; i++) {
  385. chanArr[i] = i;
  386. }
  387. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
  388. if (err1 != noErr) {
  389. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
  390. printError(err1);
  391. }
  392. }
  393. // Setup stream converters
  394. jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
  395. srcFormat.mSampleRate = samplerate;
  396. srcFormat.mFormatID = kAudioFormatLinearPCM;
  397. srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  398. srcFormat.mBytesPerPacket = sizeof(float);
  399. srcFormat.mFramesPerPacket = 1;
  400. srcFormat.mBytesPerFrame = sizeof(float);
  401. srcFormat.mChannelsPerFrame = outchannels;
  402. srcFormat.mBitsPerChannel = 32;
  403. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
  404. if (err1 != noErr) {
  405. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
  406. printError(err1);
  407. }
  408. jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
  409. dstFormat.mSampleRate = samplerate;
  410. dstFormat.mFormatID = kAudioFormatLinearPCM;
  411. dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  412. dstFormat.mBytesPerPacket = sizeof(float);
  413. dstFormat.mFramesPerPacket = 1;
  414. dstFormat.mBytesPerFrame = sizeof(float);
  415. dstFormat.mChannelsPerFrame = inchannels;
  416. dstFormat.mBitsPerChannel = 32;
  417. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
  418. if (err1 != noErr) {
  419. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
  420. printError(err1);
  421. }
  422. // Setup callbacks
  423. if (inchannels > 0 && outchannels == 0) {
  424. AURenderCallbackStruct output;
  425. output.inputProc = Render;
  426. output.inputProcRefCon = this;
  427. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
  428. if (err1 != noErr) {
  429. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
  430. printError(err1);
  431. return -1;
  432. }
  433. } else {
  434. AURenderCallbackStruct output;
  435. output.inputProc = Render;
  436. output.inputProcRefCon = this;
  437. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
  438. if (err1 != noErr) {
  439. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
  440. printError(err1);
  441. return -1;
  442. }
  443. }
  444. return 0;
  445. }
  446. void JackCoreAudioAdapter::CloseAUHAL()
  447. {
  448. AudioUnitUninitialize(fAUHAL);
  449. CloseComponent(fAUHAL);
  450. }
  451. int JackCoreAudioAdapter::Open()
  452. {
  453. OSStatus err;
  454. int in_nChannels = 0;
  455. int out_nChannels = 0;
  456. if (SetupDevices("", "", "", "") < 0)
  457. return -1;
  458. if (SetupChannels(true, true, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0)
  459. return -1;
  460. if (SetupBufferSizeAndSampleRate(fBufferSize, fSampleRate) < 0)
  461. return -1;
  462. if (OpenAUHAL(true, true, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fBufferSize, fSampleRate, true) < 0)
  463. goto error;
  464. if (SetupBuffers(fCaptureChannels, fPlaybackChannels) < 0)
  465. goto error;
  466. err = AudioOutputUnitStart(fAUHAL);
  467. if (err != noErr)
  468. goto error;
  469. return 0;
  470. error:
  471. Close();
  472. return -1;
  473. }
  474. int JackCoreAudioAdapter::Close()
  475. {
  476. #ifdef DEBUG
  477. fTable.Save();
  478. #endif
  479. AudioOutputUnitStop(fAUHAL);
  480. DisposeBuffers();
  481. CloseAUHAL();
  482. return 0;
  483. }
  484. int JackCoreAudioAdapter::SetBufferSize(jack_nframes_t buffer_size)
  485. {
  486. JackAudioAdapterInterface::SetBufferSize(buffer_size);
  487. Close();
  488. return Open();
  489. }
  490. }