duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.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