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.

315 lines
12KB

  1. /*
  2. Copyright (C) 2009 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 "JackAudioQueueAdapter.h"
  16. //#include <CoreServices/CoreServices.h>
  17. namespace Jack
  18. {
  19. // NOT YET WORKING....
  20. static void Print4CharCode(const char* msg, long c)
  21. {
  22. UInt32 __4CC_number = (c);
  23. char __4CC_string[5];
  24. //*((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number);
  25. __4CC_string[4] = 0;
  26. //printf("%s'%s'\n", (msg), __4CC_string);
  27. snprintf(__4CC_string, 5, "%s'%s'\n", (msg), __4CC_string);
  28. }
  29. static int ComputeRecordBufferSize(AudioQueueRef mQueue, const AudioStreamBasicDescription *format, float seconds)
  30. {
  31. OSStatus err;
  32. int packets, frames, bytes = 0;
  33. frames = (int)ceil(seconds * format->mSampleRate);
  34. if (format->mBytesPerFrame > 0)
  35. bytes = frames * format->mBytesPerFrame;
  36. else {
  37. UInt32 maxPacketSize;
  38. if (format->mBytesPerPacket > 0) {
  39. maxPacketSize = format->mBytesPerPacket; // constant packet size
  40. } else {
  41. UInt32 propertySize = sizeof(maxPacketSize);
  42. if ((err = AudioQueueGetProperty(mQueue, kAudioQueueProperty_MaximumOutputPacketSize, &maxPacketSize, &propertySize)) != noErr) {
  43. printf("Couldn't get queue's maximum output packet size\n");
  44. return 0;
  45. }
  46. }
  47. if (format->mFramesPerPacket > 0)
  48. packets = frames / format->mFramesPerPacket;
  49. else
  50. packets = frames; // worst-case scenario: 1 frame in a packet
  51. if (packets == 0) // sanity check
  52. packets = 1;
  53. bytes = packets * maxPacketSize;
  54. }
  55. return bytes;
  56. }
  57. void JackAudioQueueAdapter::CaptureCallback(void * inUserData,
  58. AudioQueueRef inAQ,
  59. AudioQueueBufferRef inBuffer,
  60. const AudioTimeStamp * inStartTime,
  61. UInt32 inNumPackets,
  62. const AudioStreamPacketDescription *inPacketDesc)
  63. {
  64. JackAudioQueueAdapter* adapter = (JackAudioQueueAdapter*)inUserData;
  65. OSStatus err;
  66. printf("JackAudioQueueAdapter::CaptureCallback\n");
  67. // Use the adapter to communicate with audio callback
  68. // jack_adapter_push_input(adapter, audio_output, audio_output_buffer);
  69. if ((err = AudioQueueEnqueueBuffer(adapter->fCaptureQueue, inBuffer, 0, NULL)) != noErr) {
  70. printf("JackAudioQueueAdapter::CaptureCallback error %d\n", err);
  71. } else {
  72. printf("JackAudioQueueAdapter::CaptureCallback enqueue buffer\n");
  73. }
  74. }
  75. void JackAudioQueueAdapter::PlaybackCallback(void * inUserData,
  76. AudioQueueRef inAQ,
  77. AudioQueueBufferRef inCompleteAQBuffer)
  78. {
  79. JackAudioQueueAdapter* adapter = (JackAudioQueueAdapter*)inUserData;
  80. OSStatus err;
  81. printf("JackAudioQueueAdapter::PlaybackCallback\n");
  82. // Use the adapter to communicate with audio callback
  83. // jack_adapter_pull_output(adapter, audio_input, audio_input_buffer);
  84. //if (AudioQueueEnqueueBuffer(adapter->fPlaybackQueue, inCompleteAQBuffer, 0, &adapter->fPlaybackPacketDescs) != noErr) {
  85. if ((err = AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, 0, NULL)) != noErr) {
  86. printf("JackAudioQueueAdapter::PlaybackCallback error %d\n", err);
  87. } else {
  88. printf("JackAudioQueueAdapter::PlaybackCallback enqueue buffer\n");
  89. }
  90. }
  91. void JackAudioQueueAdapter::InterruptionListener(void* inClientData, UInt32 inInterruptionState)
  92. {
  93. JackAudioQueueAdapter* obj = (JackAudioQueueAdapter*)inClientData;
  94. }
  95. void JackAudioQueueAdapter::PropListener(void* inClientData,
  96. AudioSessionPropertyID inID,
  97. UInt32 inDataSize,
  98. const void* inData)
  99. {}
  100. JackAudioQueueAdapter::JackAudioQueueAdapter(int inchan, int outchan, jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_adapter_t* adapter)
  101. :fCaptureChannels(inchan), fPlaybackChannels(outchan), fBufferSize(buffer_size), fSampleRate(sample_rate), fAdapter(adapter)
  102. {}
  103. JackAudioQueueAdapter::~JackAudioQueueAdapter()
  104. {}
  105. int JackAudioQueueAdapter::Open()
  106. {
  107. OSStatus err;
  108. int bufferByteSize;
  109. UInt32 size;
  110. /*
  111. err = AudioSessionInitialize(NULL, NULL, InterruptionListener, this);
  112. if (err != noErr) {
  113. fprintf(stderr, "AudioSessionInitialize error %d\n", err);
  114. return -1;
  115. }
  116. err = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, PropListener, this);
  117. if (err) {
  118. fprintf(stderr, "kAudioSessionProperty_AudioRouteChange error %d\n", err);
  119. }
  120. UInt32 inputAvailable = 0;
  121. UInt32 size = sizeof(inputAvailable);
  122. // we do not want to allow recording if input is not available
  123. err = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, &size, &inputAvailable);
  124. if (err != noErr) {
  125. fprintf(stderr, "kAudioSessionProperty_AudioInputAvailable error %d\n", err);
  126. }
  127. // we also need to listen to see if input availability changes
  128. err = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioInputAvailable, PropListener, this);
  129. if (err != noErr) {
  130. fprintf(stderr, "kAudioSessionProperty_AudioInputAvailable error %d\n", err);
  131. }
  132. err = AudioSessionSetActive(true);
  133. if (err != noErr) {
  134. fprintf(stderr, "AudioSessionSetActive (true) failed %d", err);
  135. return -1;
  136. }
  137. */
  138. AudioStreamBasicDescription captureDataFormat;
  139. /*
  140. captureDataFormat.mSampleRate = fSampleRate;
  141. captureDataFormat.mFormatID = kAudioFormatLinearPCM;
  142. //captureDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  143. captureDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
  144. captureDataFormat.mBytesPerPacket = sizeof(float);
  145. captureDataFormat.mFramesPerPacket = 1;
  146. captureDataFormat.mBytesPerFrame = sizeof(float);
  147. captureDataFormat.mChannelsPerFrame = fCaptureChannels;
  148. captureDataFormat.mBitsPerChannel = 32;
  149. */
  150. captureDataFormat.mSampleRate = fSampleRate;
  151. captureDataFormat.mFormatID = kAudioFormatLinearPCM;
  152. captureDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
  153. captureDataFormat.mBytesPerPacket = 4;
  154. captureDataFormat.mFramesPerPacket = 1; // this means each packet in the AQ has two samples, one for each channel -> 4 bytes/frame/packet
  155. captureDataFormat.mBytesPerFrame = 4;
  156. captureDataFormat.mChannelsPerFrame = 2;
  157. captureDataFormat.mBitsPerChannel = 16;
  158. if ((err = AudioQueueNewInput(&captureDataFormat, CaptureCallback, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &fCaptureQueue)) != noErr) {
  159. Print4CharCode("error code : unknown", err);
  160. return -1;
  161. }
  162. size = sizeof(captureDataFormat.mSampleRate);
  163. if ((err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &size, &captureDataFormat.mSampleRate)) != noErr) {
  164. printf("couldn't get hardware sample rate\n");
  165. }
  166. size = sizeof(captureDataFormat.mChannelsPerFrame);
  167. if ((err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &size, &captureDataFormat.mChannelsPerFrame)) != noErr) {
  168. printf("couldn't get input channel count\n");
  169. }
  170. size = sizeof(captureDataFormat);
  171. if ((err = AudioQueueGetProperty(fCaptureQueue, kAudioQueueProperty_StreamDescription, &captureDataFormat, &size)) != noErr) {
  172. printf("couldn't get queue's format\n");
  173. }
  174. bufferByteSize = ComputeRecordBufferSize(fCaptureQueue, &captureDataFormat, kBufferDurationSeconds); // enough bytes for half a second
  175. for (int i = 0; i < kNumberBuffers; ++i) {
  176. if ((err = AudioQueueAllocateBuffer(fCaptureQueue, bufferByteSize, &fCaptureQueueBuffers[i])) != noErr) {
  177. printf("Capture AudioQueueAllocateBuffer failed\n");
  178. }
  179. if ((err = AudioQueueEnqueueBuffer(fCaptureQueue, fCaptureQueueBuffers[i], 0, NULL)) != noErr) {
  180. printf("Capture AudioQueueEnqueueBuffer failed\n");
  181. }
  182. }
  183. //AudioQueueSetProperty(fCaptureQueue, kAudioQueueProperty_MagicCookie, cookie, size)
  184. //AudioQueueSetProperty(fCaptureQueue, kAudioQueueProperty_ChannelLayout, acl, size
  185. AudioStreamBasicDescription playbackDataFormat;
  186. /*
  187. playbackDataFormat.mSampleRate = fSampleRate;
  188. playbackDataFormat.mFormatID = kAudioFormatLinearPCM;
  189. playbackDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  190. playbackDataFormat.mBytesPerPacket = sizeof(float);
  191. playbackDataFormat.mFramesPerPacket = 1;
  192. playbackDataFormat.mBytesPerFrame = sizeof(float);
  193. playbackDataFormat.mChannelsPerFrame = fPlaybackChannels;
  194. playbackDataFormat.mBitsPerChannel = 32;
  195. */
  196. playbackDataFormat.mSampleRate = fSampleRate;
  197. playbackDataFormat.mFormatID = kAudioFormatLinearPCM;
  198. playbackDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
  199. playbackDataFormat.mBytesPerPacket = 4;
  200. playbackDataFormat.mFramesPerPacket = 1;
  201. playbackDataFormat.mBytesPerFrame = 4;
  202. playbackDataFormat.mChannelsPerFrame = fPlaybackChannels;
  203. playbackDataFormat.mBitsPerChannel = 16;
  204. if ((err = AudioQueueNewOutput(&playbackDataFormat, PlaybackCallback, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &fPlaybackQueue)) != noErr) {
  205. Print4CharCode("error code : unknown", err);
  206. return -1;
  207. }
  208. for (int i = 0; i < kNumberBuffers; ++i) {
  209. if ((err = AudioQueueAllocateBuffer(fPlaybackQueue, bufferByteSize, &fPlaybackQueueBuffers[i])) != noErr) {
  210. printf("Playback AudioQueueAllocateBuffer failed %d\n", err);
  211. }
  212. //if ((err = AudioQueueEnqueueBuffer(fPlaybackQueue, fPlaybackQueueBuffers[i], 0, NULL)) != noErr) {
  213. // printf("Playback AudioQueueEnqueueBuffer failed %d\n", err);
  214. //}
  215. }
  216. AudioQueueSetParameter(fPlaybackQueue, kAudioQueueParam_Volume, 1.0);
  217. //AudioQueueSetProperty(fPlaybackQueue, kAudioQueueProperty_MagicCookie, cookie, size);
  218. //AudioQueueSetProperty(fPlaybackQueue, kAudioQueueProperty_ChannelLayout, acl, size);
  219. //AudioQueueSetParameter(fPlaybackQueue, kAudioQueueParam_Volume, volume
  220. return 0;
  221. }
  222. int JackAudioQueueAdapter::Close()
  223. {
  224. //AudioSessionSetActive(false);
  225. AudioQueueDispose(fCaptureQueue, true);
  226. AudioQueueDispose(fPlaybackQueue, true);
  227. return 0;
  228. }
  229. int JackAudioQueueAdapter::Start()
  230. {
  231. for (int i = 0; i < kNumberBuffers; ++i) {
  232. PlaybackCallback(this, fPlaybackQueue, fPlaybackQueueBuffers[i]);
  233. }
  234. AudioQueueStart(fCaptureQueue, NULL);
  235. AudioQueueStart(fPlaybackQueue, NULL);
  236. return 0;
  237. }
  238. int JackAudioQueueAdapter::Stop()
  239. {
  240. AudioQueueStop(fCaptureQueue, NULL);
  241. AudioQueueStop(fPlaybackQueue, NULL);
  242. return 0;
  243. }
  244. int JackAudioQueueAdapter::SetSampleRate(jack_nframes_t sample_rate)
  245. {
  246. return 0;
  247. }
  248. int JackAudioQueueAdapter::SetBufferSize(jack_nframes_t buffer_size)
  249. {
  250. return 0;
  251. }
  252. };