Mercurial > sdl-ios-xcode
comparison src/audio/macosx/SDL_coreaudio.c @ 3785:da2ea0694d11 SDL-ryan-multiple-audio-device
Ton of work on CoreAudio driver for new 1.3 features...most of the
multi-device support is wired up, and the starts of capture support, too.
All is still subject to change, and what's there is still a little flakey.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Tue, 03 Oct 2006 05:58:44 +0000 |
parents | 37c9c4590689 |
children | b70f4e9291bb |
comparison
equal
deleted
inserted
replaced
3784:37c9c4590689 | 3785:da2ea0694d11 |
---|---|
19 Sam Lantinga | 19 Sam Lantinga |
20 slouken@libsdl.org | 20 slouken@libsdl.org |
21 */ | 21 */ |
22 #include "SDL_config.h" | 22 #include "SDL_config.h" |
23 | 23 |
24 #include <CoreAudio/CoreAudio.h> | |
24 #include <AudioUnit/AudioUnit.h> | 25 #include <AudioUnit/AudioUnit.h> |
25 | 26 |
26 #include "SDL_audio.h" | 27 #include "SDL_audio.h" |
27 #include "../SDL_audio_c.h" | 28 #include "../SDL_audio_c.h" |
28 #include "../SDL_sysaudio.h" | 29 #include "../SDL_sysaudio.h" |
29 #include "SDL_coreaudio.h" | 30 #include "SDL_coreaudio.h" |
31 | |
32 | |
33 typedef struct COREAUDIO_DeviceList | |
34 { | |
35 AudioDeviceID id; | |
36 const char *name; | |
37 } COREAUDIO_DeviceList; | |
38 | |
39 static COREAUDIO_DeviceList *inputDevices = NULL; | |
40 static int inputDeviceCount = 0; | |
41 static COREAUDIO_DeviceList *outputDevices = NULL; | |
42 static int outputDeviceCount = 0; | |
43 | |
44 static void | |
45 free_device_list(COREAUDIO_DeviceList **devices, int *devCount) | |
46 { | |
47 if (*devices) { | |
48 int i = *devCount; | |
49 while (i--) | |
50 SDL_free((void *) (*devices)[i].name); | |
51 SDL_free(*devices); | |
52 *devices = NULL; | |
53 } | |
54 *devCount = 0; | |
55 } | |
56 | |
57 | |
58 static void | |
59 build_device_list(int iscapture, COREAUDIO_DeviceList **devices, int *devCount) | |
60 { | |
61 Boolean outWritable = 0; | |
62 OSStatus result = noErr; | |
63 UInt32 size = 0; | |
64 AudioDeviceID *devs = NULL; | |
65 UInt32 i = 0; | |
66 UInt32 max = 0; | |
67 | |
68 free_device_list(devices, devCount); | |
69 | |
70 result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, | |
71 &size, &outWritable); | |
72 | |
73 if (result != kAudioHardwareNoError) | |
74 return; | |
75 | |
76 devs = (AudioDeviceID *) alloca(size); | |
77 if (devs == NULL) | |
78 return; | |
79 | |
80 max = size / sizeof (AudioDeviceID); | |
81 *devices = (COREAUDIO_DeviceList *) SDL_malloc(max * sizeof (**devices)); | |
82 if (*devices == NULL) | |
83 return; | |
84 | |
85 result = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, | |
86 &size, devs); | |
87 if (result != kAudioHardwareNoError) | |
88 return; | |
89 | |
90 for (i = 0; i < max; i++) { | |
91 char *ptr = NULL; | |
92 AudioDeviceID dev = devs[i]; | |
93 AudioBufferList *buflist = NULL; | |
94 int usable = 0; | |
95 | |
96 result = AudioDeviceGetPropertyInfo(dev, 0, iscapture, | |
97 kAudioDevicePropertyStreamConfiguration, | |
98 &size, &outWritable); | |
99 if (result != noErr) | |
100 continue; | |
101 | |
102 buflist = (AudioBufferList *) SDL_malloc(size); | |
103 if (buflist == NULL) | |
104 continue; | |
105 | |
106 result = AudioDeviceGetProperty(dev, 0, iscapture, | |
107 kAudioDevicePropertyStreamConfiguration, | |
108 &size, buflist); | |
109 | |
110 if (result == noErr) { | |
111 UInt32 j; | |
112 for (j = 0; j < buflist->mNumberBuffers; j++) { | |
113 if (buflist->mBuffers[j].mNumberChannels > 0) { | |
114 usable = 1; | |
115 break; | |
116 } | |
117 } | |
118 } | |
119 | |
120 SDL_free(buflist); | |
121 | |
122 if (!usable) | |
123 continue; | |
124 | |
125 /* !!! FIXME: use CFStrings, instead, and convert to UTF-8. */ | |
126 result = AudioDeviceGetPropertyInfo(dev, 0, iscapture, | |
127 kAudioDevicePropertyDeviceName, | |
128 &size, &outWritable); | |
129 | |
130 if (result != kAudioHardwareNoError) | |
131 continue; | |
132 | |
133 ptr = (char *) SDL_malloc(size + 1); | |
134 if (ptr == NULL) | |
135 continue; | |
136 | |
137 result = AudioDeviceGetProperty(dev, 0, iscapture, | |
138 kAudioDevicePropertyDeviceName, | |
139 &size, ptr); | |
140 | |
141 if (result != kAudioHardwareNoError) | |
142 continue; | |
143 | |
144 while ((size > 0) && (ptr[size-1] == ' ')) | |
145 size--; /* I have a USB device with whitespace at the end... */ | |
146 | |
147 if (size == 0) { | |
148 SDL_free(ptr); | |
149 } else { | |
150 ptr[size] = '\0'; | |
151 (*devices)[*devCount].id = dev; | |
152 (*devices)[*devCount].name = ptr; | |
153 (*devCount)++; | |
154 } | |
155 } | |
156 } | |
157 | |
158 static int | |
159 find_device_id(const char *devname, int iscapture, AudioDeviceID *id) | |
160 { | |
161 int i = ((iscapture) ? inputDeviceCount : outputDeviceCount); | |
162 COREAUDIO_DeviceList *devs = ((iscapture) ? inputDevices : outputDevices); | |
163 while (i--) { | |
164 if (SDL_strcmp(devname, devs->name) == 0) { | |
165 *id = devs->id; | |
166 return 1; | |
167 } | |
168 devs++; | |
169 } | |
170 | |
171 return 0; | |
172 } | |
30 | 173 |
31 | 174 |
32 /* Audio driver functions */ | 175 /* Audio driver functions */ |
33 | 176 |
34 static int COREAUDIO_OpenAudio(_THIS, const char *devname, int iscapture); | 177 static int COREAUDIO_OpenAudio(_THIS, const char *devname, int iscapture); |
46 } | 189 } |
47 | 190 |
48 static int | 191 static int |
49 COREAUDIO_Init(SDL_AudioDriverImpl *impl) | 192 COREAUDIO_Init(SDL_AudioDriverImpl *impl) |
50 { | 193 { |
194 /* !!! FIXME: should these _really_ be static? */ | |
195 build_device_list(0, &outputDevices, &outputDeviceCount); | |
196 build_device_list(1, &inputDevices, &inputDeviceCount); | |
197 | |
51 /* Set the function pointers */ | 198 /* Set the function pointers */ |
52 impl->OpenAudio = COREAUDIO_OpenAudio; | 199 impl->OpenAudio = COREAUDIO_OpenAudio; |
53 impl->WaitAudio = COREAUDIO_WaitAudio; | 200 impl->WaitAudio = COREAUDIO_WaitAudio; |
54 impl->PlayAudio = COREAUDIO_PlayAudio; | 201 impl->PlayAudio = COREAUDIO_PlayAudio; |
55 impl->GetAudioBuf = COREAUDIO_GetAudioBuf; | 202 impl->GetAudioBuf = COREAUDIO_GetAudioBuf; |
63 COREAUDIO_Available, COREAUDIO_Init | 210 COREAUDIO_Available, COREAUDIO_Init |
64 }; | 211 }; |
65 | 212 |
66 /* The CoreAudio callback */ | 213 /* The CoreAudio callback */ |
67 static OSStatus | 214 static OSStatus |
68 audioCallback(void *inRefCon, | 215 outputCallback(void *inRefCon, |
69 AudioUnitRenderActionFlags inActionFlags, | 216 AudioUnitRenderActionFlags *ioActionFlags, |
70 const AudioTimeStamp * inTimeStamp, | 217 const AudioTimeStamp * inTimeStamp, |
71 UInt32 inBusNumber, AudioBuffer * ioData) | 218 UInt32 inBusNumber, UInt32 inNumberFrames, |
219 AudioBufferList *ioDataList) | |
72 { | 220 { |
73 SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon; | 221 SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon; |
222 AudioBuffer *ioData = &ioDataList->mBuffers[0]; | |
74 UInt32 remaining, len; | 223 UInt32 remaining, len; |
75 void *ptr; | 224 void *ptr; |
225 | |
226 if (ioDataList->mNumberBuffers != 1) { | |
227 fprintf(stderr, "!!! FIXME SDL!\n"); | |
228 return noErr; | |
229 } | |
76 | 230 |
77 /* Only do anything if audio is enabled and not paused */ | 231 /* Only do anything if audio is enabled and not paused */ |
78 if (!this->enabled || this->paused) { | 232 if (!this->enabled || this->paused) { |
79 SDL_memset(ioData->mData, this->spec.silence, ioData->mDataByteSize); | 233 SDL_memset(ioData->mData, this->spec.silence, ioData->mDataByteSize); |
80 return 0; | 234 return 0; |
114 } | 268 } |
115 | 269 |
116 return 0; | 270 return 0; |
117 } | 271 } |
118 | 272 |
273 static OSStatus | |
274 inputCallback(void *inRefCon, | |
275 AudioUnitRenderActionFlags *ioActionFlags, | |
276 const AudioTimeStamp * inTimeStamp, | |
277 UInt32 inBusNumber, UInt32 inNumberFrames, | |
278 AudioBufferList *ioData) | |
279 { | |
280 //err = AudioUnitRender(afr->fAudioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, afr->fAudioBuffer); | |
281 // !!! FIXME: write me! | |
282 return noErr; | |
283 } | |
284 | |
285 | |
119 /* Dummy functions -- we don't use thread-based audio */ | 286 /* Dummy functions -- we don't use thread-based audio */ |
120 void | 287 void |
121 COREAUDIO_WaitAudio(_THIS) | 288 COREAUDIO_WaitAudio(_THIS) |
122 { | 289 { |
123 return; | 290 return; |
136 } | 303 } |
137 | 304 |
138 void | 305 void |
139 COREAUDIO_CloseAudio(_THIS) | 306 COREAUDIO_CloseAudio(_THIS) |
140 { | 307 { |
141 OSStatus result; | 308 if (this->hidden != NULL) { |
142 struct AudioUnitInputCallback callback; | 309 OSStatus result = noErr; |
143 | 310 AURenderCallbackStruct callback; |
144 if (this->hidden == NULL) { | 311 const AudioUnitElement output_bus = 0; |
145 return; | 312 const AudioUnitElement input_bus = 1; |
146 } | 313 const int iscapture = this->hidden->isCapture; |
147 | 314 const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus); |
148 /* stop processing the audio unit */ | 315 const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output : |
149 result = AudioOutputUnitStop(this->hidden->outputAudioUnit); | 316 kAudioUnitScope_Input); |
150 if (result != noErr) { | 317 |
151 SDL_SetError("COREAUDIO_CloseAudio: AudioOutputUnitStop"); | 318 /* stop processing the audio unit */ |
152 return; | 319 result = AudioOutputUnitStop(this->hidden->audioUnit); |
153 } | 320 |
154 | 321 /* Remove the input callback */ |
155 /* Remove the input callback */ | 322 memset(&callback, '\0', sizeof (AURenderCallbackStruct)); |
156 callback.inputProc = 0; | 323 result = AudioUnitSetProperty(this->hidden->audioUnit, |
157 callback.inputProcRefCon = 0; | 324 kAudioUnitProperty_SetRenderCallback, |
158 result = AudioUnitSetProperty(this->hidden->outputAudioUnit, | 325 scope, bus, &callback, sizeof (callback)); |
159 kAudioUnitProperty_SetInputCallback, | 326 |
160 kAudioUnitScope_Input, | 327 CloseComponent(this->hidden->audioUnit); |
161 0, &callback, sizeof(callback)); | 328 |
162 if (result != noErr) { | 329 SDL_free(this->hidden->buffer); |
163 SDL_SetError | 330 SDL_free(this->hidden); |
164 ("COREAUDIO_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)"); | 331 this->hidden = NULL; |
165 return; | 332 } |
166 } | 333 } |
167 | 334 |
168 result = CloseComponent(this->hidden->outputAudioUnit); | |
169 if (result != noErr) { | |
170 SDL_SetError("COREAUDIO_CloseAudio: CloseComponent"); | |
171 return; | |
172 } | |
173 | |
174 SDL_free(this->hidden->buffer); | |
175 SDL_free(this->hidden); | |
176 this->hidden = NULL; | |
177 } | |
178 | 335 |
179 #define CHECK_RESULT(msg) \ | 336 #define CHECK_RESULT(msg) \ |
180 if (result != noErr) { \ | 337 if (result != noErr) { \ |
181 COREAUDIO_CloseAudio(this); \ | 338 COREAUDIO_CloseAudio(this); \ |
182 SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \ | 339 SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \ |
183 return -1; \ | 340 return 0; \ |
184 } | 341 } |
342 | |
343 static int | |
344 find_device_by_name(_THIS, const char *devname, int iscapture) | |
345 { | |
346 AudioDeviceID devid = 0; | |
347 OSStatus result = noErr; | |
348 UInt32 size = 0; | |
349 UInt32 alive = 0; | |
350 pid_t pid = 0; | |
351 | |
352 if (devname == NULL) { | |
353 size = sizeof (AudioDeviceID); | |
354 const AudioHardwarePropertyID propid = | |
355 ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice : | |
356 kAudioHardwarePropertyDefaultOutputDevice); | |
357 | |
358 result = AudioHardwareGetProperty(propid, &size, &devid); | |
359 CHECK_RESULT("AudioHardwareGetProperty (default device)"); | |
360 } else { | |
361 if (!find_device_id(devname, iscapture, &devid)) { | |
362 SDL_SetError("CoreAudio: No such audio device."); | |
363 return 0; | |
364 } | |
365 } | |
366 | |
367 size = sizeof (alive); | |
368 result = AudioDeviceGetProperty(devid, 0, iscapture, | |
369 kAudioDevicePropertyDeviceIsAlive, | |
370 &size, &alive); | |
371 CHECK_RESULT("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)"); | |
372 | |
373 if (!alive) { | |
374 SDL_SetError("CoreAudio: requested device exists, but isn't alive."); | |
375 return 0; | |
376 } | |
377 | |
378 size = sizeof (pid); | |
379 result = AudioDeviceGetProperty(devid, 0, iscapture, | |
380 kAudioDevicePropertyHogMode, &size, &pid); | |
381 | |
382 /* some devices don't support this property, so errors are fine here. */ | |
383 if ((result == noErr) && (pid != -1)) { | |
384 SDL_SetError("CoreAudio: requested device is being hogged."); | |
385 return 0; | |
386 } | |
387 | |
388 this->hidden->deviceID = devid; | |
389 return 1; | |
390 } | |
391 | |
392 | |
393 static int | |
394 prepare_audiounit(_THIS, const char *devname, int iscapture, | |
395 const AudioStreamBasicDescription *strdesc) | |
396 { | |
397 OSStatus result = noErr; | |
398 AURenderCallbackStruct callback; | |
399 ComponentDescription desc; | |
400 Component comp = NULL; | |
401 int use_system_device = 0; | |
402 UInt32 enableIO = 0; | |
403 const AudioUnitElement output_bus = 0; | |
404 const AudioUnitElement input_bus = 1; | |
405 const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus); | |
406 const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output : | |
407 kAudioUnitScope_Input); | |
408 | |
409 /* !!! FIXME: move something like this to higher level. */ | |
410 if ( (devname == NULL) && (SDL_getenv("SDL_AUDIO_DEVNAME")) ) | |
411 devname = SDL_getenv("SDL_AUDIO_DEVNAME"); | |
412 | |
413 if (!find_device_by_name(this, devname, iscapture)) { | |
414 SDL_SetError("Couldn't find requested CoreAudio device"); | |
415 return 0; | |
416 } | |
417 | |
418 memset(&desc, '\0', sizeof(ComponentDescription)); | |
419 desc.componentType = kAudioUnitType_Output; | |
420 desc.componentSubType = kAudioUnitSubType_HALOutput; | |
421 desc.componentManufacturer = kAudioUnitManufacturer_Apple; | |
422 | |
423 comp = FindNextComponent(NULL, &desc); | |
424 if (comp == NULL) { | |
425 SDL_SetError("Couldn't find requested CoreAudio component"); | |
426 return 0; | |
427 } | |
428 | |
429 /* Open & initialize the audio unit */ | |
430 result = OpenAComponent(comp, &this->hidden->audioUnit); | |
431 CHECK_RESULT("OpenAComponent"); | |
432 | |
433 // !!! FIXME: this is wrong? | |
434 enableIO = ((iscapture) ? 1 : 0); | |
435 result = AudioUnitSetProperty(this->hidden->audioUnit, | |
436 kAudioOutputUnitProperty_EnableIO, | |
437 kAudioUnitScope_Input, input_bus, | |
438 &enableIO, sizeof (enableIO)); | |
439 CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO input)"); | |
440 | |
441 // !!! FIXME: this is wrong? | |
442 enableIO = ((iscapture) ? 0 : 1); | |
443 result = AudioUnitSetProperty(this->hidden->audioUnit, | |
444 kAudioOutputUnitProperty_EnableIO, | |
445 kAudioUnitScope_Output, output_bus, | |
446 &enableIO, sizeof (enableIO)); | |
447 CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO output)"); | |
448 | |
449 result = AudioUnitSetProperty(this->hidden->audioUnit, | |
450 kAudioOutputUnitProperty_CurrentDevice, | |
451 kAudioUnitScope_Global, 0, | |
452 &this->hidden->deviceID, | |
453 sizeof (AudioDeviceID)); | |
454 CHECK_RESULT("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)"); | |
455 | |
456 /* Set the data format of the audio unit. */ | |
457 result = AudioUnitSetProperty(this->hidden->audioUnit, | |
458 kAudioUnitProperty_StreamFormat, | |
459 scope, bus, strdesc, sizeof (*strdesc)); | |
460 CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)"); | |
461 | |
462 /* Set the audio callback */ | |
463 memset(&callback, '\0', sizeof (AURenderCallbackStruct)); | |
464 callback.inputProc = ((iscapture) ? inputCallback : outputCallback); | |
465 callback.inputProcRefCon = this; | |
466 result = AudioUnitSetProperty(this->hidden->audioUnit, | |
467 kAudioUnitProperty_SetRenderCallback, | |
468 scope, bus, &callback, sizeof (callback)); | |
469 CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)"); | |
470 | |
471 /* Calculate the final parameters for this audio specification */ | |
472 SDL_CalculateAudioSpec(&this->spec); | |
473 | |
474 /* Allocate a sample buffer */ | |
475 this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size; | |
476 this->hidden->buffer = SDL_malloc(this->hidden->bufferSize); | |
477 | |
478 result = AudioUnitInitialize(this->hidden->audioUnit); | |
479 CHECK_RESULT("AudioUnitInitialize"); | |
480 | |
481 /* Finally, start processing of the audio unit */ | |
482 result = AudioOutputUnitStart(this->hidden->audioUnit); | |
483 CHECK_RESULT("AudioOutputUnitStart"); | |
484 | |
485 /* We're running! */ | |
486 return 1; | |
487 } | |
185 | 488 |
186 | 489 |
187 int | 490 int |
188 COREAUDIO_OpenAudio(_THIS, const char *devname, int iscapture) | 491 COREAUDIO_OpenAudio(_THIS, const char *devname, int iscapture) |
189 { | 492 { |
190 OSStatus result = noErr; | |
191 Component comp; | |
192 ComponentDescription desc; | |
193 struct AudioUnitInputCallback callback; | |
194 AudioStreamBasicDescription strdesc; | 493 AudioStreamBasicDescription strdesc; |
195 SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); | 494 SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); |
196 int valid_datatype = 0; | 495 int valid_datatype = 0; |
197 | 496 |
198 /* Initialize all variables that we clean on shutdown */ | 497 /* Initialize all variables that we clean on shutdown */ |
202 SDL_OutOfMemory(); | 501 SDL_OutOfMemory(); |
203 return (0); | 502 return (0); |
204 } | 503 } |
205 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | 504 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
206 | 505 |
207 /* !!! FIXME: check devname and iscapture... */ | 506 this->hidden->isCapture = iscapture; |
208 | 507 |
209 /* Setup a AudioStreamBasicDescription with the requested format */ | 508 /* Setup a AudioStreamBasicDescription with the requested format */ |
210 memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription)); | 509 memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription)); |
211 strdesc.mFormatID = kAudioFormatLinearPCM; | 510 strdesc.mFormatID = kAudioFormatLinearPCM; |
212 strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked; | 511 strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked; |
249 strdesc.mBytesPerFrame = | 548 strdesc.mBytesPerFrame = |
250 strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; | 549 strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; |
251 strdesc.mBytesPerPacket = | 550 strdesc.mBytesPerPacket = |
252 strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; | 551 strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; |
253 | 552 |
254 /* Locate the default output audio unit */ | 553 if (!prepare_audiounit(this, devname, iscapture, &strdesc)) { |
255 memset(&desc, '\0', sizeof(ComponentDescription)); | 554 return 0; /* prepare_audiounit() will call SDL_SetError()... */ |
256 desc.componentType = kAudioUnitComponentType; | 555 } |
257 desc.componentSubType = kAudioUnitSubType_Output; | 556 |
258 desc.componentManufacturer = kAudioUnitID_DefaultOutput; | 557 return 1; /* good to go. */ |
259 desc.componentFlags = 0; | |
260 desc.componentFlagsMask = 0; | |
261 | |
262 comp = FindNextComponent(NULL, &desc); | |
263 if (comp == NULL) { | |
264 COREAUDIO_CloseAudio(this); | |
265 SDL_SetError | |
266 ("Failed to start CoreAudio: FindNextComponent returned NULL"); | |
267 return 0; | |
268 } | |
269 | |
270 /* Open & initialize the default output audio unit */ | |
271 result = OpenAComponent(comp, &this->hidden->outputAudioUnit); | |
272 CHECK_RESULT("OpenAComponent") | |
273 result = AudioUnitInitialize(this->hidden->outputAudioUnit); | |
274 CHECK_RESULT("AudioUnitInitialize") | |
275 /* Set the input format of the audio unit. */ | |
276 result = AudioUnitSetProperty(this->hidden->outputAudioUnit, | |
277 kAudioUnitProperty_StreamFormat, | |
278 kAudioUnitScope_Input, | |
279 0, &strdesc, sizeof(strdesc)); | |
280 CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)") | |
281 /* Set the audio callback */ | |
282 callback.inputProc = audioCallback; | |
283 callback.inputProcRefCon = this; | |
284 result = AudioUnitSetProperty(this->hidden->outputAudioUnit, | |
285 kAudioUnitProperty_SetInputCallback, | |
286 kAudioUnitScope_Input, | |
287 0, &callback, sizeof(callback)); | |
288 CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)") | |
289 /* Calculate the final parameters for this audio specification */ | |
290 SDL_CalculateAudioSpec(&this->spec); | |
291 | |
292 /* Allocate a sample buffer */ | |
293 this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size; | |
294 this->hidden->buffer = SDL_malloc(this->hidden->bufferSize); | |
295 | |
296 /* Finally, start processing of the audio unit */ | |
297 result = AudioOutputUnitStart(this->hidden->outputAudioUnit); | |
298 CHECK_RESULT("AudioOutputUnitStart") | |
299 /* We're running! */ | |
300 return (1); | |
301 } | 558 } |
302 | 559 |
303 /* vi: set ts=4 sw=4 expandtab: */ | 560 /* vi: set ts=4 sw=4 expandtab: */ |