Changeset 2825
- Timestamp:
- 2007-05-31 05:23:22 (2 years ago)
- Files:
-
- liboggplay/trunk/plugin/audio/sydney_audio_mac.c (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
liboggplay/trunk/plugin/audio/sydney_audio_mac.c
r2804 r2825 37 37 #include "sydney_audio_new.h" 38 38 39 /* 40 * The Mac's audio interface is based on a "pull" I/O model, which means you 41 * can't just provide a data buffer and tell the audio device to play; you must 42 * register a callback and provide data as the device asks for it. To support 43 * sydney audio's "write-to-play" style interface, we have to buffer up the 44 * data as it arrives and feed it to the callback as required. 45 * 46 * This is handled by a simple linked list of buffers; data is always written 47 * to the tail and read from the head. Each buffer tracks the start and end 48 * positions of its contained data. Buffers are allocated when the tail buffer 49 * fills, and freed when the head buffer empties. There is always at least one 50 * buffer allocated. 51 * 52 * s e s e s e + data read 53 * +++##### -> ######## -> ####---- # data written 54 * ^ ^ - empty 55 * bl_head bl_tail 56 */ 57 39 58 typedef struct sa_buf sa_buf; 40 59 struct sa_buf { … … 50 69 pthread_mutex_t mutex; 51 70 bool playing; 71 int64_t bytes_played; 52 72 53 73 /* audio format info */ … … 76 96 77 97 78 OSStatus audio_callback(void *arg, AudioUnitRenderActionFlags *action_flags,98 static OSStatus audio_callback(void *arg, AudioUnitRenderActionFlags *action_flags, 79 99 const AudioTimeStamp *time_stamp, UInt32 bus_num, UInt32 n_frames, AudioBufferList *data); 80 100 … … 132 152 s->output_unit = NULL; 133 153 s->playing = FALSE; 154 s->bytes_played = 0; 134 155 s->rate = rate; 135 156 s->n_channels = n_channels; … … 340 361 while (s->n_bufs == BUF_LIMIT) { 341 362 pthread_mutex_unlock(&s->mutex); 342 struct timespec ts = {0, 10000 };363 struct timespec ts = {0, 1000000}; 343 364 nanosleep(&ts, NULL); 344 365 pthread_mutex_lock(&s->mutex); … … 379 400 380 401 381 OSStatus402 static OSStatus 382 403 audio_callback( 383 404 void * arg, … … 399 420 pthread_mutex_lock(&s->mutex); 400 421 401 unsigned char * dst = data->mBuffers[0].mData; 402 unsigned int to_copy = n_frames * s->n_channels * s->bytes_per_ch; 422 unsigned char * dst = data->mBuffers[0].mData; 423 unsigned int bytes_per_frame = s->n_channels * s->bytes_per_ch; 424 unsigned int bytes_to_copy = n_frames * bytes_per_frame; 425 426 /* 427 * Keep track of the number of bytes we've consumed so far. mSampleTime 428 * is actually the number of *frames* that have been consumed by the 429 * audio output unit so far. I don't know why it's a float. 430 */ 431 assert(time_stamp->mFlags & kAudioTimeStampSampleTimeValid); 432 s->bytes_played = (int64_t)time_stamp->mSampleTime * bytes_per_frame; 403 433 404 434 /* … … 409 439 unsigned int avail = s->bl_head->end - s->bl_head->start; 410 440 411 if (avail >= to_copy) {441 if (avail >= bytes_to_copy) { 412 442 413 443 /* 414 444 * We have all we need in the head buffer, so just grab it and go. 415 445 */ 416 memcpy(dst, s->bl_head->data + s->bl_head->start, to_copy);417 s->bl_head->start += to_copy;446 memcpy(dst, s->bl_head->data + s->bl_head->start, bytes_to_copy); 447 s->bl_head->start += bytes_to_copy; 418 448 break; 419 449 … … 426 456 s->bl_head->start += avail; 427 457 dst += avail; 428 to_copy -= avail;458 bytes_to_copy -= avail; 429 459 430 460 /* … … 436 466 if (next == NULL) { 437 467 printf("NOT ENOUGH DATA\n"); 438 memset(dst, 0, to_copy);468 memset(dst, 0, bytes_to_copy); 439 469 break; 440 470 } … … 443 473 s->n_bufs--; 444 474 445 } /* if (avail >= to_copy), else */475 } /* if (avail >= bytes_to_copy), else */ 446 476 447 477 } /* while (1) */ … … 478 508 } 479 509 *size = BUF_SIZE * BUF_LIMIT - used; 510 511 pthread_mutex_unlock(&s->mutex); 512 return SA_SUCCESS; 513 } 514 515 516 int 517 sa_stream_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos) { 518 519 if (s == NULL || s->output_unit == NULL) { 520 return SA_ERROR_NO_INIT; 521 } 522 if (position != SA_POSITION_WRITE_SOFTWARE) { 523 return SA_ERROR_NOT_SUPPORTED; 524 } 525 526 pthread_mutex_lock(&s->mutex); 527 *pos = s->bytes_played; 528 pthread_mutex_unlock(&s->mutex); 529 return SA_SUCCESS; 530 } 531 532 533 int 534 sa_stream_change_write_volume(sa_stream_t *s, const int32_t vol[], unsigned n) { 535 //!todo 536 if (s == NULL || s->output_unit == NULL) { 537 return SA_ERROR_NO_INIT; 538 } 539 if (n != 1) { 540 return SA_ERROR_NOT_SUPPORTED; 541 } 542 543 pthread_mutex_lock(&s->mutex); 544 545 Float32 volume = 0; 546 AudioUnitGetParameter(s->output_unit, kHALOutputParam_Volume, 547 kAudioUnitParameterFlag_Output, 0, &volume); 548 549 /* 550 * The vol parameter is in hundredths of dB. If our current volume 551 * is the reference level, we can calculate the new volume by 552 * applying a factor of 10^(dB/20). 553 */ 554 volume *= pow(10, (double)vol[0] / 2000); 555 556 AudioUnitSetParameter(s->output_unit, kHALOutputParam_Volume, 557 kAudioUnitParameterFlag_Output, 0, volume, 0); 558 printf("set_vol: %f\n", volume); 559 560 pthread_mutex_unlock(&s->mutex); 561 return SA_SUCCESS; 562 } 563 564 565 int 566 sa_stream_get_write_volume(sa_stream_t *s, int32_t vol[], unsigned *n) { 567 //!todo 568 if (s == NULL || s->output_unit == NULL) { 569 return SA_ERROR_NO_INIT; 570 } 571 572 pthread_mutex_lock(&s->mutex); 573 574 Float32 volume; 575 AudioUnitGetParameter(s->output_unit, kHALOutputParam_Volume, 576 kAudioUnitParameterFlag_Output, 0, &volume); 577 printf("get_vol: %f\n", volume); 480 578 481 579 pthread_mutex_unlock(&s->mutex); … … 519 617 UNSUPPORTED(int sa_stream_change_device(sa_stream_t *s, const char *device_name)) 520 618 UNSUPPORTED(int sa_stream_change_read_volume(sa_stream_t *s, const int32_t vol[], unsigned n)) 521 UNSUPPORTED(int sa_stream_change_write_volume(sa_stream_t *s, const int32_t vol[], unsigned n))522 619 UNSUPPORTED(int sa_stream_change_rate(sa_stream_t *s, unsigned rate)) 523 620 UNSUPPORTED(int sa_stream_change_meta_data(sa_stream_t *s, const char *name, const void *data, size_t size)) … … 544 641 UNSUPPORTED(int sa_stream_get_device(sa_stream_t *s, char *device_name, size_t *size)) 545 642 UNSUPPORTED(int sa_stream_get_read_volume(sa_stream_t *s, int32_t vol[], unsigned *n)) 546 UNSUPPORTED(int sa_stream_get_write_volume(sa_stream_t *s, int32_t vol[], unsigned *n))547 643 UNSUPPORTED(int sa_stream_get_meta_data(sa_stream_t *s, const char *name, void*data, size_t *size)) 548 644 UNSUPPORTED(int sa_stream_get_adjust_rate(sa_stream_t *s, sa_adjust_t *direction)) … … 553 649 UNSUPPORTED(int sa_stream_get_event_error(sa_stream_t *s, sa_error_t *error)) 554 650 UNSUPPORTED(int sa_stream_get_event_notify(sa_stream_t *s, sa_notify_t *notify)) 555 UNSUPPORTED(int sa_stream_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos))556 651 UNSUPPORTED(int sa_stream_read(sa_stream_t *s, void *data, size_t nbytes)) 557 652 UNSUPPORTED(int sa_stream_read_ni(sa_stream_t *s, unsigned channel, void *data, size_t nbytes))