| 31 |
#define AUDIO_CAP "coreaudio" |
#define AUDIO_CAP "coreaudio" |
| 32 |
#include "audio_int.h" |
#include "audio_int.h" |
| 33 |
|
|
|
#define DEVICE_BUFFER_FRAMES (512) |
|
|
|
|
| 34 |
struct { |
struct { |
| 35 |
int buffer_frames; |
int buffer_frames; |
| 36 |
} conf = { |
} conf = { |
| 130 |
{ |
{ |
| 131 |
va_list ap; |
va_list ap; |
| 132 |
|
|
| 133 |
AUD_log (AUDIO_CAP, "Can not initialize %s\n", typ); |
AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ); |
| 134 |
|
|
| 135 |
va_start (ap, fmt); |
va_start (ap, fmt); |
| 136 |
AUD_vlog (AUDIO_CAP, fmt, ap); |
AUD_vlog (AUDIO_CAP, fmt, ap); |
| 145 |
|
|
| 146 |
err = pthread_mutex_lock (&core->mutex); |
err = pthread_mutex_lock (&core->mutex); |
| 147 |
if (err) { |
if (err) { |
| 148 |
dolog ("Can not lock voice for %s\nReason: %s\n", |
dolog ("Could not lock voice for %s\nReason: %s\n", |
| 149 |
fn_name, strerror (err)); |
fn_name, strerror (err)); |
| 150 |
return -1; |
return -1; |
| 151 |
} |
} |
| 158 |
|
|
| 159 |
err = pthread_mutex_unlock (&core->mutex); |
err = pthread_mutex_unlock (&core->mutex); |
| 160 |
if (err) { |
if (err) { |
| 161 |
dolog ("Can not unlock voice for %s\nReason: %s\n", |
dolog ("Could not unlock voice for %s\nReason: %s\n", |
| 162 |
fn_name, strerror (err)); |
fn_name, strerror (err)); |
| 163 |
return -1; |
return -1; |
| 164 |
} |
} |
| 266 |
return audio_pcm_sw_write (sw, buf, len); |
return audio_pcm_sw_write (sw, buf, len); |
| 267 |
} |
} |
| 268 |
|
|
| 269 |
static int coreaudio_init_out (HWVoiceOut *hw, int freq, |
static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as) |
|
int nchannels, audfmt_e fmt) |
|
| 270 |
{ |
{ |
| 271 |
OSStatus status; |
OSStatus status; |
| 272 |
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; |
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; |
| 279 |
/* create mutex */ |
/* create mutex */ |
| 280 |
err = pthread_mutex_init(&core->mutex, NULL); |
err = pthread_mutex_init(&core->mutex, NULL); |
| 281 |
if (err) { |
if (err) { |
| 282 |
dolog("Can not create mutex\nReason: %s\n", strerror (err)); |
dolog("Could not create mutex\nReason: %s\n", strerror (err)); |
| 283 |
return -1; |
return -1; |
| 284 |
} |
} |
| 285 |
|
|
| 286 |
if (fmt == AUD_FMT_S16 || fmt == AUD_FMT_U16) { |
if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) { |
| 287 |
bits = 16; |
bits = 16; |
| 288 |
endianess = 1; |
endianess = 1; |
| 289 |
} |
} |
| 290 |
|
|
| 291 |
audio_pcm_init_info ( |
audio_pcm_init_info ( |
| 292 |
&hw->info, |
&hw->info, |
| 293 |
freq, |
as, |
|
nchannels, |
|
|
fmt, |
|
| 294 |
/* Following is irrelevant actually since we do not use |
/* Following is irrelevant actually since we do not use |
| 295 |
mixengs clipping routines */ |
mixengs clipping routines */ |
| 296 |
audio_need_to_swap_endian (endianess) |
audio_need_to_swap_endian (endianess) |
| 297 |
); |
); |
|
hw->bufsize = 4 * conf.buffer_frames * nchannels * bits; |
|
| 298 |
|
|
| 299 |
/* open default output device */ |
/* open default output device */ |
| 300 |
propertySize = sizeof(core->outputDeviceID); |
propertySize = sizeof(core->outputDeviceID); |
| 304 |
&core->outputDeviceID); |
&core->outputDeviceID); |
| 305 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 306 |
coreaudio_logerr2 (status, typ, |
coreaudio_logerr2 (status, typ, |
| 307 |
"Can not get default output Device\n"); |
"Could not get default output Device\n"); |
| 308 |
return -1; |
return -1; |
| 309 |
} |
} |
| 310 |
if (core->outputDeviceID == kAudioDeviceUnknown) { |
if (core->outputDeviceID == kAudioDeviceUnknown) { |
| 311 |
dolog ("Can not initialize %s - Unknown Audiodevice\n", typ); |
dolog ("Could not initialize %s - Unknown Audiodevice\n", typ); |
| 312 |
return -1; |
return -1; |
| 313 |
} |
} |
| 314 |
|
|
| 315 |
/* set Buffersize to conf.buffer_frames frames */ |
/* set Buffersize to conf.buffer_frames frames */ |
| 316 |
propertySize = sizeof(core->audioDevicePropertyBufferSize); |
propertySize = sizeof(core->audioDevicePropertyBufferSize); |
| 317 |
core->audioDevicePropertyBufferSize = |
core->audioDevicePropertyBufferSize = |
| 318 |
conf.buffer_frames * sizeof(float) * 2; |
conf.buffer_frames * sizeof(float) << (as->nchannels == 2); |
| 319 |
status = AudioDeviceSetProperty( |
status = AudioDeviceSetProperty( |
| 320 |
core->outputDeviceID, |
core->outputDeviceID, |
| 321 |
NULL, |
NULL, |
| 326 |
&core->audioDevicePropertyBufferSize); |
&core->audioDevicePropertyBufferSize); |
| 327 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 328 |
coreaudio_logerr2 (status, typ, |
coreaudio_logerr2 (status, typ, |
| 329 |
"Can not set device buffer size %d\n", |
"Could not set device buffer size %d\n", |
| 330 |
kAudioDevicePropertyBufferSize); |
kAudioDevicePropertyBufferSize); |
| 331 |
return -1; |
return -1; |
| 332 |
} |
} |
| 341 |
&propertySize, |
&propertySize, |
| 342 |
&core->audioDevicePropertyBufferSize); |
&core->audioDevicePropertyBufferSize); |
| 343 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 344 |
coreaudio_logerr2 (status, typ, "Can not get device buffer size\n"); |
coreaudio_logerr2 (status, typ, "Could not get device buffer size\n"); |
| 345 |
return -1; |
return -1; |
| 346 |
} |
} |
| 347 |
|
hw->samples = (core->audioDevicePropertyBufferSize / sizeof (float)) |
| 348 |
|
>> (as->nchannels == 2); |
| 349 |
|
|
| 350 |
/* get StreamFormat */ |
/* get StreamFormat */ |
| 351 |
propertySize = sizeof(core->outputStreamBasicDescription); |
propertySize = sizeof(core->outputStreamBasicDescription); |
| 358 |
&core->outputStreamBasicDescription); |
&core->outputStreamBasicDescription); |
| 359 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 360 |
coreaudio_logerr2 (status, typ, |
coreaudio_logerr2 (status, typ, |
| 361 |
"Can not get Device Stream properties\n"); |
"Could not get Device Stream properties\n"); |
| 362 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
| 363 |
return -1; |
return -1; |
| 364 |
} |
} |
| 365 |
|
|
| 366 |
/* set Samplerate */ |
/* set Samplerate */ |
| 367 |
core->outputStreamBasicDescription.mSampleRate = (Float64)freq; |
core->outputStreamBasicDescription.mSampleRate = (Float64)as->freq; |
| 368 |
propertySize = sizeof(core->outputStreamBasicDescription); |
propertySize = sizeof(core->outputStreamBasicDescription); |
| 369 |
status = AudioDeviceSetProperty( |
status = AudioDeviceSetProperty( |
| 370 |
core->outputDeviceID, |
core->outputDeviceID, |
| 375 |
propertySize, |
propertySize, |
| 376 |
&core->outputStreamBasicDescription); |
&core->outputStreamBasicDescription); |
| 377 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 378 |
coreaudio_logerr2 (status, typ, "Can not set samplerate %d\n", freq); |
coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n", freq); |
| 379 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
| 380 |
return -1; |
return -1; |
| 381 |
} |
} |
| 383 |
/* set Callback */ |
/* set Callback */ |
| 384 |
status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw); |
status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw); |
| 385 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 386 |
coreaudio_logerr2 (status, typ, "Can not set IOProc\n"); |
coreaudio_logerr2 (status, typ, "Could not set IOProc\n"); |
| 387 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
| 388 |
return -1; |
return -1; |
| 389 |
} |
} |
| 392 |
if (!core->isPlaying) { |
if (!core->isPlaying) { |
| 393 |
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); |
| 394 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 395 |
coreaudio_logerr2 (status, typ, "Can not start playback\n"); |
coreaudio_logerr2 (status, typ, "Could not start playback\n"); |
| 396 |
AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); |
AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); |
| 397 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
| 398 |
return -1; |
return -1; |
| 413 |
if (core->isPlaying) { |
if (core->isPlaying) { |
| 414 |
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); |
| 415 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 416 |
coreaudio_logerr (status, "Can not stop playback\n"); |
coreaudio_logerr (status, "Could not stop playback\n"); |
| 417 |
} |
} |
| 418 |
core->isPlaying = 0; |
core->isPlaying = 0; |
| 419 |
} |
} |
| 421 |
/* remove callback */ |
/* remove callback */ |
| 422 |
status = AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc); |
| 423 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 424 |
coreaudio_logerr (status, "Can not remove IOProc\n"); |
coreaudio_logerr (status, "Could not remove IOProc\n"); |
| 425 |
} |
} |
| 426 |
core->outputDeviceID = kAudioDeviceUnknown; |
core->outputDeviceID = kAudioDeviceUnknown; |
| 427 |
|
|
| 428 |
/* destroy mutex */ |
/* destroy mutex */ |
| 429 |
err = pthread_mutex_destroy(&core->mutex); |
err = pthread_mutex_destroy(&core->mutex); |
| 430 |
if (err) { |
if (err) { |
| 431 |
dolog("Can not destroy mutex\nReason: %s\n", strerror (err)); |
dolog("Could not destroy mutex\nReason: %s\n", strerror (err)); |
| 432 |
} |
} |
| 433 |
} |
} |
| 434 |
|
|
| 443 |
if (!core->isPlaying) { |
if (!core->isPlaying) { |
| 444 |
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc); |
| 445 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 446 |
coreaudio_logerr (status, "Can not unpause playback\n"); |
coreaudio_logerr (status, "Could not unpause playback\n"); |
| 447 |
} |
} |
| 448 |
core->isPlaying = 1; |
core->isPlaying = 1; |
| 449 |
} |
} |
| 454 |
if (core->isPlaying) { |
if (core->isPlaying) { |
| 455 |
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); |
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc); |
| 456 |
if (status != kAudioHardwareNoError) { |
if (status != kAudioHardwareNoError) { |
| 457 |
coreaudio_logerr (status, "Can not pause playback\n"); |
coreaudio_logerr (status, "Could not pause playback\n"); |
| 458 |
} |
} |
| 459 |
core->isPlaying = 0; |
core->isPlaying = 0; |
| 460 |
} |
} |