Changeset 2825

Show
Ignore:
Timestamp:
2007-05-31 05:23:22 (2 years ago)
Author:
tahn
Message:

Implemented sa_stream_get_position, and first cuts for sa_stream_change_write_volume and sa_stream_get_write_volume.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • liboggplay/trunk/plugin/audio/sydney_audio_mac.c

    r2804 r2825  
    3737#include "sydney_audio_new.h" 
    3838 
     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 
    3958typedef struct sa_buf sa_buf; 
    4059struct sa_buf { 
     
    5069  pthread_mutex_t   mutex; 
    5170  bool              playing; 
     71  int64_t           bytes_played; 
    5272 
    5373  /* audio format info */ 
     
    7696 
    7797 
    78 OSStatus audio_callback(void *arg, AudioUnitRenderActionFlags *action_flags, 
     98static OSStatus audio_callback(void *arg, AudioUnitRenderActionFlags *action_flags, 
    7999  const AudioTimeStamp *time_stamp, UInt32 bus_num, UInt32 n_frames, AudioBufferList *data); 
    80100 
     
    132152  s->output_unit  = NULL; 
    133153  s->playing      = FALSE; 
     154  s->bytes_played = 0; 
    134155  s->rate         = rate; 
    135156  s->n_channels   = n_channels; 
     
    340361        while (s->n_bufs == BUF_LIMIT) { 
    341362          pthread_mutex_unlock(&s->mutex); 
    342           struct timespec ts = {0, 10000}; 
     363          struct timespec ts = {0, 1000000}; 
    343364          nanosleep(&ts, NULL); 
    344365          pthread_mutex_lock(&s->mutex); 
     
    379400 
    380401 
    381 OSStatus 
     402static OSStatus 
    382403audio_callback( 
    383404  void                        * arg, 
     
    399420  pthread_mutex_lock(&s->mutex); 
    400421 
    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; 
    403433 
    404434  /* 
     
    409439    unsigned int avail = s->bl_head->end - s->bl_head->start; 
    410440 
    411     if (avail >= to_copy) { 
     441    if (avail >= bytes_to_copy) { 
    412442 
    413443      /* 
    414444       * We have all we need in the head buffer, so just grab it and go. 
    415445       */ 
    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; 
    418448      break; 
    419449 
     
    426456      s->bl_head->start += avail; 
    427457      dst += avail; 
    428       to_copy -= avail; 
     458      bytes_to_copy -= avail; 
    429459 
    430460      /* 
     
    436466      if (next == NULL) { 
    437467        printf("NOT ENOUGH DATA\n"); 
    438         memset(dst, 0, to_copy); 
     468        memset(dst, 0, bytes_to_copy); 
    439469        break; 
    440470      } 
     
    443473      s->n_bufs--; 
    444474 
    445     } /* if (avail >= to_copy), else */ 
     475    } /* if (avail >= bytes_to_copy), else */ 
    446476 
    447477  } /* while (1) */ 
     
    478508  } 
    479509  *size = BUF_SIZE * BUF_LIMIT - used; 
     510 
     511  pthread_mutex_unlock(&s->mutex); 
     512  return SA_SUCCESS; 
     513} 
     514 
     515 
     516int 
     517sa_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 
     533int 
     534sa_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 
     565int 
     566sa_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); 
    480578 
    481579  pthread_mutex_unlock(&s->mutex); 
     
    519617UNSUPPORTED(int sa_stream_change_device(sa_stream_t *s, const char *device_name)) 
    520618UNSUPPORTED(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)) 
    522619UNSUPPORTED(int sa_stream_change_rate(sa_stream_t *s, unsigned rate)) 
    523620UNSUPPORTED(int sa_stream_change_meta_data(sa_stream_t *s, const char *name, const void *data, size_t size)) 
     
    544641UNSUPPORTED(int sa_stream_get_device(sa_stream_t *s, char *device_name, size_t *size)) 
    545642UNSUPPORTED(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)) 
    547643UNSUPPORTED(int sa_stream_get_meta_data(sa_stream_t *s, const char *name, void*data, size_t *size)) 
    548644UNSUPPORTED(int sa_stream_get_adjust_rate(sa_stream_t *s, sa_adjust_t *direction)) 
     
    553649UNSUPPORTED(int sa_stream_get_event_error(sa_stream_t *s, sa_error_t *error)) 
    554650UNSUPPORTED(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)) 
    556651UNSUPPORTED(int sa_stream_read(sa_stream_t *s, void *data, size_t nbytes)) 
    557652UNSUPPORTED(int sa_stream_read_ni(sa_stream_t *s, unsigned channel, void *data, size_t nbytes))