tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cubeb_ring_array.h (3916B)


      1 /*
      2 * Copyright © 2016 Mozilla Foundation
      3 *
      4 * This program is made available under an ISC-style license.  See the
      5 * accompanying file LICENSE for details.
      6 */
      7 
      8 #ifndef CUBEB_RING_ARRAY_H
      9 #define CUBEB_RING_ARRAY_H
     10 
     11 #include "cubeb_utils.h"
     12 #include <CoreAudio/CoreAudioTypes.h>
     13 
     14 /** Ring array of pointers is used to hold buffers. In case that
     15    asynchronous producer/consumer callbacks do not arrive in a
     16    repeated order the ring array stores the buffers and fetch
     17    them in the correct order. */
     18 
     19 typedef struct {
     20  AudioBuffer * buffer_array; /**< Array that hold pointers of the allocated
     21                                 space for the buffers. */
     22  unsigned int tail;     /**< Index of the last element (first to deliver). */
     23  unsigned int count;    /**< Number of elements in the array. */
     24  unsigned int capacity; /**< Total length of the array. */
     25 } ring_array;
     26 
     27 static int
     28 single_audiobuffer_init(AudioBuffer * buffer, uint32_t bytesPerFrame,
     29                        uint32_t channelsPerFrame, uint32_t frames)
     30 {
     31  assert(buffer);
     32  assert(bytesPerFrame > 0 && channelsPerFrame && frames > 0);
     33 
     34  size_t size = bytesPerFrame * frames;
     35  buffer->mData = operator new(size);
     36  if (buffer->mData == NULL) {
     37    return CUBEB_ERROR;
     38  }
     39  PodZero(static_cast<char *>(buffer->mData), size);
     40 
     41  buffer->mNumberChannels = channelsPerFrame;
     42  buffer->mDataByteSize = size;
     43 
     44  return CUBEB_OK;
     45 }
     46 
     47 /** Initialize the ring array.
     48    @param ra The ring_array pointer of allocated structure.
     49    @retval 0 on success. */
     50 static int
     51 ring_array_init(ring_array * ra, uint32_t capacity, uint32_t bytesPerFrame,
     52                uint32_t channelsPerFrame, uint32_t framesPerBuffer)
     53 {
     54  assert(ra);
     55  if (capacity == 0 || bytesPerFrame == 0 || channelsPerFrame == 0 ||
     56      framesPerBuffer == 0) {
     57    return CUBEB_ERROR_INVALID_PARAMETER;
     58  }
     59  ra->capacity = capacity;
     60  ra->tail = 0;
     61  ra->count = 0;
     62 
     63  ra->buffer_array = new AudioBuffer[ra->capacity];
     64  PodZero(ra->buffer_array, ra->capacity);
     65  if (ra->buffer_array == NULL) {
     66    return CUBEB_ERROR;
     67  }
     68 
     69  for (unsigned int i = 0; i < ra->capacity; ++i) {
     70    if (single_audiobuffer_init(&ra->buffer_array[i], bytesPerFrame,
     71                                channelsPerFrame,
     72                                framesPerBuffer) != CUBEB_OK) {
     73      return CUBEB_ERROR;
     74    }
     75  }
     76 
     77  return CUBEB_OK;
     78 }
     79 
     80 /** Destroy the ring array.
     81    @param ra The ring_array pointer.*/
     82 static void
     83 ring_array_destroy(ring_array * ra)
     84 {
     85  assert(ra);
     86  if (ra->buffer_array == NULL) {
     87    return;
     88  }
     89  for (unsigned int i = 0; i < ra->capacity; ++i) {
     90    if (ra->buffer_array[i].mData) {
     91      operator delete(ra->buffer_array[i].mData);
     92    }
     93  }
     94  delete[] ra->buffer_array;
     95 }
     96 
     97 /** Get the allocated buffer to be stored with fresh data.
     98    @param ra The ring_array pointer.
     99    @retval Pointer of the allocated space to be stored with fresh data or NULL
    100   if full. */
    101 static AudioBuffer *
    102 ring_array_get_free_buffer(ring_array * ra)
    103 {
    104  assert(ra && ra->buffer_array);
    105  assert(ra->buffer_array[0].mData != NULL);
    106  if (ra->count == ra->capacity) {
    107    return NULL;
    108  }
    109 
    110  assert(ra->count == 0 || (ra->tail + ra->count) % ra->capacity != ra->tail);
    111  AudioBuffer * ret = &ra->buffer_array[(ra->tail + ra->count) % ra->capacity];
    112 
    113  ++ra->count;
    114  assert(ra->count <= ra->capacity);
    115 
    116  return ret;
    117 }
    118 
    119 /** Get the next available buffer with data.
    120    @param ra The ring_array pointer.
    121    @retval Pointer of the next in order data buffer or NULL if empty. */
    122 static AudioBuffer *
    123 ring_array_get_data_buffer(ring_array * ra)
    124 {
    125  assert(ra && ra->buffer_array);
    126  assert(ra->buffer_array[0].mData != NULL);
    127 
    128  if (ra->count == 0) {
    129    return NULL;
    130  }
    131  AudioBuffer * ret = &ra->buffer_array[ra->tail];
    132 
    133  ra->tail = (ra->tail + 1) % ra->capacity;
    134  assert(ra->tail < ra->capacity);
    135 
    136  assert(ra->count > 0);
    137  --ra->count;
    138 
    139  return ret;
    140 }
    141 
    142 #endif // CUBEB_RING_ARRAY_H