| 20 | | #include "JackAudioQueueAdapter.h" |
|---|
| 21 | | //#include <CoreServices/CoreServices.h> |
|---|
| 22 | | |
|---|
| 23 | | namespace Jack |
|---|
| 24 | | { |
|---|
| 25 | | |
|---|
| 26 | | // NOT YET WORKING.... |
|---|
| 27 | | |
|---|
| 28 | | static void Print4CharCode(const char* msg, long c) |
|---|
| 29 | | { |
|---|
| 30 | | UInt32 __4CC_number = (c); |
|---|
| 31 | | char __4CC_string[5]; |
|---|
| 32 | | //*((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number); |
|---|
| 33 | | __4CC_string[4] = 0; |
|---|
| 34 | | //printf("%s'%s'\n", (msg), __4CC_string); |
|---|
| 35 | | snprintf(__4CC_string, 5, "%s'%s'\n", (msg), __4CC_string); |
|---|
| 36 | | } |
|---|
| 37 | | |
|---|
| 38 | | static int ComputeRecordBufferSize(AudioQueueRef mQueue, const AudioStreamBasicDescription *format, float seconds) |
|---|
| 39 | | { |
|---|
| 40 | | OSStatus err; |
|---|
| 41 | | int packets, frames, bytes = 0; |
|---|
| 42 | | frames = (int)ceil(seconds * format->mSampleRate); |
|---|
| 43 | | |
|---|
| 44 | | if (format->mBytesPerFrame > 0) |
|---|
| 45 | | bytes = frames * format->mBytesPerFrame; |
|---|
| 46 | | else { |
|---|
| 47 | | UInt32 maxPacketSize; |
|---|
| 48 | | if (format->mBytesPerPacket > 0) { |
|---|
| 49 | | maxPacketSize = format->mBytesPerPacket; // constant packet size |
|---|
| 50 | | } else { |
|---|
| 51 | | UInt32 propertySize = sizeof(maxPacketSize); |
|---|
| 52 | | if ((err = AudioQueueGetProperty(mQueue, kAudioQueueProperty_MaximumOutputPacketSize, &maxPacketSize, &propertySize)) != noErr) { |
|---|
| 53 | | printf("Couldn't get queue's maximum output packet size\n"); |
|---|
| 54 | | return 0; |
|---|
| 55 | | } |
|---|
| 56 | | } |
|---|
| 57 | | if (format->mFramesPerPacket > 0) |
|---|
| 58 | | packets = frames / format->mFramesPerPacket; |
|---|
| 59 | | else |
|---|
| 60 | | packets = frames; // worst-case scenario: 1 frame in a packet |
|---|
| 61 | | if (packets == 0) // sanity check |
|---|
| 62 | | packets = 1; |
|---|
| 63 | | bytes = packets * maxPacketSize; |
|---|
| 64 | | } |
|---|
| 65 | | return bytes; |
|---|
| 66 | | } |
|---|
| 67 | | |
|---|
| 68 | | void JackAudioQueueAdapter::CaptureCallback(void * inUserData, |
|---|
| 69 | | AudioQueueRef inAQ, |
|---|
| 70 | | AudioQueueBufferRef inBuffer, |
|---|
| 71 | | const AudioTimeStamp * inStartTime, |
|---|
| 72 | | UInt32 inNumPackets, |
|---|
| 73 | | const AudioStreamPacketDescription *inPacketDesc) |
|---|
| 74 | | { |
|---|
| 75 | | JackAudioQueueAdapter* adapter = (JackAudioQueueAdapter*)inUserData; |
|---|
| 76 | | OSStatus err; |
|---|
| 77 | | printf("JackAudioQueueAdapter::CaptureCallback\n"); |
|---|
| 78 | | |
|---|
| 79 | | // Use the adapter to communicate with audio callback |
|---|
| 80 | | // jack_adapter_push_input(adapter, audio_output, audio_output_buffer); |
|---|
| 81 | | |
|---|
| 82 | | if ((err = AudioQueueEnqueueBuffer(adapter->fCaptureQueue, inBuffer, 0, NULL)) != noErr) { |
|---|
| 83 | | printf("JackAudioQueueAdapter::CaptureCallback error %d\n", err); |
|---|
| 84 | | } else { |
|---|
| 85 | | printf("JackAudioQueueAdapter::CaptureCallback enqueue buffer\n"); |
|---|
| 86 | | } |
|---|
| 87 | | } |
|---|
| 88 | | |
|---|
| 89 | | void JackAudioQueueAdapter::PlaybackCallback(void * inUserData, |
|---|
| 90 | | AudioQueueRef inAQ, |
|---|
| 91 | | AudioQueueBufferRef inCompleteAQBuffer) |
|---|
| 92 | | { |
|---|
| 93 | | JackAudioQueueAdapter* adapter = (JackAudioQueueAdapter*)inUserData; |
|---|
| 94 | | OSStatus err; |
|---|
| 95 | | printf("JackAudioQueueAdapter::PlaybackCallback\n"); |
|---|
| 96 | | |
|---|
| 97 | | |
|---|
| 98 | | // Use the adapter to communicate with audio callback |
|---|
| 99 | | // jack_adapter_pull_output(adapter, audio_input, audio_input_buffer); |
|---|
| 100 | | |
|---|
| 101 | | //if (AudioQueueEnqueueBuffer(adapter->fPlaybackQueue, inCompleteAQBuffer, 0, &adapter->fPlaybackPacketDescs) != noErr) { |
|---|
| 102 | | if ((err = AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, 0, NULL)) != noErr) { |
|---|
| 103 | | printf("JackAudioQueueAdapter::PlaybackCallback error %d\n", err); |
|---|
| 104 | | } else { |
|---|
| 105 | | printf("JackAudioQueueAdapter::PlaybackCallback enqueue buffer\n"); |
|---|
| 106 | | } |
|---|
| 107 | | } |
|---|
| 108 | | |
|---|
| 109 | | void JackAudioQueueAdapter::InterruptionListener(void* inClientData, UInt32 inInterruptionState) |
|---|
| 110 | | { |
|---|
| 111 | | JackAudioQueueAdapter* obj = (JackAudioQueueAdapter*)inClientData; |
|---|
| 112 | | } |
|---|
| 113 | | |
|---|
| 114 | | void JackAudioQueueAdapter::PropListener(void* inClientData, |
|---|
| 115 | | AudioSessionPropertyID inID, |
|---|
| 116 | | UInt32 inDataSize, |
|---|
| 117 | | const void* inData) |
|---|
| 118 | | {} |
|---|
| 119 | | |
|---|
| 120 | | |
|---|
| 121 | | JackAudioQueueAdapter::JackAudioQueueAdapter(int inchan, int outchan, jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_adapter_t* adapter) |
|---|
| 122 | | :fCaptureChannels(inchan), fPlaybackChannels(outchan), fBufferSize(buffer_size), fSampleRate(sample_rate), fAdapter(adapter) |
|---|
| 123 | | {} |
|---|
| 124 | | |
|---|
| 125 | | JackAudioQueueAdapter::~JackAudioQueueAdapter() |
|---|
| 126 | | {} |
|---|
| 127 | | |
|---|
| 128 | | int JackAudioQueueAdapter::Open() |
|---|
| 129 | | { |
|---|
| 130 | | OSStatus err; |
|---|
| 131 | | int bufferByteSize; |
|---|
| 132 | | UInt32 size; |
|---|
| 133 | | |
|---|
| 134 | | /* |
|---|
| 135 | | err = AudioSessionInitialize(NULL, NULL, InterruptionListener, this); |
|---|
| 136 | | if (err != noErr) { |
|---|
| 137 | | fprintf(stderr, "AudioSessionInitialize error %d\n", err); |
|---|
| 138 | | return -1; |
|---|
| 139 | | } |
|---|
| 140 | | |
|---|
| 141 | | err = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, PropListener, this); |
|---|
| 142 | | if (err) { |
|---|
| 143 | | fprintf(stderr, "kAudioSessionProperty_AudioRouteChange error %d\n", err); |
|---|
| 144 | | } |
|---|
| 145 | | |
|---|
| 146 | | UInt32 inputAvailable = 0; |
|---|
| 147 | | UInt32 size = sizeof(inputAvailable); |
|---|
| 148 | | |
|---|
| 149 | | // we do not want to allow recording if input is not available |
|---|
| 150 | | err = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, &size, &inputAvailable); |
|---|
| | 20 | #include "TiPhoneCoreAudioRenderer.h" |
|---|
| | 21 | |
|---|
| | 22 | static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) |
|---|
| | 23 | { |
|---|
| | 24 | printf("- - - - - - - - - - - - - - - - - - - -\n"); |
|---|
| | 25 | printf(" Sample Rate:%f\n", inDesc->mSampleRate); |
|---|
| | 26 | printf(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID); |
|---|
| | 27 | printf(" Format Flags:%lX\n", inDesc->mFormatFlags); |
|---|
| | 28 | printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); |
|---|
| | 29 | printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); |
|---|
| | 30 | printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); |
|---|
| | 31 | printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); |
|---|
| | 32 | printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); |
|---|
| | 33 | printf("- - - - - - - - - - - - - - - - - - - -\n"); |
|---|
| | 34 | } |
|---|
| | 35 | |
|---|
| | 36 | static void printError(OSStatus err) |
|---|
| | 37 | { |
|---|
| | 38 | switch (err) { |
|---|
| | 39 | case kAudioConverterErr_FormatNotSupported: |
|---|
| | 40 | printf("error code : kAudioConverterErr_FormatNotSupported\n"); |
|---|
| | 41 | break; |
|---|
| | 42 | case kAudioConverterErr_OperationNotSupported: |
|---|
| | 43 | printf("error code : kAudioConverterErr_OperationNotSupported\n"); |
|---|
| | 44 | break; |
|---|
| | 45 | case kAudioConverterErr_PropertyNotSupported: |
|---|
| | 46 | printf("error code : kAudioConverterErr_PropertyNotSupported\n"); |
|---|
| | 47 | break; |
|---|
| | 48 | case kAudioConverterErr_InvalidInputSize: |
|---|
| | 49 | printf("error code : kAudioConverterErr_InvalidInputSize\n"); |
|---|
| | 50 | break; |
|---|
| | 51 | case kAudioConverterErr_InvalidOutputSize: |
|---|
| | 52 | printf("error code : kAudioConverterErr_InvalidOutputSize\n"); |
|---|
| | 53 | break; |
|---|
| | 54 | case kAudioConverterErr_UnspecifiedError: |
|---|
| | 55 | printf("error code : kAudioConverterErr_UnspecifiedError\n"); |
|---|
| | 56 | break; |
|---|
| | 57 | case kAudioConverterErr_BadPropertySizeError: |
|---|
| | 58 | printf("error code : kAudioConverterErr_BadPropertySizeError\n"); |
|---|
| | 59 | break; |
|---|
| | 60 | case kAudioConverterErr_RequiresPacketDescriptionsError: |
|---|
| | 61 | printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n"); |
|---|
| | 62 | break; |
|---|
| | 63 | case kAudioConverterErr_InputSampleRateOutOfRange: |
|---|
| | 64 | printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n"); |
|---|
| | 65 | break; |
|---|
| | 66 | case kAudioConverterErr_OutputSampleRateOutOfRange: |
|---|
| | 67 | printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n"); |
|---|
| | 68 | break; |
|---|
| | 69 | default: |
|---|
| | 70 | printf("error code : unknown\n"); |
|---|
| | 71 | break; |
|---|
| | 72 | } |
|---|
| | 73 | } |
|---|
| | 74 | |
|---|
| | 75 | OSStatus TiPhoneCoreAudioRenderer::Render(void *inRefCon, |
|---|
| | 76 | AudioUnitRenderActionFlags *ioActionFlags, |
|---|
| | 77 | const AudioTimeStamp *inTimeStamp, |
|---|
| | 78 | UInt32, |
|---|
| | 79 | UInt32 inNumberFrames, |
|---|
| | 80 | AudioBufferList *ioData) |
|---|
| | 81 | { |
|---|
| | 82 | TiPhoneCoreAudioRendererPtr renderer = (TiPhoneCoreAudioRendererPtr)inRefCon; |
|---|
| | 83 | AudioUnitRender(renderer->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); |
|---|
| | 84 | |
|---|
| | 85 | float coef = float(LONG_MAX); |
|---|
| | 86 | float inv_coef = 1.f/float(LONG_MAX); |
|---|
| | 87 | |
|---|
| | 88 | for (int chan = 0; chan < renderer->fDevNumInChans; chan++) { |
|---|
| | 89 | for (int frame = 0; frame < inNumberFrames; frame++) { |
|---|
| | 90 | renderer->fInChannel[chan][frame] = float(((long*)ioData->mBuffers[chan].mData)[frame]) * inv_coef; |
|---|
| | 91 | } |
|---|
| | 92 | } |
|---|
| | 93 | |
|---|
| | 94 | renderer->PerformAudioCallback((int)inNumberFrames); |
|---|
| | 95 | |
|---|
| | 96 | for (int chan = 0; chan < renderer->fDevNumOutChans; chan++) { |
|---|
| | 97 | for (int frame = 0; frame < inNumberFrames; frame++) { |
|---|
| | 98 | ((long*)ioData->mBuffers[chan].mData)[frame] = long(renderer->fOutChannel[chan][frame] * coef); |
|---|
| | 99 | } |
|---|
| | 100 | } |
|---|
| | 101 | |
|---|
| | 102 | return 0; |
|---|
| | 103 | } |
|---|
| | 104 | |
|---|
| | 105 | void TiPhoneCoreAudioRenderer::InterruptionListener(void *inClientData, UInt32 inInterruption) |
|---|
| | 106 | { |
|---|
| | 107 | TiPhoneCoreAudioRenderer *obj = (TiPhoneCoreAudioRenderer*)inClientData; |
|---|
| | 108 | printf("Session interrupted! --- %s ---", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption"); |
|---|
| | 109 | |
|---|
| | 110 | if (inInterruption == kAudioSessionEndInterruption) { |
|---|
| | 111 | // make sure we are again the active session |
|---|
| | 112 | AudioSessionSetActive(true); |
|---|
| | 113 | AudioOutputUnitStart(obj->fAUHAL); |
|---|
| | 114 | } |
|---|
| | 115 | |
|---|
| | 116 | if (inInterruption == kAudioSessionBeginInterruption) { |
|---|
| | 117 | AudioOutputUnitStop(obj->fAUHAL); |
|---|
| | 118 | } |
|---|
| | 119 | } |
|---|
| | 120 | |
|---|
| | 121 | int TiPhoneCoreAudioRenderer::OpenDefault(int bufferSize, int samplerate) |
|---|
| | 122 | { |
|---|
| | 123 | OSStatus err1; |
|---|
| | 124 | UInt32 outSize; |
|---|
| | 125 | UInt32 enableIO; |
|---|
| | 126 | AudioStreamBasicDescription srcFormat, dstFormat; |
|---|
| | 127 | |
|---|
| | 128 | printf("OpenDefault fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate); |
|---|
| | 129 | |
|---|
| | 130 | // Initialize and configure the audio session |
|---|
| | 131 | err1 = AudioSessionInitialize(NULL, NULL, InterruptionListener, this); |
|---|
| | 132 | if (err1 != noErr) { |
|---|
| | 133 | printf("Couldn't initialize audio session\n"); |
|---|
| | 134 | printError(err1); |
|---|
| | 135 | return OPEN_ERR; |
|---|
| | 136 | } |
|---|
| | 137 | |
|---|
| | 138 | err1 = AudioSessionSetActive(true); |
|---|
| | 139 | if (err1 != noErr) { |
|---|
| | 140 | printf("Couldn't set audio session active\n"); |
|---|
| | 141 | printError(err1); |
|---|
| | 142 | return OPEN_ERR; |
|---|
| | 143 | } |
|---|
| | 144 | |
|---|
| | 145 | UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord; |
|---|
| | 146 | err1 = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); |
|---|
| | 147 | if (err1 != noErr) { |
|---|
| | 148 | printf("Couldn't set audio category\n"); |
|---|
| | 149 | printError(err1); |
|---|
| | 150 | return OPEN_ERR; |
|---|
| | 151 | } |
|---|
| | 152 | |
|---|
| | 153 | //err1 = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self), "couldn't set property listener"); |
|---|
| | 154 | |
|---|
| | 155 | Float64 hwSampleRate; |
|---|
| | 156 | outSize = sizeof(hwSampleRate); |
|---|
| | 157 | err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &outSize, &hwSampleRate); |
|---|
| | 158 | if (err1 != noErr) { |
|---|
| | 159 | printf("Couldn't get hw sample rate\n"); |
|---|
| | 160 | printError(err1); |
|---|
| | 161 | return OPEN_ERR; |
|---|
| | 162 | } else { |
|---|
| | 163 | printf("Get hw sample rate %f\n", hwSampleRate); |
|---|
| | 164 | } |
|---|
| | 165 | |
|---|
| | 166 | Float32 hwBufferSize; |
|---|
| | 167 | outSize = sizeof(hwBufferSize); |
|---|
| | 168 | err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &outSize, &hwBufferSize); |
|---|
| | 169 | if (err1 != noErr) { |
|---|
| | 170 | printf("Couldn't get hw buffer duration\n"); |
|---|
| | 171 | printError(err1); |
|---|
| | 172 | return OPEN_ERR; |
|---|
| | 173 | } else { |
|---|
| | 174 | printf("Get hw buffer duration %f\n", hwBufferSize); |
|---|
| | 175 | } |
|---|
| | 176 | |
|---|
| | 177 | UInt32 hwInput; |
|---|
| | 178 | outSize = sizeof(hwInput); |
|---|
| | 179 | err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &outSize, &hwInput); |
|---|
| | 180 | if (err1 != noErr) { |
|---|
| | 181 | printf("Couldn't get hw input channels\n"); |
|---|
| | 182 | printError(err1); |
|---|
| | 183 | return OPEN_ERR; |
|---|
| | 184 | } else { |
|---|
| | 185 | printf("Get hw input channels %d\n", hwInput); |
|---|
| | 186 | } |
|---|
| | 187 | |
|---|
| | 188 | UInt32 hwOutput; |
|---|
| | 189 | outSize = sizeof(hwOutput); |
|---|
| | 190 | err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels, &outSize, &hwOutput); |
|---|
| | 191 | if (err1 != noErr) { |
|---|
| | 192 | printf("Couldn't get hw output channels\n"); |
|---|
| | 193 | printError(err1); |
|---|
| | 194 | return OPEN_ERR; |
|---|
| | 195 | } else { |
|---|
| | 196 | printf("Get hw output channels %d\n", hwOutput); |
|---|
| | 197 | } |
|---|
| | 198 | |
|---|
| | 199 | Float32 preferredBufferSize = float(bufferSize) / float(samplerate); |
|---|
| | 200 | printf("preferredBufferSize %f \n", preferredBufferSize); |
|---|
| | 201 | |
|---|
| | 202 | err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize); |
|---|
| | 203 | if (err1 != noErr) { |
|---|
| | 204 | printf("Couldn't set i/o buffer duration\n"); |
|---|
| | 205 | printError(err1); |
|---|
| | 206 | return OPEN_ERR; |
|---|
| | 207 | } |
|---|
| | 208 | |
|---|
| | 209 | Float64 preferredSamplerate = float(samplerate); |
|---|
| | 210 | err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(preferredSamplerate), &preferredSamplerate); |
|---|
| | 211 | if (err1 != noErr) { |
|---|
| | 212 | printf("Couldn't set i/o sample rate\n"); |
|---|
| | 213 | printError(err1); |
|---|
| | 214 | return OPEN_ERR; |
|---|
| | 215 | } |
|---|
| | 216 | |
|---|
| | 217 | // AUHAL |
|---|
| | 218 | AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple, 0, 0}; |
|---|
| | 219 | AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd); |
|---|
| | 220 | |
|---|
| | 221 | err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL); |
|---|
| | 222 | if (err1 != noErr) { |
|---|
| | 223 | printf("Error calling OpenAComponent\n"); |
|---|
| | 224 | printError(err1); |
|---|
| | 225 | goto error; |
|---|
| | 226 | } |
|---|
| | 227 | |
|---|
| | 228 | enableIO = 1; |
|---|
| | 229 | err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); |
|---|
| | 230 | if (err1 != noErr) { |
|---|
| | 231 | printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n"); |
|---|
| | 232 | printError(err1); |
|---|
| | 233 | goto error; |
|---|
| | 234 | } |
|---|
| | 235 | |
|---|
| | 236 | enableIO = 1; |
|---|
| | 237 | err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); |
|---|
| | 238 | if (err1 != noErr) { |
|---|
| | 239 | printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n"); |
|---|
| | 240 | printError(err1); |
|---|
| | 241 | goto error; |
|---|
| | 242 | } |
|---|
| | 243 | |
|---|
| | 244 | UInt32 maxFPS; |
|---|
| | 245 | outSize = sizeof(maxFPS); |
|---|
| | 246 | err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, &outSize); |
|---|
| | 247 | if (err1 != noErr) { |
|---|
| | 248 | printf("Couldn't get kAudioUnitProperty_MaximumFramesPerSlice\n"); |
|---|
| | 249 | printError(err1); |
|---|
| | 250 | goto error; |
|---|
| | 251 | } else { |
|---|
| | 252 | printf("Get kAudioUnitProperty_MaximumFramesPerSlice %d\n", maxFPS); |
|---|
| | 253 | } |
|---|
| | 254 | |
|---|
| | 255 | err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32)); |
|---|
| | 256 | if (err1 != noErr) { |
|---|
| | 257 | printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); |
|---|
| | 258 | printError(err1); |
|---|
| | 259 | goto error; |
|---|
| | 260 | } |
|---|
| | 261 | |
|---|
| | 262 | err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32)); |
|---|
| | 263 | if (err1 != noErr) { |
|---|
| | 264 | printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); |
|---|
| | 265 | printError(err1); |
|---|
| | 266 | goto error; |
|---|
| | 267 | } |
|---|
| | 268 | |
|---|
| | 269 | err1 = AudioUnitInitialize(fAUHAL); |
|---|
| | 270 | if (err1 != noErr) { |
|---|
| | 271 | printf("Cannot initialize AUHAL unit\n"); |
|---|
| | 272 | printError(err1); |
|---|
| | 273 | goto error; |
|---|
| | 274 | } |
|---|
| | 275 | |
|---|
| | 276 | // Setting format |
|---|
| | 277 | |
|---|
| | 278 | if (fDevNumInChans > 0) { |
|---|
| | 279 | outSize = sizeof(AudioStreamBasicDescription); |
|---|
| | 280 | err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize); |
|---|
| | 281 | if (err1 != noErr) { |
|---|
| | 282 | printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); |
|---|
| | 283 | printError(err1); |
|---|
| | 284 | } |
|---|
| | 285 | PrintStreamDesc(&srcFormat); |
|---|
| | 286 | |
|---|
| | 287 | srcFormat.mFormatID = kAudioFormatLinearPCM; |
|---|
| | 288 | srcFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved; |
|---|
| | 289 | srcFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); |
|---|
| | 290 | srcFormat.mFramesPerPacket = 1; |
|---|
| | 291 | srcFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); |
|---|
| | 292 | srcFormat.mChannelsPerFrame = fDevNumInChans; |
|---|
| | 293 | srcFormat.mBitsPerChannel = 32; |
|---|
| | 294 | |
|---|
| | 295 | PrintStreamDesc(&srcFormat); |
|---|
| | 296 | |
|---|
| | 297 | err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); |
|---|
| | 298 | if (err1 != noErr) { |
|---|
| | 299 | printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); |
|---|
| | 300 | printError(err1); |
|---|
| | 301 | } |
|---|
| | 302 | } |
|---|
| | 303 | |
|---|
| | 304 | if (fDevNumOutChans > 0) { |
|---|
| | 305 | outSize = sizeof(AudioStreamBasicDescription); |
|---|
| | 306 | err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize); |
|---|
| | 307 | if (err1 != noErr) { |
|---|
| | 308 | printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); |
|---|
| | 309 | printError(err1); |
|---|
| | 310 | } |
|---|
| | 311 | PrintStreamDesc(&dstFormat); |
|---|
| | 312 | |
|---|
| | 313 | dstFormat.mFormatID = kAudioFormatLinearPCM; |
|---|
| | 314 | dstFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved; |
|---|
| | 315 | dstFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); |
|---|
| | 316 | dstFormat.mFramesPerPacket = 1; |
|---|
| | 317 | dstFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); |
|---|
| | 318 | dstFormat.mChannelsPerFrame = fDevNumOutChans; |
|---|
| | 319 | dstFormat.mBitsPerChannel = 32; |
|---|
| | 320 | |
|---|
| | 321 | PrintStreamDesc(&dstFormat); |
|---|
| | 322 | |
|---|
| | 323 | err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); |
|---|
| | 324 | if (err1 != noErr) { |
|---|
| | 325 | printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); |
|---|
| | 326 | printError(err1); |
|---|
| | 327 | } |
|---|
| | 328 | } |
|---|
| | 329 | |
|---|
| | 330 | if (fDevNumInChans > 0 && fDevNumOutChans == 0) { |
|---|
| | 331 | AURenderCallbackStruct output; |
|---|
| | 332 | output.inputProc = Render; |
|---|
| | 333 | output.inputProcRefCon = this; |
|---|
| | 334 | err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output)); |
|---|
| | 335 | if (err1 != noErr) { |
|---|
| | 336 | printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n"); |
|---|
| | 337 | printError(err1); |
|---|
| | 338 | goto error; |
|---|
| | 339 | } |
|---|
| | 340 | } else { |
|---|
| | 341 | AURenderCallbackStruct output; |
|---|
| | 342 | output.inputProc = Render; |
|---|
| | 343 | output.inputProcRefCon = this; |
|---|
| | 344 | err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output)); |
|---|
| | 345 | if (err1 != noErr) { |
|---|
| | 346 | printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n"); |
|---|
| | 347 | printError(err1); |
|---|
| | 348 | goto error; |
|---|
| | 349 | } |
|---|
| | 350 | } |
|---|
| | 351 | |
|---|
| | 352 | return NO_ERR; |
|---|
| | 353 | |
|---|
| | 354 | error: |
|---|
| | 355 | AudioUnitUninitialize(fAUHAL); |
|---|
| | 356 | AudioComponentInstanceDispose(fAUHAL); |
|---|
| | 357 | return OPEN_ERR; |
|---|
| | 358 | } |
|---|
| | 359 | |
|---|
| | 360 | int TiPhoneCoreAudioRenderer::Close() |
|---|
| | 361 | { |
|---|
| | 362 | AudioUnitUninitialize(fAUHAL); |
|---|
| | 363 | AudioComponentInstanceDispose(fAUHAL); |
|---|
| | 364 | return NO_ERR; |
|---|
| | 365 | } |
|---|
| | 366 | |
|---|
| | 367 | int TiPhoneCoreAudioRenderer::Start() |
|---|
| | 368 | { |
|---|
| | 369 | AudioSessionSetActive(true); |
|---|
| | 370 | OSStatus err = AudioOutputUnitStart(fAUHAL); |
|---|
| | 371 | |
|---|
| 163 | | fprintf(stderr, "AudioSessionSetActive (true) failed %d", err); |
|---|
| 164 | | return -1; |
|---|
| 165 | | } |
|---|
| 166 | | */ |
|---|
| 167 | | |
|---|
| 168 | | AudioStreamBasicDescription captureDataFormat; |
|---|
| 169 | | |
|---|
| 170 | | /* |
|---|
| 171 | | captureDataFormat.mSampleRate = fSampleRate; |
|---|
| 172 | | captureDataFormat.mFormatID = kAudioFormatLinearPCM; |
|---|
| 173 | | //captureDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; |
|---|
| 174 | | captureDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; |
|---|
| 175 | | captureDataFormat.mBytesPerPacket = sizeof(float); |
|---|
| 176 | | captureDataFormat.mFramesPerPacket = 1; |
|---|
| 177 | | captureDataFormat.mBytesPerFrame = sizeof(float); |
|---|
| 178 | | captureDataFormat.mChannelsPerFrame = fCaptureChannels; |
|---|
| 179 | | captureDataFormat.mBitsPerChannel = 32; |
|---|
| 180 | | */ |
|---|
| 181 | | |
|---|
| 182 | | |
|---|
| 183 | | captureDataFormat.mSampleRate = fSampleRate; |
|---|
| 184 | | captureDataFormat.mFormatID = kAudioFormatLinearPCM; |
|---|
| 185 | | captureDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; |
|---|
| 186 | | captureDataFormat.mBytesPerPacket = 4; |
|---|
| 187 | | captureDataFormat.mFramesPerPacket = 1; // this means each packet in the AQ has two samples, one for each channel -> 4 bytes/frame/packet |
|---|
| 188 | | captureDataFormat.mBytesPerFrame = 4; |
|---|
| 189 | | captureDataFormat.mChannelsPerFrame = 2; |
|---|
| 190 | | captureDataFormat.mBitsPerChannel = 16; |
|---|
| 191 | | |
|---|
| 192 | | |
|---|
| 193 | | if ((err = AudioQueueNewInput(&captureDataFormat, CaptureCallback, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &fCaptureQueue)) != noErr) { |
|---|
| 194 | | Print4CharCode("error code : unknown", err); |
|---|
| 195 | | return -1; |
|---|
| 196 | | } |
|---|
| 197 | | |
|---|
| 198 | | size = sizeof(captureDataFormat.mSampleRate); |
|---|
| 199 | | if ((err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &size, &captureDataFormat.mSampleRate)) != noErr) { |
|---|
| 200 | | printf("couldn't get hardware sample rate\n"); |
|---|
| 201 | | } |
|---|
| 202 | | |
|---|
| 203 | | size = sizeof(captureDataFormat.mChannelsPerFrame); |
|---|
| 204 | | if ((err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &size, &captureDataFormat.mChannelsPerFrame)) != noErr) { |
|---|
| 205 | | printf("couldn't get input channel count\n"); |
|---|
| 206 | | } |
|---|
| 207 | | |
|---|
| 208 | | size = sizeof(captureDataFormat); |
|---|
| 209 | | if ((err = AudioQueueGetProperty(fCaptureQueue, kAudioQueueProperty_StreamDescription, &captureDataFormat, &size)) != noErr) { |
|---|
| 210 | | printf("couldn't get queue's format\n"); |
|---|
| 211 | | } |
|---|
| 212 | | |
|---|
| 213 | | bufferByteSize = ComputeRecordBufferSize(fCaptureQueue, &captureDataFormat, kBufferDurationSeconds); // enough bytes for half a second |
|---|
| 214 | | for (int i = 0; i < kNumberBuffers; ++i) { |
|---|
| 215 | | if ((err = AudioQueueAllocateBuffer(fCaptureQueue, bufferByteSize, &fCaptureQueueBuffers[i])) != noErr) { |
|---|
| 216 | | printf("Capture AudioQueueAllocateBuffer failed\n"); |
|---|
| 217 | | } |
|---|
| 218 | | if ((err = AudioQueueEnqueueBuffer(fCaptureQueue, fCaptureQueueBuffers[i], 0, NULL)) != noErr) { |
|---|
| 219 | | printf("Capture AudioQueueEnqueueBuffer failed\n"); |
|---|
| 220 | | } |
|---|
| 221 | | } |
|---|
| 222 | | |
|---|
| 223 | | |
|---|
| 224 | | //AudioQueueSetProperty(fCaptureQueue, kAudioQueueProperty_MagicCookie, cookie, size) |
|---|
| 225 | | //AudioQueueSetProperty(fCaptureQueue, kAudioQueueProperty_ChannelLayout, acl, size |
|---|
| 226 | | |
|---|
| 227 | | AudioStreamBasicDescription playbackDataFormat; |
|---|
| 228 | | |
|---|
| 229 | | /* |
|---|
| 230 | | playbackDataFormat.mSampleRate = fSampleRate; |
|---|
| 231 | | playbackDataFormat.mFormatID = kAudioFormatLinearPCM; |
|---|
| 232 | | playbackDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; |
|---|
| 233 | | playbackDataFormat.mBytesPerPacket = sizeof(float); |
|---|
| 234 | | playbackDataFormat.mFramesPerPacket = 1; |
|---|
| 235 | | playbackDataFormat.mBytesPerFrame = sizeof(float); |
|---|
| 236 | | playbackDataFormat.mChannelsPerFrame = fPlaybackChannels; |
|---|
| 237 | | playbackDataFormat.mBitsPerChannel = 32; |
|---|
| 238 | | */ |
|---|
| 239 | | |
|---|
| 240 | | playbackDataFormat.mSampleRate = fSampleRate; |
|---|
| 241 | | playbackDataFormat.mFormatID = kAudioFormatLinearPCM; |
|---|
| 242 | | playbackDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; |
|---|
| 243 | | playbackDataFormat.mBytesPerPacket = 4; |
|---|
| 244 | | playbackDataFormat.mFramesPerPacket = 1; |
|---|
| 245 | | playbackDataFormat.mBytesPerFrame = 4; |
|---|
| 246 | | playbackDataFormat.mChannelsPerFrame = fPlaybackChannels; |
|---|
| 247 | | playbackDataFormat.mBitsPerChannel = 16; |
|---|
| 248 | | |
|---|
| 249 | | |
|---|
| 250 | | if ((err = AudioQueueNewOutput(&playbackDataFormat, PlaybackCallback, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &fPlaybackQueue)) != noErr) { |
|---|
| 251 | | Print4CharCode("error code : unknown", err); |
|---|
| 252 | | return -1; |
|---|
| 253 | | } |
|---|
| 254 | | |
|---|
| 255 | | for (int i = 0; i < kNumberBuffers; ++i) { |
|---|
| 256 | | if ((err = AudioQueueAllocateBuffer(fPlaybackQueue, bufferByteSize, &fPlaybackQueueBuffers[i])) != noErr) { |
|---|
| 257 | | printf("Playback AudioQueueAllocateBuffer failed %d\n", err); |
|---|
| 258 | | } |
|---|
| 259 | | //if ((err = AudioQueueEnqueueBuffer(fPlaybackQueue, fPlaybackQueueBuffers[i], 0, NULL)) != noErr) { |
|---|
| 260 | | // printf("Playback AudioQueueEnqueueBuffer failed %d\n", err); |
|---|
| 261 | | //} |
|---|
| 262 | | } |
|---|
| 263 | | |
|---|
| 264 | | AudioQueueSetParameter(fPlaybackQueue, kAudioQueueParam_Volume, 1.0); |
|---|
| 265 | | |
|---|
| 266 | | |
|---|
| 267 | | //AudioQueueSetProperty(fPlaybackQueue, kAudioQueueProperty_MagicCookie, cookie, size); |
|---|
| 268 | | //AudioQueueSetProperty(fPlaybackQueue, kAudioQueueProperty_ChannelLayout, acl, size); |
|---|
| 269 | | //AudioQueueSetParameter(fPlaybackQueue, kAudioQueueParam_Volume, volume |
|---|
| 270 | | |
|---|
| 271 | | return 0; |
|---|
| 272 | | } |
|---|
| 273 | | int JackAudioQueueAdapter::Close() |
|---|
| 274 | | { |
|---|
| 275 | | //AudioSessionSetActive(false); |
|---|
| 276 | | |
|---|
| 277 | | AudioQueueDispose(fCaptureQueue, true); |
|---|
| 278 | | AudioQueueDispose(fPlaybackQueue, true); |
|---|
| 279 | | return 0; |
|---|
| 280 | | } |
|---|
| 281 | | |
|---|
| 282 | | int JackAudioQueueAdapter::Start() |
|---|
| 283 | | { |
|---|
| 284 | | for (int i = 0; i < kNumberBuffers; ++i) { |
|---|
| 285 | | PlaybackCallback(this, fPlaybackQueue, fPlaybackQueueBuffers[i]); |
|---|
| 286 | | } |
|---|
| 287 | | |
|---|
| 288 | | AudioQueueStart(fCaptureQueue, NULL); |
|---|
| 289 | | AudioQueueStart(fPlaybackQueue, NULL); |
|---|
| 290 | | |
|---|
| 291 | | return 0; |
|---|
| 292 | | } |
|---|
| 293 | | |
|---|
| 294 | | int JackAudioQueueAdapter::Stop() |
|---|
| 295 | | { |
|---|
| 296 | | |
|---|
| 297 | | AudioQueueStop(fCaptureQueue, NULL); |
|---|
| 298 | | AudioQueueStop(fPlaybackQueue, NULL); |
|---|
| 299 | | |
|---|
| 300 | | return 0; |
|---|
| 301 | | } |
|---|
| 302 | | |
|---|
| 303 | | |
|---|
| 304 | | int JackAudioQueueAdapter::SetSampleRate(jack_nframes_t sample_rate) |
|---|
| 305 | | { |
|---|
| 306 | | return 0; |
|---|
| 307 | | } |
|---|
| 308 | | |
|---|
| 309 | | int JackAudioQueueAdapter::SetBufferSize(jack_nframes_t buffer_size) |
|---|
| 310 | | { |
|---|
| 311 | | return 0; |
|---|
| 312 | | } |
|---|
| 313 | | |
|---|
| 314 | | }; |
|---|
| | 385 | printf("Error while closing device : device close error \n"); |
|---|
| | 386 | return OPEN_ERR; |
|---|
| | 387 | } else { |
|---|
| | 388 | return NO_ERR; |
|---|
| | 389 | } |
|---|
| | 390 | } |
|---|