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.

557 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 "JackCoreAudioIOAdapter.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 JackCoreAudioIOAdapter::SRNotificationCallback(AudioDeviceID inDevice,
  89. UInt32 inChannel,
  90. Boolean isInput,
  91. AudioDevicePropertyID inPropertyID,
  92. void* inClientData)
  93. {
  94. JackCoreAudioIOAdapter* driver = static_cast<JackCoreAudioIOAdapter*>(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 JackCoreAudioIOAdapter::Render(void *inRefCon,
  105. AudioUnitRenderActionFlags *ioActionFlags,
  106. const AudioTimeStamp *inTimeStamp,
  107. UInt32 inBusNumber,
  108. UInt32 inNumberFrames,
  109. AudioBufferList *ioData)
  110. {
  111. JackCoreAudioIOAdapter* adapter = static_cast<JackCoreAudioIOAdapter*>(inRefCon);
  112. AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
  113. jack_nframes_t time1, time2;
  114. adapter->ResampleFactor(time1, time2);
  115. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  116. adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2);
  117. adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames);
  118. }
  119. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  120. adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1);
  121. adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames);
  122. }
  123. #ifdef DEBUG
  124. adapter->fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
  125. adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace());
  126. #endif
  127. return noErr;
  128. }
  129. OSStatus JackCoreAudioIOAdapter::GetDefaultDevice(AudioDeviceID* id)
  130. {
  131. OSStatus res;
  132. UInt32 theSize = sizeof(UInt32);
  133. AudioDeviceID inDefault;
  134. AudioDeviceID outDefault;
  135. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
  136. return res;
  137. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
  138. return res;
  139. jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
  140. // Get the device only if default input and ouput are the same
  141. if (inDefault == outDefault) {
  142. *id = inDefault;
  143. return noErr;
  144. } else {
  145. jack_error("Default input and output devices are not the same !!");
  146. return kAudioHardwareBadDeviceError;
  147. }
  148. }
  149. OSStatus JackCoreAudioIOAdapter::GetTotalChannels(AudioDeviceID device, int* channelCount, bool isInput)
  150. {
  151. OSStatus err = noErr;
  152. UInt32 outSize;
  153. Boolean outWritable;
  154. AudioBufferList* bufferList = 0;
  155. *channelCount = 0;
  156. err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
  157. if (err == noErr) {
  158. bufferList = (AudioBufferList*)malloc(outSize);
  159. err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
  160. if (err == noErr) {
  161. for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
  162. *channelCount += bufferList->mBuffers[i].mNumberChannels;
  163. }
  164. if (bufferList)
  165. free(bufferList);
  166. }
  167. return err;
  168. }
  169. // Setup
  170. int JackCoreAudioIOAdapter::SetupDevices(const char* capture_driver_uid,
  171. const char* playback_driver_uid,
  172. char* capture_driver_name,
  173. char* playback_driver_name)
  174. {
  175. if (GetDefaultDevice(&fDeviceID) != noErr) {
  176. jack_error("Cannot open default device");
  177. return -1;
  178. }
  179. return 0;
  180. }
  181. int JackCoreAudioIOAdapter::SetupChannels(bool capturing,
  182. bool playing,
  183. int& inchannels,
  184. int& outchannels,
  185. int& in_nChannels,
  186. int& out_nChannels,
  187. bool strict)
  188. {
  189. OSStatus err = noErr;
  190. err = GetTotalChannels(fDeviceID, &in_nChannels, true);
  191. if (err != noErr) {
  192. jack_error("Cannot get input channel number");
  193. printError(err);
  194. return -1;
  195. }
  196. err = GetTotalChannels(fDeviceID, &out_nChannels, false);
  197. if (err != noErr) {
  198. jack_error("Cannot get output channel number");
  199. printError(err);
  200. return -1;
  201. }
  202. return 0;
  203. }
  204. int JackCoreAudioIOAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate)
  205. {
  206. OSStatus err = noErr;
  207. UInt32 outSize;
  208. Float64 sampleRate;
  209. // Setting buffer size
  210. outSize = sizeof(UInt32);
  211. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes);
  212. if (err != noErr) {
  213. jack_error("Cannot set buffer size %ld", nframes);
  214. printError(err);
  215. return -1;
  216. }
  217. // Get sample rate
  218. outSize = sizeof(Float64);
  219. err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
  220. if (err != noErr) {
  221. jack_error("Cannot get current sample rate");
  222. printError(err);
  223. return -1;
  224. }
  225. // If needed, set new sample rate
  226. if (samplerate != (jack_nframes_t)sampleRate) {
  227. sampleRate = (Float64)samplerate;
  228. // To get SR change notification
  229. err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
  230. if (err != noErr) {
  231. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
  232. printError(err);
  233. return -1;
  234. }
  235. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
  236. if (err != noErr) {
  237. jack_error("Cannot set sample rate = %ld", samplerate);
  238. printError(err);
  239. return -1;
  240. }
  241. // Waiting for SR change notification
  242. int count = 0;
  243. while (!fState && count++ < 100) {
  244. usleep(100000);
  245. jack_log("Wait count = %ld", count);
  246. }
  247. // Remove SR change notification
  248. AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
  249. }
  250. return 0;
  251. }
  252. int JackCoreAudioIOAdapter::SetupBuffers(int inchannels, int outchannels)
  253. {
  254. jack_log("JackCoreAudioIOAdapter::SetupBuffers: input = %ld output = %ld", inchannels, outchannels);
  255. // Prepare buffers
  256. fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
  257. if (fInputData == 0) {
  258. jack_error("Cannot allocate memory for input buffers");
  259. return -1;
  260. }
  261. fInputData->mNumberBuffers = inchannels;
  262. for (int i = 0; i < fCaptureChannels; i++) {
  263. fInputData->mBuffers[i].mNumberChannels = 1;
  264. fInputData->mBuffers[i].mDataByteSize = fBufferSize * sizeof(float);
  265. fInputData->mBuffers[i].mData = malloc(fBufferSize * sizeof(float));
  266. }
  267. return 0;
  268. }
  269. void JackCoreAudioIOAdapter::DisposeBuffers()
  270. {
  271. if (fInputData) {
  272. for (int i = 0; i < fCaptureChannels; i++)
  273. free(fInputData->mBuffers[i].mData);
  274. free(fInputData);
  275. fInputData = 0;
  276. }
  277. }
  278. int JackCoreAudioIOAdapter::OpenAUHAL(bool capturing,
  279. bool playing,
  280. int inchannels,
  281. int outchannels,
  282. int in_nChannels,
  283. int out_nChannels,
  284. jack_nframes_t nframes,
  285. jack_nframes_t samplerate,
  286. bool strict)
  287. {
  288. ComponentResult err1;
  289. UInt32 enableIO;
  290. AudioStreamBasicDescription srcFormat, dstFormat;
  291. 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);
  292. // AUHAL
  293. ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
  294. Component HALOutput = FindNextComponent(NULL, &cd);
  295. err1 = OpenAComponent(HALOutput, &fAUHAL);
  296. if (err1 != noErr) {
  297. jack_error("Error calling OpenAComponent");
  298. printError(err1);
  299. return -1;
  300. }
  301. err1 = AudioUnitInitialize(fAUHAL);
  302. if (err1 != noErr) {
  303. jack_error("Cannot initialize AUHAL unit");
  304. printError(err1);
  305. return -1;
  306. }
  307. // Start I/O
  308. enableIO = 1;
  309. if (capturing && inchannels > 0) {
  310. jack_log("Setup AUHAL input");
  311. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
  312. if (err1 != noErr) {
  313. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
  314. printError(err1);
  315. if (strict)
  316. return -1;
  317. }
  318. }
  319. if (playing && outchannels > 0) {
  320. jack_log("Setup AUHAL output");
  321. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
  322. if (err1 != noErr) {
  323. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
  324. printError(err1);
  325. if (strict)
  326. return -1;
  327. }
  328. }
  329. // Setup up choosen device, in both input and output cases
  330. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
  331. if (err1 != noErr) {
  332. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
  333. printError(err1);
  334. if (strict)
  335. return -1;
  336. }
  337. // Set buffer size
  338. if (capturing && inchannels > 0) {
  339. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*) & nframes, sizeof(UInt32));
  340. if (err1 != noErr) {
  341. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  342. printError(err1);
  343. if (strict)
  344. return -1;
  345. }
  346. }
  347. if (playing && outchannels > 0) {
  348. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*) & nframes, sizeof(UInt32));
  349. if (err1 != noErr) {
  350. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  351. printError(err1);
  352. if (strict)
  353. return -1;
  354. }
  355. }
  356. // Setup channel map
  357. if (capturing && inchannels > 0 && inchannels < in_nChannels) {
  358. SInt32 chanArr[in_nChannels];
  359. for (int i = 0; i < in_nChannels; i++) {
  360. chanArr[i] = -1;
  361. }
  362. for (int i = 0; i < inchannels; i++) {
  363. chanArr[i] = i;
  364. }
  365. AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
  366. if (err1 != noErr) {
  367. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
  368. printError(err1);
  369. }
  370. }
  371. if (playing && outchannels > 0 && outchannels < out_nChannels) {
  372. SInt32 chanArr[out_nChannels];
  373. for (int i = 0; i < out_nChannels; i++) {
  374. chanArr[i] = -1;
  375. }
  376. for (int i = 0; i < outchannels; i++) {
  377. chanArr[i] = i;
  378. }
  379. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
  380. if (err1 != noErr) {
  381. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
  382. printError(err1);
  383. }
  384. }
  385. // Setup stream converters
  386. jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
  387. srcFormat.mSampleRate = samplerate;
  388. srcFormat.mFormatID = kAudioFormatLinearPCM;
  389. srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  390. srcFormat.mBytesPerPacket = sizeof(float);
  391. srcFormat.mFramesPerPacket = 1;
  392. srcFormat.mBytesPerFrame = sizeof(float);
  393. srcFormat.mChannelsPerFrame = outchannels;
  394. srcFormat.mBitsPerChannel = 32;
  395. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
  396. if (err1 != noErr) {
  397. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
  398. printError(err1);
  399. }
  400. jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
  401. dstFormat.mSampleRate = samplerate;
  402. dstFormat.mFormatID = kAudioFormatLinearPCM;
  403. dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  404. dstFormat.mBytesPerPacket = sizeof(float);
  405. dstFormat.mFramesPerPacket = 1;
  406. dstFormat.mBytesPerFrame = sizeof(float);
  407. dstFormat.mChannelsPerFrame = inchannels;
  408. dstFormat.mBitsPerChannel = 32;
  409. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
  410. if (err1 != noErr) {
  411. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
  412. printError(err1);
  413. }
  414. // Setup callbacks
  415. if (inchannels > 0 && outchannels == 0) {
  416. AURenderCallbackStruct output;
  417. output.inputProc = Render;
  418. output.inputProcRefCon = this;
  419. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
  420. if (err1 != noErr) {
  421. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
  422. printError(err1);
  423. return -1;
  424. }
  425. } else {
  426. AURenderCallbackStruct output;
  427. output.inputProc = Render;
  428. output.inputProcRefCon = this;
  429. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
  430. if (err1 != noErr) {
  431. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
  432. printError(err1);
  433. return -1;
  434. }
  435. }
  436. return 0;
  437. }
  438. void JackCoreAudioIOAdapter::CloseAUHAL()
  439. {
  440. AudioUnitUninitialize(fAUHAL);
  441. CloseComponent(fAUHAL);
  442. }
  443. int JackCoreAudioIOAdapter::Open()
  444. {
  445. OSStatus err;
  446. int in_nChannels = 0;
  447. int out_nChannels = 0;
  448. if (SetupDevices("", "", "", "") < 0)
  449. return -1;
  450. if (SetupChannels(true, true, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0)
  451. return -1;
  452. if (SetupBufferSizeAndSampleRate(fBufferSize, fSampleRate) < 0)
  453. return -1;
  454. if (OpenAUHAL(true, true, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fBufferSize, fSampleRate, true) < 0)
  455. goto error;
  456. if (SetupBuffers(fCaptureChannels, fPlaybackChannels) < 0)
  457. goto error;
  458. err = AudioOutputUnitStart(fAUHAL);
  459. if (err != noErr)
  460. goto error;
  461. return 0;
  462. error:
  463. Close();
  464. return -1;
  465. }
  466. int JackCoreAudioIOAdapter::Close()
  467. {
  468. #ifdef DEBUG
  469. fTable.Save();
  470. #endif
  471. AudioOutputUnitStop(fAUHAL);
  472. DisposeBuffers();
  473. CloseAUHAL();
  474. return 0;
  475. }
  476. int JackCoreAudioIOAdapter::SetBufferSize(jack_nframes_t buffer_size)
  477. {
  478. JackIOAdapterInterface::SetBufferSize(buffer_size);
  479. Close();
  480. return Open();
  481. }
  482. }